--- /dev/null
+PRELOAD-HACKS
+~~~~~~~~~~~~~
+
+What is it?
+
+ The preload-hacks distribution contains a couple of LD_PRELOAD-
+ able libraries which I find very useful. Well, one useful one,
+ and one which is really handy in theory.
+
+ uopen Traps when a process is trying to open(2) a Unix-domain
+ socket, and does the appropriate socket(2)/connect(2)
+ dance instead. I've no idea why it doesn't work like
+ this in the first place.
+
+ noip Traps when a process is trying to make an Internet
+ socket, and makes a Unix-domain socket instead.
+
+ The first one is the one which is useful in theory but I've not
+ really made much use of in practice.
+
+
+uopen
+
+ The main use-case is variable signatures. Many mail and news
+ clients nowadays have built-in sigmonsters, which choose a
+ .signature at random from a collection. Some don't, of course,
+ which is a shame. It would be nice if the sigmonster was
+ detachable, so you could just write a sigmonster and attach it
+ to your favourite newsreader. It would extra nice if
+ newsreaders (and mail clients) don't have to use some kind of
+ weirdo sigmonster interface just to do this stupid thing with
+ .signatures.
+
+ All mail and news clients know how to read a .signature file.
+ It's why it's got that name. So the right answer seems to be to
+ make this file magically have different contents each time it's
+ read. Noticing when someone tries to read a regular file is
+ just awful so let's not think about that idea any more. We
+ could make .signature be a named pipe; but named pipe servers
+ are very difficult to get right when there are multiple
+ simultaneous clients. Sockets are, of course, the right answer
+ when client/server architectures come up. And we've got a
+ convenient way of stashing sockets in the filesystem: PF_UNIX
+ sockets.
+
+ So, we write our sigmonster:
+
+ $ fwd -d from unix:$HOME/.signature to exec.fortune
+
+ And now we check to see whether it works.
+
+ $ cat ~/.signature
+ cat: /home/mdw/.signature: No such device or address
+
+ Hmm. That blows. Surely it's obvious how to read from a
+ socket. But, no, the kernel won't do the socket/connect thing
+ for us.
+
+ Enter uopen.
+
+ $ uopen cat ~/.signature
+ Noise proves nothing. Often a hen who has merely laid an egg
+ cackles as if she laid an asteroid.
+ -- Mark Twain
+
+ Joy!
+
+ This isn't perfect. The file is weird and not a proper file.
+ Emacs will refuse to visit it as a result. But it /will/
+ happily insert the contents of the file into existing buffers.
+ Hopefully other editors are similar. `less' wants the -f option
+ before it will bother. But actually it works pretty well.
+
+ The right place for the functionality of uopen is in the kernel.
+ It shouldn't be difficult. I even submitted a patch to the
+ Linux kernel list to do precisely that, once, back in the days
+ of 2.0.x. It was ignored, and I gave up; the patch bitrotted
+ hopelessly. My LD_PRELOAD hack still works. There's no
+ configuration. It just works.
+
+ My .signature has been `-- [mdw]' for years now, and that's
+ unlikely to change. So I don't actually use uopen very much.
+ But it's cool to know that it exists.
+
+
+noip
+
+ The basic idea
+
+ This I use every day. All the time. Here's the use case.
+ We'll see some more examples later.
+
+ Some random program has a client/server split between the main
+ guts of the thing and its user interface, and the two
+ communicate over TCP sockets. There are lots of examples: SLIME
+ (the Superior Lisp Interaction Mode for Emacs) runs a Common
+ Lisp system as a separate process. The SAGE notebook runs a web
+ server and you're meant to use a Javascript-supporting web
+ browser to drive it. All sorts of stuff. Usually the
+ programmer knew just enough to remember to bind the server's
+ listening socket to 127.0.0.1, to stop everyone on the Internet
+ from connecting, but often the security consciousness stops
+ there. If you're very lucky, there's some sort of password
+ mechanism.
+
+ The problem, of course, occurs on a multi-user system. Binding
+ to localhost doesn't stop any other user of the same machine
+ from connecting. In the cases of SLIME and SAGE, this is a big
+ problem: both provide a full programming environment
+ (respectively Common Lisp and Python) which would let an
+ attacker do anything he likes in your name.
+
+ Passwords are wretched as a security mechanism. Besides, I
+ shouldn't need a damned password to talk to one of my own
+ processes from another one of my own processes! The operating
+ system should be able to ensure that processes owned by the same
+ user can communicate securely. There's a whole filesystem with
+ access control and everything.
+
+ The right answer is to use Unix-domain sockets, which live in
+ the filesystem and have proper access control applied to them.
+ But programmers are lazy, and Unix-domain sockets don't exist on
+ Windows (well, unless you install Cygwin, but I can see why
+ that's an unpopular idea).
+
+ The noip LD_PRELOAD hack intercepts the socket(2) system call.
+ If the process is asking for a PF_INET socket, then it hands out
+ a PF_UNIX socket instead. If the process tries to bind(2) its
+ socket to 127.0.0.1:12345, say, then noip binds it to
+ /tmp/noip-USER/127.0.0.1:12345 instead (having previously
+ created the directory /tmp/noip-USER and made sure that nobody
+ else can get to it). If the process tries to connect(2)
+ somewhere, noip fixes up the address. The noip hack intercepts
+ 14 different system calls in order to prevent its systematic
+ dishonesty from being discovered.
+
+ Configuration
+
+ Running a program under noip effectively only allows it to talk
+ to other programs running under noip. This is sort of the idea,
+ but it's rather restrictive in practice. I can happily run
+
+ $ noip emacs
+
+ and start up SLIME, and Emacs and SLIME will communicate
+ securely over a Unix-domain socket without either of them
+ noticing. But now Emacs can't talk to anything other than
+ SLIME, which makes w3m-el less useful than it used to be, and,
+ worse, my Common Lisp programs can't talk to anything external
+ either, which may make writing network-aware Lisp programs
+ annoying.
+
+ It gets worse with SAGE. I can run
+
+ $ noip sage -notebook
+
+ and in another window
+
+ $ noip iceweasel http://localhost:8000/
+
+ (or Firefox, on Ubuntu), and the two will communicate happily.
+ But now my Iceweasel is crippled and can't actually talk to the
+ rest of the Internet. The point of the exercise was to make my
+ SAGE process secure, not to make me run two copies of Iceweasel
+ and have to cope with the inevitable profile fork.
+
+ So noip can be configured. It still defaults to safety:
+ whenever the process asks for a new Internet socket, noip hands
+ it a fake plastic Unix-domain socket instead. But when the
+ process tries to bind or connect its socket, noip will look the
+ address up in a list decide what to do. If the result comes
+ back `allow', then noip will do a three-card Monte, rustling up
+ a real PF_INET socket and replacing the plastic imitation; if
+ the result comes back `deny' then noip will continue with its
+ elaborate deception.
+
+ The configuration file lives in $HOME/.noip. Mine says
+ something like this.
+
+ ## standard configuration
+
+ ## debug
+ realconnect +172.29.199.2:25
+ realconnect +172.29.199.2:53
+ realconnect +172.29.199.2:80
+ realconnect +172.29.199.2:3128
+ realconnect +127.0.0.1:6010-6020
+ realconnect -127.0.0.0/8
+ realconnect -local
+
+ (172.29.199.2 is the IP address of the machine I took this
+ from.) What this says is as follows.
+
+ * Don't produce debugging output, but let me turn it on easily
+ if I feel the urge.
+
+ * Allow direct connection to my SMTP server, on port 25. (The
+ `+' means `allow'.)
+
+ * Allow conversations with my local DNS server. (The noip
+ hack is not particularly discriminating. It replaces UDP
+ sockets with Unix-domain datagram sockets, just as it
+ replaces TCP sockets with Unix-domain stream sockets.)
+
+ * Allow conversations with my local web server.
+
+ * Allow conversations with my local squid proxy.
+
+ * Allow conversations with SSH-forwarded X displays.
+
+ * Don't allow any other communication with anything else on
+ the loopback network 127.0.0.0/8. (I've still no idea why
+ each machine needs 16 million IP addresses for talking to
+ itself. The `-' means `deny'.)
+
+ * Don't allow any other communication with any of my other
+ local IP addresses. (noip will work out which IP addresses
+ are local from your network interface configuration.)
+
+ * And finally, implicitly, allow anything else.
+
+ The rules follow the squid convention: the default is to do
+ whatever the last rule didn't do, so if the last rule says
+ `deny' then the default is `allow', and vice versa.
+
+ Armed with this configuration, I now routinely run both Emacs
+ and Iceweasel exclusively under the control of noip. And I've
+ done this for several years.
+
+ SSH tricks
+
+ SSH is made of win. Its X forwarding is lovely. Its port
+ forwarding divine. Almost.
+
+ Here's a common scenario. I'm running on a multi-user server,
+ shared with several other people whom I don't necessarily trust.
+ I want to check some files out from my office's version-control
+ system. Traditional answer:
+
+ $ ssh -L 12345:vcs.work.com:345 mdw@gateway.work.com
+
+ Now I can run
+
+ $ vcs -d localhost:12345 checkout ...
+
+ and all works well. Of course, anyone else on the server can do
+ the same thing, so I've just leaked my company's secret sauce.
+ (I don't believe in secret sauce, but I ought to show willing.)
+
+ How do I fix this? Easy!
+
+ $ noip ssh -L 12345:vcs.work.com:345 mdw@gateway.work.com
+
+ $ noip vcs -d localhost:12345 checkout ...
+
+ And it all works. In this case, in particular, it's essential
+ that the /same/ SSH process binds a safe, plastic local end to
+ its forwarded VCS port, and is able to make a real, potentially
+ dangerous Internet connection to gateway.work.com. Of course,
+ since I run Emacs under noip anyway, all the version control
+ stuff that Emacs does magically find the SSH tunnel and work
+ without me having to care.
+
+\f
+Local variables:
+mode: text
+fill-column: 72
+End: