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
RUN=yes
DAEMON=/usr/sbin/sslh
DAEMON_OPTS="--user sslh --listen 0.0.0.0:443 --ssh 127.0.0.1:22 --pidfile /var/run/sslh/sslh.pid"

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 127.0.0.1:443’’ 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 proxy.net:8080 %h %p" -p 443 user1@myhopserver.com

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

$ ssh -o ProxyCommand="corkscrew proxy.net 8080 %h %p" -p 443 user1@myhopserver.com

Multihop SSH with OpenSSH

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

$ ~/.ssh/config
Host myhopserver.com
 User user1
 HostName myhopserver.com
 Port 443
 ServerAliveInterval 30
 ProxyCommand /bin/nc -X connect -x proxy.net:8080 %h %p

Host mysecondserver.com
 User user1
 HostName mysecondserver.com
 Port 22
 ServerAliveInterval 30
 ProxyCommand /usr/bin/ssh myhopserver.com /bin/nc -w 600 %h %p

$ ssh mysecondserver.com

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

Session: myhopserver.com
Host: myhopserver.com
Port: 443
Auto-login username: user1
Proxy type: HTTP
Proxy hostname: proxy.net
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

Session: mysecondserver.com
Host: mysecondserver.com
Port: 22
Auto-login username: user1
Proxy type: Local
Telnet command, or
local proxy command: plink.exe -load myhopserver.com -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 myhopserver.com

PuTTy setup

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

Voila! Now you have your own SOCKS proxy: 127.0.0.1:1080

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 proxy.net 8080

CONNECT google.com:443 HTTP/1.1
Host: google.com:443

...

Example B

$ curl --proxy http://proxy.net:8080 ftp://ftp.mozilla.org/pub/mozilla.org

Example C

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

/bin/nc -X connect -x proxy.net:8080 %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 https://github.com/yrutschle/sslh

Prerequisites

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 0.0.0.0:443 -l /usr/sbin/sslh -- sslh -i -p 127.0.0.1:443 --user sslh --ssh 127.0.0.1:22

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 0.0.0.0:443 -l /usr/sbin/sslh -- sslh -i -p 127.0.0.1:443 --user sslh --ssh 127.0.0.1:22)" |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 0.0.0.0:443 --ssh 127.0.0.1:22)" | at now + 1 minute

SSH client configuration with proxytunnel

$ cat .ssh/config
 Host myhopserver.com
 User user1
 HostName myhopserver.com
 Port 443
 ServerAliveInterval 30
 # ProxyCommand /bin/nc -X connect -x proxy.net:8080 %h %p
 ProxyCommand /usr/bin/proxytunnel -e -p proxy.net:8080 -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 0.0.0.0:443 -l /usr/sbin/sslh -- sslh -i -p 127.0.0.1:443 --user sslh --ssh 127.0.0.1:22 &

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
RUN=no

See also