How Secure can Secure Shell (SSH) be? (OpenSSH VPN tunnelling)

This article is the third part of the series on OpenSSH and configurations and includes tricks which make using the protocol more secure. This article concentrates on Virtual Private Networks supported by OpenSSH.

What you will learn

VPN as Virtual Private Network is a set of protocols and apps to enable a (virtual) tunnel inside the network. In this case, the network means layer 2 and layer 3 of the OSI (Open System Interconnection) model but we are focusing on layer 3, VPN tunnel. Admittedly, the OpenSSH supports layer 2 tunnelling, but for ease of use and understanding, this article will focus on layer 3 tunnelling.

Please look at the depicted Figure 1. There is a scheme of the small network configuration where our OpenSSH tunnel is through the Internet. It means that two separated private networks are connected directly via Internet and packets are routed to the appropriate network to the other side. The goal is to ensure secure traffic between and networks. VPNs can provide protection in unsecure networks as well.

OpenSSH is very configurable and we can use it independently of existing SSH configuration in order not to disturb a terminal access client/server model (further explanation is in article 1 of the series – issue 11/2013 of BSD Magazine). Whole traffic between these networks is as secure as OpenSSH protocol is secure. Therefore, encryption is enabled and no one can easily understand what we send through the Internet. Be informed, the OpenSSH team quotation from man ssh advises: Since an SSH-based setup entails a fair amount of overhead, it may be more suited to temporary setups, such as for wireless VPNs. More permanent VPNs are better provided by tools such as ipsecctl(8) and isakmpd(8). So, we can use it for small traffic but a large amount of bandwidth.

Figure 1


First, we have to create virtual interfaces for temporary use and potentially for future use. Both interfaces should be made up on the server and client side. To do it for temporary use (until first system reboot or /etc/netstart command release) type the following commands:

server# ifconfig tun0 create

server# ifconfig tun0 netmask

The results should be similar to Listing 1. Secondly, we should be sure the forwarding is enabled on both sides. To check it, run the command shown below.

server# sysctl | grep ip.forwarding

Output (required):


If the result is equal to 0, then run the following command.

server# sysctl net.inet.ip.forwarding=1


net.inet.ip.forwarding: 0 -> 1

To set it permanently add the line net.inet.ip.forwarding=1 into the /etc/sysctl.conf file.

Listing 1-2

For the client side, check whether forwarding is enabled and then create the pseudo-device interface tun0. The command sequence is as follows; results of the commands are shown in Listing 2:

client# ifconfig tun0 create

client# ifconfig tun0 netmask

Thirdly, for future use of pseudo-device at start up after reboot or similar, create the following file at OpenBSD or modify specified file at FreeBSD.

OpenBSD (on server and client side)

server# echo “ netmask” > /etc/hostname.tun0

client# echo “ netmask” > /etc/hostname.tun0

FreeBSD (on server and client side)

server# echo ‘ifconfig_tun0=”inet

netmask”’ >> /etc/rc.conf

client# echo ‘ifconfig_tun0=”inet

netmask”’ >> /etc/rc.conf

Last but not least, set up the appropriate routing table for both server and client. Let’s look at Figure 1 again to understand better what we should do and along with the packets’ destination. For temporary use commands are as follows:

OpenBSD (on server and client side)

server# route add

client# route add

FreeBSD (on server and client side)

server# route add –net

client# route add –net

To set the permanent routing entries (static routes) after reboot etc., modify your configuration files with the following commands:

OpenBSD (on server and client side)

server# echo “!route add > /dev/

null 2>&1” >> /etc/hostname.tun0

client# echo “!route add > /dev/

null 2>&1” >> /etc/hostname.tun0

FreeBSD (on server and client side)

server# echo ‘static_routes=”vpn1”’ >> /etc/rc.conf

server# echo ‘route_vpn1=”-net”’

>> /etc/rc.conf

client# echo ‘static_routes=”vpn1”’ >> /etc/rc.conf

client# echo ‘route_vpn1=”-net”’

>> /etc/rc.conf

This is the end of the discussion on IP settings for VPN tunnelling, so let’s begin to prepare OpenSSH server and then SSH client to negotiate and start tunnelling.

Openssh: Server And Client Configuration

This section of the article focuses on configuration of the SSH server and client, which is the same for both OpenBSD and FreeBSD operating systems. Let’s assume that we use OpenSSH as a server for a terminal use, a file transfer or even another VPN tunnelling connection as well as an all-in-one.

It’s good to know that we can use a separate sshd process started with a specific defined configuration file and use a different server port. For example, we use standard SSH port 22 for terminal connections and we can use non-standard 2468 port for VPN connections. The configuration file mentioned above can be different as well, so we can forget about any existing SSH connections, configuration etc. and start to use it only for VPN tunnelling.


The first step is to copy the existing configuration file sshd_config to the new file:

server# cp /etc/sshd_conig /etc/sshd_config_vpn

After that we need to change some options and values, so edit the new file sshd _ config _ vpn and add/change the following lines.You should be familiar with these options, described in the 1st in the series (issue 11/2013 of BSD Magazine). There are two new options PermitTunnel and AllowTcp-Forwarding responsible for enabling tunnelling and forwarding packets relatively.

PermitTunnel point-to-point

Port 2468


AllowUsers root

PermitRootLogin yes

AuthenticationMethods publickey

AllowTcpForwarding yes

On the server side we generate the new private/public key, which we will use to start securing SSH connections. That is the same step described in the 1st article as well. The command generating these keys is as follows (Please leave the passphrase empty to prevent continuously being asked for that during every VPN connection):

server# ssh-keygen -b 4096

As described in the 1st article, copy a public key file to authorized_keys file and private file into the client file system.


The next step is to copy existing configuration file ssh_config to the new file:

server# cp /etc/ssh_conig /etc/ssh_config_vpn

We need to change a couple of options and values as well. Edit the file ssh_config_vpn and add/modify the following lines.

Port 2468

Protocol 2

Tunnel point-to-point

PasswordAuthentication no

AddressFamily inet

IdentityFile /my_own_path_to_ssh/private_key

TunnelDevice 0:0

Some explanation is needed for the TunnelDevice option. This option is asking for what pseudo-device interface number should be used for both sides. 0:0 means for tun0.

After that we are ready to run our OpenSSH VPN tunnel. Let’s run the following command from the client.

client# ssh -v -F /etc/ssh/ssh_config_vpn -l root true

To troubleshoot connection problems it is good to set -v option in order to output more debug data during creation of the VPN connection. A successful setting of VPN tunnelling is shown on Listing 3.

Listing 3

If everything works great, we can do some hardening: running VPN at start up and prevent to login as any user, especially root to terminal on the other side, just allow only to create VPN.

To run the VPN tunnel after reboot, etc., we should do as follows (commands for OpenBSD and FreeBSD):

OpenBSD (on the client side)

client# echo “/usr/bin/ssh -F /etc/ssh/ssh_config_vpn -l

root true” >> /etc/rc.local

FreeBSD (on the client side)

client# echo “#!/bin/sh” >> /usr/local/etc/rc.d/

client# echo “. /etc/rc.subr” >> /usr/local/etc/rc.d/

client# echo “rcvar=sshvpn_enable”

client# echo ‘command=”/usr/bin/ssh -F /etc/ssh/ssh_config_

vpn -l root true”’ >> /usr/local/etc/rc.d/

client# chmod 550 /usr/local/etc/rc.d/

client# echo ‘sshvpn_enable=”YES”’ >> /etc/rc.conf

The last thing is to use SSH connection for VPN tunnelling only. To do that we have to change the following line on the server side in the file sshd_config.

PermitRootLogin forced-commands-only

And on the client side add/modify the following line at the file ssh_config_vpn.

tunnel=”1”,command=”sh /etc/netstart tun0” ssh-rsa


Virtual Private Networks are good solutions to provide secure and low cost internal traffic between branches. OpenSSH is one of the many such worthwhile methods for using VPN tunnels but not the best. You can use it for small networks with low traffic between sites. You can use it as a secure gateway to enable new traces as well for security purposes only. OpenSSH is very flexible so it’s good to concatenate SSH terminal connections with VPN tunnelling to improve your security access into the system. You can try to make up the fake traffic as circumstances for threats and thus decrease your system’s vulnerabilities. This part is the last about strictly securing OpenSSH. The last one will explain why OpenSSH used for SFTP (SSH File Transfer Protocol) is better than FTP or even FTPS.

In the next series you will find out more about: SFTP – known as SSH File Transfer Protocol to opposite of a standard FTP.



Arkadiusz Majewski comes from Poland. He has 15 years of experience with ICT technologies, including 15 years of IT networks, 10 years of BSD systems and MS Windows Server solutions. He also has 5 years of experience with programming languages and Telco solutions. He’s interested in security on all business and ICT levels. In his free time, he reads ICT books and deepens his knowledge about science (math, physics, chemistry). His hobby is cycling and motorization. He’s a graduate of Warsaw Information Technology under the auspices of the Polish Academy of Sciences. Feel free to contact the author via e-mail

ESG Labs: TrueNAS Technical Report
Download Enterprise Storage Guide Button
iXsystems values privacy for all visitors. Learn more about how we use cookies and how you can control them by reading our Privacy Policy.