Kjetil's Information Center: A Blog About My Projects

VPN Through SSH Tunnel

Not just VPN through an SSH tunnel, but also a Wi-Fi hotspot that directs all traffic through it! I needed this to be able to reach the Google Play store on my Android phone in China. I used two WLAN interfaces for this, but it should be possible with one WLAN and one wired connection as well.

VPN through SSH tunnel principle diagram.

Here are the complete steps, with the contents of the files listed after. Many of the commands are started through screen sessions, since they are daemons that will keep running.

First of all, make sure the interface that will be used to connect to the remote SSH server is up and running, then connect to the server and create the SSH tunnel for port 1194, which is used for VPN:

ssh user@your-ssh-server.com -L

One the remote server, enter the following commands:

# Start OpenVPN server:
screen -S openvpn -d -m sudo openvpn server.cfg

# Forward all the traffic from the OpenVPN tunnel interface:
sudo iptables -A INPUT -i tun0 -j ACCEPT
sudo iptables -A FORWARD -i tun0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -d -j ACCEPT

# Enable IP forwarding on server:
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

Back on the local machine, enter the following commands:

# IP address for Wi-Fi hotspot:
sudo ifconfig wlan0 netmask

# Start DHCP server for Wi-Fi hotspot:
screen -S dnsmasq -d -m sudo dnsmasq --conf-file=dnsmasq.conf --no-daemon

# Start Host-AP deamon:
screen -S hostapd -d -m sudo hostapd hostapd.conf

# Start OpenVPN client:
screen -S openvpn -d -m sudo openvpn client.cfg

# Let the SSH connection bypass the VPN default route:
SSH_IP=`host your-ssh-server.com | sed -e 's/.*address //'`
GW_IP=`route -n | grep "^" | grep $SSH_IF | sed -e 's/ *//' | sed -e 's/ .*//'`
sudo route add $SSH_IP gw $GW_IP $SSH_IF

# Override the DNS resolver:
sudo cp resolv.conf /etc/resolv.conf

# Enable IP forwarding on local machine:
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

# Enable NATing through the tunnel interface from the Wi-Fi hotspot:
sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
sudo iptables -A FORWARD -i tun0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o tun0 -j ACCEPT

That should be it, now the phone can connect to the local Wi-Fi hotspot and reach the Internet through the remote SSH server.

Some useful commands for troubleshooting:

sudo iptables -L -v -n
sudo tcpdump -i tun0

OpenVPN client configuration. (client.cfg):

proto tcp-client
dev tun
secret static.key
redirect-gateway local def1

OpenVPN server configuration. (server.cfg):

dev tun
proto tcp-server
secret static.key

New DNS resolver configuration, using the Google DNS. This is important because it could have been set by a local DHCP client to a Chinese DNS resolver. (resolv.conf):


DHCP server configuration. (dnsmasq.conf):


Host-AP Wi-Fi hotspot configuration. These are the more important options, I have excluded lots of others. (hostapd.conf):

wpa_key_mgmt=WPA-PSK WPA-EAP

Topic: Configuration, by Kjetil @ 10/06-2018, Article Link