0

I have some rules on the FILTER table of Netfilter, which block HTTPS access to some websites:

-A FORWARD -s 10.255.255.0/26 -p tcp -m tcp --dport 443 -m string --string "facebook.com" --algo bm -j DROP
-A FORWARD -s 10.255.255.0/26 -p tcp -m tcp --dport 443 -m string --string "instagram.com" --algo bm -j DROP
-A FORWARD -s 10.255.255.0/26 -p tcp -m tcp --dport 443 -m string --string "snapchat.com" --algo bm -j DROP
-A FORWARD -s 10.255.255.0/26 -p tcp -m tcp --dport 443 -m string --string "tumblr.com" --algo bm -j DROP
-A FORWARD -s 10.255.255.0/26 -p tcp -m tcp --dport 443 -m string --string "twitter.com" --algo bm -j DROP
-A FORWARD -s 10.255.255.0/26 -p tcp -m tcp --dport 443 -m string --string "youtube.com" --algo bm -j DROP

All rules work pretty fine, with the exception of the last rule (YouTube), that does not work when requesting youtube.com via Google Chrome. I tried to use other Web Browsers like Mozilla Firefox and Microsoft Edge, and for these Web Browsers, the rule works perfectly.

I'm not an expert on HTTP/HTTPS protocol, regarding headers, packets and the exact information that comes from a Web Server, but my guess, is that when the YouTube servers reply to a request (SYN-ACK) that comes from Google Chrome User-Agent, the information that comes with the packets, does not contain any string regarding "youtube.com" and maybe there could be other modifications in that case, in order to improve the performance of Google Chrome (YouTube + Google) regarding Google products.

I tried to change the algorithm, from bm (Boyer-Moore) to kmp (Knuth-Pratt-Morris), but no use.

My question is:

  • Is there any IPTABLES rule for blocking requests for "youtube" via Google Chrome, without blocking IPs?
  • 1
    Netfilter/iptables is simply the wrong tool for the job. Beyond that, you're dropping (all) outgoing packets that contain the string "youtube.com". This doesn't include encrypted packets, and potentially includes things that aren't connections to that domain. Use the right tool for the job. Use DNS – Fox Feb 2 '18 at 18:17
  • Your statement is correct and I'm truly thinking about this possibility, but I really would like to understand the issue. Although there are some problems regarding these rules, I'd like to understand why they do not work when requests are performed via Google Chrome, for example. Anyway, thanks for the insight :). – ivanleoncz Feb 2 '18 at 18:44
  • 1
    You might have a look at traffic on port 53 instead. I don't know what DNS traffic looks like, but you might have some luck there – Fox Feb 2 '18 at 20:06
  • Sounds a good track to follow. At least, interesting... I'll research about it and let your know here. Thanks :). – ivanleoncz Feb 2 '18 at 20:11
4

Given the comments, you appear to realize that netfilter is the wrong tool for the job, so I won't reiterate that here.

What's actually going on here?

Google Chrome isn't using the TLS Server Name Indication (SNI) extension, so none of the packets it's sending are being matched by the rules you specified since they don't contain the name of the destination host unencrypted, and your router cannot read encrypted traffic unless you set it up as a transparent proxy and performs a man-in-the-middle attack on every single HTTPS connection made through it.

TLS SNI is an extension to the regular TLS protocol used to encrypt HTTPS connections used to specify what host the system is trying to connect to. In particular, this part of the TLS handshake is sent unencrypted, because the choice of TLS certificate used to encrypt the connection is dependent on the host the client is trying to access. On the face of it, this all sounds kind of pointless, until you consider web hosting sites which may serve hundreds or thousands of hostnames through the same IP address.

HTTP actually specifies (at least in versions 1.1 and 2.0) a request header for this purpose as well, but because that gets sent after the TLS handshake is finished, it can't be used to determine what TLS certificate to use for the connection, and therefore is only an option if all the hosted sites are under the same domain and the connection uses a wildcard certificate for that domain.

From a practical perspective, TLS SNI is usually not needed, simply because most of the sites people visit regularly (including those you are trying to block) are either singly hosted, or use the HTTP header and a wildcard certificate, and in fact some rare sites don't support it at all (and the handshake can fail in that case if the client tries to use it). Additionally, TLS SNI presents an information leak if the user is obtaining DNS information locally, as it is trivial to see what service they are trying to access.

As a result of this, Google Chrome (and Chromium and most of its other derivatives) will first try to connect without using SNI (which will work most of the time for most people), and only falls back to using SNI if connecting without it fails. Most other browsers take the more liberal (and less secure and easier to censor) approach of connecting with SNI first, and then trying without SNI if that fails (which it usually won't form most people).

What's the best way to fix it?

First, simply consider not doing this. Trying to rigidly enforce policies like this will usually backfire, and is functionally impossible unless you go to the rather draconian level of only allowing explicitly approved services (instead of blocking explicitly disallowed services), because people can still get to them using VPN connections or proxies (and you can't block every VPN and proxy method).

If you are particularly insistent on actually stopping this, change the rules to match on UDP port 53. This will prevent any unencapsulated DNS traffic for the domains from crossing your router (note that it is possible to encrypt and obfuscate DNS traffic, and you can't easily do anything about that without doing deep packet inspection and blocking a lot of other things). Make sure to also make the rules symmetrical (that is, don't just block outbound traffic, but inbound too), as that will prevent a handful of workarounds for this kind of thing from functioning properly.

  • 1
    Very complete. I was not aware about TLS-SNI, at all. I guess that setting up a BIND and doing some blackholes for such domains, could be more efficient, although verifying/filtering UDP traffic for port 53 could be something interesting, obviously, considering the aspects that you pointed. Thanks, Austin :). Well pointed about the "draconian level", but regarding students that are going to classes and their missions are to study and not messing around, this might an option as well (I'm still inclined to deploying a DNS server). – ivanleoncz Feb 2 '18 at 20:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.