The company I work for sometimes intercepts employees ssl connections to https websites by making the ssl connection on their behalf from a proxy, and then using the own generated certificate to send the page to the user. Obviously this only works because they installed their own root certificate on the employees PCs but you can tell when you go to a https website and look at the certificate and find that it's signed by [company] and not by one of the usual CAs/

Now I don't intend to get into the morality or legality of this practice here even though I have opinions on it :P

My question is, is there any way to detect that this is happening from the webserver and refuse to deliver the page if it's being intercepted like this?

I was thinking that maybe some javscript on the webpage could find out which certificate the page was signed with and issue a warning if it was wrong - but there doesn't seem to be any way I can find to check the certificate from javascript. (I realise that if the company could modify the certificate they could modify the javascript too, but I'm assuming they wouldn't write custom code for each website)...

Is there any other trick I can use to do this?

  • Good question! Obviously the actual SSL connection without client authentication does not differ from actual browsers - but perhaps somebody comes up with a funky trick that would catch most of the cases somehow...
    – Nakedible
    Jul 30, 2011 at 8:13

5 Answers 5


If I understand the question correctly you are asking if it's possible to detect (on the server end of a HTTPS-connection) whether the connection is coming from a proxy-server or an actual client (a browser)?

(I initially failed to see how the certificate would provide any valuable information, but realize now what I missed before. What was suggested is to provide the user with a javascript, trigger it through the HTML-code and have the user send back the extracted data from the SSL-certificate as it would be the certificate provided by the proxy. Yeah, that should work and it seems somewhat unlikely that the proxy-server would filter such "actions" from the javascript. Clever suggestion!)

Analyzing the following may help discover the originator of a connection:

  • HTTP-header ordering
  • Non-browser specific HTTP-headers
  • HTTP-cookie values
  • HTTP behavior

HTTP-header ordering - Detecting the originator of the connection should theoretically be possible by analyzing the order of HTTP headers. Browsers tend to structure their HTTP-headers in specific "patterns", utilizing this knowledge it may be possible to:

  1. Create a unique fingerprint for the proxy by determining how the proxy arranges HTTP-headers.
  2. By "in-advance" knowing how common browsers order their HTTP-headers and compare this to the ordering of the current request. (Clearly not the greatest idea...)

Non-browser specific HTTP-headers - It may be possible that the proxy-server includes specific HTTP-headers that a browser wouldn't. These might be for load-balancing, or request type redirections and so forth.

HTTP-cookie values - It's also concievable that the proxy would insert a specific cookie value to drect a connection to a specific server if load-balancing or clustering is used.

HTTP behavior - While not exactly easy to implement it may be possible to detect the presence of a proxy by initiate a number of HTTP-specific return codes and analyze how the "client" responds to the requests. Perhaps this may allow for the detection of an unusual behavior that would be considered uncommon for regular browsers.

Assuming an Apache HTTP-server it may be possible to use mod_security rules to achieve some of the above.

Some other, probably unlikely and unreliable, ways of detecting the origin of a connection would be to inspect protocol specific (IP/TCP) fields such as time stamps, IP-options. These may change in particular ways assuming a proxy-server origin.

It may also be possible to determine origin based on timings despite that they would be subjected to quite a bit of jitter and noise, it theoretically could be determined if a proxy intercepts the connection. I'm not suggesting this would at all be reliable or even possible, but quite a bit can be determined through timings.

  • If the proxy simply forwards (and maybe logs) the connection from the browser, I see no reason that the HTTP header and such would be different. Jul 30, 2011 at 17:30
  • Since it's an SSL-connection I doubt (although I can't substantiate my thought) that the proxy-server would simply forward the connection attempt. A new SSL-connection would be negotiated with the remote server, and I would argue it's more likely that the proxy-server would differ from the browser in regards to HTTP-header ordering. Unless of course the proxy-server copies all headers from the browser, and settle for only negotiating the SSL-connection. Jul 30, 2011 at 21:48
  • 2
    Okay, we should say it so: If the proxy wants to hide itself from the real server, it certainly can do so. The SSL connection is on a lower level than the HTTP requests/responses which are transported over it - each can be independently modified or not. Jul 30, 2011 at 22:07
  • 2
    "provide the user with a javascript [...] and have [it] send back the extracted data from the SSL-certificate" - Unfortunately, as far as I know, there is no way for Javascript running on the browser to find out what server certificate was used on the current connection. Therefore, this doesn't work.
    – D.W.
    Aug 1, 2011 at 3:46
  • This could detect the presence of a proxy, but can it really tell whether the proxy is doing MITM with a custom root certificate installed on the client machine? I know my proxy at work does not do that.
    – Ajedi32
    Jan 5, 2015 at 22:27

The only way I can see is to open a XMLHTTPRequest over SSL and pull the certificate out of that connection:

This doesn't work from a web-page, but is required to be run from an extension.

As already pointed out the proxy can easily change the javascript to kill this.

  • I didn't know you could get the certificate parameters from XMLHTTPRequest. I believe this is what the original poster wanted.
    – Nakedible
    Jul 30, 2011 at 11:24
  • This looks very interesting, so +1, however it looks like it's mozilla only as far as I can tell
    – JohnB
    Jul 30, 2011 at 13:39
  • 5
    Does this actually work for ordinary web pages? Have you tried it? The web page you link to says "This code requires elevated privileges to run; you can only call it from a browser extension [..]", which seems to suggest an ordinary web page cannot use this.
    – D.W.
    Aug 1, 2011 at 3:44
  • You are right, not pretty, the question is why can't you get this information from an ordinary webpage? It's not like it's that sensitive, unless it exposes the private keys, in which case, still, why not just not expose the private keys?
    – ewanm89
    Aug 1, 2011 at 20:39
  • @ewanm89 Probably because it would break the abstraction. Web pages generally shouldn't need to know what protocol was used to deliver them, or any details about stuff such as what security certificate that protocol was using at the time.
    – Ajedi32
    Jan 5, 2015 at 22:29

If the server uses certificate-based client authentication (i.e. the client also has a certificate and uses his private key to authenticate itself), then the server will detect the interceptor -- because in that case the client signs a hash value computed over the previously received handshake messages, which include the server certificate as seen by the client. In the presence of the interceptor, the client signs the wrong value, and the interceptor cannot correct that.

An alternate solution is to use TLS with SRP, in which authentication is not certificate-based but password-based and mutual.

Otherwise, no.

  • Mutual authentication is the only sure way, but there tends to need some user interaction for it to work.
    – ewanm89
    Aug 1, 2011 at 20:41

By convention, a standard proxy should include the X-Forwarded-For HTTP request header, even though it's not in the RFC it is considered defacto standard.

That said, if the proxy wants to hide it's existance, there is no problem to simply ignore putting this header in.


These answer are a bit dated, and the following recent developments should be of relevance:


A Pin is a relationship between a hostname and a cryptographic identity (in this document, 1 or more of the public keys in a chain of X.509 certificates). Pin Validation is the process a UA performs to ensure that a host is in fact authenticated with its previously- established Pin.

Key pinning is a trust-on-first-use (TOFU) mechanism. The first time a UA connects to a host, it lacks the information necessary to
perform Pin Validation; UAs can only apply their normal cryptographic identity validation. (In this document, it is assumed that UAs apply X.509 certificate chain validation in accord with [RFC5280].)

The UA will not be able to detect and thwart a MITM attacking the
UA's first connection to the host. (However, the requirement that
the MITM provide an X.509 certificate chain that can pass the UA's
validation requirements, without error, mitigates this risk
somewhat.) Worse, such a MITM can inject its own PKP header into the HTTP stream, and pin the UA to its own keys. To avoid post facto
detection, the attacker would have to be in a position to intercept
all future requests to the host from that UA.

Thus, key pinning as described in this document is not a perfect
defense against MITM attackers capable of passing certificate chain
validation procedures -- nothing short of pre-shared keys can be.
However, it provides significant value by allowing host operators to
limit the number of certification authorities than can vouch for the host's identity, and allows UAs to detect in-process MITM attacks
after the initial communication.


2.1.4. The report-uri Directive

The OPTIONAL report-uri directive indicates the URI to which the UA SHOULD report Pin Validation failures (Section 2.6). The UA POSTs
the reports to the given URI as described in Section 3.

In addition to being standardized, I believe it is currently supported by at least Chrome and Firefox, but would have to check.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .