I'm primarily a networking person and don't work with web servers very often. I have an internal server, A, that serves data on port 4040, and an external server, B, needs to retrieve that data over the internet. I want all traffic to pass through a VM running Nginx in a DMZ.
My understanding is that B connects to the proxy's public IP, Nginx receives the request, and then forwards it to server A. What I'm unclear about is how the response gets back to Nginx. Does server A need any special configuration or routing information so it knows to return the requested data to the proxy instead of directly to server B?
4 Answers
The basic setup is for B to connect to the proxy’s public address while Nginx is configured with A’s private address and port as its upstream. B and A never establish a direct session with each other.
If you are only trying to provide private connectivity between the two servers rather than publish an HTTP service, a site-to-site VPN such as WireGuard could be another option. But for an HTTP endpoint, the reverse-proxy design you described is standard.
Think of Nginx as being on two separate conversations at once: one TCP/HTTP session with B and another session with A. It relays the request and response between those sessions; it is not merely forwarding packets like a router or firewall. A just replies to the machine that established the connection, which is Nginx.
Make sure the protocol matches what Nginx is intended to proxy. If port 4040 carries HTTP or HTTPS, an HTTP reverse-proxy configuration is appropriate. If it carries some other TCP-based protocol, you may need Nginx’s stream/TCP proxying instead.
For HTTP services, also account for headers such as Host, X-Forwarded-Host, and X-Forwarded-Proto. Otherwise, an application on A might generate redirects or absolute URLs containing its internal hostname or port instead of the public address B used.
A reverse proxy creates a separate connection to the backend. Nginx receives B’s request, opens its own connection to A on port 4040, and sends the request over that connection. From A’s perspective, Nginx is simply the client, so A sends the response back to Nginx using the normal TCP connection. Nginx then sends that response back to B over B’s original connection.
Server A does not need to know that B exists, and it generally does not need special routing or NAT configuration for this. The important part is configuring Nginx’s upstream or proxy_pass target with A’s internal address and port.
One consequence is that A will normally see the proxy’s IP as the source address, not B’s real address. If the application needs the original client IP for logging or access controls, Nginx can add headers such as X-Forwarded-For, provided the application is configured to trust them.

That clears it up. I was thinking about it like packet forwarding, but the proxy is actually terminating one connection and initiating another.