by Bill Brassfield, Dev Ops Technical Consultant at Taos
First, a review of simple TCP SSH tunnels:
Forwarding a local TCP port to a remote TCP port:
(using the -L option)
ssh -L 127.0.0.1:2022:10.150.35.74:22 email@example.com
ssh -L 8080:localhost:80 firstname.lastname@example.org
ssh -L 192.168.3.45:8080:web01.example.com:80 email@example.com
Forwarding a remote TCP port to a local TCP port:
(using the -R option)
ssh -R localhost:2022:localhost:22 firstname.lastname@example.org
sudo ssh -R web99.example.com:80:localhost:80 email@example.com
A few quick notes on sshd_config directives:
- Make sure that “AllowTcpForwarding” is enabled (set to “yes”).
- If setting up a TCP-forwarding listener on a non-loopback network interface,
it may be necessary to set “GatewayPorts” to “yes”.
- If setting up a TCP-forwarding listener on a privileged port (0 to 1023), this must be done
as root. If opening a privileged port for listening on a remote system, the “PermitRootLogin”
directive must be set to either “yes” or “without-password”.
Useful command-line options for the commands discussed above:
- The “-f” option tells SSH to run in the background.
- The “-N” option tells SSH to not run any command on the remote server.
- Adding both the “-f” and “-N” options to the SSH commands listed above will effectively run them quietly in the background (in a “daemonized” mode). To terminate these tunnels, it will be necessary to find their process-ID (PID) and send a SIGTERM kill signal.
- Adding the “-o ServerAliveInterval=30” option will help to keep the tunnels up by keeping the
TCP connections active. (Some network appliances terminate TCP sessions which sit idle
for a few minutes.)
Tunneling non-TCP protocols with Layer-2 and Layer-3 VPN tunnels:
Establishing a layer-3 SSH VPN using “tun” devices:
On the local server, issue the following command:
sudo ssh -f -w 0:0 firstname.lastname@example.org true
(NOTE: You must be root on BOTH the local system and the remote system in order to create the “tun0” virtual network devices and connect them via SSH’s tunneling protocol.) On the local server:
sudo ifconfig tun0 192.168.1.101 netmask 255.255.255.0
On the remote server:
sudo ifconfig tun0 192.168.1.102 netmask 255.255.255.0
At this point, it should be possible to the local and remote servers to ICMP ping each other at their 192.168.1.x IP addresses. If the pings are successful, then it should also be possible to pass TCP and UDP traffic over the tunnel. To shut down the tunnel, find the process-ID (PID) of the ssh command on the local server and send it a SIGTERM kill signal.
- Make sure “PermitTunnel” is set to “yes” in sshd_config on both ends.
- Check to make sure IPTables isn’t blocking traffic in/out of the tun0 network interfaces.
- Make sure “PermitRootLogin” is set to “yes” in sshd_config on the remote system.
Establishing a layer-2 SSH VPN using “tap” devices:
On both the local and remote servers, run the following command to create a “tap0” virtual network interface:
sudo tunctl -t tap0
sudo ip tuntap add dev tap0 mode tap
Next, configure the “tap0” interfaces on both ends: On the local host:
sudo ifconfig tap0 192.168.1.101 netmask 255.255.255.0
On the remote host:
sudo ifconfig tap0 192.168.1.102 netmask 255.255.255.0
Now start the SSH Layer-2 VPN tunnel by issuing the following command on the localhost:
ssh -o Tunnel=ethernet -f -w 0:0 email@example.com true
Assuming all went well, the tunnel should be up, and it should be possible for the local and remote servers to ping each other on their 192.168.1.x IP addresses. Also, running the command “ethtool tap0” on both ends should show “Link detected: yes” in the output. TCP and UDP protocols should work over the tunnel (provided that there are no IPTables firewall rules blocking such traffic). Additionally, DHCP and network-bridging can also be done over the tunnel. (For details on how to do this, see the white paper on Advanced SSH Tunneling.)