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.

This entry was posted in Linux. Bookmark the permalink.

17 Responses to How to VPN using SSH

  1. Pingback: Ubuntu Trucchi

  2. Mike Trebot says:

    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.

  3. Pingback: Lewis

  4. bodhi.zazen says:

    I agree with your Mike Trebot, but I kind of like to have this option in my bag of tricks.

  5. mzs says:

    I see in your later article:

    http://bodhizazen.com/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.

  6. bodhi.zazen says:

    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.

  7. Behzadsh says:

    I do not have root access on server. when I type “sudo ifup tun0” it ask me for password of root.

  8. bodhi.zazen says:

    @Behzadsh : I am not sure you can do this without root access.

  9. Mostafa Galmad says:

    Dear Brother,
    I’ve VPN one way is that configuration will make my VPN 2 way with out modifying any rule @ router??

  10. Wayne says:

    When I have the force command at the start of the ssh-rsa line, I get prompted for a password. If I remove the force command, I can ssh to the server as root w/o a password.

    What am I missing?

  11. bodhi.zazen says:

    @Wayne

    I would assume your syntax is off a bit. Post the first part of the key, the forced command, on a forums somewhere.

    Examine the key and make sure it is all on one line.

  12. Wayne says:

    key is on a single line.

    ssh-dsa AAA……..
    tunnel=”0″,command=”/sbin/ifdown tun0; /sbin/ifup tun0″,no-port-forwarding,no-ptty,no-X11-forwarding,no-agent-forwarding ssh-rsa AAA…..

  13. biabani says:

    hi
    thanks for this document.

    I want connect to vpn over ssh from windows, but I can’t find any software that do this work.
    I don’t want that a port forward.
    please tell me a ssh client for windows that do it work?

  14. Richard says:

    I get a message: Control socket connect(/var/run/ssh-vpn-tunnel-control): No such file or directory

    On SUSE 11.3.

    Any ideas? What should the contents of ssh-vpn-tunnel-control be?

  15. bodhi.zazen says:

    @Richard – How did you set up your tun ?

    What was your ssh command ?

  16. Pingback: I'm looking at sharing a printer over the internet, what are the implications? - Just just easy answers

  17. james houston says:

    what is ssh command? i didn’t hear about it before, and if you chose vpn according to vpnranks (Top Quality VPN) then where we have to use this command.

Leave a Reply

Your email address will not be published. Required fields are marked *