Using SSH as a VPN

This article discusses a way to use SSH and bridging to create a simple VPN. This VPN will be able to act as part of the network that it connects into. Unlike other articles that I have found that use a point-to-point tunnel, I will set up an ethernet tunnel.

In order to be able to connect to the network, I need to be able to get the IP address from the DHCP server on the network I'm connecting into. To do this, I set up a bridge on the computer that is running SSH that bridges the interface and tap connection. Note that if the interface is using VLANs, then the bridge needs to be on the VLAN interface and not on the native interface. This may require that traffic previously sent to the computer untagged be changed to be tagged as well.

Configuring the Switch

Since I am bridging an interface that also uses VLANs, I need to create a virtual interface on the computer to receive traffic, and I need to configure the switch to send user traffic tagged. By changing the native VLAN on the switchport connected to the computer, I can ensure all other VLANs are tagged.

(config)# int f0/2
(config-if)# switchport mode trunk
(config-if)# switchport trunk native vlan 100

Configuring the Server

Now I want to create the interfaces that are going to be used for the server. Since VLAN 99 is for management, I can't bridge the native interface directly, so I need to create a subinterface for the user VLAN. I also need to create the virtual network interface. Since I am using VLAN 2 for the switchport connecting to the home router, I use that VLAN on the computer.

# ip link add link eth0 name eth0.2 type vlan id 2
# tunctl -t tap0
# ip link add dev br0 type bridge
# ip link set dev eth0.2 master br0
# ip link set dev tap0 master br0

The bridge won't work if the interfaces aren't up, so I need to bring up the interfaces. While I do this, I also set the address on the bridge interface.

# ip link set dev eth0.2 up
# ip link set dev tap0 up
# ip addr add 192.168.1.10/24 dev br0
# ip link set dev br0 up

IP Forwarding needs to be enabled. Also any firewall rules that are needed should be added to allow forwarding over the bridge.

echo 1 > /proc/net/ipv4/ip_forward

Finally, the SSH server needs to be configured to allow tunelling. This will allow the use of ethernet tunnels, and will permit the root user access without password. What that means is the root user must use key-based authentication.

PermitTunnel ethernet
PermitRootLogin without-password

With this setup, the computer will still be able to be part of the main network using br0, and will be able to accept incoming connections. I need to make sure that the firewall allows incoming connections to SSH, that it allows forwarding, and that the home router is forwarding SSH traffic to this computer.

Configuring the Client

There isn't much to configure on the client. A single comment will connect from the client to the server and tunnel any traffic over the client's interface to the servers interface.

# ssh -N -f -n -w 0:0 -o Tunnel=ethernet root@publicip

This establishes the connection, tells SSH to go into the background and not execute any remote commands, and sets up the local tap interface to tunnel to the remote tap interface. Once the connection is up, the tap interface can be configured.

# dhclient tap0

Automating the Server Setup

The setup for the interfaces can be automated in the interfaces file as follows.

auto eth0.2
interface eth0.2 inet static
    address 0.0.0.0

auto tap0
interface tap0 inet static
    address 0.0.0.0
    pre-up tunctl -t tap0
    post-down tunctl -d tap0

auto br0
interface br0 inet static
    address 192.168.1.10
    netmask 255.255.255.0
    pre-up ip link add dev br0 type bridge
    pre-up ip link set dev eth0.2 master br0
    pre-up ip link set dev tap0 master br0
    post-down ip link delete br0
/etc/network/interfaces
net.ipv4.ip_forward = 1
/etc/sysctl.conf

Security Considerations

As it is, this setup doesn't offer much in security. The following steps can be performed to increase security.

  • Dont use root login. Assign the tap interface to a different user and have that user account used for connecting to the interface.
  • Edit the authorized-keys file for the user to ensure only certain commands are executed and certain options set up.
  • In order to allow more than one connection, use vde_switch instead of tunctl to create the tap interface. Then when a user logs in to the vpn user account, the automatic command would be to use vde_plug on the switch. This would require the client to also use vde_switch and vde_plug to make the connection.