I'm looking to use the stream module of nginx to proxy HTTP traffic. This works well for HTTPS, as the ngx_stream_ssl_preread
module exists. This allows me to extract the requested server name from the TLS handshake, which I can then use to determine which server I should proxy the stream to. However, I can't seem to find an equivalent for plain HTTP.
I would imagine that this is because most people simply use a normal HTTP proxy, as the proxy server can see the Host header in the HTTP request (since it's unencrypted). Using streams would be a much nicer solution for my scenario though, and it seems to be more lightweight than a full HTTP proxy.
With the ngx_stream_ssl_preread
module, you gain access to a variable named ssl_preread_server_name
. I'm looking for something that would provide essentially the same thing, but derived from the Host
header in the HTTP request. Does such a thing exist?
Best Answer
I couldn't find any built-in way, so I implemented one myself.
With the ngx_stream_js_module module and some custom JavaScript (njs) I can read the server name from the HTTP Host header into $preread_server_name and configure HTTP traffic pretty similar to HTTPS.
First, install the extra module required to support JavaScript in nginx:
Load the module in nginx.conf:
/etc/nginx/http_server_name.js implements reading the server name:
Here's my stream.conf
Include stream.conf in nginx.conf:
Apply the configuration by reloading nginx:
The proxied servers can now be configured in one way to read the real client data from the PROXY protocol for both HTTP and HTTPS: