Plan your escape – SSH Tunneling

As a regular user of open, publics, or “restricted” WiFi networks,  I thought about the best way to protect my communications and use the most part of my applications on port-restricted networks.

The most prevalent choice for this is a VPN (for example with OpenVPN). However, this does not really suit with the intended use, as these protocols allows to secure communications only depending on the destination network address, whereas I want to encrypt communications on the basis of the application used.

In this case, the best solution is to use… a good old SSH server.

Port forwarding setup

First, I connect to an host I trust this way :

$ ssh -D 8080 server_IP

With the specified option -D 8080, ssh stats a local proxy server on the client. All data send throughout this proxy are encrypted until the ssh server, then the server transmits them on Internet in a classic way. The only thing to do is configure each application to use the localhost:8080 proxy, then all data transfered by this application will be encrypted.

This feature can be improved with the following options :

$ ssh -D 8080 -C -N -p 443 <server_IP>

In details :

  • -C : enable data compression.
  • -N : disable distant shell, thus disabling command execution on the server.
  • -p 443 : connect to the port 443. This port is generally open on public networks, because it is required for the HTTPS protocol. The only requirement is a server configured to serve on this port. This way, whatever the required port for the tunneled application, only port 443 must be opened.

If the local network of the client require an HTTP proxy authentication, Corkscrew handles the SSH send through this kind of proxy.

Encryption configuration

By default, ssh authentication is done with a password, but the best practice is to use asymmetric keys.
To generate the keys :

$ ssh-keygen -t rsa -b 4096 -C <key_identification>

This command then ask for a password to protect the keys in interactive mode.

The two files id_rsa et id_rsa.pub are created in the ~/.ssh directory. The private key could also be converted to the PKCS#8 format for better protection against brute force attacks [1] :

$ mv ~/.ssh/id_rsa ~/.ssh/id_rsa.old
$ openssl pkcs8 -topk8 -v2 aes-256-cbc -in ~/.ssh/id_rsa.old -out ~/.ssh/id_rsa
$ chmod 600 ~/.ssh/id_rsa
# Make some tests.
$ rm ~/.ssh/id_rsa.old

Then, the id_rsa.pub content (public key) can be copied into the file ~/.ssh/authorized_keys on the remote server. As soon as the key is defined, authentication is done automatically with the key pair.

I noticed on some of my hosts that ssh sometimes still uses MD5 based message authentication. The HMAC and encryption algorithm is therefore passed as an option :

$ ssh -c aes256-gcm@openssh.com -m hmac-sha2-512
$ ssh -c aes256-ctr -m hmac-sha1 # For older openssh versions

For more information about the available HMAC and algorithms on each host, and on those chosen during the handshake, debug messages can be displayed this way :

$ ssh -vvv

Applications configuration

First, if the application only use on port, the ssh -L option can be used. For example, for a mail client connecting to GMail via IMAP :

$ ssh -L 8081:imap.gmail.com:993

Then, configure the client to connect to IMAP server localhost:8081, the communication will be transparently forwarded to the imap.gmail.com server, port 993.

For any application with an SOCKS v5 proxy support, the only configuration needed is to use the proxy available on 127.0.0.1, with the port defined as parameter for ssh.

For web browsing, the FoxyProxy extension allows to use a proxy depending on the website, or to redirect all traffic through the proxy. This way, only communications with required websites will be encrypted, including the corresponding DNS request.

For FTP, Fillezilla includes SOCKS proxy support.

Finally, for any application which does not include proxy support, like wget or elinks, tsocks handles the redirection of all traffic through the proxy. Its configuration is done in /etc/tsocks.conf :

server = 127.0.0.1
server_port = 8080

If the configuration file is stored elsewhere, use this variable to declare it :

$ export TSOCKS_CONF_FILE = /path/to/config/file

Then start the application using tsocks :

$ tsocks command_to_forward

HTTPS by default

By the way, use HTTPS is always a good idea, that’s why EFF launched the HTTPS Everywhere extension for Firefox and Chrome. The use of this extension is essential on public networks, especially since the creation of Firesheep, which is designed to simply hijack web credentials.

2013 Update : With the currently known attacks on TLS [2] (for both RC4 and AES-CBC), it may be a good idea to :

  • Disable RC4. Seriously. It’s not 90’s anymore. For example, with this Firefox addon.
  • Use TLS 1.2. In Firefox [3], set the following parameters with about:config :
    security.tls.version.min = 3
    security.tls.version.max = 3


N.B. : Right, this post title is not a coincidence. And it also could be “From here to There”, or even “This War Is Silent”.

[1] : http://martin.kleppmann.com/2013/05/24/improving-security-of-ssh-private-keys.html
[2] : https://en.wikipedia.org/wiki/Transport_Layer_Security#Cipher
[3] : http://kb.mozillazine.org/Security.tls.version.*