Part 4 - Proxy HTTP(S) into the internal network
What’s the idea here?
We want to use Nginx as reverse proxy to make HTTP(S) requests to internal machines without noticing that they are actually on a private network.
Expected requests workflow
- Someone requests
test-a.pve-internal.protossnet.local
- We need to make sure the domain resolves to our Proxmox server (HOW???)
- If HTTPS is being used, Nginx provides a valid TLS certificate
- We need a wildcard certificate for
*.pve-internal.protoss.local
(HOW???)
- We need a wildcard certificate for
- Nginx proxies the request to the internal machine
- It uses the same protocol that is being requested
Reverse proxy for Specific Machines
If only a single machine shall be available from outside the internal network, a machine-specific configuration can be added to nginx in the following path:
/etc/nginx/sites-available/test-a
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name test-a.pve-internal.protossnet.local;
# Certificate should be valid for the domain
ssl_certificate_key /etc/pve/local/pve-ssl.key;
ssl_certificate /etc/pve/local/pve-ssl.pem;
# Proxy configuration
location / {
# Use internal DNS server for name resolution
resolver 10.0.0.2;
set $backend $scheme://test-a.pve-internal.protossnet.local;
proxy_pass $backend;
proxy_buffering off;
client_max_body_size 0;
proxy_set_header Host $host;
proxy_ssl_name $host;
}
}
Make sure to use the internal DNS server to resolve the internal hostname. This will return the internal IP address, and Nginx can use that to reverse proxy to the internal server.
As always, we must create a softlink from the sites-enabled
directory to make it available:
We check if Nginx can spot any errors:
Finally, restart Nginx
Reverse proxy for all machines
This will expose all internal network machines to the external network via HTTP(S). Your internal network thus has only limited protection against attacks via HTTP.
For automated proxying to any internal machine, use this file:
/etc/nginx/sites-available/internal-host-proxy
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name *.pve-internal.protossnet.local;
ssl_certificate_key /etc/pve/local/pve-ssl.key;
ssl_certificate /etc/pve/local/pve-ssl.pem;
# Proxy configuration
location / {
# Use internal DNS server for name resolution
resolver 10.0.0.2;
set $backend $scheme://$host;
proxy_pass $backend;
proxy_buffering off;
client_max_body_size 0;
proxy_set_header Host $host;
proxy_ssl_name $host;
}
}
This is a more generic version of the single-host configuration that uses wildcard to match any host and also now sets the backend dynamically
Remember to create the softlink, test and restart the service as always:
⚠ Don’t Proxy to External Servers!
As we have deleted the default
configuration, now our server proxies any unknown server name. We have to explicitly define a default server which just returns a static response instead. Create the following file:
/etc/nginx/sites-available/default
Remember to create the softlink, test and restart the service as always. Now any impersonation attempt will be answered with a 404 Not found
: