{"id":526,"date":"2016-06-10T17:56:03","date_gmt":"2016-06-10T17:56:03","guid":{"rendered":"https:\/\/blog.afach.de\/?p=526"},"modified":"2016-08-22T13:53:10","modified_gmt":"2016-08-22T13:53:10","slug":"tunnel-through-https-to-your-ssh-server-the-perfect-tunnel-haproxy-tunnel","status":"publish","type":"post","link":"https:\/\/blog.afach.de\/?p=526","title":{"rendered":"Tunnel through https to your ssh server, and bypass all firewalls &#8211; The perfect tunnel! (HAProxy + socat)"},"content":{"rendered":"<h3><span style=\"color: #ff0000;\">Disclaimer<\/span><\/h3>\n<p><span style=\"color: #ff0000;\">Perhaps there&#8217;s no way to emphasize this more, but I don&#8217;t encourage violation of corporate policy. I do this stuff for fun, as I love programming and I love automating my life and gaining more convenience and control with technology.\u00a0I&#8217;m not responsible for\u00a0any problem you might get with your boss in your job for using this against your company&#8217;s firewall, or any similar problem for that matter.<\/span><\/p>\n<h2>Introduction<\/h2>\n<p>I was in a hotel in Hannover, when I tried to access my server&#8217;s ssh. My ssh client, Putty, gave this disappointing message<\/p>\n<p><a href=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttyConnectionRefused.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-527 aligncenter\" src=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttyConnectionRefused.png\" alt=\"PuttyConnectionRefused\" width=\"297\" height=\"170\" \/><\/a><\/p>\n<p>At first I got scared as I thought my server is down, but then\u00a0I visited the websites of that server, and\u00a0they were fine. After some investigation, I found that my hotel blocks any access to many ports, including port 22, i.e., ssh.\u00a0Did this mean that I won&#8217;t have access to my server during my trip? Not really!<\/p>\n<p>I assume you&#8217;re using a\u00a0Windows client, but in case you&#8217;re using linux, the changes you have to do are minimal, and I provide side-by-side how to do the same on a\u00a0linux client. Let me know if you have a problem with any of this.<\/p>\n<h2>Tunneling mechanism, and problems with other methods that are already available<\/h2>\n<p>There are software that does something similar\u00a0for you automatically, like <a href=\"http:\/\/www.rutschle.net\/tech\/sslh.shtml\">sslh<\/a>, but\u00a0there&#8217;s a problem there.<\/p>\n<h6>What does sslh do?<\/h6>\n<p>When you install sslh on your server, you choose, for example, port 443 for it. Port 443 is normally for http-ssl (https), that&#8217;s normally taken by your webserver. So you change also your webserver&#8217;s port to some arbitrary\u00a0port, say 22443. Then, say you want to connect to that server: sslh analyzes and detects\u00a0whether the incoming network packets are ssh or http. If the packets are ssh, it forwards them to port 22. If the packets\u00a0looks like https, it forwards them to the\u00a0dummy port you chose, which is 22443 as we assumed.<\/p>\n<h6>What&#8217;s the problem with sslh, and similar programs?<\/h6>\n<p>It all depends on how sophisticated the firewall you&#8217;re fighting is. Some firewalls are mediocre, and they just blindly open port 443, and you can do\u00a0your sslh trick there and everything\u00a0will work fine. But smart\u00a0firewalls are not that dull; they analyze your packets and then judge whether you&#8217;re allowed to be connected. Hence, a smart firewall will detect that you&#8217;re\u00a0trying to tunnel ssh, and will stop you!<\/p>\n<h6>How do we solve this problem?<\/h6>\n<p>The solution is: Masquerade the ssh packets inside an https connection, hence, the firewall will have to do a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Man-in-the-middle_attack\">man-in-the-middle attack<\/a> in order to know what you&#8217;re trying to do. This will never happen! Hence, I call this solution: &#8220;<strong><span style=\"color: #ff0000;\">The perfect solution<\/span><\/strong>&#8220;.<\/p>\n<h2>How to create the tunnel?<\/h2>\n<p>I use <a href=\"http:\/\/www.haproxy.org\/\">HAProxy<\/a> for this purpose. You need that on your server. It&#8217;s available in standard linux systems. In Debian and Ubuntu, you can install it using<\/p>\n<pre>sudo apt-get install haproxy<\/pre>\n<p>You will need &#8220;socat&#8221; on your client to connect to this tunnel. This comes later after setting up HAProxy.<\/p>\n<h6>How does HAProxy work?<\/h6>\n<p>I don&#8217;t have a PhD in HAProxy, it&#8217;s fairly a complicated program that can be used for many purposes, including load balancing and simple internal proxying between different ports, and\u00a0I use it only for this purpose. Let me give a brief explanation on how it works. HAProxy uses the model\u00a0of frontends and backends. A frontend is what\u00a0a client sees. You set a port there, and a communication mode (tcp, for example). You tell also a frontend &#8220;where these packets should go&#8221;, based on some conditions (called ACL, Access Control Lists). You choose to which\u00a0<em>backend<\/em> the packets have to go. The backend contains information about the target local port. So in short words, you tell HAProxy where to forward these packets from the frontend to the backend based on some conditions.<\/p>\n<h6>A little\u00a0complication if you use https websites on the same server<\/h6>\n<p>If you use https webserver on the same machine, you&#8217;ll have a problem. The problem is that you&#8217;ll need to check whether the packets are ssh <strong>before decrypting them<\/strong>, because once you decrypt them, you can&#8217;t\u00a0use them as non-encrypted again (hence haproxy doesn&#8217;t support forking encrypted and decrypted\u00a0packets side-by-side). This is because you choose to decrypt in your frontend. That&#8217;s why we\u00a0use <a href=\"https:\/\/en.wikipedia.org\/wiki\/Server_Name_Indication\">SNI (Server Name Indication)<\/a>\u00a0and do a trick:<\/p>\n<ul>\n<li>If there&#8217;s no SNI (no server name, just IP address), then forward to ssh<\/li>\n<li>If server name used is\u00a0ssh.example.com (some subdomain you choose), then forward to ssh (optional)<\/li>\n<li>If anything else is the case, forward to the https web server\u00a0port<\/li>\n<\/ul>\n<p>We also use 2-frontends. The first one is the main one, and the second is a dummy\u00a0frontend, and is only used to decrypt the ssh connection&#8217;s https masquerade. HAProxy decrypts only in frontends.<\/p>\n<h2>Let&#8217;s do it!<\/h2>\n<p>The configuration file of HAProxy in Debian\/Ubuntu is<\/p>\n<pre>\/etc\/haproxy\/haproxy.cfg<\/pre>\n<p>You could use nano, vi or vim to edit it (you definitely have to be root or use sudo). For example:<\/p>\n<pre>sudo nano \/etc\/haproxy\/haproxy.cfg<\/pre>\n<h6>Assumptions<\/h6>\n<ol>\n<li>Your main https port is 443<\/li>\n<li>Your main ssh port is 22<\/li>\n<li>Your\u00a0https webserver is now on 22443<\/li>\n<li>The dummy ssh port is 22222 (used just for decryption, it doesn&#8217;t matter what you put it)<\/li>\n<\/ol>\n<h6>Main frontend<\/h6>\n<p>This is the frontend that will take care of the main port (supposedly 443). Everything after a sharp sign (#) on a line is a comment.<\/p>\n<pre>#here's a definition of a frontend. You always give frontends and backends a name\r\nfrontend TheMainSSLPort\r\n mode tcp\r\n option tcplog\r\n bind 0.0.0.0:443 #listen to port 443 under all ip-addresses\r\n\r\n timeout client 5h #timeout is quite important, so that you don't get disconnected on idle\r\n option clitcpka\r\n\r\n tcp-request inspect-delay 5s\r\n tcp-request content accept if { req_ssl_hello_type 1 }\r\n\r\n #here you define the backend you wanna use. The second parameter is the backend name\r\n use_backend sshDecrypt if !{ req_ssl_sni -m found } #if no SNI is given, then go to SSH\r\n use_backend sshDecrypt if { req_ssl_sni -i ssh.exmple.com } #if SNI is ssh.example.com, also go to ssh\r\n\r\ndefault_backend sslWebServerPort #if none of the above apply, then this is https<\/pre>\n<p>In the previous configuration, we have\u00a0two paths for the packets, i.e., two backends:<\/p>\n<ol>\n<li>If the connection is ssh, the backend named &#8220;sshDecrypt&#8221; will be used.<\/li>\n<li>If the connection is https, the backend named &#8220;sslWebServerPort&#8221; will be used.<\/li>\n<\/ol>\n<h6>The https backend<\/h6>\n<p>I put this here first because it&#8217;s easier. All you have to do here is forward the packets to your webserver&#8217;s port, which we assumed to be port 22433. The following is the relevant configuration:<\/p>\n<pre>backend sslWebServerPort\r\n mode tcp\r\n option tcplog\r\n server local_https_server 127.0.0.1:22443 #forward to this server, port 22443<\/pre>\n<p>Now the https part is done. Let&#8217;s work on the ssh part.<\/p>\n<h6>The ssh front- and backends<\/h6>\n<p>We&#8217;ll have to use a trick, as mentioned before, to get this to work. Once a judgment is done for packets to go to ssh (using SNI), the packets have to be decrypted. This is not possible in a backend, thus we use a backend to forward the packets to a dummy frontend that decrypts the packets, and then send these to another backend to send the packets to the ssh server.<\/p>\n<pre>backend sshToDecryptor\r\n mode tcp\r\n option tcplog\r\n server sshDecFrontend 127.0.0.1:22222\r\n timeout server 5h<\/pre>\n<p>This forwards the packets to port 22222. Now we build a frontend at that port that decrypts the packets.<\/p>\n<pre>frontend sshDecyprtionPort\r\n timeout client 5h\r\n option clitcpka\r\n\r\n bind 0.0.0.0:22222 ssl crt \/path\/to\/combined\/certs.pem no-sslv3\r\n mode tcp\r\n option tcplog\r\n\r\n tcp-request inspect-delay 5s\r\n tcp-request content accept if HTTP\r\n\r\ndefault_backend sshServ #forward to the ssh server backend<\/pre>\n<p>The file\u00a0\/path\/to\/combined\/certs.pem has to contain your private key, certificate and certificate chain in one file of your SSL. Concatenate them all in one file.<\/p>\n<p>Finally, the back end to the ssh server:<\/p>\n<pre>backend sshServ\r\n mode tcp\r\n option tcplog\r\n server sshServer1 127.0.0.1:22\r\n timeout server 5h<\/pre>\n<p>That&#8217;s all you need to create the tunnel.<\/p>\n<h6>Test your haproxy configuration on the server<\/h6>\n<p>To test your configuration, stop HAProxy using<\/p>\n<pre>sudo service haproxy stop<\/pre>\n<p>and run the following command to start HAProxy in debug mode:<\/p>\n<pre>sudo haproxy -d -f \/etc\/haproxy\/haproxy.cfg<\/pre>\n<p>The &#8220;-d&#8221; flag is debug mode, and the &#8220;-f&#8221; flag is used to choose the config file. The typical output looks like:<\/p>\n<pre>Available polling systems :\r\n epoll : pref=300, test result OK\r\n poll : pref=200, test result OK\r\n select : pref=150, test result FAILED\r\nTotal: 3 (2 usable), will use epoll.\r\nUsing epoll() as the polling mechanism.<\/pre>\n<p>If you don&#8217;t get any errors, then your configuration is OK. Press ctrl+c to close this foreground version of HAProxy, and start the HAProxy service:<\/p>\n<pre>sudo service haproxy start<\/pre>\n<h6>Test your tunnel from your client<\/h6>\n<p>To test your client, you can use OpenSSL. The following command will connect to the server.<\/p>\n<pre><code>openssl s_client -connect ssh.example.com:443<\/code><\/pre>\n<p>You can also use your IP address. This will connect to HAProxy, and will be interpreted as ssh, if your configuration is correct. Once it reaches the ssh server, you&#8217;re good! You&#8217;ll see lots of stuff from OpenSSL, and finally a few seconds later the following message will appear if you&#8217;re using a Debian server:<\/p>\n<pre>SSH-2.0-OpenSSH_6.7p1 Debian-5+deb8u2<\/pre>\n<p>The message will change depending on your server&#8217;s linux distribution and OpenSSH server version. Once you see this message, this shows that you reached your ssh server successfully. You now have to setup a connection to your server&#8217;s\u00a0tunnel.<\/p>\n<h2>Connecting to the ssh server using the tunnel<\/h2>\n<p>You need <em>socat<\/em> to connect\u00a0to the https tunnel, and then you ssh to that tunnel. The program, socat, can be downloaded either as a zip package (please google it and\u00a0try it, if it works, great. I had problem with OpenSSL dlls back then when I first tried this). Or you can use <a href=\"https:\/\/www.cygwin.com\/\">Cygwin<\/a> to get it. Cygwin is a set of linux programs compiled for Windows. Don&#8217;t get too confident in the installer and just download all its components or you&#8217;ll easily consume 30 GB of diskspace and consume 10 hours installing these components. Just download what you need.<\/p>\n<p>In case you&#8217;re using a linux client, socat is a standard program in linux. Just install it with your default package manager, e.g. in Debian\/Ubuntu<\/p>\n<pre>sudo apt-get install socat<\/pre>\n<h6>Running the socat tunnel<\/h6>\n<p>Open your Windows command prompt <strong>as administrator<\/strong> (or linux terminal), and use the following command to connect to your server using socat<\/p>\n<pre>socat -d TCP-LISTEN:8888,fork,range=127.0.0.1\/32 OPENSSL-CONNECT:ssh.example.com:443,verify=0<\/pre>\n<p>Here we use port 8888 as an intermediate local port on your client. Once this works with no errors, you&#8217;re good to use an ssh client.<\/p>\n<p>Warning: A &#8220;-v&#8221; flag is\u00a0verbose for socat. Don&#8217;t do this for serious connections, but only for tests, as it writes everything on the terminal where socat is running, and since Windows Command Prompt\u00a0prints messages synchronously, it&#8217;ll slow down everything for you.<\/p>\n<h6>Connect with your ssh client<\/h6>\n<p>Assuming you&#8217;re using putty, this is how your client should look like<\/p>\n<p><a href=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttySSHTunnel.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-541 aligncenter\" src=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttySSHTunnel-300x295.png\" alt=\"PuttySSHTunnel\" width=\"300\" height=\"295\" srcset=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttySSHTunnel-300x295.png 300w, https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttySSHTunnel.png 681w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Or if you&#8217;re using a linux client, simply\u00a0use this in your terminal<\/p>\n<pre>ssh 127.0.0.1 -p 443<\/pre>\n<p>And you should connect, and you&#8217;re done! Congratulations! You&#8217;re connected to your ssh server through https.<\/p>\n<h2>What about the other ports, other than ssh?<\/h2>\n<p>Once you got ssh working, everything else is easy. You can use an ssh SOCKS proxy tunnel.\u00a0Putty does this easily for you. All you have to do is configure your connection as in the picture:<\/p>\n<p><a href=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttySOCKS.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-542 aligncenter\" src=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttySOCKS-300x297.png\" alt=\"PuttySOCKS\" width=\"300\" height=\"297\" srcset=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttySOCKS-300x297.png 300w, https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttySOCKS-150x150.png 150w, https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/PuttySOCKS.png 678w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>This creates a SOCKS proxy. To use it, I provide the following example that I do on Thunderbird to secure my e-mail connections. You can do the same on any program you like, even on your web browser:<\/p>\n<p><a href=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/SOCKSProxySettingsThunderbird.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-543 aligncenter\" src=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/SOCKSProxySettingsThunderbird-295x300.png\" alt=\"SOCKSProxySettingsThunderbird\" width=\"295\" height=\"300\" srcset=\"https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/SOCKSProxySettingsThunderbird-295x300.png 295w, https:\/\/blog.afach.de\/wp-content\/uploads\/2016\/06\/SOCKSProxySettingsThunderbird.png 638w\" sizes=\"auto, (max-width: 295px) 100vw, 295px\" \/><\/a><\/p>\n<p>You can do the same on linux. Please google how to create an ssh tunnel on linux for SOCKS proxy.<\/p>\n<h2>Conclusion<\/h2>\n<p>You&#8217;re connected! You can bypass any firewall you want just by being given access\u00a0port 443. The only way to stop you is by cutting off your internet completely \ud83d\ude42<\/p>\n<p>Share this if you like it! I welcome your questions and any other thoughts in the comments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Disclaimer Perhaps there&#8217;s no way to emphasize this more, but I don&#8217;t encourage violation of corporate policy. I do this stuff for fun, as I love programming and I love automating my life and gaining more convenience and control with technology.\u00a0I&#8217;m not responsible for\u00a0any problem you might get with your boss in your job for &hellip; <a href=\"https:\/\/blog.afach.de\/?p=526\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Tunnel through https to your ssh server, and bypass all firewalls &#8211; The perfect tunnel! (HAProxy + socat)<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[1],"tags":[5,6,4,8,3,2,7],"class_list":["post-526","post","type-post","status-publish","format-standard","hentry","category-miscillaneous","tag-debian","tag-linux","tag-proxy","tag-putty","tag-ssh","tag-tunnel","tag-windows"],"_links":{"self":[{"href":"https:\/\/blog.afach.de\/index.php?rest_route=\/wp\/v2\/posts\/526","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.afach.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.afach.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.afach.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.afach.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=526"}],"version-history":[{"count":42,"href":"https:\/\/blog.afach.de\/index.php?rest_route=\/wp\/v2\/posts\/526\/revisions"}],"predecessor-version":[{"id":641,"href":"https:\/\/blog.afach.de\/index.php?rest_route=\/wp\/v2\/posts\/526\/revisions\/641"}],"wp:attachment":[{"href":"https:\/\/blog.afach.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=526"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.afach.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=526"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.afach.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=526"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}