3

I have an apache 2.4.18 server running with multiple vhosts.

/etc/apache2/sites-enabled/000-default.conf:

<VirtualHost *:80>
    DocumentRoot /var/www/html
    Redirect 400 /
</VirtualHost>

/etc/apache2/sites-enabled/000-default-ssl.conf:

<VirtualHost _default_:443>
    DocumentRoot /var/www/html
    SSLEngine on
    SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
    SSLCertificateKeyFile   /etc/ssl/private/ssl-cert-snakeoil.key
</VirtualHost>

/etc/apache2/sites-enabled/001-custom.conf:

<VirtualHost _default_:443>
    ServerName www.example.org

    Include /etc/apache2/letsencrypt/main.conf
    SSLCertificateFile      /etc/letsencrypt/live/example.org/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.org/privkey.pem

    Include /etc/apache2/proxytunnel/main.conf
</VirtualHost>

<VirtualHost *:80>
    ServerName www.example.org
    Redirect permanent / https://www.example.org/
</VirtualHost>

/etc/apache2/proxytunnel/main.conf:

ProxyRequests On
AllowConnect 2222
<Proxy *>
    Order deny,allow
    Deny from all
</Proxy>
<Proxy 127.0.0.1>
    Order deny,allow
    Allow from all
</Proxy>

I also have a running SSH server running on port 2222 of the same machine.

If I use proxytunnel from a remote machine to access the SSH server over SSL, using apache as the proxy server:

proxytunnel -v -E -p www.example.org:443 -d 127.0.0.1:2222

I get the following error:

SSL client to proxy enabled
Local proxy www.example.org resolves to xxx.xxx.xxx.xxx
Connected to www.example.org:443 (local proxy)

Tunneling to 127.0.0.1:2222 (destination)
Communication with local proxy:
 -> CONNECT 127.0.0.1:2222 HTTP/1.1
 -> Host: 127.0.0.1:2222
 -> Proxy-Connection: Keep-Alive
 <- HTTP/1.1 405 Method Not Allowed

HTTP return code: 405 Method Not Allowed
 <- Date: Thu, 14 Apr 2016 00:55:57 GMT
 <- Server: Apache/2.4.18 (Debian)
 <- Allow: GET,HEAD,POST,OPTIONS
 <- Content-Length: 309
 <- Content-Type: text/html; charset=iso-8859-1

But if I include the file /etc/apache2/proxytunnel/main.conf in my /etc/apache2/sites-enabled/000-default-ssl.conf vhost, it works...

SSL client to proxy enabled
Local proxy www.example.org resolves to xxx.xxx.xxx.xxx
Connected to www.example.org:443 (local proxy)

Tunneling to 127.0.0.1:2222 (destination)
Communication with local proxy:
 -> CONNECT 127.0.0.1:2222 HTTP/1.1
 -> Host: 127.0.0.1:2222
 -> Proxy-Connection: Keep-Alive
 <- HTTP/1.0 200 Connection Established

 <- Proxy-agent: Apache/2.4.18 (Debian)

 Tunnel established.
 SSH-2.0-OpenSSH_7.2p2 Debian-2

So my conclusion is that for a CONNECT request to work through an apache server over SSL, the AllowCONNECT directive must be placed in the default vhost for the apache proxy port in addition to the actual vhost the request is made.

Note that the behavior is not reproduced when using CONNECT over HTTP (instead of HTTPS) and encryption is disabled in proxytunnel. Also, the problem does not come from proxytunnel as the request is correctly forwarded to apache and is present in the server logs: it is apache that actively refuses it because it considers the HTTP method (CONNECT) invalid on this server (although it is allowed in the vhost which is concerned).

Maxime Rossini
  • 241
  • 3
  • 8

3 Answers3

1

Also, the problem does not come from proxytunnel as the request is correctly forwarded to apache and is present in the server logs

This was wrong, proxytunnel does not support SNI in the version I use (latest commit from their repository as of the date of this post, so something a little ahead of 1.9.1 if I trust their release tags).

The consequence is that the vhost selected by apache is the default vhost, no matter which host I try to CONNECT to.

Maxime Rossini
  • 241
  • 3
  • 8
1

I would like to add to this question by providing feedback on my own experience.. I can't comment yet.

I am using Proxytunnel 1.9.9 (circa April 2018) on Windows 7 which I compiled from sources using Cygwin 32-bit.

From my testing I found that Proxytunnel does not correctly match the Hostname from the -p argument with the ServerName in an Apache2 Virtualhost. Using Proxytunnel to tunnel past one http OR https local proxy fails unless the virtualhost that contains the AllowCONNECT method is the default Virtualhost.

List out the Virtualhosts that are enabled in Apache and see which is the default:

apachectl -S

In my set up I have each virtualhost in its own file in sites-available directory. Run this command:

ls -1

The first file listed in the sites-available directory is the virtualhost that apache2 will make the default virtualhost. In this way I swapped my http (or https) forward proxy as being the default and second-in-line virtualhost... by changing its name so that it would not appear first in a directory listing.

I found that this command for a http local proxy:

proxytunnel -v -p http-forward-proxy.com:80 -d 192.168.0.10:22

Or this command for a https local proxy:

proxytunnel -v -E -C root.pem https-forward-proxy.com:443 -d 192.168.0.10:22

Gave me the OpenSSH banner if the AllowCONNECT method was in the default Virtualhost but a HTTP 405 error if it was not... even when a non-default port 80 virtualhost contained:

ServerName http-forward-proxy.com

Or in the case of proxying to a https forward proxy, when a non-default port 443 virtualhost contained:

ServerName https-forward-proxy.com

I looked at the Apache2 logs and confirmed processing always goes to the default virtualhost.

I have also posted an "Issue" about the HTTP case at the Proxytunnel GitHub page https://github.com/proxytunnel/proxytunnel/issues/31

However

I use Proxytunnel client side with sslh and stunnel server side. In this scenario I found that the hostname in the Proxytunnel command does match with the sni_hostnames{} feature in sslh so in this context the hostname does seem to transfer correctly at least when encrypted and SNI is used.

FlexMcMurphy
  • 203
  • 2
  • 9
0

Thanks for the question and for writing your conclusion. I have a working setup now, thanks to you! Using the apache default vhost works nicely.

I wonder if proxytunnel's SNI is truly the problem, though. In my case, I have https://app1.example.com which comes out as apache's default vhost and another vhost https://example.com. My letsencrypt cert has commonname app1.example.com and a subjectaltname is example.com.

If I add ProxyRequests on to example.com, it simply has no effect. If I move it to app1.example.com, it works fine.

Its my understanding that SNI is not required in the case of one certificate on a single ip for many vhosts.

Also, I use curl for tests as in curl -v -x https://example.com https://somethingelse.com. Curl supports SNI and I checked with wireshark: it DOES send the correct hostname in the handshake extension for the CONNECT request and for the GET request. I still get 405 Method Not Allowed.

So it would seem that the problem lies with mod_proxy not activating correctly. What do you think?

I'm on apache 2.4.25.

moritz
  • 113
  • 1
  • 5