
Use Nginx Layer 4 SNI preread and TLS passthrough to relay traffic from nodes with restricted outbound access through a healthy host on the same LAN—without terminating TLS or managing certificates.
I deployed two servers on OCI: S1 and S2. S1 has no issues accessing the public internet, but S2 times out or gets connection-refused errors on certain HTTPS endpoints. Same destination, same request—the only variable is the egress node, yet the outcome is completely different.
The cause could be a network issue or an allowlist/blocklist on the destination server. I tried swapping S2’s public IP, but that would add cost, and the outcome was uncertain. Moving the service back to S1 would leave S2’s existing resources underused. Deploying another application-level proxy on S1 would also increase the maintenance burden.
I wanted to solve the problem without adding another network service.Why do servers from the same cloud service provider have such different outbound connectivity results? Is this IP being treated differently?
S2's outbound failure does not mean the target service is down. A more likely explanation is that the target blocks S2's public egress IP, or that routing is restricted along a specific path.
Both hosts run in the same private network within the same Oracle Cloud Infrastructure (OCI) region. Yet the behavior is sharply different. From S1, requests to the external HTTPS service complete the TCP handshake and TLS negotiation in tens of milliseconds. From S2, the exact same request waits for tens of seconds before the console reports Connection timed out.
Rendering Mermaid diagram...
Think of it like mailing a letter. The postal network works, and the letter itself is valid. But the recipient may have a filtering rule, or the delivery route for that area may be broken. As soon as the recipient sees S2's return address, the letter disappears. Send the same letter using S1's trusted address, and communication resumes immediately.
The following observations support this conclusion:
Cloud providers such as OCI guarantee basic connectivity from a cloud instance to the public gateway. They cannot control a third-party site's security policy or Internet routing decisions.
Engineers facing this issue often assume opening a cloud support ticket will unblock external access. But if the OCI Security List and Route Table already allow egress to 0.0.0.0/0, the cloud configuration is not dropping your packets.
Rendering Mermaid diagram...
External blocks and routing failures are often asymmetric. Several factors can cause them:
At best, an OCI ticket only confirms the cloud gateway is up. Support cannot force an external site to change its firewall policy or steer routes across third-party autonomous systems (ASes)—so burning time on tickets won't shorten your downtime.
The practical workaround is to leverage what you already have. Because S1 and S2 share the same Virtual Cloud Network (VCN), inter-host private traffic is unrestricted and incurs no egress fees. Routing S2's outbound traffic through S1 as a relay allows S1's clean public IP to make external calls, restoring connectivity without changing the underlying infrastructure.
S1 doesn't need the target site's certificate to route S2's HTTPS connections to the right domain. It only needs to read the Server Name Indication (SNI) from the TLS handshake, then forward the TCP byte stream unchanged.
Think of S1 as a mail sorter reading only the envelope: it extracts the target hostname from the TLS ClientHello without decrypting the payload. Unlike raw packet routing, however, S1 initiates a completely separate outbound TCP session to the target rather than forwarding the original IP packets.
Nginx provides this through ngx_stream_ssl_preread_module. TLS ClientHello messages usually carry the SNI domain in plaintext. When you enable ssl_preread on in an Nginx Stream / Layer 4 Proxy, Nginx can use that domain to choose an upstream destination. The TLS handshake and HTTP traffic then pass through directly. S1 has no certificate private key and cannot decrypt the request.
This is often confused with standard HTTPS reverse proxying. Unlike a reverse proxy, which terminates TLS and requires certificates, this is pure TCP passthrough: Nginx inspects only the initial SNI field without terminating or decrypting the TLS session.
Whether your Nginx package includes this module depends on the distribution. Many prebuilt Nginx packages for major Linux distributions include Stream and SSL preread support. Still, verify it on S1 instead of assuming it is available by default.
Place the following block in S1's top-level Nginx stream configuration. Replace <DNS resolvers available to S1> with a DNS server that S1 can reach.
Because proxy_pass uses the SNI variable, Nginx needs resolver to resolve the target domain at runtime. Without it, Nginx may not be able to resolve a variable-based upstream hostname, and the connection will fail. After changing the configuration, run nginx -t and then reload Nginx gracefully.
Rendering Mermaid diagram...
The tradeoff is straightforward. The Stream listener exclusively occupies TCP port 443 on the same S1 IP address. If S1 already hosts regular HTTPS sites on that IP, those sites can no longer listen on that port directly. You can use another public IP or move local sites to other ports. The HTTP and Stream modules cannot both bind to the same IP:443 address.
This design also depends on clients sending visible SNI. It cannot dynamically select a target for older clients without SNI, or for clients using Encrypted ClientHello (ECH) when Nginx cannot access the domain name.
S2 does not need a proxy client. Map the target domain to S1's private IP locally, while keeping the domain unchanged in the URL.
After that, when S2 requests https://target.example.com, the connection actually reaches port 443 on S1. But the TLS SNI value and certificate validation name remain target.example.com. S1 reads that name, opens a new outbound TCP connection to the real target, and forwards bytes in both directions.
At the TCP layer, the target server sees S1's public egress IP as the source IP. It does not see S2's public IP. S2's address is not part of this TCP session. The caveat is that if the application layer explicitly carries identity metadata—such as a client-injected X-Forwarded-For header—that information still leaks through; this setup only replaces the network-layer source address.
When testing from S2, keep using the original domain instead of S1's IP address:
Check three things: whether the TLS handshake completes, whether the certificate matches the target domain, and whether the HTTP status code is what you expect. You should also restrict access to port 443 on S1 so only S2 can reach it. Otherwise, any host that can connect to S1 may use it as a TCP egress proxy for arbitrary domains.
Use Nginx Layer 4 SNI preread and TLS passthrough to relay traffic from nodes with restricted outbound access through a healthy host on the same LAN—without terminating TLS or managing certificates.
Use this when an internal node drops external traffic due to IP bans, asymmetric packet loss, or BGP routing failures, but a healthy peer on the same LAN or VPC still has full egress connectivity.