Your corporate proxy sits between your internal network and the internet, and that position feels protective. But being in the middle of every request does not mean your proxy is keeping secrets. By default, it is probably broadcasting your internal hostnames, your clients’ real IP addresses, and your software version strings to every external server that any of your employees visits. No breach required. No attacker needed. The information leaves quietly, attached to ordinary HTTP headers, with every single request.
Network Exposure Snapshot
- Corporate proxies forward
Via,X-Forwarded-For, and version headers to external servers in default configurations. - These headers expose your internal hostnames, client IP addresses, and exact software versions to outside parties.
- Running an HTTP header inspector against your egress IP shows the full picture before you touch a single config file.
- Squid and nginx each have native directives to strip or overwrite offending headers with just a few lines of configuration.
- Always test again after applying fixes, and repeat after every proxy software upgrade, since defaults can silently reset.
The Headers Carrying Your Internal Network Details Outbound
HTTP headers are short metadata fields that travel with every request and response. Most of them are benign. The content type, accepted encoding, cache control instructions. These are harmless. A specific subset, however, is generated by proxy software for operational reasons, and they carry details that belong inside your network, not outside it.
The Via header is one of the most revealing offenders. Its defined purpose, per the HTTP semantics specification, is to track the chain of intermediaries a request travels through. The format includes the protocol version and the hostname of the proxy. A request leaving a default Squid installation might carry something like Via: 1.1 proxy.corp.example.internal (Squid/5.7). That single field tells any external server your internal proxy hostname, the exact proxy software you run, and its version number. All three pieces of information are useful to an attacker conducting early-stage reconnaissance.
The X-Forwarded-For header is even more direct about what it reveals. Its job is to append the IP address of the original requesting client to the outbound request. That way the destination server can log the actual employee machine IP rather than the proxy’s egress IP. Inside a trusted environment that makes operational sense. On the public internet, it means every website your staff visits can read an internal RFC 1918 address. Sometimes they see a chain of several internal addresses, one per hop the request made before leaving your network.
Headers like X-Real-IP and the standardized Forwarded field carry similar risk. On the response side, Server and X-Powered-By headers from upstream servers can pass straight through your proxy and reach the client with version strings intact, giving away backend software details to anyone who intercepts the response.
Why Leaked Headers Are a Concrete Security Problem
Individually, none of these data points sounds catastrophic. Combined and viewed from the outside, they assemble a map. Your internal proxy hostname reveals your naming convention, which an attacker can use to guess other internal hostnames. Your internal IP ranges confirm whether you use standard blocks or custom addressing. The software version strings translate directly into a CVE search. The attacker does not need to scan your perimeter. Your employees are delivering the reconnaissance data automatically with their normal browsing traffic.
There is also a compliance dimension that catches some organizations off guard. Internal IP addresses can qualify as personal data under GDPR and similar frameworks when they can be linked to an identifiable individual. If your proxy is appending employee machine IPs to requests that reach third-party advertising networks or analytics platforms, you may have a data residency issue alongside the security concern. The header leakage is not a hypothetical scenario. It happens in default proxy configurations daily, across thousands of corporate networks, with no one ever noticing.
Penetration testers routinely check for header leakage during the reconnaissance phase of an engagement. Before they attempt any exploit, they want to understand the environment. Your proxy headers can hand them a useful head start at zero cost and zero detectable effort on their part.
How to See Exactly What Your Egress IP Is Sending
Before changing any configuration, establish a baseline. You need to see what headers your proxy is actually forwarding to the outside world right now, from the perspective of a server receiving your requests. The most reliable way to do this is to route a test request through your proxy and inspect what the destination sees.
An HTTP header inspector gives you exactly that outside perspective. The tool receives your request and reflects back every header it received, including the proxy-generated ones that your browser never surfaces. Run the test from a machine that is genuinely routing through your corporate proxy, so the result matches what real outbound traffic carries.
Follow these steps to get a clean, usable baseline:
- Confirm your test machine is routing through the corporate proxy. Check your outbound IP against your expected egress range. If you see a different IP, you are not testing through the proxy.
- Open the header inspection tool and trigger a test request. The result appears immediately and lists every header the server received from your connection.
- Look specifically for
Via,X-Forwarded-For,Forwarded,X-Real-IP, and any custom headers your proxy software injects by default. - Copy or screenshot the full output. This is your before state. Every header visible here is one that external parties can read today.
- After applying suppression rules and reloading your proxy, return to the same tool from the same machine and run the identical test. Any header still present means your fix has a gap.
Squid Directives That Close the Most Common Gaps
Squid has been the default proxy server in corporate Linux environments for a long time, and its configuration options for header control are thorough once you know the right directives. These changes all belong in squid.conf.
To suppress the Via header entirely, add via off. This prevents Squid from appending its own Via entry and strips any existing Via headers that arrived from internal upstream hops. If full suppression creates compliance issues with your internal logging requirements, httpd_suppress_version_string on removes the software name and version from the header while keeping the pseudonymized hostname entry.
For X-Forwarded-For, the directive forwarded_for off stops Squid from adding its own entry. That is useful, but it does not remove accumulated internal entries that arrived with the request from other internal proxies or load balancers. For those, use forwarded_for delete instead. The delete option strips the header entirely on outbound requests, regardless of what arrived. For most outbound egress scenarios, delete is the safer choice.
Squid’s request_header_access and reply_header_access directives give you surgical control over individual headers. Adding request_header_access X-Real-IP deny all strips that header from every outbound request. Stacking several of these directives in sequence lets you clean up every header your baseline test identified. Watch for conflicting rules if your squid.conf has been edited by multiple people over the years. A later allow rule silently overrides an earlier deny for the same header. Running squid -k parse before reloading surfaces those conflicts.
Nginx Proxy Header Suppression Configuration
If nginx handles your forward or reverse proxy traffic, the configuration model differs from Squid but the outcome is the same. Nginx uses proxy_set_header to control what gets sent to upstream servers, and proxy_hide_header to suppress headers on the response path.
To clear X-Forwarded-For entirely, add proxy_set_header X-Forwarded-For ""; inside your proxy location block. That overwrites any accumulated chain with an empty value before the request leaves. If your application tier genuinely needs the immediate client IP but not the internal chain, proxy_set_header X-Forwarded-For $remote_addr; replaces the full chain with only the connecting address, which limits what gets forwarded outward.
The Via header in nginx requires the ngx_headers_more module for full control on the request path. With the module loaded, more_clear_headers Via; removes the header in both directions. Without the module, proxy_hide_header Via; covers the response path only. For most outbound scenarios the response path is the lower-priority concern, but both directions matter in a transparent proxy setup.
Response-side version disclosure is handled with proxy_hide_header Server; and proxy_hide_header X-Powered-By;. Pair those with server_tokens off; in your http block, which suppresses nginx’s own version string from error pages and default Server response headers. That combination covers both what your proxy adds and what it passes through.
Header Suppression Options: Squid vs Nginx
| Header | Squid Directive | Nginx Directive |
|---|---|---|
Via |
via off |
more_clear_headers Via; |
X-Forwarded-For |
forwarded_for delete |
proxy_set_header X-Forwarded-For ""; |
X-Real-IP |
request_header_access X-Real-IP deny all |
proxy_hide_header X-Real-IP; |
Server |
reply_header_access Server deny all |
proxy_hide_header Server; server_tokens off; |
X-Powered-By |
reply_header_access X-Powered-By deny all |
proxy_hide_header X-Powered-By; |
The Verification Step That Most Admins Skip
Applying the configuration changes and reloading the proxy service is not the end of the process. It is the halfway point. After every reload, run the same header inspection test from the same machine and the same network position you used to capture the baseline. Compare the two outputs directly. Any header that still appears in the post-fix result means the suppression rule did not apply cleanly, is scoped to the wrong traffic type, or is being overridden somewhere else in the configuration file.
One commonly missed scenario involves TLS inspection. Many transparent proxy deployments apply header suppression rules only to plaintext HTTP traffic on port 80. If your proxy decrypts and re-encrypts HTTPS traffic for inspection purposes, confirm that the same suppression rules apply to that decrypted stream. Testing only against port 80 targets can give you a false sense of completeness while HTTPS traffic continues leaking through.
Another thing worth checking is your internal proxy chain. If requests pass through more than one proxy hop before reaching the egress point, the suppression rules need to be applied at the final outbound proxy, not just at internal intermediaries. Internal hops can add headers that then travel through an unconfigured egress proxy without being stripped.
Put the header inspection test into your regular maintenance cycle. Proxy software upgrades can reset directive defaults, introduce new headers, or change how existing directives interact with new configuration options. A test that passed six months ago may fail after a version bump that nobody explicitly flagged as a header-handling change.
Closing the Gap Between What Your Proxy Does and What You Intended
HTTP header leakage does not announce itself. There are no error messages. No alerts. No log entries flagging the problem. Sensitive metadata flows outward silently with every request your employees generate, and it keeps flowing until someone explicitly configures the proxy to stop it.
That is the central frustration with this class of problem. The defaults were never designed with external exposure in mind. They were designed for operational convenience inside a trusted environment. When that environment has an outward-facing egress point, those operational defaults become an information disclosure risk.
The good news is that the fix is entirely within your control. A targeted inspection tells you exactly what is leaking. A handful of specific directives in Squid or nginx stops it. A verification test confirms the fix held. The whole process, from baseline to confirmed remediation, can be completed in an afternoon. The harder part was always knowing the problem existed. Now you do.