Nginx Tcp Proxy Example
You set up an nginx tcp proxy example by adding a stream block to your main settings file. This block tells the server to listen on a port and forward raw traffic to a backend pool. Engineering teams often use this setup to expose internal databases or custom services on a single public IP. Still, opening raw network ports gives any user on that network path full reach to the backend service. If a developer holds broad database roles, the network router cannot stop them from running destructive
Database Proxy (ProxySQL, PgBouncer) + NGINX Security Configuration: the complete guide
Architecture patterns, implementation strategies, and security best practices. Delivered to your inbox.
You set up an nginx tcp proxy example by adding a stream block to your main settings file. This block tells the server to listen on a port and forward raw traffic to a backend pool. Engineering teams often use this setup to expose internal databases or custom services on a single public IP. Still, opening raw network ports gives any user on that network path full reach to the backend service. If a developer holds broad database roles, the network router cannot stop them from running destructive queries.
How an nginx tcp proxy example works in practice
Standard web servers read HTTP headers to route web pages to the right app. A TCP router works at a lower network layer and moves raw packets of data instead. It does not care if the traffic is a database query, an SSH session, or a custom binary protocol.
To build this setup, you first check that your server software includes the stream module. Most modern software packages include this module by default. You then define a top-level stream context right alongside your standard web traffic settings. Inside this stream context, you create two main parts: an upstream group and a server block.
The upstream group lists the private IP addresses and ports of your backend machines. You can list several database read replicas or internal app nodes in this group. The server block defines the public port that listens for incoming client traffic. It points those incoming requests directly to the upstream group you just named.
When a user or app connects to the public port, the server completes a three-way network handshake. It then opens a second network path to one of the healthy backend servers in your pool. From that moment on, it copies bytes back and forth between the client and the backend machine.
Configuring health checks and load balancing
A basic port forwarder sends traffic to backends even when a machine goes down. In a real system, you must configure active or passive health checks within your stream settings. Passive checks watch live client traffic and mark a backend node as down when connection attempts fail.
You can also pick how the server distributes network sessions across your backend pool. Round-robin routing sends each new session to the next server in the list. Least-connections routing sends new traffic to the backend server with the fewest active sessions right now. This method works well for database workloads where some queries keep sessions open for a long time.
Database Proxy (ProxySQL, PgBouncer) + NGINX Security Configuration: architecture patterns and best practices
Continue reading? Get the full guide.
Free. No spam. Unsubscribe anytime.
Teams also use the stream block to handle TLS encryption at the network edge. The server can read the client certificate and decrypt the raw traffic before forwarding it. This offloads heavy math from your backend databases and keeps key files in one central place.
What raw TCP routing solves and what it misses
Routing raw TCP traffic solves key network topology and load balancing problems for engineering teams. It lets you hide private server IP addresses behind a single static entry point. You can swap out broken backend servers or scale out read replicas without changing client settings. Network teams can also enforce IP allowlists and connection rate limits at the edge.
Yet a raw network forwarder is blind to what happens inside the session after it starts. The server only sees a stream of bytes moving between two IP addresses and ports. It cannot tell who the human user is behind a shared database account or app role.
Because it operates at the transport layer, it cannot read SQL statements or shell commands in flight. If an engineer logs in and drops a production table, the network log only shows bytes sent. It cannot block a dangerous query, and it cannot rewrite sensitive fields like emails or card numbers in results. Securing the network path decides which machines can talk, not what commands a user can run.
Check database and API queries on the wire
Identity tools, roles, and network rules decide who opens a session. Setup alone cannot check what each query does or mask sensitive values in a response once a session starts. When workflows touch Postgres, MySQL, SQL Server, MongoDB, ClickHouse, Kubernetes APIs, SSH, or internal HTTP APIs, hoop.dev runs beside those services as an open-source proxy, a sidecar for your Postgres or API. It inspects requests coming in and results going back on the wire.
Your login details and client tools stay as they are while hoop.dev guardrails refuse bad deletes or drops before they run. On responses, hoop.dev data masking rewrites matched sensitive values in memory. Furthermore, hoop.dev holds SOC 2 Type II, is MIT licensed, and writes every query and decision to an audit trail that generates evidence for HIPAA, GDPR, and PCI DSS. See the source on GitHub.
Frequently asked questions
Where do I place the stream block in my settings?
You place the stream block at the root level of your main server settings file. It sits at the same level as the main HTTP block, never inside it. Putting a stream block inside an HTTP folder will cause the server check to fail on startup.
Can I route both web traffic and TCP traffic on the same port?
No, a standard port listener can only bind to either the HTTP engine or the stream engine. One exception is when you inspect TLS server name headers to split encrypted traffic before decryption. Otherwise, you must assign distinct port numbers for your raw TCP services and standard web apps.
What information gets recorded in stream logs?
Stream logs record network facts like the client IP address, session duration, and total bytes sent. They also log the upstream server IP and the final network status code. They never record the user identity, the queries run, or the data returned by the backend service.
Related guides
In this post