Publishing a website through a tunnel and giving users VPN access are two different arrangements that share a cable. In the first, a public reverse proxy accepts the visitor's request and forwards it across the tunnel to an origin nobody can reach directly. In the second, the user must join the VPN before the application is reachable at all. Mixing the two descriptions is how a private backend ends up publicly exposed.

Two models that look alike on a diagram

Draw the arrows before choosing anything. A public-publishing model runs browser to proxy over HTTPS, then proxy to origin across the tunnel, and the origin never accepts a connection from the internet. A VPN-only model runs client to gateway, and the application is reachable only from inside that path. The user's laptop sits on the same network as the application, which is the whole point of that model.

The models differ in who authenticates and where. In the first, the proxy is the public entry and it relays whatever request arrives, including a hostile one, subject to the policy configured on it. In the second, reachability itself is the gate, which is coarse but real admission.

Where TLS stops, and what it actually proves

TLS between browser and proxy protects that hop and lets the browser verify the site it intended to visit. If the proxy terminates TLS, the request exists in readable form inside that process before it is forwarded. A second TLS session to the origin can protect the next hop and verify the application endpoint separately. Neither session decides which human may use the application. A wildcard certificate on the proxy does not extend to that second hop either.

This is the part people collapse into the word encrypted. Confidentiality, integrity and server identity are transport properties; authorization is an application decision. A private address behind a tunnel changes who can reach the socket, not who may log in once they do.

Trust forwarded headers only from the proxy

Applications that log or authorize on the client address usually read a header the proxy adds. That header is just text, so anything able to reach the origin directly can claim any address it likes. Restrict the origin so only the proxy's tunnel address may connect, and configure the application to accept the header only from that address.

curl -s -o /dev/null -w '%{http_code}
' -H 'X-Forwarded-For: 203.0.113.9' http://172.20.5.40/

If that request succeeds from a host that is not the proxy, the origin is trusting a header it should ignore. Fix the listener before touching the application. A denial is a much better outcome than a log line carrying a forged address.

Keep the origin reachable from exactly one place

Bind the origin's listener to the tunnel address or firewall it to the proxy, then confirm what is actually listening. A service started with a wildcard bind accepts connections on every interface the host has, including one you forgot was routable. The listening table is the ground truth, not the configuration file you meant to apply. If the wildcard bind is intentional, the firewall still has to be the component that narrows it.

ss -ltnp | grep -E ':(80|443)'

Do the same review for management interfaces, which are the usual accidental exposure. Then write the two models down separately: the public site through the proxy, and the administration interface reachable only through the tunnel. The sentence that the server is behind a VPN says none of that.

ဆက်စပ်ဆောင်းပါးများ