Note: This post is from 2009 and should be considered depreciated… things move quickly in IT!
Most of the time I feel relatively secure when I’m browsing the web or checking twitter on my iPhone. That said, I rarely use the built in wireless for these purposes, and rely instead on the reasonably good 3G network in Austria. When I’m out of the country I usually try to buy a pay-as-you-go sim card and pay for the daily data transfer. This isn’t as expensive as you’d think. For example in the Netherlands it costs around €3.50 per day of data transfer. Not cheap if you’re using it long-term, but if you’re only there for a couple of days it’s a lot cheaper than paying for a hotel WLAN that’s insecure and only works inside the hotel. Still, this solution doesn’t work everywhere and isn’t for everyone. The fallback is to use whatever wireless you can find, insecure or not. This is something I’ve been fighting with for a while now. Stemming (mostly) from my unwillingness to setup a VPN server (my home ADSL isn’t good enough quality, and doesn’t have a fixed IP) or pay a huge price for a VPN solution through my existing hosting provider (thanks for the cheap hosting Dreamhost).
The iPhone (at least version 2.2.1) supports the use of HTTP proxies when connecting via a wireless connection. This is great. Surely I can setup an SSH Tunnel to my server and tell the iPhone to use this as a SOCKS proxy. As with everything on the iPhone however, simple always turns into complicated very quickly. I experimented with this solution and found that the HTTP proxy support was really just that, HTTP proxy support and nothing else. So back to the drawing board. I searched for another solution and settled on using the 3proxy application (in cydia for those lucky enough to have a jailbroken iPhone) to setup a local HTTP proxy.
A few requirements to get this up and running on your iPhone.
- A Jailbroken iPhone (or iPod Touch)
- SSH Client installed
- 3proxy (available in cydia)
- terminal application
- An SSH server (setup for either password or certificate access)
- Backgrounder (or some other way to run commands and have them running in the background)
- OPTIONAL: iFile (easy file editing)
Starting off we’ll take a look at the configuration of 3proxy. By using the following configuration you tell 3proxy to forward all traffic to a second proxy server, this time a SOCKS proxy (in this case my SSH tunnel).
log /var/log/3proxy.log D
allow * * 127.0.0.1
parent 1000 socks5+ 127.0.0.1 8081
proxy -p8080 -a -i127.0.0.1
The quick rundown on the above configuration.
- #!/usr/bin/3proxy – Tells the script what interpreter program to use
- daemon – Tells 3proxy to run as a background process
- auth iponly – sets the authorization to be ip restricted
- log – Setup a log that rotates daily (the D option)
- rotate 5 – Sets the number of log files to keep before rotating
- fakeresolve – Tells 3proxy to route DNS lookups through the proxy
- internal – Listen in the internal interface only
- allow – Currently set to * for all (you can limit this by username/password or IP, however this caused issues in testing)
- parent – This is where we’re setting the next proxy in the chain (1000 is always use this parent, SOCKS5+ is the type and then the SSH tunnel listening ip and port)
- proxy – this final command tells 3proxy to start a proxy on port 8080 using anonymous proxy mode (-a) and listen only in internal loopback
You can find more configuration information on the 3proxy website. Although leaving the allow set to * (all) is a concern, remember that the proxy is only listening on the localhost address and from outside the port is blocked.
Now that we’ve got the 3proxy.cfg file saved (mines stored in /usr/bin with the 3proxy executable) you’ll need to run chmod +x to make it executable. Next up is the SSH Tunnel, and doing this on an iPhone isn’t much different to a normal linux system (just harder to type for obvious reasons). I opted to add a certificate for quick easy access and restricted access to the certificate to the root user on the iPhone (you have changed your root password right ???). I added the private key to ~/.ssh/id_dsa (or id_rsa, your choice) and setup a bash script to kick off the SSH tunnel (typing that command each time gets boring fast).
ssh -D 8081 -N -C email@example.com -2 -p 64000 -i /home/root/.ssh/id_dsa
The above command is a simple SSH tunnel setup to connect to port 64000 on remotehost.your.domain and logon as the user username using the certificate file stored in /home/root/.ssh/id_dsa. It will then setup a local listener on port 8081 and dynamically route all traffic coming to this port through the SSH tunnel. As we’re treating the tunnel as a SOCKS proxy we don’t need to have anything else setup at the other end (no other proxy server waiting to route the requests) although you could setup privoxy or any other kind of proxy if you wanted more control.
So, now that we have the two parts of our configuration ready we just need to drop to the shell and kickoff the SSH Tunnel (using your bash script), and then startup the 3proxy using the /usr/bin/3proxy.cfg command. I’ve linked it all into a single bash script to make things a little quicker.
In testing Safari works pretty well (minor decrease in performance as you’d expect). Twitterfon was the second application I tested. Although this follows the HTTP proxy rule, it still insists on doing DNS lookups for advertising outside of the proxy. This is also the case for a couple of other applications. Mail doesn’t follow the HTTP rules, however you can easily setup additional 3proxy ports for these, or use SSL and make sure your DNS is all piped over the local listener and through the SSH tunnel (3proxy supports a DNS caching proxy, tcp and udp forwarding proxies also).
- Twitterfon (partially: Advert DNS lookups are still a possible concern/attack vector)
- WordPress (partially: As with the Twitterfon issue, the DNS appears to ignore the HTTP proxy settings)
Obviously these were just the applications I tested. I’d suggest running your own tests to ensure that you’re seeing the same results.
- Mail (setup a port forwarder to achieve support for email)
- Siphon (This is a real disappointment)
- … probably more, so your mileage may vary
If you test any other applications please let me know and I’ll add it to my list.
Once you’ve finished using the SSH Tunnel and proxy, remember to kill -9 them using the console.
- Test with alternative “allow” settings to restrict access further (username/password too easy)
- Prevent initial DNS lookup on SSH Tunnel (i.e. dyndns service)
- Log Bug with Twitterfon regardin DNs lookups
- Find an easier way to trigger the tunnel & 3proxy build-up/tear-down
- Resolve issue of tunnel disconnecting when screen gets locked (FOR loop ???)
- Use the tunnel for 3G connections (paranoid much !!!)
It could be that Dreamhosts sshd configuration doesn’t allow tunnelling
Unlikely, since I tunnel through it on my linux and windows boxes everyday (I live in China). I’m using the same port on the iPhone as well, so I know that’s open. After I enter the password, the terminal just hangs… no command line, no error, nothing. Tried on different Wi-Fi connections as well.
Just a thought… but what do you expect to happen? The -N command specifically tells SSH not to run anything. In this case, the lck of response, command-line or error says that the forwarding is probably working just fine. You need to make sure you background the terminal to keep the command running.
Sorry, maybe I’m a bit thick on this one. There seem to be a couple of problems I don’t understand. I guess what I was expecting it to drop back to the command line so I can run 3proxy.cfg. Does this mean after enabling backgrounder, I can quit that terminal session and start a fresh one to run 3proxy.cfg and the tunnel will still be active? I thought that would kill the tunnel.
Also, when I run 3proxy.cfg, it says “100328113238.941 8080 000 – 127.0.0.1:8080 0.0.0.0:0 0 0 0 bind(): Address already in use”
I assume something wrong with my 3proxy.cfg but I’m not familiar enough to figure it out. I appreciate the help so far. I’d really like to figure out how to use this to circumvent the Great Firewall of China on my iPhone.
After you’ve run the SSH command it will sit and just run without feedback. You can force it to go into the background by adding an & to the end of the command. This will leave you free to run the 3proxy command straight afterwards. I’ve not played about with using nohup (not even sure it works on iPhone) but you might want to look into that as well.
The error you get with 3proxy sounds like it’s already running. Run a ps | grep 3proxy and see if it’s running in the background.