You can take away my Facebook, but you’ll never take my Github!
I live in Beijing, so I’m used to websites suddenly not being available, packets being dropped, and the internet acting flakey in general. Usually this doesn’t affect me too much, because to be honest, it’s probably better that I don’t spend a lot of time on Facebook and Twitter.
However, this week, my connection to GitHub kept timing out while trying to update some repositories that I was working with. When pinging the server, 60-70% of packets were being dropped. That’s terrible.
My standard solution of setting up a SOCKS proxy through an SSH tunnel in System Preferences didn’t work, because that was only affecting HTTP requests. My strategy was right, but the tactics were wrong. I did a lot of research and found that you can use git through a proxy, but you can’t do it through System Preferences on Mac OS X.
In the end, I now have three scripts in my PATH that together let me use Github through firewalls.
The first is startproxy. This command will open a SOCKS proxy. It’s basically just an alias for ssh -D.
~/bin/startproxy
# -D opens a socks proxy
ssh -D 127.0.0.1:9090 user@myserver
The second starts an SSH session that first uses the tunnel from startproxy, then continues on to its destination. I need this so that the SSH connection used by git goes along a stable tunnel to my server, then on a stable connection from my server to GitHub. Without this, git will try to connect along an unstable connection directly to GitHub.
~/bin/socks-ssh
#!/bin/sh
# Starts an ssh session through a socks proxy (started with ~/bin/startproxy)
ssh -o ProxyCommand="/usr/bin/nc -X 5 -x 127.0.0.1:9090 %h %p" $@
Finally, I have a short command that tells git to use socks-ssh instead of plain ssh:
~/bin/git-use-proxy
#!/bin/sh
export GIT_SSH="socks-ssh"
In normal use, I have startproxy running all the time, so when I find git timing out, I just have to run git-use-proxy and after that, git will work fine.
If you don’t usually have a proxy going, you can add an additional line to git-use-proxy so it will also take care of starting the proxy for you:
~/bin/git-use-proxy
#!/bin/sh
export GIT_PROXY_COMMAND="startproxy"
export GIT_SSH="socks-ssh"
References
- http://threebytesfull.com/2008/04/git-with-and-without-proxy/ a great start, except that connect.c is not available on OSX, so I found
- http://www.bartbusschots.ie/blog/?p=184 which has a comment that points out how to use nc instead