http reverse proxy with sslh

Using sslh as a reverse proxy for the poor man

sslh is an awesome protocol multiplexer (e.g. share ssh and https on the same port) which can be used as a http reverse proxy as well. This is a bit of a hack and can be considered a http reverse proxy for the poor man :-)

Diagram showing multiple hosts and protocols, which are multiplexed by sslh. Incoming ports 80 and 443 are redirected to host_A.acme and host_B.acme for port 80 and 443, while ssh is redirected to gateway.acme.

Example of using sslh as http reverse proxy

Assuming you are running a host on the public IP address 1.2.3.4 and you want to redirect http requests to two virtual machines host_A.acme (192.168.0.2) and host_B.acme (192.168.0.3), then you can use the following template to make sslh be your http reverse proxy:

{ name: "regex"; host: "192.168.0.2"; port: "80"; regex_patterns: ["^(GET|POST|PUT|OPTIONS|DELETE|HEADER) [^ ]* HTTP/[0-9.]*[\r\n]*Host: host_A.acme"] },
{ name: "regex"; host: "192.168.0.3"; port: "80"; regex_patterns: ["^(GET|POST|PUT|OPTIONS|DELETE|HEADER) [^ ]* HTTP/[0-9.]*[\r\n]*Host: host_B.acme"] },

sslh takes the first receive data packet and tries to match the given regular expression on it. The given regex should work with all http versions, while still trying to match a valid http header as best as it can.

Here is a more complete example configuration file for sslh:

# /etc/sslh.cfg

# where the sslh server will listen
listen:
(
    { host: "1.2.3.4"; port: "443"; keepalive: true; },
    { host: "1.2.3.4"; port: "80"; keepalive: true; }
);
# Protocols and rules that will be applied
protocols:
(
    # Have ssh on the multiplexing port
    { name: "ssh"; service: "ssh"; host: "localhost"; port: "22";  keepalive: true; fork: true; },
    # http multiplexing
    { name: "regex"; host: "192.168.0.2"; port: "80"; regex_patterns: ["^(GET|POST|PUT|OPTIONS|DELETE|HEADER) [^ ]* HTTP/[0-9.]*[\r\n]*Host: host_A.acme"] },
    { name: "regex"; host: "192.168.0.3"; port: "80"; regex_patterns: ["^(GET|POST|PUT|OPTIONS|DELETE|HEADER) [^ ]* HTTP/[0-9.]*[\r\n]*Host: host_B.acme"] },
);

Thanks to Yves Rutschle for helping me out here. You’re amazing!