Fun with sockets
Knowing how to forward ports with ssh can make it easier to work remotely. Combining that with a little knowledge of sockets lets you accomplish some pretty cool shit.
It turns out that it's pretty easy to deal with sockets in Python. Check out my Answers/Code/SocketScript for a small script that will let you do most of the things you want to do. Run it without arguments for instructions. Basically, "socket host port" will read from standard input until it gets and end-of-file, and then write everything to the specified port on the specified host. You'll also need "socket -l host port" which says "listen for socket connections on the specified port and host, and write anything you get to standard output." There are arguments that will let you do other things besides just write to standard output.
So, a trivial use would be to type:
# listen on port 9999 of my laptop (192... is its IP address) and put the results into file received.txt socket -l -f received.txt 192.168.1.7 9999 & # ssh to campus, forwarding a port up there to the one on my laptop ssh -R 9999:192.168.1.7:9999 ssh.ucolick.org # Now the text "Hello" automagically appears in the file on my laptop, # even though I'm logged in to a machine on campus. echo "Hello" > socket localhost 9999
The uses of this are limited only by your imagination. I read my mail by logging in to the machines on campus and running mutt. Sometimes people send me mail with HTML and I want to look at them in a browser. I could save the file, scp it to my laptop, and then load it into my browser, but that's a pain in the nheck. I've set things up so that a command in mutt shoves the message over the ssh link to my laptop, where socket is listening and it catches the message and then instructs my browser to load it up. Ie, I hit one key in mutt and the message appears in my locally running web browser.
My favorite use so far is Answers/Code/SlnScript. I've named it sln to mean "secure link" in analogy with "scp" for secure copy. So, I have a plotting program that I like to use and it's installed on my machine at work. The problem is that when I'm working from home and I try to have it pop an X window on my laptop, it sends the entire bitmap of the plot (rather than just the X11 commands to draw lines and text) which is slow as hell. So, I have it produce eps files instead of trying to pop an X11 window. Ordinarily I'd have to produce the plot, scp it to my laptop, and then run a viewer on it. Instead I type sln remote-host remote-file local-file port which means "watch for remote-file on remote-host to change. When it does, use socket to make the new version appear in local-file. Use port to make this happen." You'll also need Answers/Code/WatchFileScript, which waits for a specified file to change, and when it does writes it to some port on some host.
Ok, that was a long description, but here's the upshot: I've "linked" a file on my machine at work to a local one on my laptop. When the remote one changes, the local one magically changes too. Therefore, when I'm logged in to a machine at work, running my plotting program, and I run a command that produces a new version of a plot, the new version also magically appears on my local machine. Since I've run gv -watch local-file.eps to view the local file, gv watches for the local file to change and then updates the view. Therefore the plot automatically updates itself, just as if I were sitting at my machine at work.
A few notes: "But why don't you just run 'gv file.eps' on the remote machine and let it pop an X window on your laptop?" I could do that, but it's slow, b/c gv sends all the pixel data. This takes a full minute for me, even over a fast broadband connection. "But why don't you just use scp to copy the file from the remote machine to your laptop, instead of using socket?" This would work if 1) my laptop had a real IP address instead of being behind a NAT firewall and 2) there were no firewall at work so that I could directly access the ports on my machine.
If you're still reading, congratulations on wading through my murky explanation. Let me (Greg) know if you have problems, questions, or cool uses.
Preventing remote X11 windows from dying
I run emacs on a machine on campus and have it pop up a window on my iBook running OSX at home. This is accomplished by forwarding X11 connections over ssh by typing "ssh -X ssh.ucolick.org" instead of just "ssh ssh.ucolick.org". I did this successfully for a long time, then Emacs started crashing when I did certain things, like highlight text with the mouse. The error message was something like "X11 Protocol Error: Bad Window Parameter." This totally sucked for a while and I couldn't find anything on the web about it. Then, finally, the solution started showing up in Google searches.
The punchline: Use ssh -Y instead of ssh -X. This makes the X clients run as "Trusted" clients instead of "untrusted" ones, which surely is less safe, but on the other hand it actually works. Alternatively, you can change Forward X11: yes to ForwardX11Trusted: yes in your .ssh/config file.
SSH Compression
If you work from home and tunnel X connections over SSH, you'll find that some applications are more responsive than others. I use Ghostview to look at plots I've just drawn and found that it's dog slow. You can give the "-C" option to ssh to compress data that goes over the connection. This increased Ghostview's performance by a factor of four.
Background SSH tunnels
You can launch an ssh process to do port forwarding and have it fork into the background and do it's thing without you having an extra xterm window floating around. If that made sense to you, here's how to do it.
ssh -f -N -g -L 9022:serendipity.ucolick.org:22 ssh.ucolick.org
Making Cheap DSL Routers maintain your SSH connections
I have a cheap wireless router so that multiple computers can use our DSL connection. I want to run SSH and leave terminals open on remote machines, sometimes leaving them idle for a long time. The router wants all traffic to be like HTTP traffic (ie, mostly stateless: request, response, pause, request, response, pause...). The router was cutting connections if they were idle for more than five minutes. The router is cheap, so this delay is not easily configurable.
Sandra Faber found this solution via Google: for Netgear routers at least, it turns out that you can fix it by hacking the config file. Download the config file from the router, and look inside it (it's apparently a text file). There's a setting called IDLETIME, which you can set from 1-256 for the number of minutes after which to snip a connection. You can also set it to zero to indicate that it should never snip connections. This should solve the problem.
Maintaining the Connections with Keepalive packets under OSX
If have a different router where this isn't possible, you can fix it under OSX by doing the following:
I set SSH to send KEEPALIVE packets to maintain some traffic on the connection, but it didn't start sending them until fifteen minutes had gone by. SSH didn't seem to allow this time delay to be configurable. It turns out that SSH can request keepalive packets, but it's up to the networking code in the operating system kernel to decide when to start sending them and how often to send them.
So, the big solution is that you need to set a few kernel variables to set the time delays. Type sysctl -a to see a list of all the kernel variables and look for ones with names like net.inet.tcp.keepintvl and such. Change the delays (measured in seconds) with: sysctl -w name=value
Next you'll ask...
How do I add something to the OSX startup sequence?
Too detailed to cover here, but it's thoroughly covered in the O'Reilly book "Mac OS X for Unix Geeks."
Bandwidth priority queing for DSL lines
If you have DSL, you probably have noticed how any outgoing traffic like file sharing will totally kill network response. There is a very handy way of improving DSL line use by incorporating bandwidth priority queing of different types of traffic. That way interactive traffic like ssh packets can have higher priority and take precedence over less important traffic. It's sort of a pain to set up, and it requires you use a Linux machine as a router, but it's SO worth it. Check it out at http://www.tldp.org/HOWTO/ADSL-Bandwidth-Management-HOWTO/index.html
