March 17, 2014

Traverse Corporate Firewalls

If you are behind a firewall and forced to use some HTTP proxy that allows you only HTTP/HTTPS protocols, then you probably interested how to traverse it.

You will need two things:

  • sslh Applicative protocol multiplexer

  • Your own server you can SSH to sslh accepts connections on specified ports, and forwards them further based on tests performed on the first data packet sent by the remote client.

sslh and iptables configuration below is done on your private server that you will use as a hopserver.

sslh configuration on Debian

# cat /etc/default/sslh
DAEMON_OPTS="--user sslh --listen --ssh --pidfile /var/run/sslh/"

Start the sslh

 # /etc/init.d/sslh start

Now sslh is going to listen over *:443 port and will forward incoming SSH connections to localhost:22 port. Besides that you can also reconfigure your webserver to listen only over localhost and add ‘’–ssl’’ argument after the ‘’–ssh’’ (Order is important!)

In this case sslh will decide whether to forward the connection to SSH daemon or to a WebServer which will depend on what is the client trying to access.

iptables config

Make sure you are not filtering HTTPS port at your hopserver

# For the SSLH
-A INPUT -p tcp -m state --state NEW --dport 443 -j ACCEPT

SSH to your server via HTTPS

Now you can try to access your server via HTTPS port.

With netcat-openbsd

$ ssh -o ProxyCommand="nc -X connect -x %h %p" -p 443

The same can be achieved with connect-proxy or corkscrew, e.g.:

$ ssh -o ProxyCommand="corkscrew 8080 %h %p" -p 443

Multihop SSH with OpenSSH

You can access any target server via your hopserver(s).

$ ~/.ssh/config
 User user1
 Port 443
 ServerAliveInterval 30
 ProxyCommand /bin/nc -X connect -x %h %p

 User user1
 Port 22
 ServerAliveInterval 30
 ProxyCommand /usr/bin/ssh /bin/nc -w 600 %h %p

$ ssh

Multihop SSH with PuTTy

Use PuTTYgen to generate your public/private key pair.

Copy Public key and insert to ~/.ssh/authorized_keys on your servers where you will connect.

Save Private key as C:\Users\wuser1\Desktop\pka-putty\privatekey.ppk

IMPORTANT NOTE DO NOT set key passphrase, otherwise plink will just hang (it doesn’t ask for password prompt when using with PuTTy)

Remember, if it prompts for user name or password at any of the intermediate steps it will fail.

Intermediate server

Port: 443
Auto-login username: user1
Proxy type: HTTP
Proxy hostname:
Proxy port: 8080
Telnet command, or
local proxy command: connect %host %port\n
Private key file for
authentication: C:\Users\wuser1\Desktop\pka-putty\privatekey.ppk
Connection - Seconds between keepalives (0 to turn off): 30

Final server

Port: 22
Auto-login username: user1
Proxy type: Local
Telnet command, or
local proxy command: plink.exe -load -nc %host:%port
Private key file for
authentication: C:\Users\wuser1\Desktop\pka-putty\privatekey.ppk
Connection - Seconds between keepalives (0 to turn off): 30

Own SOCKS proxy

Make your own SOCKS proxy out of your SSH over HTTPS connection.

You can make it with OpenSSH or PuTTy, depending what you prefer.

OpenSSH way

$ ssh -fN -D127.0.0.1:1080

PuTTy setup

Connection -> SSH -> [x] Don't start a shell or command at all
Connection -> SSH -> Tunnels
Add new forwarded port
Source port: 1080

Voila! Now you have your own SOCKS proxy:

More about KeepAlive

To enable the keep alive system-wide (root access required), edit /etc/ssh/ssh_config; to set the settings for just your user, edit ~/.ssh/config (create the file if it doesn’t exist). Insert the following:

Host *
ServerAliveInterval 30
ServerAliveCountMax 2

You can also make your OpenSSH server keep alive all connections with clients by adding the following to /etc/ssh/sshd_config:

ClientAliveInterval 30
ClientAliveCountMax 2

“DNS resolution” through HTTP Proxy

If you also have DNS port 53 (udp/tcp) blocked, then you have only the HTTP proxy to get connected to a server using hostname.

Example A

$ telnet 8080



Example B

$ curl --proxy

Example C

In your ~/.ssh/config it is done with netcat-openbsd

/bin/nc -X connect -x %h %p

SSH encapsulation by HTTPS

If you are connecting through a proxy that checks that the outgoing connection really is SSL and rejects SSH, you can encapsulate all your traffic in SSL using stunnel & proxytunnel.

For more, see Using proxytunnel with sslh at the


stunnel will be configured on a server side and proxytunnel on a client side.

Generating PEM certificate for stunnel

# cd /etc/stunnel/
 # touch stunnel.pem && chmod 600 stunnel.pem
 # openssl req -new -x509 -days 365 -nodes -out stunnel.pem -keyout stunnel.pem
 # openssl gendh 2048 >> stunnel.pem
# openssl x509 -subject -dates -fingerprint -in stunnel.pem

Starting stunnel

Manually in foreground to see how it works

# stunnel -f -p /etc/stunnel/stunnel.pem -d -l /usr/sbin/sslh -- sslh -i -p --user sslh --ssh

If you want to restart it (it will drop your connection for about 1-2 seconds)

# echo "\$(killall stunnel4; killall sslh; sleep 1; stunnel -p /etc/stunnel/stunnel.pem -d -l /usr/sbin/sslh -- sslh -i -p --user sslh --ssh" |at now + 1 minute

To kill stunnel/sslh and start only sslh (without SSH request encapsulation by HTTPS at the client side - first network packets)

# echo "\$(killall stunnel4; killall sslh; sleep 1; sslh --user sslh --listen --ssh" | at now + 1 minute

SSH client configuration with proxytunnel

$ cat .ssh/config
 User user1
 Port 443
 ServerAliveInterval 30
 # ProxyCommand /bin/nc -X connect -x %h %p
 ProxyCommand /usr/bin/proxytunnel -e -p -d %h:%p -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)\n"
Setup stunnel start automatically
# grep stunnel /etc/rc.local
 /usr/bin/stunnel -p /etc/stunnel/stunnel.pem -d -l /usr/sbin/sslh -- sslh -i -p --user sslh --ssh &

You may also want to disable sslh if prefer only the encapsulated by HTTPS connection.

# update-rc.d sslh disable
# grep ^RUN /etc/default/sslh

See also