In short, domain fronting leverages how SSL/TLS works with content delivery networks (CDNs) to "hide" the true destination of traffic under HTTPS. This is a gross oversimplification, but hopefully it will become clearer as we discuss it.
Before we talk in more detail about domain fronting, we should make sure that we are all on the same page with some of the underlying concepts. First, let's talk about how a normal HTTPS connection works when you type https://anawesomesite.com/ into your browser.
First, your system needs to resolve the address you typed in (anawesomesite.com) to an IP. It does this through Domain Name Services (DNS). The first place your system looks is in your hosts file. Your hosts file is a static mapping of hostnames to IP addresses. anawesomesite.com is probably not in your hosts file, so your system checks your local DNS cache to see if anawesomesite.com is there. The DNS cache is a dynamic map of hostnames to IPs that you have received from an upstream DNS server (like the one on your router or at your ISP). How long your system holds onto records in the cache (or if it caches at all) depends on your operating system. If the site is not in your cache, your system will ask its configured DNS server for the IP. If your local DNS server (likely your router) does not know, it asks its configured DNS server until someone finds an answer (if there is an answer).
Because the site we want to go to is https, our browser knows it needs to negotiate a secure connection. Your browser will send a client HELLO message to the server at anawesomesite.com that outlines some connection parameters like what ciphers it supports, what domain it is trying to connect to, some key generation material, among others
The server responds with its own key generation material, its public key, and the strongest cipher that both the server and client support, among other things. The client checks the domain name in the response with the one it asked for. If they match, the connection is set up. If they do not match, you will get a warning about an invalid certificate (specifically that the host name you expected did not match what the server gave you). An extension to TLS called Server Name Indication (SNI) was a solution to the problem of a single server hosting multiple secure domains. When your browser asks for a site, it will put that site in the client HELLO message, as in this screen shot:
Now, we can talk about domain fronting. Domain fronting works by modifying the specified host at each layer that we talked about. Normally, the three requests (DNS, SNI server name, and inner Host Header) will share the same host name. The DNS request and Client HELLO are sent in the clear. The inner HTTP traffic is sent through the encrypted tunnel. In domain fronting, the DNS request and SNI name will typically be the same (and of a site that does not raise suspicion) while the inner host header will have a server with a different name (like the name you want to go to that is not allowed). The outside addresses will typically be those of a CDN that would have a large number of domains behind it (such as s3.amazonaws.com) and the host address would be a small "reflector" hosted on that CDN.
The reflector would be a small application that forwards traffic in the HTTP request to wherever it needs to go and forwards the responses to the client through the HTTPS tunnel. A transport called meek is one implementation of domain fronting. The client would run a meek client, and the reflector hosted on the CDN would run the meek server (which handles the traffic as we talked about above). Given how inexpensive some of these CDNs are (a few cents a GB), this could be an effective way to pass a large amount of traffic through.
While this has uses in evading censorship, it also has implications in information security. If you wanted to evade traffic filtering, this could be an effective way of evading the filter because in theory, the filter would see the SSL traffic to an allowed host and let the traffic through. Many filters do not break the SSL underneath to see that the host header does not match and the traffic might look "funky."
Can we do anything from a defensive perspective with regards to domain fronting?It would probably not work to filter the CDNs where domain fronting works. Popular domains like Microsoft Azure, Amazon AWS, and Google work with this technique. If you block those domains, your users might be upset and you might not be able to get any work done if your business uses any resources hosted by those CDNs.
Because domain fronting assumes that the network is not monitoring HTTPS traffic, a defender would have to employ proper egress filtering (filtering of traffic leaving the network). This includes forcing all outgoing traffic through a proxy, and essentially performing SSL man-in-the-middle on your users at that proxy. That involves decrypting the client's traffic to a server, examining it, re-encrypting the traffic that is allowed out, and sending it to the destination. When the destination sends its response, the proxy would have to do the reverse (serve as the man in the middle of the connection). On the client side, it would have to trust the proxy's certificate. You could push this through Group Policy on Windows machines.
On your proxy, you could check that the three indicators above (DNS request, SNI server name, and HTTP Host Header) all match. It would be tough to block all of the reflectors, because they are easy and cheap to stand up. It would be very tough to keep up with them. You could also look inside the HTTP traffic and see if it is looks legitimate. Often times, there will be encrypted or encoded traffic sent via the reflector which will not look like HTTP. You could train your proxy to key in to that traffic or at least alert on it so your network defenders can take a look at it.
What do you think about domain fronting? Can you think of any other defenses against it? I would appreciate your thoughts. Thanks for reading!