SSH via HTTP

SSH is a hugely powerful tool for communicating with and manipulating remote machines, and as a result many companies fear it and try to block it. As such, many corporate firewalls block port 22, the port naturally used by SSH. However, few corporations can afford to block ports 80 or 443, the ports designated for http traffic.

It is possible to work around these firewalls by configuring SSH to listen on either port 80 or 443. However, this approach is only suitable if you are not already using, or planning to use, port 80 or 443 to serve your websites. There is, however, another option. If you have are running an Apache webserver, you can configure it to act as an HTTP or HTTPS proxy and use it to forward SSH traffic that comes in on ports 80 and 443 to your SSH server. To do so, you will need to configure Apache to act as a proxy, and you will need to use proxytunnel when running your SSH client to make it work with the Apache proxy.

Apache Configuration

The first step is to configure Apache to act as an HTTP and HTTPS proxy. To do so on a recent Fedora system, you should create a file and place it in /etc/httpd/conf.d. The name of the file is somewhat arbitrary, but it should end in .conf. Also, the files in this directory are processed in alphabetic order, and so you may want to choose a name earlier in the alphabetic sort order if there is a chance another file may interfere. Neglecting this, assume that the file name chosen is 10-proxy.conf.

This file is suitable for use on an Apache version 2.4 or later server. It explicitly prevents proxying to any other destination than localhost port 22:

<VirtualHost _default_:80>
    ProxyRequests on
    ProxyVia block
    AllowCONNECT 22
    <Proxy *>
        # Deny all proxying by default ...
        Require all denied
    </Proxy>
    <Proxy 127.0.0.1>
        # Now allow proxying through localhost only
        Require all granted
    </Proxy>
</VirtualHost>

<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
        # enable ssl
        SSLEngine on

        # proxytunnel
        ProxyRequests On
        AllowConnect 22
        <Proxy *>
            # Deny all proxying by default ...
            Require all denied
        </Proxy>
        <Proxy 127.0.0.1>
            # Now allow proxying by localhost only
            Require all granted
        </Proxy>
    </VirtualHost>
</IfModule>

This file configures a proxy for both port 80 and 443. You can remove the appropriate section if you only want one port to act as a proxy.

You also need to assure that Apache loads the appropriate modules: proxy, proxy_connect. proxy_http. That is done in /etc/httpd/conf.module.d. For me, this was preconfigured. I had the following lines in the file 00-proxy.conf:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_http_module modules/mod_proxy_http.so

You activate the proxy by running:

sudo systemctl reload httpd

or:

sudo apachectl graceful

Installing ProxyTunnel

On Fedora, you can install proxytunnel with:

sudo yum install proxytunnel

Testing the Proxy

You can use proxytunnel to test your Apache setup. Simply run the following:

proxytunnel -p myserver.com:80 -d 127.0.0.1:22 -v

and:

proxytunnel -E -p myserver.com:443 -d 127.0.0.1:22 -v

It should respond by saying that the tunnel was established. If you choose any other destination (IP address or port) it should fail.

Configuring Your OpenSSH Client

Add an entry to your SSH config file (~/.ssh/config) for your host that looks like the following:

host home80
   HostName myserver.com
   ProxyCommand proxytunnel -q -p myserver.com:80 -d 127.0.0.1:22
   Port 80

host home443
   HostName myserver.com
   ProxyCommand proxytunnel -q -E -p myserver.com:443 -d 127.0.0.1:22
   Port 443

Be sure to add the -E flag on proxytunnel when connecting to port 443 to turn on SSL encryption.

SELinux

If SELinux is running, it will likely stop Apache from connecting to SSH. If your proxy is not working, you can determine if SELinux is the problem by temporarily disabling SELinux with:

sudo setenforce permissive

If the proxy starts working, you have discovered the problem. Generally this is because SELinux nominally blocks httpd from accessing the local network, which prevents it from accessing the SSH daemon. You can circumvent this problem using:

sudo setsebool -P httpd_can_network_connect 1

The -P makes the solution persistent across reboots.

You should reactivate SELinux using:

sudo setenforce enforcing