Tuesday, July 5, 2016

Ubuntu - Create a wifi hotspot (access point accessible by Android devices) whose traffic is forwarded through a SOCKS proxy

The objective is to take my ubuntu laptop connected to the internet via ethernet and create a wifi hotspot (access point) that will allow an android device to connect. The hotspot will provide internet access to all connected devices.

The crucial feature is that all traffic from devices connected to the hotspot must pass through a SOCKS proxy. This means that all requests and connections from these devices seem to come from the external end of the SOCKS connection.

Although the internet is full of advice on this there is very little that works. Surprisingly the solution is actually quite simple.

The first step is to create the hotspot. On ubuntu the network-manager takes care of this with a simple modification. The steps are detailed in http://ubuntuhandbook.org/index.php/2014/09/3-ways-create-wifi-hotspot-ubuntu/. Basically create a new infrastructure mode wifi network using the network-manager and then edit a single configuration file (in /etc/NetworkManager/system-connections/) to change the mode to ap.

Once this network is enabled using the network-manager, your devices (including those running Android) will be able to connect the network and receive internet through the ethernet connection on your computer.

Step two is to create a SOCKS tunnel using ssh -D. This can be achieved using a single command on the terminal or by adding an entry in ~/.ssh/config for example:
Host <name>

    User <user>
    Hostname <host address>
    IdentityFile <full path to ssh key file>
    DynamicForward <port>
    ServerAliveInterval 60

With this configuration issuing the command ssh <name> will establish a connection the remote machine while the DynamicForward instruction will create a SOCKS5 tunnel such that any packets sent to port number <port> will be sent through the ssh tunnel. The packets will appear to come from the remote machine itself.

The SOCKS tunnel can be tested using a browser on the computer (not the hotspot yet) by setting it to use a SOCKS proxy. Point the browser at www.icanhazip.com and/or www.whoismyisp.org to check that packets are being sent over the tunnel.

The ssh socks port can interface with a browser (the latter being intelligent about it) but it won't handle raw ip traffic from the hotspot. We need a proxy that can take the traffic and send it via the ssh socks port. Enter redsocks a lightweight socks proxy. Unlike squid or polipo it is NOT a proxy server, that is, it cannot be used directly by a browser. redsocks connects to the socks port upstream and provides an incoming port where all incident traffic is sent out via the socks tunnel. Traffic is redirected to the redsocks incoming port using iptables.

Once redsocks is installed (sudo apt-get install redsocks) modify /etc/redsocks.conf. Focus on the redsocks {} section. Change local_ip to (don't know if this is strictly necessary). local_port specifies the incoming port. I chose 12345.

Set port to the socks port set in the ssh config file and set type to socks5. Then restart redsocks (sudo service redsocks restart).

With redsocks set up we are now at the final stage and ready to redirect traffic from the wifi hotspot to through the socks tunnel. To that end we need the ip address block assigned to the hotspot. Since my hotspot works on the wlan0 interface I simply ran ifconfig wlan0 (or ip addr) to discover the address block which turned out to be, that is, address and netmask

When the network-manager creates the wifi hotspot (using the technique defined above) it creates a number of iptables rules to take care of the traffic forwarding. Since we need all traffic forwarded to the redsocks incoming port (12345) we simply delete all these rules and provided just one of our own.

    sudo iptables -F
    sudo iptables -t nat -F
    sudo iptables -t nat -A PREROUTING -s -p tcp -j REDIRECT --to-ports 12345

Basically we are instructing iptables to take all packets that come from the subnet and redirect it to the incoming port of redsocks which sends it over the socks ssh tunnel.

The final step is to enable ip packet forwarding in the kernel using

sudo sysctl -w net.ipv4.ip_forward=1

And we are set. On your hotspot connected device (Android phone for example) navigate to www.icanhazip.com and www.whoismyisp.org to confirm.