How do Virtual Hosts and TLS work together? - ssl

As I understand it Virtual Hosts work in HTTP servers by receiving a HTTP request from the client and examining the Host header, which contains service1.example.com or service2.example.com, etc. and then forwarding the request based on some rules in the HTTP server configuration.
But as I understand it TLS works as follows:
Client opens connection to server.
Client and server have a handshake where the client checks the server's certificate is valid for the name the client is trying to access.
Client transmits the request.
Server transmits the response.
These two seem like they would be incompatible, the server doesn't know which TLS certificate to present to the client until after the request has been sent, but the client won't send the request until the handshake is completed.
They clearly aren't incompatible, I have run web servers with multiple separate TLS virtual hosts each with completely separate certificates. Where have I gone wrong here?

Related

DNS a-route with SSL and Apache

I have a domain served at server A and I have set up an A-record to server B.
For http://mypage.com all works fine.
But there is also SSL on the domain. On server B there are a few virtual hosts set up. One of which has an SSL virtual host (443), theirpage.com. If I now go to https://mypage.com I end up at theirpage.com.
If I set up mypage.com MUST I have the SSL certificate from server A available for this new specific ssl-virualhost? The provider at server A does not share their ssl-certificates...
Assuming:
Server A - DNS only, no web services.
Server B - Web server.
The following is extreme oversimplification of what actually happens. For simplicity we exclude all caches, networking and application complexity.
What happens on the client:
User navigates to mypage.com (HTTPS)
Browser/OS does a lookup of who mypage.com is; receives the IP
Browser attempts to establish secure connection with IP of a webserver.
It is at this point browser will look at the SSL certificate provided by your web server. That certificate must be signed by trusted authority and have a valid alternate name of mypage.com. Not signed or name does not match to what user typed into the browser you will receive a certificate error.
If the certificate passed:
Browser will complete establishing connection
Browser will request a content named mypage.com
Browser displays content revived from the web server
In this scenario only web server must have a valid certificate, prooving to the client that it is indeed the server client attempts to connect to.
HTTP Scenario is similar, but connection is not secured and site will load. Most of the websites setup redirect request on HTTP calls, forcing the user's browser repeat it's request via HTTPS protocol.

IIS 7 Non SSL site loading certificate of another site's

I have a IIS 7 server hosting a few different sites. Recently I purchased and installed a SSL certificate to one of the site. Both http and https binding are setup with host header xxx.com and www.xxx.com.
But now i discover that other site with no SSL is loading the certificate and show the untrusted cert error when accessing through https.
Can i know how I can stop other non SSL site from loading the certificate?
Thank you.
I assume that
you are using the server on a single IP address
provide service for multiple names on this single IP address
have configured SSL for some of the names but not for others
This means, that
The server is listening on this specific IP address for SSL connections.
The server can only decide after receiving the initial SSL request from the client (ClientHello) which certificate it should use. The Client hash to use SNI (server name indication) to tell the server which hostname it expects. Most newer clients support this but for example IE8/XP does not.
Since the server has to listen for SSL connections on this IP address it can happen, that it receives a SSL request for a hostname, where it has not certificate configured. In this cases a server could do the following:
Use some other certificate it has configured. This is what your server is doing. This results in an error on the client about an invalid certificate since the name in the certificate does not match the expected name.
Simply close the connection or issue some SSL error. This would result in an SSL handshake error on the client which browsers usually display in a way so that end users are not able to understand what's going on. For the browser the situation is simply a server error and the server is not able to give the browser more detailed information (this is not part of the SSL protocol).
If you don't like any of these two problems you must serve the non-SSL hosts from a different IP address than the SSL hosts, so that the server will not even listen on the SSL port for connections for the non-SSL hosts.
I hope this explanation helps with your problem. If you have now specific questions about the configuration of the server to achieve the outlined solution you should ask them at serverfault.com instead.

How to make Socks request over http proxy?

I have built an application called Tun2Socks GUI. It's program to make Socks proxy o be transparent.
Usually it use SSH port forward or TOR as SOCKS service, but I want it can use HTTP proxy too. So I build SOCKS5 proxy my self that connect to that HTTP proxy. It's working good with capturing HTTP request from client to be sent to HTTP Proxy.
The problem when the client send SSL request, I cannot capture the request to be forwarded. How the best method to make SSL request from SOCKS proxy through HTTP Proxy?
Schema of request transportation like here :
Client SSL request > SOCKS Proxy > HTTP Proxy > Internet
Thanks
When a client intentionally wants to establish an SSL session with a target server through a proxy, it does not establish an SSL session with the proxy itself. The client first tells the proxy to establish a connection to the target server, and THEN the client initiates an SSL session with the target server. In that situation, it is not possible for the proxy to sniff the traffic as it is encrypted, nor should it be trying to. A proxy is just a pass-through, it exchanges raw data back and forth between client and server as needed. The proxy should not care what kind of requests the client is sending, since the client tells the proxy where to connect.
If you have injected your proxy in between the client and server in such a way that the client has no knowledge that your proxy exists, the client will not know that it needs to adjust its requests to make them proxy-friendly. The client will be connected to your proxy but it will think it is connected to the target server, and thus will initiate an SSL handshake that your proxy will have to respond to. Only then will your proxy have access to the client's request data (provided the handshake is successful, such as if the client does not verify peer certificates), and can then tunnel the unencrypted data to the next proxy as needed.
Update: I just thought of another scenario that should work for both cleartext and SSL connections. Regardless of whether you are transparently redirecting the client's outbound connection to your SOCKS proxy without the client knowing about it, or the client intentionally connects to the SOCKS proxy and tells it where to go, the SOCKS proxy knows the client's target host/IP:port. The SOCKS proxy can either connect directly to the target, or it can connect to the HTTP proxy and ask it to create a tunnel to the target via the HTTP CONNECT method. If successful, the client has a viable connection to the target, and any data the client sends, SSL or otherwise, will flow as-is to the target, and vice versa. Neither the SOCKS proxy nor the HTTP proxy needs to know anything about the client's request other than the target host/IP:port. That is in the initial SOCKS request, either captured from the intercepted TCP header, or explicit from the client.

https requests using a proxy

Let's say you want to perform an https request to a certain website but you have a proxy on the middle.
The aforesaid proxy doesn't look into the request but just relay all the traffic to the actual HTTPS server after the user-agent has used the HTTP CONNECT method (as in http://www.web-cache.com/Writings/Internet-Drafts/draft-luotonen-web-proxy-tunneling-01.txt).
Now my question is the following: after the proxy opens a SSL connection to the destination webserver, should it also upgrade the socket which handles the connection with the client to SSL as well? And if so, how would it forward packets to the server without sniffing the actual content?
What I mean here is that if the proxy actually reads data from SSL client socket and forwards them to SSL server socket, the data will be not encrypted to it.
The proxy has a plaintext connection open to the client, via which it received the CONNECT command. It opens a plaintext connection to the server. Thereafter it just copies bytes in both directions. The bytes coming from both client and server are SSL, so this works without the proxy knowing what's inside the ciphertext.

CONNECT request to a forward HTTP proxy over an SSL connection?

I am writing an HTTP proxy and I am having trouble understanding some details of making a CONNECT request over TLS. To get a better picture, I am experimenting with Apache to observe how it interacts with clients. This is from my default virtual host.
NameVirtualHost *:443
<VirtualHost>
ServerName example.com
DocumentRoot htdocs/example.com
ProxyRequests On
AllowConnect 22
SSLEngine on
SSLCertificateFile /root/ssl/example.com-startssl.pem
SSLCertificateKeyFile /root/ssl/example.com-startssl.key
SSLCertificateChainFile /root/ssl/sub.class1.server.ca.pem
SSLStrictSNIVHostCheck off
</VirtualHost>
The conversation between Apache and my client goes like this.
a. client connects to example.com:443 and sends example.com in the TLS handshake.
b. client sends HTTP request.
CONNECT 192.168.1.1:22 HTTP/1.1
Host: example.com
Proxy-Connection: Keep-Alive
c. Apache says HTTP/1.1 400 Bad Request. The Apache error log says
Hostname example.com provided via SNI and hostname 192.168.1.1
provided via HTTP are different.
It appears that Apache does not look at the Host header other than to see that it is there since HTTP/1.1 requires it. I get identical failed behavior if the client sends Host: foo. If I make the HTTP request to example.com:80 without TLS, then Apache will connect me to 192.168.1.1:22.
I don't completely understand this behavior. Is there something wrong with the CONNECT request? I can't seem to locate the relevant parts of the RFCs that explain all this.
It's not clear whether you're trying to use Apache Httpd as a proxy server, this would explain the 400 status code you're getting.
CONNECT is used by the client, and sent to the proxy server (possibly Apache Httpd, but usually not), not to the destination web server.
CONNECT is used between the client and the proxy server before establishing the TLS connection between the client and the end server. The client (C) connects to the proxy (P) proxy.example.com and sends this request (including blank line):
C->P: CONNECT www.example.com:443 HTTP/1.1
C->P: Host: www.example.com:443
C->P:
The proxy opens a TCP connection to www.example.com:443 (P-S) and responds to the client with a 200 status code, accepting the request:
P->C: 200 OK
P->C:
After this, the connection between the client and the proxy (C-P) is kept open. The proxy server relays everything on the C-P connection to and from P-S. The client upgrades its active (P-S) connection to an SSL/TLS connection, by initiating a TLS handshake on that channel. Since everything is now relayed to the server, it's as if the TLS exchange was done directly with www.example.com:443.
The proxy doesn't play any role in the handshake (and thus with SNI). The TLS handshake effectively happens directly between the client and the end server.
If you're writing a proxy server, all you need to do for allowing your clients to connect to HTTPS servers is read in the CONNECT request, make a connection from the proxy to the end server (given in the CONNECT request), send the client with a 200 OK reply and then forward everything that you read from the client to the server, and vice versa.
RFC 2616 treats CONNECT as a a way to establish a simple tunnel (which it is). There is more about it in RFC 2817, although the rest of RFC 2817 (upgrades to TLS within a non-proxy HTTP connection) is rarely used.
It looks like what you're trying to do is to have the connection between the client (C) and the proxy (P) over TLS. That's fine, but the client won't use CONNECT to connect to external web servers (unless it's a connection to an HTTPS server too).
You're doing everything right. It's Apache that got things wrong. Support for CONNECT over TLS was only added recently (https://issues.apache.org/bugzilla/show_bug.cgi?id=29744) and there's still some things to be ironed out. The issue you're hitting is one of them.
From RFC 2616 (section 14.23):
The Host request-header field specifies the Internet host and port
number of the resource being requested, as obtained from the original
URI given by the user or referring resource (generally an HTTP URL,
as described in section 3.2.2). The Host field value MUST represent
the naming authority of the origin server or gateway given by the
original URL.
My understanding is that you need to copy the address from CONNECT line to HOST line. All in all, the address of the resource is 192.168.1.1, and the fact that you are connecting via example.com doesn't change anything from RFC point of view.
It is quite seldom to see CONNECT Method inside TLS (https). I actually don't know any client who does that (and I would be interested to know who it does, cause I think it is actually a good feature).
Normally the client connects with http (plain tcp) to the proxy and sends the CONNECT method (and host header) to host:443. Then the proxy will make a transparent connection to the endpoint and then the client sends the SSL handshake through.
In this scenario the data is ssl protected "end to end".
The CONNECT method is not really specified, it is only reserved in the HTTP RFC. But typically it is quite simple so it is interoperable. The Method specifies host[:port]. Host: header can simply be ignored. Some additional proxy authentication headers might be needed. When the body of the connection begins no parsing has to happen by the proxy anymore (some do, because they check for valid SSL handshake).