Set up Apache server and SSH client to allow tunneling SSH over HTTP(s)

From ezUnix
Jump to: navigation, search
                                    pdf_icon.png Download this article as a single PDF document 

Introduction

This document explains how to set up an Apache server and SSH client to allow tunneling SSH over HTTP(S).
This can be useful on restricted networks that either firewall everything except HTTP traffic (tcp/80,tcp/443) or require users to use a local (HTTP) proxy.

A lot of people asked why doing it like this if you can just make sshd listen on port 443.
Well, that might work if your environment is not hardened like I have seen at several companies, but this setup has a few advantages.

  • You can proxy to anywhere (see the Proxy directive in Apache) based on names.
  • You can proxy to any port you like (see the AllowCONNECT directive in Apache)
  • It works even when there is a layer-7 protocol firewall.
  • If you enable proxytunnel ssl support, it is indistinguishable from real SSL traffic.
  • You can come up with nice hostnames like 'downloads.yourdomain.com' and 'pictures.yourdomain.com' and for normal users these will look like normal websites when visited.
  • There are many possibilities for doing authentication further along the path
  • You can do proxy-bouncing to the n-th degree to mask where you're coming from or going to (however this requires more changes to proxytunnel, currently I only added support for one remote proxy).
  • You do not have to dedicate an IP-address for sshd, you can still run an HTTPS site.


Preqrequisites

You need:

  • An internet connected Apache server (eg. with IP address 10.1.2.3).
  • A FQDN that points to this IP address (eg. ssh.yourdomain.com).
  • A virtual host configuration in Apache for this domain (eg. /etc/httpd/conf.d/ssh.yourdomain.com.conf).
  • A configuration to adapt ssh to use the HTTP tunnel.


Configuration

Apache configuration

Here is an example configuration file for Apache (/etc/httpd/conf.d/ssh.yourdomain.com.conf) that
allows access from 2 dialup IP addresses (customer location) to machine1.yourdomain.com and machine2.yourdomain.com.

<VirtualHost 10.1.2.3>
       DocumentRoot /var/www/html
       Customlog ssh.yourdomain.com-access.log combined
       ErrorLog ssh.yourdomain.com-error.log
       HostnameLookups On

       ProxyRequests on
       AllowCONNECT 22 2022
       ProxyVia on

       ### Deny everything by default
       <Proxy *>
               Order deny,allow
               Deny from all
       </proxy>

#       <Proxy 123.45.67.89>
#       <Proxy machine.yourdomain.com>
#       <ProxyMatch .*\.yourdomain\.com>
       <ProxyMatch (machine1|machine2)\.yourdomain\.com>
               Order deny,allow
               Deny from all

               ### External (customer) sites allowed to connect
               Allow from 194-78-234-211.dialup.skynet.be
               Allow from 114-149.241.81.adsl.skynet.be
       </ProxyMatch>
</VirtualHost>


OpenSSH configuration

Download proxytunnel from http://proxytunnel.sourceforge.net/.
Then add something similar to this to you ~/.ssh/config file.

Host *.yourdomain.com *.otherdomain.net someserver.org
      DynamicForward 1080
      ProxyCommand proxytunnel -v -p proxy.local.net:8080 -r ssh.yourdomain.com:443 -d %h:%p -H "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Win32)\n"
      ServerAliveInterval 30

This will make SSH use the proxytunnel utility to tunnel SSH over HTTP(S). After that you can simply do:

# ssh machine1.yourdomain.com
Connected to proxy.local.net:8080
Tunneling to ssh.yourdomain.com:443 (destination)
Starting tunnel
user@machine1.yourdomain.com's password: 


Tunneling over SSH

The above configuration allows you to forward SSH connections to multiple destinations (without the requirement to have SSH running on another port than 22).
To simplify tunneling over SSH, you might want to create a 'dynamic' tunnel using the -D 1080 OpenSSH option.
This allows you to socksify any TCP connection and direct it over the SSH tunnel dynamicly.
Most browers allow to socksify their own stack by simplying configuring a socks proxy.
In this case you should point your browser to localhost:1080 to surf using the SSH tunnel.


Tunneling to HTTPS

proxytunnel has support for SSL tunneling by using the -e option.
Unfortunately there is a bug in Apache that causes CONNECT (mod_proxy) to fail when SSL is being enabled.
You can find more information in Apache's bugzilla at: http://issues.apache.org/bugzilla/show_bug.cgi?id=29744


Sources

Original Howto: http://dag.wieers.com/howto/ssh-http-tunneling/


That's all folks!

Marcin


<comments />

Neo said ...
05:57, 19 October 2010 (CEST)
hi,

I am trying what you have finished and I add configuration with copy and paste to my apache, and I restart it with error. ProxyRequests is not supported. Can you help me out ?

neo.
Neo said ...
06:10, 19 October 2010 (CEST)
My environment is like the following,

A firewall point 80 port to my internal server 172.31.7.2 with apache(#80) on that. That firewall can only open 80 port, and cannt open any other port for security issue. I need to access this webserver machine from outside world.

Here is my apache configure, I add a new line to apache configuration.

Include conf/extra/httpd-webssh.conf,

and I create a new file inside extra folder like the following,

===============================
  1. httpd-webssh.conf

<VirtualHost 172.31.7.2>

      DocumentRoot /var/www/html
      Customlog ssh.testdomain.com-access.log combined
      ErrorLog ssh.testdomain.com-error.log
      HostnameLookups On
      ProxyRequests on
      AllowCONNECT 22 2022
      ProxyVia on
      ### Deny everything by default
      <Proxy *>
              Order deny,allow
              Deny from all
      </proxy>
      <ProxyMatch .*\.testdomain\.com>
              Order deny,allow
              Deny from all
              ### External (customer) sites allowed to connect
              Allow from all 
      </ProxyMatch>

</VirtualHost>

================================

AND I restart apache and it complains with ProxyRequests is not recognized.

Any clue ?

Neo.