How to use sshuttle on a router running openwrt?

I'm using a TP-Link TL-WR1043ND router running OpenWrt and Gargoyle. I'd like to forward all traffic from my local network (served by the router) to a remote server transparently. Essentially as a socks proxy would work, just without the need to configure the connected client machines for proxy.

I've read that sshuttle is the way to go for this kind of requirement. After much fiddling, I finally managed to satisfy all prerequisites, and I can start sshuttle without any error messages, like this:

./sshuttle --dns -vvr [email protected] 0/0

Where XXXXXX is my username at a remote server YY.YY.YY.YY sshuttle seems to initialize just fine, no error messages, adds all necessary rules to iptables, yet after the local proxy is established, I'm unable to connect anywhere from my local network. This is sshuttle's output:

Starting sshuttle proxy.
Binding: 12300
Listening on ('127.0.0.1', 12300).
DNS listening on ('127.0.0.1', 12300).
firewall manager ready.
c : connecting to server...
c : executing: ['ssh', '[email protected]', '--', 'P=python2; $P -V 2>/dev/null || P=python; exec "$P" -c \'import sys; skip_imports=1; verbosity=2; exec compile(sys.stdin.read(764), "assembler.py", "exec")\'']
c :  > channel=0 cmd=PING len=7 (fullness=0)
WARNING: Ignoring unknown argument '--'
[email protected]'s password:
server: assembling 'cmdline_options.py' (29 bytes)
server: assembling 'helpers.py' (914 bytes)
server: assembling 'ssubprocess.py' (13668 bytes)
server: assembling 'ssnet.py' (5446 bytes)
server: assembling 'hostwatch.py' (2270 bytes)
server: assembling 'server.py' (2370 bytes)
 s: latency control setting = True
 s: available routes:
 s:   69.64.32.0/22
 s:  > channel=0 cmd=PING len=7 (fullness=0)
c : connected.
Connected.
c : Waiting: 3 r=[3, 5, 9] w=[9] x=[] (fullness=7/0)
c :   Ready: 3 r=[] w=[9] x=[]
c : mux wrote: 15/15
c : Waiting: 3 r=[3, 5, 9] w=[] x=[] (fullness=7/0)
 s:  > channel=0 cmd=ROUTES len=14 (fullness=7)
 s: Waiting: 1 r=[4] w=[5] x=[] (fullness=21/0)
 s:   Ready: 1 r=[] w=[5] x=[]
 s: mux wrote: 15/15
 s: mux wrote: 22/22
 s: Waiting: 1 r=[4] w=[] x=[] (fullness=21/0)
c :   Ready: 3 r=[9] w=[] x=[]
c : <  channel=0 cmd=PING len=7
c :  > channel=0 cmd=PONG len=7 (fullness=7)
c : <  channel=0 cmd=ROUTES len=14
firewall manager: starting transproxy.
 s:   Ready: 1 r=[4] w=[] x=[]
 s: <  channel=0 cmd=PING len=7
 s:  > channel=0 cmd=PONG len=7 (fullness=21)
 s: mux wrote: 15/15
 s: Waiting: 1 r=[4] w=[] x=[] (fullness=28/0)
>> iptables -t nat -N sshuttle-12300
>> iptables -t nat -F sshuttle-12300
>> iptables -t nat -I OUTPUT 1 -j sshuttle-12300
>> iptables -t nat -I PREROUTING 1 -j sshuttle-12300
>> iptables -t nat -A sshuttle-12300 -j RETURN --dest 127.0.0.0/8 -p tcp
>> iptables -t nat -A sshuttle-12300 -j REDIRECT --dest 0.0.0.0/0 -p tcp --to-ports 12300 -m ttl ! --ttl 42
>> iptables -t nat -A sshuttle-12300 -j REDIRECT --dest 127.0.0.1/32 -p udp --dport 53 --to-ports 12300 -m ttl ! --ttl 42
c : mux wrote: 15/15
c : <  channel=0 cmd=PONG len=7
c : received PING response
c : Waiting: 3 r=[3, 5, 9] w=[] x=[] (fullness=0/0)
 s:   Ready: 1 r=[4] w=[] x=[]
 s: <  channel=0 cmd=PONG len=7
 s: received PING response
 s: Waiting: 1 r=[4] w=[] x=[] (fullness=0/0)

I have no idea how to even start debugging this issue. If I stop sshuttle, it will remove the iptables rules and network connections will work again:

firewall manager: undoing changes.
>> iptables -t nat -D OUTPUT -j sshuttle-12300
>> iptables -t nat -D PREROUTING -j sshuttle-12300
>> iptables -t nat -F sshuttle-12300
>> iptables -t nat -X sshuttle-12300
c :
c : Keyboard interrupt: exiting.

Has anyone managed to set up a working sshuttle instance on openwrt? Or is there any other way to achieve what I need here (transparent proxy on an openwrt router)?

Related and unanswered question: sshuttle on a DD-WRT / OpenWRT Router


Solution 1:

Luckily I got an answer at the sshuttle google group from the author of sshuttle. He wrote:

You might need to add '-l 0.0.0.0' (that's a lowercase L) in order to tell sshuttle to listen for connections from other than localhost (the router itself). For security reasons, sshuttle won't route other people's traffic by default.

And it works perfectly! Use:

./sshuttle -l 0.0.0.0 --dns -vvr [email protected] 0/0

Solution 2:

A few things that tripped me up:

From stock OpenWRT 12.09 AA, you have to install these packages:

  1. python (with dependencies, consumes 3-4 MB of flash)
  2. iptables-mod-nat-extra
  3. iptables-mod-ipopt

Then, to SSH into the remote server using an SSH key, you have to create a Dropbear-format key:

dropbearkey -t rsa -f /root/.ssh/id_rsa

And finally, provide the key location on the sshuttle command line:

./sshuttle -e "ssh -i /root/.ssh/id_rsa" -l 0.0.0.0 -r [email protected] 0/0 -vv --dns