Wednesday, July 6, 2011

a network layer proxy

i've been wanting to get this going for a long time. i'm often on untrusted networks, and it would be nice to use a secure tunnel to get onto the internet. luckily there is this cool program called redsocks that will interface with iptables to transparently use a socks proxy. this page was an excellent guide to setting things up.

first, we setup a chain to setup our routing policy. we will put all the policy in a chain called REDSOCKS:
sudo iptables -t nat -N REDSOCKS
sudo iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
sudo iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 12345

the bulk of the rules (the ones with RETURN) are to not change the routing of connections to private addresses. the last rule is key; it will cause all other connections to get routed through redsocks. specifically, it will cause the kernel to forward connections to the port 12345 which redsocks will be listening on. redsocks then uses SOCKS to route the connection through ssh and out to the internet. (for the curious, i was, you figure out the original target of the socket using a sockopt.)

note that in this case the server we are sshing to is 127.0.0.1, which we cannot route through redsocks. (otherwise we have a chicken and egg situation.) if we are connecting to routable addresses, we need to add an entry to iptables. if X.X.X.X is the machine that we are sshing to, the table setup would be as follows:

sudo iptables -t nat -N REDSOCKS
sudo iptables -t nat -A REDSOCKS -d X.X.X.X/32 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
sudo iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN
sudo iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 12345
one other thing to note is that the link above says to use the DNAT target rather than REDIRECT. for this part of the project both worked, but i couldn't get DNAT working for connections routed through my laptop from the router. we will get to how to setup this routing in the next post.

ok, now the REDSOCKS chain is setup, but nothing will happen since it is just a chain floating out there in iptables. we've got to connect it to a chain that is actively involved in packet processing. the chain we are looking for is the OUTPUT chain. this chain is used in the initial stages of local packet routing.
sudo iptables -t nat -A OUTPUT -p tcp -j REDSOCKS
the iptables has an excellent explanation of the iptable chains and how/why they are used.

with that last rule the kernel will start routing connections to port 12345. we need to start something listening on that port. that something is redsocks. you'll need to download it and compile it.

before we start up redsocks, we need to point it at a configuration file.

base {
        log_info = on;
        log = stderr;
        daemon = off;
        redirector = iptables;
}
redsocks {
        local_ip = 127.0.0.1;
        local_port = 12345;
        // `ip' and `port' are IP and tcp-port of proxy-server
        ip = 127.0.0.1;
        port = 1080;
        type = socks5;
}

nothing really tricky here. the local_port is the port that the kernel will use to forward connections to redsocks. ip and port are the ip address and port of the socks server. once you have created the config file, i called it redsocks.conf, start redsocks with:
redsocks -c ./redsocks.conf
of course make sure your socks server is up. from the previous post i was forwarding an ssh port to local port 2222, so i started up socks with:
ssh -p 2222 -D 1080 127.0.0.1
the -D 1080 flag tells ssh to service SOCKS clients on port 1080. so there you go. transparent tunneling over the internet. pretty cool huh? of course we have to do a bit more if we want to route connections through the machine.

No comments:

Post a Comment