I have system of IoT devices behind a NAT, so they are not accessible from the public internet (although it's desired).
To overcome this I tied them into a VPN, with one member exposed to the public internet to act as a gateway.
The VPN has an internal domain set up, and each member of the network has a subdomain based on a unique ID (let's go with MAC address), like so: 12a4f81ead4e.vpn.example.com
I wish to create a reverse proxy on the Gatway
to proxy requests, running nginx.
The plan is to create a DNS record for the gateway, *.gateway.com
, and route (ahem, proxy) traffic going to/from 12a4f81ead4e.gateway.com
to 12a4f81ead4e.vpn.example.com
. And so the end-user would just need to type 12a4f81ead4e.gateway.com
into their browser to access their device.
I'd like to use nginx, as the gateway is already running nginx for other purposes.
I expect HTTP requests to be easy, and can be done with a carefully crafted nginx proxy_pass
directive.
But what about HTTPS requests? As far as I understand, TLS passthrough based on SNI is now implemented by nginx, but all the examples I've seen so far create a static map for ... well mapping the incoming SNI to a target upstream:
stream {
map $ssl_preread_server_name $selected_upstream {
example.org upstream_1;
example.net upstream_2;
example.com upstream_3;
default upstream_4;
}
upstream upstream_1 { server 10.0.0.1:443; }
upstream upstream_2 { server 10.0.0.2:443; }
upstream upstream_3 { server 10.0.0.3:443; }
upstream upstream_4 { server 10.0.0.4:443; }
server {
listen 10.0.0.5:443;
proxy_pass $selected_upstream;
ssl_preread on;
}
}
Problem is devices are added/removed dynamically from the VPN, and I don't want to rewrite the nginx config files all the time. If reading the map from a file is possible, that's a step in the right direction, although I think nginx would need to be reloaded every time that changes, which raises permissions issues, that could be circumvented with sudo rules of course, but not the best solution.
Also I only want to proxy requests coming in to *.gateway.com
, and server other https requests normally to the existing vhosts. If at all possile, I would like to avoid terminating the SSL connection. Not really a hard requirement, but would like to implement it that way if techinically doable. Also just for the kicks.
I'm fine internally listening on an alternate port for the other vhosts, I did something similar for HTTP when I wanted to set a "global" location, and moved all HTTP vhosts to port 81, and implemented a catch-all vhost on port 80 that served the "global" location, and proxied everything else to port 81. :)
So... What I would need it something like this (obviously not working):
stream {
map $ssl_preread_server_name $selected_upstream {
(.*).gateway.com $1.vpn.example.com;
default normal_serve;
}
upstream normal_serve { server 127.0.0.1:8443; }
server {
listen 0.0.0.0:443;
proxy_pass $selected_upstream;
ssl_preread on;
}
server {
listen 127.0.0.1:8443;
server_name other.website.com;
(...)
}
}