How to VPN using SSH
This post will cover how to establish a VPN (Virtual Private Network) using SSH.
This is technically termed “layer-3 IP-in-SSH tunnelling” and is not using ssh to port forward (ssh -L ) or create a dynamic “application level” forwarding (SOCKS) (ssh -D ). Rather a VPN is established using a SSH connection to create a virtual interface, tun0.
If you would like a more detailed description of the commands in this tutorial, I posted more detail HERE
For this how to I will assume the following network topology , you will have to adapt to your actual IP Addresses, netmask, route, gateway, and nameserver.
Server :
Public IP Address 1.2.3.4
Private Network 172.0.0.0/24
Private IP address 172.0.0.10
default gw 172.0.0.1
Client :
Private network 192.168.0.0/24
Private IP address 192.168.1.10
Default gw 192.168.0.1
Tunnel :
Server tun0 IP address = 10.0.0.1
Client tun0 IP address = 10.0.0.2
Server Configuration
1. Using any editor, open /etc/ssh/sshd_config and change the “PermitRootLogin” line and add the “PermitTunnel” line :
PermitRootLogin without-password
PermitTunnel point-to-point
2. Allow NAT. These commands will enable NAT without the need to reboot (NAT will be persistent).
# enable now
sudo sysctl -w net.ipv4.ip_forward=1
To set as default, using any editor, open /etc/sysctl.conf and add :
# Needed to add for forwarding
net.ipv4.ip_forward = 1
Next, configure iptables to allow masquerade (NAT)
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
Your iptables settings will be lost when you reboot unless you configure a way of saving your settings. This can be done several ways, here I will use “iptables-save” and “iptables-restore” to setting masquerade as default.
sudo bash -c “iptables-save > /etc/iptables.rules”
Using any editor, open /etc/rc.local and add this line (above the exit 0 line)
sudo bash -c “iptables-save > /etc/iptables.rules”
Using any editor, edit /etc/rc.local and add this line (above the exit 0 line)
iptables-restore < /etc/iptables.rules
3. Configure the tunnel (tun0). Using any editor, open /etc/network/interfaces and add these lines (works on Debian/Ubuntu).
iface tun0 inet static
address 10.0.0.1
netmask 255.255.255.0
pointopoint 10.0.0.2 # Client tunnel address
The interface, tun0, will be brought up and down automatically when the client establishes a ssh connection, using forced commands on the ssh key (see below).
Client Configuration
1. Make a ssh key , call it “VPN”.
ssh-keygen -f VPN
When generating the key, simply hit enter when asked for a password. This creates a “passwordless key”. Alternately, if you wish to increase security you can enter a password.
2. On the client, put the private key (VPN) in /root/.ssh and set permissions.
#If needed, make the directory /root/.ssh first.
sudo mkdir /root/.ssh
sudo cp VPN /root/.ssh/VPN
sudo chown root:root /root/.ssh/VPN
sudo chmod 400 /root/.ssh/VPN
3. Configure the key on the server.
After transferring the public key (VPN.pub) to the server, first put it in /root/.ssh/authorized_keys.
#If needed, make the directory /root/.ssh first.
sudo mkdir /root/.ssh
sudo bash -c “cat VPN.pub >> /root/.ssh/authorized_keys”
Next, edit /root/.ssh/authorized_keys adding a “forced command” (just before the ssh-rsa AAA …):
tunnel=”0″,command=”/sbin/ifdown tun0; /sbin/ifup tun0″,no-port-forwarding,no-ptty,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAA …. (long sequence of random numbers / letters )
Keep the forced command and the rest of the key all on a single line.
Note: The options “no-port-forwarding,no-ptty,no-X11-forwarding,no-agent-forwarding” further enhance security.
4. Add the servers nameserver in the client /etc/resolv.conf
On the client, use any editor and add the server’s nameserver to /etc/resolv.conf.
5. Configure tun0 on the client.
Using any editor, add the following lines to /etc/network/interfaces :
You will need to change “1.2.3.4″ to the IP address of your server and “192.168.0.1″ to the default gateway of your client.
iface tun0 inet static
pre-up ssh -i /root/.ssh/VPN -S /var/run/ssh-vpn-tunnel-control -M -f -w 0:0 1.2.3.4 true
pre-up sleep 5
address 10.0.0.2
pointopoint 10.0.0.1
netmask 255.255.255.0
up route add -host 1.2.3.4 dev eth0
up route add default gw 10.0.0.1 dev tun0
up route del default gw 192.168.0.1 dev eth0
down route add default gw 192.168.0.1 dev eth0
down route del default gw 10.0.0.1 dev tun0
down route del -host 1.2.3.4 dev eth0
post-down ssh -i /root/.ssh/VPN -S /var/run/ssh-vpn-tunnel-control -O exit 1.2.3.4
Note : “pre-up … 1.2.3.4 true” and”post-down … exit 1.2.3.4″ are all on one line.
6. Make a new group, “vpn”, and add users you wish to use the tunnel to the vpn group. Change the user “bodhi” to your actual user name.
sudo addgroup vpn
sudo adduser bodhi vpn
7. Allow members of the vpn group to establish the ssh-vpn tunnel without a password.
export EDITOR=gedit && sudo -E visudo
Add this line (near the bottom, in the group section, under the line which begins %admin … )
%vpn ALL=NOPASSWD: /sbin/ifup,/sbin/ifdown
Save the file and exit gedit.
Using the VPN connection
Users in the vpn group can establish and disconnect the VPN.
Bring the connection up:
sudo ifup tun0
Bring the connection down:
sudo ifdown tun0
Testing the connection
One way to test the connection is with tracepath.
tracepath google.com
Use tracepath both before and after establishing the VPN tunnel. Before you establish the tunnel you will see the network traffic going through eth0 to your LAN, after it will go through tun0 to the remote LAN.
Posted in Linux
Configurare una VPN attraverso SSH…
Un articolo di qualche giorno fa spiega come configurare una VPN sfruttando il server e il protocollo SSH. Verrà configurata un’interfaccia virtuale chiamata tun0 che per la subnet 10.0.0.0/24 farà transitare il traffico attraverso una connession…
Trackback by Ubuntu Trucchi — May 23, 2009 @ 2:06 pm
Hi,
It might be easier (and possibly slightly faster in use) to use OpenVPN to manage the tunnel connections. It’s obviously a little more work initially, since you’d need to add the OpenVPN package but for a really high speed VPN connection its widely thought of as being the best all-round solution.
Comment by Mike Trebot — August 17, 2009 @ 7:10 am
network security vpn…
I can’t believe I missed this! I’m going to have to do some more reading me thinks….
Trackback by Lewis — August 17, 2009 @ 11:56 pm
I agree with your Mike Trebot, but I kind of like to have this option in my bag of tricks.
Comment by bodhi.zazen — August 18, 2009 @ 7:51 pm
I see in your later article:
http://bodhizazen.net/Tutorials/VPN-Over-SSH/
“”"
#3 This protocol uses udp to transmit tunneled tcp connections resulting in a more stable connection compared with port forwarding (using ssh with the -L or -D options).
“”"
I believe this is incorrect, though I have not read your article in full. If you take a look at netstat, lsof, or tcpdump you should see that all traffic is being tunneled over a single TCP port.
Your idea of using sudo is very clever though, thanks for that, though I would limit the args as well.
Comment by mzs — January 15, 2010 @ 10:52 am
Thank you fro your comments, they are appreciated.
ssh uses TCP, so, yes, you are correct the connection will show as a tcp connection.
I am referring not to the tunnel, but the way the traffic is transported within the tunnel if that makes sense.
My explanation is probably wrong, and it has been some time since I looked at the exact details, and I have seen more then one opinion on the technical details, so I need to apologize for not haveing a better answer or any errors in my understanding.
I would have to refer you to the technical documents, here is one example;
http://www.debian-administration.org/article/Setting_up_a_Layer_3_tunneling_VPN_with_using_OpenSSH
I think the “simple message” is that this protocol is not the same as port forwarding or tunneling over ssh.
I will have to leave the technical details for those who are interested further to review / debate, but if anyone knows a better technical review perhaps they can post back.
Comment by bodhi.zazen — January 15, 2010 @ 11:31 am