我对Netfilter的FILTER表有一些规则,阻止对某些网站的HTTPS访问:
-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
youtube.com
所有规则都工作得很好,除了最后一条规则 (YouTube),它在通过 Google Chrome请求时不起作用。我尝试使用其他 Web 浏览器,例如 Mozilla Firefox 和 Microsoft Edge,对于这些 Web 浏览器,该规则非常有效。
我不是 HTTP/HTTPS 协议方面的专家,关于标头、数据包和来自 Web 服务器的确切信息,但我的猜测是,当 YouTube 服务器回复来自 Google 的请求 (SYN-ACK) 时Chrome 用户代理(数据包附带的信息)不包含任何有关“youtube.com”的字符串,在这种情况下可能会有其他修改,以提高 Google Chrome(YouTube + Google)的性能谷歌产品。
我尝试更改算法,从bm
(Boyer-Moore)更改为kmp
(Knuth-Pratt-Morris),但没有用。
我的问题是:
- 有没有IP表阻止通过 Google Chrome 对“youtube”的请求而不阻止 IP 的规则?
答案1
鉴于这些评论,您似乎意识到 netfilter 是完成这项工作的错误工具,因此我不会在这里重申这一点。
这里到底发生了什么?
Google Chrome 不使用 TLS 服务器名称指示 (SNI) 扩展,因此它发送的数据包均不符合您指定的规则,因为它们不包含未加密的目标主机的名称,并且您的路由器无法读取加密流量,除非您将其设置为透明代理并对通过它建立的每个 HTTPS 连接执行中间人攻击。
TLS SNI 是常规 TLS 协议的扩展,用于加密 HTTPS 连接,用于指定系统尝试连接到的主机。特别是,这部分 TLS 握手是未加密发送的,因为用于加密连接的 TLS 证书的选择取决于客户端尝试访问的主机。从表面上看,这一切听起来毫无意义,除非您考虑可能通过同一 IP 地址为数百或数千个主机名提供服务的 Web 托管站点。
HTTP 实际上也为此目的指定了(至少在版本 1.1 和 2.0 中)请求标头,但由于该标头是在 TLS 握手完成后发送的,因此无法用于确定用于连接的 TLS 证书,因此,只有当所有托管站点都在同一域下并且连接使用该域的通配符证书时,这才是一个选项。
从实际角度来看,通常不需要 TLS SNI,因为人们经常访问的大多数网站(包括您试图阻止的网站)要么是单独托管的,要么是使用 HTTP 标头和通配符证书,而且事实上还有一些罕见的网站站点根本不支持它(如果客户端尝试使用它,在这种情况下握手可能会失败)。此外,如果用户在本地获取 DNS 信息,则 TLS SNI 会出现信息泄漏,因为查看他们尝试访问的服务是微不足道的。
因此,Google Chrome(以及 Chromium 和大多数其他衍生产品)将首先尝试在不使用 SNI 的情况下进行连接(这对大多数人来说大部分时间都有效),并且只有在不使用 SNI 进行连接时才会回退到使用 SNI失败。大多数其他浏览器采用更自由(且安全性较低且更容易审查)的方法,首先与 SNI 连接,然后在失败时尝试不使用 SNI(大多数人通常不会这么做)。
修复它的最佳方法是什么?
首先,考虑不这样做。尝试严格执行这样的策略通常会适得其反,并且在功能上是不可能的,除非您达到仅允许明确批准的服务(而不是阻止明确不允许的服务)的相当严格的级别,因为人们仍然可以使用 VPN 连接或代理来访问它们(并且您无法阻止所有 VPN 和代理方法)。
如果您特别坚持要实际停止此操作,请更改规则以在 UDP 端口 53 上匹配。这将防止域的任何未封装的 DNS 流量穿过您的路由器(请注意,是可以加密和混淆 DNS 流量,并且如果不进行深度数据包检查和阻止许多其他事情,您就无法轻松地对此做任何事情)。确保规则对称(也就是说,不仅阻止出站流量,还阻止入站流量),因为这将阻止此类事情的一些解决方法正常运行。