c# proxy, generating certificate for https traffic?

1.5k views Asked by At

I'm trying to get this code running with https: http://www.codeproject.com/Articles/93301/Implementing-a-Multithreaded-HTTP-HTTPS-Debugging

It says on the bottom of the page that I need to make a new certificate with a private key to get this running with https using makecert.exe. This is the command author used:

makecert.exe cert.cer -a sha1 -n "CN=matt-dot-net" -sr LocalMachine -ss My -sky signature -pe -len 2048

I ran the same command, just changed CN to my hostname and replaced the certificate. Now when I access https site, I get a warning in firefox (same as when using fiddler):

This Connection is Untrusted. I understand the risks -> add exception

and then I get this error:

The site attempts to identify itself with invalid information. Wrong site: Certificate belongs to a different site, which could indicate an identity theft. Certificate is not trusted, because it hasn't been verified by a recognized authority.

Then I click [Confirm Security Exception] and everything seems to work.

How do I remove the "Wrong site certificate" error? Did I generate the certificate incorrectly? as far as I understood in the makecert.exe example on the site, private key is not included? Thanks!

3

There are 3 answers

3
Daniel Powell On

I would assume your self-signed certificate is the one being used for the site and because its a self signed certificate it isnt trusted, you would need to purchase one from VeriSign or the like to have the message go away.

4
500 - Internal Server Error On

Make the certificate name the same as your host name, i.e. "stackoverflow" for stackoverflow.com.

0
Bruno On

Firstly, you could generate self-signed certificate (with CA basic constraints) for your application (you could have your application generate it automatically) and import that certificate into your browser as a trusted CA.

Then, you could generate a new certificate on the fly depending on the requested host name, issued by your CA (i.e. signed using its private key and with the CA's Subject DN as the new certificate's Issuer DN). There are details about generating certificates in C# in this question: Is it possible to programmatically generate an X509 certificate using only C#?

This certificate must follow the specifications of the HTTP over TLS specification:

If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used. Although the use of the Common Name is existing practice, it is deprecated and Certification Authorities are encouraged to use the dNSName instead.

[...]

In some cases, the URI is specified as an IP address rather than a hostname. In this case, the iPAddress subjectAltName must be present in the certificate and must exactly match the IP in the URI.

In short, if what's requested is just a host name, you should be fine with simply a CN=hostname RDN in the Subject DN (although a Subject Alt Name would be better), but if it's an IP address, you should put an IP addr Subject Alternative Name entry (although some browsers will let you get away with the IP address in the CN RDN in practice).

If you want a proxy that captures the TCP packets, without server name indication, you may actually find it very hard to find which actual host name is requested. I would suggest doing a reverse DNS lookup for the IP address (which you should be able to find) and putting a DNS Subject Alt Name entry for each reverse DNS entry, as well as an IP Subject Alt Name entry for the IP address. This should cover most cases, except those where the client uses a host name for which the IP address doesn't have a reverse DNS entry. Failing that, you'll just have to add the exception by hand in your browser (which is fine since you'll know that you're intercepting your own communication) or set it up by hand within your proxy.

Finding the host name is easier with an HTTP proxy configured in the browser, since you don't need to guess the host name, it will be passed to the CONNECT HTTP verb.

(Of course, to begin with, for a specific host, you can generate the certificate with makecert rather than doing it on the fly.)