Waujito/youtubeUnblock
GitHub: Waujito/youtubeUnblock
通过伪造 SNI 和数据包分片技术绕过基于 SNI 的 YouTube 检测系统,支持路由器和 Linux 主机部署。
Stars: 1450 | Forks: 125
- [youtubeUnblock](#youtubeunblock)
- [配置](#configuration)
- [OpenWRT 预配置](#openwrt-pre-configuration)
- [Entware](#entware)
- [PC 配置](#pc-configuration)
- [防火墙配置](#firewall-configuration)
- [nftables 规则](#nftables-rules)
- [Iptables 规则](#iptables-rules)
- [IPv6](#ipv6)
- [检查](#check-it)
- [参数标志](#flags)
- [UDP/QUIC](#udpquic)
- [Cloudflare](#cloudflare)
- [故障排除](#troubleshooting)
- [电视 (TV)](#tv)
- [EPERMS 故障排除(操作不允许)](#troubleshooting-eperms-operation-not-permitted)
- [Conntrack](#conntrack-troubleshooting)
- [NAT 硬件/软件卸载](#nat-hardwaresoftware-offloading)
- [编译](#compilation)
- [OpenWRT 案例](#openwrt-case)
- [构建 OpenWRT .ipk 包](#building-openwrt-ipk-package)
- [使用工具链构建](#building-with-toolchain)
- [内核模块](#kernel-module)
- [构建内核模块](#building-kernel-module)
- [在宿主系统上构建](#building-on-host-system)
- [在任意内核上构建](#building-on-any-kernel)
- [使用 openwrt SDK 构建](#building-with-openwrt-sdk)
- [Padavan](#padavan)
# youtubeUnblock
绕过基于 SNI 的 YouTube 检测系统。
该程序主要是为了绕过俄罗斯境内的 YouTube 封锁而开发的。
该程序应**仅用于 YouTube 平台**。由于在俄罗斯**并未官方限制访问 YouTube**,因此使用它是合法的。您**不得**将该程序用于任何其他目的。我尊重所有俄罗斯法律,并不希望违反任何法律。
从最初为我的笔记本电脑加速 YouTube 开始,这个项目发展成了一个独立的工具,可以在各种设备上解除对 YouTube 的封锁。这个项目实现了我创建一个大规模、高可靠性、开源 GitHub 项目以帮助他人的梦想。我重视所有的反馈,这也是我继续维护它的原因。在开发过程中,我学到了很多东西,例如 Linux 内核网络栈的各个方面。在为人们开发项目的同时探索新技术,这种体验是无可比拟的,远非做一个普通的个人项目所能及。
**因此,请仅将其用于 YouTube,并仅遵守您所在国家的法律。**
如果您有任何问题、建议或疑问,请随时开启一个 [issue](https://github.com/Waujito/youtubeUnblock/issues)。
也欢迎您通过我的 GitHub 个人资料描述中提供的链接直接联系我;但是,请仅在有特殊提议时联系我。如需有关程序的帮助,最好通过在 [GitHub Discussions](https://github.com/Waujito/youtubeUnblock/discussions) 上发帖让我们的对话公开。
该程序在 GNU GPL v3 开源许可证下分发。
```
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
```
该程序仅适用于 Linux。它也完全兼容运行 [OpenWRT](https://github.com/openwrt) 的路由器。
该程序分两个版本发布:
- 一个用户空间应用程序,运行在 nfnetlink queue 之上,需要内核中有 nfnetlink 模块和防火墙规则。这种方式是默认的,通常应该被使用,但在可能不支持 nfnetlink 的嵌入式设备上有一些限制。此外,由于每个数据包都需要在用户空间和内核空间之间跳转,这种解决方案可能会降低互联网速度并增加设备的 CPU 负载(这种行为可以通过 connbytes 修复,但也需要 conntrack 内核模块)。
- 一个内核模块,深度集成在 netfilter 栈中,不与用户空间防火墙交互。该模块只需要 netfilter 内核支持,而这在每个连接到互联网的设备上肯定都存在。唯一的困难是如何构建它。我无法通过 Github Actions 为每一个内核版本提供模块,即使我们只讨论 OpenWRT 版本。如果您想了解更多关于该模块的信息,请跳转到 [README 中的相关部分](#kernel-module)。内核模块有什么好处?好处体现在某些特定情况下:内核模块是最快的,它允许我们处理发送到 linux 网络栈的每一个数据包,而普通的 youtubeUnblock 需要 connbytes 来保持网速。说到 connbytes,它也需要 conntrack 才能运行,这在某些传输流量的机器上可能是一个限制。此外,用户空间 youtubeUnblock 需要 netlink queue 模块、用户空间防火墙应用程序及其模块。内核模块要简单得多,只需要内置 netfilter 的 linux 内核。
该程序兼容基于 OpenWRT、Entware(Keenetic/ASUS) 的路由器和主机。该程序通过 Github Actions 提供二进制文件。这些二进制文件也可以通过 [github releases](https://github.com/Waujito/youtubeUnblock/releases) 获取。请使用最新的预发布版本以获得最新的构建。如果您想查看所有曾编译过的二进制文件,请查看 [Github Actions](https://github.com/Waujito/youtubeUnblock/actions/workflows/build-ci.yml)。您应该了解您的硬件架构才能使用二进制文件。在 OpenWRT 上,您可以使用命令 `grep ARCH /etc/openwrt_release` 进行检查。
在 OpenWRT 和 Entware 上,使用 opkg 安装程序。如果遇到只读文件系统错误,您可以手动解压二进制文件或指定 opkg 路径 `opkg -o `。
## 配置
### OpenWRT 预配置
当您获得发布包后,应该安装它。进入路由器界面,*System->Software*(系统->软件),执行 *Update lists*(更新列表),然后通过 *install_package*(安装包)按钮安装 youtubeUnblock。然后,您应该进入 *System-Startup*(系统-启动项)菜单并重新加载防火墙(您也可以在 *Services->youtubeUnblock* 菜单中执行此操作)。
由于 OpenWRT **main** 分支已切换到 apk 而不是 opkg,但这尚未发布,因此**Releases** 中没有针对 apk 的部署。但在 PR #196 中**支持 apk**。
要使其工作,您应该注册一个 iptables 规则并安装所需的内核模块。模块列表取决于 OpenWRT 的版本以及您使用的防火墙(iptables 或 nftables)。对于大多数现代版本的 OpenWRT(v23.x, v22.x),您应该使用 nftables 规则,对于旧版本则取决于情况,但通常是 iptables。
常见的依赖是
```
kmod-nfnetlink-queue
```
但它是作为另一个防火墙包的依赖项提供的。
因此,如果您使用的是 **iptables**,您应该安装:
```
kmod-ipt-nfqueue
iptables-mod-nfqueue
kmod-ipt-conntrack-extra
iptables-mod-conntrack-extra
```
当然,iptables 用户空间应用程序应该可用。
在 **nftables** 上,依赖项是:
```
kmod-nft-queue
kmod-nf-conntrack
```
下一步是添加所需的防火墙规则。
对于 OpenWRT 上的 nftables,规则是开箱即用的,存储在 `/usr/share/nftables.d/ruleset-post/537-youtubeUnblock.nft` 下。您只需要安装需求并执行 `/etc/init.d/firewall reload`。如果不行,请转到 [防火墙配置](#firewall-configuration)。
现在我们进入配置。对于 OpenWRT,这里有通过 [UCI](https://openwrt.org/docs/guide-user/base-system/uci) 和 [LuCI](https://openwrt.org/docs/guide-user/luci/start) 可用的配置(分别是 CLI 和 GUI)。
对于 **LuCI**(也就是 **GUI** 或**路由器 web 界面**),您应该像安装普通的 youtubeUnblock 软件包一样安装 **luci-app-youtubeUnblock** 软件包。请注意,官方 opkg 源的列表应该被加载(**通过 Update lists 选项完成**)。
如果您遇到 ` * pkg_hash_check_unresolved: cannot find dependency luci-lua-runtime for luci-app-youtubeUnblock` 错误,说明您使用的是旧版 openwrt。请安装 [这个虚拟包](https://github.com/xiaorouji/openwrt-passwall/files/12605732/luci-lua-runtime_all_fake.zip)。查看 [此评论](https://github.com/Waujito/youtubeUnblock/issues/168#issuecomment-2449227547) 了解更多详情。
LuCI 配置位于 **Services->youtubeUnblock** 部分。它是自描述的,每个标志都有描述。请注意,当您按下 `Save & Apply`(保存并应用)按钮后,配置会自动应用,服务也会重启。
UCI 配置在 /etc/config/youtubeUnblock 文件的 `youtubeUnblock.youtubeUnblock` 部分中可用。您可以将任何参数作为字符串传递给参数 `args`,但在此之前请禁用交互式标志(您可以用它进行配置,但这比较困难,我建议仅与 `luci-app-youtubeUnblock` 一起使用):
```
uci set youtubeUnblock.youtubeUnblock.conf_strat="args"
uci set youtubeUnblock.youtubeUnblock.args="--queue-num=537 --threads=1"
```
要保存配置,您应该执行 `uci commit`,然后执行 `reload_config` 以重启 youtubeUnblock。
您可以在 CLI 模式下使用 `logread -l 200 | grep youtubeUnblock` 命令查看日志。
在 CLI 模式下,您将把 youtubeUnblock 作为一个普通的 init.d 服务使用:
例如,您可以通过 `/etc/init.d/youtubeUnblock enable` 启用它。
### Entware
对于 Keenetic 上的 Entware,这里有一份 [安装指南 (俄语)](https://help.keenetic.com/hc/ru/articles/360021214160-%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B-%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BE%D0%B2-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D1%8F-Entware-%D0%BD%D0%B0-USB-%D0%BD%D0%B0%D0%BA%D0%BE%D0%BF%D0%B8%D1%82%D0%B5%D0%BB%D1%8C)。
使用 `opkg install youtubeUnblock-*.ipk` 安装二进制文件。安装后,`/opt/bin` 中的二进制文件和 `/opt/etc/init.d/S51youtubeUnblock` 中的启动脚本将可用。要运行 youtubeUnblock,只需运行 `/opt/etc/init.d/S51youtubeUnblock start`。
### NFNETLINK_QUEUE 内核模块
请注意,您应该为目标内核加载 nfnetlink_queue 内核模块。该模块可能被禁用甚至不存在。Entware 的 S51youtubeUnblock 会尝试以任何方式插入 kmods,但如果软件未提供它们,您应该手动安装。据我所知,在 keenetics 上有一个由客户编译的模块仓库。您可以在设备的 web 界面某处找到它们。在其他路由器上,您可能需要在这种情况下进行更深入的研究并找到您的 kmods。如果找不到任何东西,您可以向客户索取 linux 内核(甚至可能是 OpenWRT)的 GPL 代码并手动编译 kmods。
您应该使用以下命令插入模块(在 Entware 和 OpenWRT 上可能会省略此步骤):
```
modprobe nfnetlink_queue
```
### PC 配置
在本地主机上,确保在以下防火墙规则集中将 **FORWARD** 更改为 **OUTPUT** 链。
将 `youtubeUnblock.service` 复制到 `/usr/lib/systemd/system`(您应该将文件内的路径更改为程序位置,例如 `/usr/bin/youtubeUnblock`,您也可能希望删除 systemd 文件中的默认 iptables 规则添加以便手动控制)。然后运行 `systemctl start youtubeUnblock`。
### 防火墙配置
#### nftables 规则
在 nftables 上,您应该放置以下 nftables 规则:
```
nft add chain inet fw4 youtubeUnblock '{ type filter hook postrouting priority mangle - 1; policy accept; }'
nft add rule inet fw4 youtubeUnblock 'tcp dport 443 ct original packets < 20 counter queue num 537 bypass'
nft add rule inet fw4 youtubeUnblock 'meta l4proto udp ct original packets < 9 counter queue num 537 bypass'
nft insert rule inet fw4 output 'mark and 0x8000 == 0x8000 counter accept'
```
#### Iptables 规则
在 iptables 上,您应该放置以下 iptables 规则:
```
iptables -t mangle -N YOUTUBEUNBLOCK
iptables -t mangle -A YOUTUBEUNBLOCK -p tcp --dport 443 -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:19 -j NFQUEUE --queue-num 537 --queue-bypass
iptables -t mangle -A YOUTUBEUNBLOCK -p udp -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:8 -j NFQUEUE --queue-num 537 --queue-bypass
iptables -t mangle -A POSTROUTING -j YOUTUBEUNBLOCK
iptables -I OUTPUT -m mark --mark 32768/32768 -j ACCEPT
```
#### IPv6
对于 iptables 上的 IPv6,您需要为 ip6tables 复制上述规则:
```
ip6tables -t mangle -N YOUTUBEUNBLOCK
ip6tables -t mangle -A YOUTUBEUNBLOCK -p tcp --dport 443 -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:19 -j NFQUEUE --queue-num 537 --queue-bypass
ip6tables -t mangle -A YOUTUBEUNBLOCK -p udp -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:8 -j NFQUEUE --queue-num 537 --queue-bypass
ip6tables -t mangle -A POSTROUTING -j YOUTUBEUNBLOCK
ip6tables -I OUTPUT -m mark --mark 32768/32768 -j ACCEPT
```
请注意,上述规则使用 *conntrack* 仅将连接的前 20 个数据包路由到 **youtubeUnblock**。
如果您遇到麻烦,例如 **youtubeUnblock** 未检测到 YouTube,请尝试从规则中删除 *connbytes*。但这是一种不太可能发生的行为,您应该检查您的规则集。
您可以将 `--queue-balance` 与多个 **youtubeUnblock** 实例一起使用以提高性能。这种行为通过多线程支持。只需传递 `--threads=n`,其中 n 代表您希望启用的线程数。n 默认为 **1**。最大线程数默认为 **16**,但可以通过编程方式更改。请注意,如果您打算增加它,那么有 100% 的可能性您走错了路。
此外,为了额外的匿名性,首选 [DNS over HTTPS](https://github.com/curl/curl/wiki/DNS-over-HTTPS)。
## 检查
这里是测试它是否工作的命令:
```
curl -o/dev/null -k --connect-to ::google.com -k -L -H Host:\ mirror.gcr.io https://test.googlevideo.com/v2/cimg/android/blobs/sha256:6fd8bdac3da660bde7bd0b6f2b6a46e1b686afb74b9a4614def32532b73f5eaa
```
如果没有 **youtubeUnblock**,它应该返回低速,有了它则更快。有了 **youtubeUnblock**,速度应该与以下命令的速度一样快:
```
curl -o/dev/null -k --connect-to ::google.com -k -L -H Host:\ mirror.gcr.io https://mirror.gcr.io/v2/cimg/android/blobs/sha256:6fd8bdac3da660bde7bd0b6f2b6a46e1b686afb74b9a4614def32532b73f5eaa
```
对于 ECH 检查,这变得更加复杂,因为它仍然是 CURL 中的实验性功能。如果您想测试它,首先,您应该编译带有 ECH 支持的 curl。您可以遵循 [本指南](https://github.com/curl/curl/blob/master/docs/ECH.md)。接下来,您可以使用以下命令检查它
```
LD_LIBRARY_PATH=$HOME/code/openssl $HOME/code/curl/src/curl --ech hard --doh-url https://one.one.one.one/dns-query https://www.opengl.org --ipv4
```
## 参数标志
将标志放在 **BINARY**(二进制文件)中,而不是 init 脚本中。如果您在 OpenWRT 上,您应该将标志放在脚本中:使用任何文本编辑器(如 vi 或 nano)打开 `/etc/init.d/youtubeUnblock`,并将您的标志放在 `procd_set_param command /usr/bin/youtubeUnblock` 行之后。
可用标志:
#### 通用标志
不局限于特定部分的标志,用于整个 youtubeUnblock
- `--queue-num=` **youtubeUnblock** 将链接到的 netfilter queue 编号。默认为 **537**。
- `--silent` 禁用详细模式。
- `--trace` 用于调试目的的最大详细程度。
- `--instaflush` 与跟踪一起使用。立即刷新缓冲区,不等待显式的换行符。对于调试崩溃非常有用。
- `--no-gso` 禁用对使用 GSO 的 TCP 包的支持。此功能现在已经过充分测试,因此此标志可能无法修复任何问题。
- `--use-conntrack` 在 youtubeUnblock 中启用对 conntrack 的支持。默认禁用。在内核模块中启用。
- `--no-ipv6` 禁用对 ipv6 的支持。如果您不想打开 ipv6 套接字,这可能很有用。
- `--threads=` 指定您希望为程序运行的线程数量。这默认为 **1**,正常使用不应编辑。但是,如果您真的想要多个 youtubeUnblock 队列实例,请注意您应该将 --queue-num 更改为 --queue balance。例如,使用 4 个线程时,在 iptables 上使用 `--queue-balance 537:540`,在 nftables 上使用 `queue num 537-540`。
- `--connbytes-limit=` **仅限内核模块!** 指定 kyoutubeUnblock 应处理连接的多少个数据包。如果您希望处理每个数据包,请传递 0。此标志对于 UDP 流量可能很有用,因为无限的 youtubeUnblock 可能导致流量泛洪和意外的封禁。默认为 19。在大多数情况下,您不想更改它。
- `--daemonize` 将 youtubeUnblock 守护进程化(forks 并将其从 shell 中分离)。使用 `killall youtubeUnblock` 终止程序。如果您想在 logread 或 journalctl 中跟踪 youtubeUnblock 的日志,请使用 **--syslog** 标志。
- `--syslog` 将日志重定向到系统日志。您可以使用 `journalctl` 或 `logread` 读取它。
- `--noclose` 仅与 `--daemonize` 一起使用。不会将 io 流重定向到 /dev/null。
- `--packet-mark=` 如果 youtubeUnblock 与其他依赖数据包标记的系统冲突,请使用此选项。请注意,您可能希望更改 iptables 的接受规则以跟随该标记。
#### 部分范围标志
- `--fbegin` 和 `--fend` 标志:youtubeUnblock 支持针对特定过滤器的多组策略。您可能希望在默认策略之后启动一组新策略,例如:`--sni-domains=googlevideo.com --faking-strategy=md5sum --fbegin --sni-domains=youtube.com --faking-strategy=tcp_check --fbegin --sni-domains=l.google.com --faking-strategy=pastseq`。请注意,这些组的优先级是倒序的:最后一个是第一,默认(不以 --fbegin 开头的那个)是最后。如果您开始新的部分,将实施默认设置,就像没有任何参数的 youtubeUnblock 一样。请注意,上面的配置只是一个示例,对您不起作用。
- `--tls={enabled|disabled}` 如果您不想在当前部分处理 TLS 流量,请设置它。如果您只想设置基于 UDP 的部分,可以使用它。(这里的部分是 `--fbegin` 和 `--fend` 标志之间的单元)。
- `--tcp-dport-filter=<5,6,200-500>` 过滤 TCP 目标端口。默认为无端口。指定您希望由 youtubeUnblock 处理的端口。默认情况下,youtubeUnblock 将仅过滤 443 TLS 端口。这可以通过 `--no-dport-filter` 禁用。
- `--tcp-match-connpackets` 在设置 `--use-conntrack` 的情况下使用。不是通过 TLS 域匹配,而是通过 OS conntrack connpackets 变量(例如,连接存活期间发送的数据包数量,SYN 包含在 connpackets 计数器中,但无论如何都会被 youtubeUnblock 跳过)匹配数据包。您不应设置太高的匹配数量。我建议像 4 或 5 这样的数字。如果发生匹配,youtubeUnblock 将根据分段和伪造设置发送伪造数据并分片数据包。
- `--tcp-match-all` 匹配 youtubeUnblock 捕获的每个数据包。更严格的规则可以通过 tcp-dport-filter 应用。
- `--fake-sni={0|1}` 此标志启用 fake-sni,它强制 **youtubeUnblock** 发送至少三个数据包而不是一个带有 TLS *ClientHello* 的数据包:Fake *ClientHello*,原始 *ClientHello* 的第一部分,原始 *ClientHello* 的第二部分。此标志可能与某些操作不允许错误消息有关,因此在提出问题之前,请参阅 [EPERMS 故障排除](#troubleshooting-eperms-operation-not-permitted)。默认为 **1**。
- `--fake-sni-seq-len=` 此标志指定 **youtubeUnblock** 构建复杂的伪造 client hello 数据包结构。length 决定将发送多少伪造包。默认为 **1**。
- `--fake-sni-type={default|custom|random}` 此标志指定应用于伪造数据包的伪造消息类型。对于 `random`,将发送随机长度和随机负载的消息。对于 `default`,使用默认负载 (sni=www.google.com)。对于 `custom` 选项,利用来自 `--fake-custom-payload` 部分的负载。默认为 `default`。
- `--fake-custom-payload=` 与 `--fake-sni-type=custom` 一起使用。您应该手动指定伪造消息的负载。使用十六进制格式:`--fake-custom-payload=0001020304` 意味着 5 字节序列:`0x00`, `0x01`, `0x02`, `0x03`, `0x04` 用作伪造。
- `--fake-custom-payload-file=` 与 `--fake-custom-payload` 相同,但是是二进制文件而不是十六进制。文件应包含原始二进制 TLS 消息(TCP 负载)。
- `--faking-strategy={randseq|ttl|tcp_check|pastseq|md5sum|timestamp}` 此标志确定伪造数据包失效的策略。用户可以指定多个伪造选项,因此多种技术将应用于伪造数据包。默认为 `tcp_check,timestamp`。
- `randseq` 指定将设置随机序列/确认号。此选项可能被使用 *conntrack* 并在启用无效 *conntrack* 状态防火墙规则时丢弃的提供商处理。
- `ttl` 指定数据包将在 `--faking-ttl=n` 跳后失效。`ttl` 更好,但如果未配置可能会导致问题。
- `pastseq` 类似于 `randseq`,但序列号不是随机的,而是引用过去发送的数据包(当前之前)。
- `tcp_check` 将使用无效的校验和使伪造数据包失效。可能会被一些提供商/TSPU 处理并丢弃。
- `md5sum` 将使用无效的 TCP md5sum 使伪造数据包失效。md5sum 是一个 TCP 选项,由目标服务器处理,但可能被 TSPU 跳过。
- `timestamp` 利用 TCP Timestamp 选项。Timestamp TSVal 减少 `--faking-timestamp-decrease=n` 参数,因此它被服务器拒绝。
- `--faking-ttl=` 调整 fake SNI 消息的生存时间 (TTL)。指定 TTL 的方式是使数据包通过 DPI 系统并被其捕获,但不会到达目标服务器。默认为 **8**。
- `--fake-seq-offset` 调整伪造数据包相对于原始序列号的偏移量。由 randseq 伪造策略使用。默认为 10000。如果为 0,则设置随机序列号。
- `--faking-timestamp-decrease=` 将伪造数据包中 Timestamp 选项的 TSVal 参数减少此值。默认为 600000。根据在 zapret 项目中进行的研究,此参数可能在 100 到 0x80000000 之间工作。
- `--frag={tcp,ip,none}` 指定数据包的分段策略。默认使用 tcp。IP 分段可能被 DPI 系统阻止。None 指定无分段。这可能不起作用,但可能对某些 fake sni 策略有效。
- `--frag-sni-reverse={0|1}` 指定 **youtubeUnblock** 以相反的顺序发送 *ClientHello* 片段。默认为 **1**。
- `--frag-sni-faked={0|1}` 指定 **youtubeUnblock** 在 *ClientHello* 附近发送伪造数据包(用零填充负载)。默认为 **0**。
- `--frag-middle-sni={0|1}` 使用此选项,**youtubeUnblock** 将在 SNI 数据中间拆分数据包。默认为 1。
- `--frag-sni-pos=` 使用此选项,**youtubeUnblock** 将在位置 pos 处拆分数据包。默认为 1。
- `--frag-origin-retries=` 如果设置,youtubeUnblock 将向套接字发送 n + 1 个具有原始内容的数据包。不应用任何额外的分段。
- `--fk-winsize=` 指定分段 TCP 数据包的窗口大小。如果您希望响应被分段,则适用。可能会减慢连接初始化。
- `--synfake={1|0}` 如果为 1,将在每个请求之前发送 syn 负载。这个想法取自 zapret 项目的 syndata。Syn 负载通常会被端点丢弃,但可能会被 TSPU 处理。此选项在该负载中发送正常的伪造包。请注意,该选项适用于所有站点,因此 --sni-domains 不会改变任何东西。
- `--synfake-len=` 在 synfake 中发送的伪造数据包可能太大。如果您遇到问题,请降低 synfake-len。其中 len 代表作为 syndata 发送的字节数。如果您想发送整个伪造数据包,请传递 0。默认为 0
- `--sni-detection={parse|brute}` 指定如何检测 SNI。Parse 通常会通过解析 Client Hello 消息来检测它。Brute 将遍历整个消息并检查 SNI 出现的可能性。请注意,当 `--sni-domains` 选项不是 all 时,brute 将是 O(nm) 时间复杂度,其中 n 代表消息的长度,m 是域的数量。默认为 parse。
- `--seg2delay=` 此标志强制 **youtubeUnblock** 在发送拆分数据包的第二部分之前稍微等待一下。
- `--sni-domains=|all` 您希望通过 SNI 处理的域列表。如果您想更改默认域列表,请使用此字符串。默认为 `googlevideo.com,ggpht.com,ytimg.com,youtube.com,play.google.com,youtu.be,googleapis.com,googleusercontent.com,gstatic.com,l.google.com`。如果您希望处理每个 *ClientHello*,可以传递 **all**。您可以使用 `--exclude-domains` 标志排除某些域。
- `--exclude-domains=` 要从目标中排除的域列表。
- `--sni-domains-file=` 与 `--sni-domains` 相同,但接受容器文件的路径而不是内联域列表。文件格式可以包含逗号分隔的域列表以及换行分隔的列表。
- `--exclude-domains-file=` 与 `--exclude-domains` 相同,但接受容器文件的路径而不是内联域列表。文件格式可以包含逗号分隔的域列表以及换行分隔的列表。
- `--udp-mode={drop|fake}` 此标志指定 udp 处理策略。如果 drop,udp 数据包将被丢弃(当浏览器可以回退到 tcp 时对 quic 很有用),如果 fake,udp 将被伪造。默认为 fake。
- `--udp-fake-seq-len=` 指定将在网络上发送多少伪造数据包。默认为 6。
- `--udp-fake-len=` udp 伪造负载的大小(通常负载为零)。默认为 64。
- `--udp-dport-filter=<5,6,200-500>` 过滤 UDP 目标端口。默认为无端口。指定您希望由 youtubeUnblock 处理的端口。请注意,它可能与 `--quic-drop` 冲突,因为 `--quic-drop` 全局将 `--udp-mode` 设置为 drop。因此,请确保在不同的配置部分中处理它。
- `--udp-stun-filter` 过滤所有 UDP STUN 请求数据包。对语音聊天非常有用。请注意,它可能与 `--quic-drop` 冲突,因为 `--quic-drop` 全局将 `--udp-mode` 设置为 drop。因此,请确保在不同的配置部分中处理它。
- `--udp-faking-strategy={checksum|ttl|none}` udp 的伪造策略。`checksum` 将伪造 UDP 校验和,`ttl` 不会伪造但会使 UDP 内容相对较小,`none` 表示无伪造。默认为 none。
- `--udp-filter-quic={disabled|all|parse}` 为 UDP 处理程序启用 QUIC 过滤。如果 disabled,quic 将不会被处理,如果 all,将处理所有 quic 初始数据包。`parse` 将解密并解析 QUIC 初始消息,并将其与 `--sni-domains` 匹配。默认为 disabled。
- `--quic-drop` 丢弃所有发送到 youtubeUnblock 的 QUIC包。不会影响任何其他 UDP 数据包。只是 `--udp-filter-quic=all --udp-mode=drop` 的别名。请注意,由于 `--udp-mode=drop`,它可能与其他过滤选项冲突。确保使用多个部分。
- `--no-dport-filter` 默认情况下,youtubeUnblock 将过滤 TLS 和 QUIC 443。如果您想禁用它,请传递此标志。(这不会影响 `--udp-dport-filter`)
## UDP/QUIC
UDP 是另一种通信协议。使用它的知名技术包括 DNS、QUIC。UDP 不提供可靠的连接,其标头比 TCP 简单得多,因此分段受到限制。所提供的支持主要通过伪造实现。
**对于内核模块中的 UDP 伪造**,确保将 `--connbytes-limit` 减少到 5。这将允许不处理额外的数据包并防止网络泛洪。
目前,QUIC 伪造可能无法很好地工作,因此请使用 `--udp-mode=drop` 选项。
QUIC 通过 `--udp-filter-quic` 标志启用。该标志支持两种模式:`all` 将处理所有 QUIC 初始消息,而 `parse` 将解密并解析 QUIC 初始消息,然后将其与 `--sni-domains` 标志进行比较。
**我建议使用** `--udp-mode=drop --udp-filter-quic=parse`。
对于**其他 UDP 协议**,我建议在与 TCP 分开的部分中配置 UDP 支持,例如 `--fbegin --udp-dport-filter=50000-50099 --tls=disabled`。**除非您确定自己在做什么,否则不要在这里传递 `--quic-drop`**
## Cloudflare
在俄罗斯,Cloudflare 技术受到 RKN 的特别关注。
这主要是由 ECH 技术引起的,该技术允许轻松绕过 TSPU。RKN 阻止 ECH,但同时也阻止了许多无害的网络协议。目前,Cloudflare 网络上只允许 TLS(可能还有 HTTP)协议。如果 TSPU 无法确定协议和服务器名称(TLS 的 SNI),它将在传输 16 KB 后断开连接。这不仅影响 443 或 80 端口,还影响 Cloudflare 网络上的每个端口。
因此,ECH 和大量协议不可用。大量的各种自定义服务器/实用程序/游戏都宕机了,因为自定义协议被阻止了。
例如:Hypixel Minecraft 服务器依赖 Cloudflare 并在端口 25565 上运行自定义 Minecraft 协议。TSPU 无法确定此协议,因此它在传输 16 KB 后阻止连接,因此服务器无法工作。
请注意,这里的伪造是绕过 TSPU 的关键。
解决方案示例:
```
sudo ./build/youtubeUnblock --use-conntrack --tls=disabled --tcp-match-connpackets=4 --tcp-dport-filter=25565 --frag-sni-pos=1 --fake-sni=1 --faking-strategy=tcp_check,timestamp
```
也不要忘记在自定义端口上添加 iptables 规则:
```
sudo iptables -t mangle -A YOUTUBEUNBLOCK -p tcp --dport 25565 -m connbytes --connbytes-dir original --connbytes-mode packets --connbytes 0:19 -j NFQUEUE --queue-num 537 --queue-bypass
```
## 故障排除
查看 [此 issue](https://github.com/Waujito/youtubeUnblock/issues/148) 以获取有用的配置。
如果您在某些网站上遇到麻烦,并且您确定它们被 SNI 阻止(例如 youtube),您可以尝试调整 [flags](#flags) 及其组合。首先建议尝试 `--faking-strategy` 标志和 `--frag-sni-faked=1`。
如果您在某些被代理的网站上遇到麻烦,您可以调整标志值。例如,对于某些人来说,`--faking-strategy=ttl` 有效。您应该指定适当的 `--fake-sni-ttl=`,其中 ttl 是您和 DPI 之间的跳数。
如果您使用的是 Chromium,您可能需要禁用 *kyber*(使 TLS *ClientHello* 非常大的功能)。我在路由器上遇到了它的问题,为了避免可能的错误,最好禁用它:在 `chrome://flags` 中搜索 kyber 并将其切换为禁用状态。或者您可以设置 `--sni-detection=brute` 并可能调整 `--sni-domains` 标志。
Firefox 上的 *Kyber* 通过 `about:config` 中的 `security.tls.enable_kyber` 禁用。
如果您的浏览器使用 QUIC,它可能无法正常工作。在 Chrome 的 `chrome://flags` 和 Firefox 的 `about:config` 中的 `network.http.http{2,3}.enable(d)` 选项中禁用它。
似乎有些 TSPU 开始阻止 wrongseq 数据包,因此您应该尝试各种伪造策略。我个人建议从 `md5sum` 伪造策略开始。
#### 带有 `--sni-domains=all` 的 youtube
我知道这个问题,但这**基本上不是 youtubeUnblock 的问题**。问题在于很长的 `*.googlevideo.com` 域名。您只需要为仅 youtube 创建一个新的配置部分。它应该在所有域的部分之后。对于纯字符串参数,只需在参数列表末尾加上 `--fbegin` 即可。在 luci 中,您可以交互式地创建部分。
### 电视
电视是最令人头疼的问题。
在 [此 issue](https://github.com/Waujito/youtubeUnblock/issues/59) 中,问题已得到解决。现在 youtubeUnblock 应该可以使用默认标志工作。如果不行,请尝试各种伪造策略和其他标志。此外,您可能需要禁用 QUIC。为此,您可以使用带有适当防火墙配置的 `--quic-drop` [flag](#flags)(查看标志的描述)。请注意,此标志不会禁用 gQUIC,某些电视可能依赖它。要禁用 gQUIC,您需要在防火墙配置中阻止整个 443 端口的 udp:
对于 **nftables**,执行
```
nft insert rule inet fw4 forward ip saddr 192.168.. udp dport 443 counter drop
```
对于 **iptables**
```
iptables -I FORWARD --src 192.168.. -p udp --dport 443 -j DROP
```
其中您必须将 192.168.. 替换为您电视的 ip。
### EPERMS 故障排除(操作不允许)
*EPERM* 可能出现在很多地方,但通常有两个:*mnl_cb_run* 和通过 *rawsocket* 发送数据包时(raw_frags_send 和 send fake sni)。
- **mnl_cb_run** *Operation not permitted* 表示建立 netfilter queue 时出现问题。这可能是由于多种原因发生的,但最常见的两种是:nfqueue 内核模块问题和另一个 youtubeUnblock 实例使用相同的队列号运行。对于第一个问题,请检查内核模块是否已安装并正在运行。在 OpenWRT 上,您可能忘记了安装必要的依赖项 [#openwrt-pre-configuration](#openwrt-pre-configuration)。对于第二个问题,请使用命令 `ps -e | grep youtubeUnblock` 检查正在运行的 youtubeUnblock 实例。如果发现任何实例,可以使用命令 `killall youtubeUnblock` 终止它们。
- **rawsocket** *Operation not permitted* 表示数据包被 netfilter 规则丢弃。实际上,这是来自内核的提示,表明出现了问题,我们应该检查防火墙规则。在深入问题之前,让我们先弄清楚被修改的数据包是如何发送的。Netfilter queue 为我们提供了动态修改数据包的能力,但这并不适合本程序,因为我们需要将数据包拆分为至少两个独立的数据包。所以我们使用 [linux raw sockets](https://man7.org/linux/man-pages/man7/raw.7.html),它允许我们发送任何 ipv4 数据包。**即使 FORWARD 上设置了 NFQUEUE(适用于 OpenWRT),数据包也会从 OUTPUT 链发出。** 所以我们需要在这里避免数据包拒绝。
* raw_frags_send EPERM:只需确保允许传出流量(RELATED,ESTABLISHED 应该可以,如果不行,请转到第 3 步)
* send fake sni EPERM:Fake SNI 是一种超出状态的东西,可能会破坏连接(该行为是预期的)。conntrack 将其视为无效数据包。默认情况下,OpenWRT 设置为丢弃此类传出数据包。您可以删除丢弃具有无效 conntrack 状态的数据包的 nftables/iptables 规则,但我不建议这样做。第 3 步是更好的解决方案。
* 第 3 步,终极解决方案。使用 mark(不要与 connmark 混淆)。youtubeUnblock 在内部使用标记来避免无限数据包循环(当数据包由 youtubeUnblock 发送但在下一步由其自身处理时)。目前它使用标记 (1 << 15) = 32768。您应该在 filter OUTPUT 链的最开始放置最终接受此类标记的 iptables/nftables:`iptables -I OUTPUT -m mark --mark 32768/32768 -j ACCEPT` 或 `nft insert rule inet fw4 output mark and 0x8000 == 0x8000 counter accept`。
### Conntrack 故障排除
youtubeUnblock *可选地* 依赖于 conntrack。
对于内核模块,如果 conntrack 破坏了依赖关系,请使用 `make kmake EXTRA_CFLAGS="-DNO_CONNTRACK"` 编译它以完全禁用它。
如果您希望在 conntrack 损坏的自定义栈中使用 connbytes,请查看 #220 和 #213 以获取可能的参考。
### NAT 硬件/软件卸载
youtubeUnblock 将与卸载冲突。但希望 youtubeUnblock 只需要处理连接中的前几个数据包。因此,在某些设备上确实可以将 youtubeUnblock 与卸载一起使用,尤其是在由 nftables 驱动的设备上(OpenWRT 23+)。请注意,这未经我测试,但用户 [报告为一种变通方法](https://github.com/Waujito/youtubeUnblock/issues/199#issuecomment-2519418553):
编辑 `/usr/share/firewall4/templates/ruleset.uc`,将
```
meta l4proto { tcp, udp } flow offload @ft;
```
替换为
```
meta l4proto { tcp, udp } ct original packets ge 30 flow offload @ft;
```
并使用 `service firewall restart` 重启防火墙。
## 编译
在编译之前,请确保已安装 `gcc`, `make`, `autoconf`, `automake`, `pkg-config` 和 `libtool`。对于 Fedora,还应安装 `glibc-static`。
使用 `make` 编译。使用 `make install` 安装。该软件包包含 `libnetfilter_queue`, `libnfnetlink` 和 `libmnl` 作为静态依赖项。该软件包需要 `linux-headers` 和使用 netfilter nfqueue 支持构建的内核。
## OpenWRT 案例
该软件包也兼容路由器。路由器应由基于 linux 的系统(如 [OpenWRT](https://openwrt.org/))运行。
您可以在 OpenWRT 下使用两个选项进行构建:第一个 - 通过 SDK,这是首选方式;第二个 - 使用 OpenWRT 工具链手动交叉编译。
### 构建 OpenWRT .ipk 包
OpenWRT 为软件包构建提供了高级 SDK。
第一步是为您的特定平台下载或编译 OpenWRT SDK。SDK 可以根据 [本教程](https://openwrt.org/docs/guide-developer/toolchain/using_the_sdk) 进行编译。
除了 SDK 的原始源代码外,OpenWRT 还为您的路由器提供预编译的 SDK。您可以在路由器页面上找到它。例如,我有基于 ramips/mt76x8 的路由器,所以对我来说,sdk 位于 https://downloads.openwrt.org/releases/23.05.3/targets/ramips/mt76x8/ 并名为 `openwrt-sdk-23.05.3-ramips-mt76x8_gcc-12.3.0_musl.Linux-x86_64`。
您需要 [在您的系统上安装 sdk 需求](https://openwrt.org/docs/guide-developer/toolchain/install-buildsystem) 如果您遇到任何问题,请使用 docker ubuntu:24.04 镜像。确保是非 root 用户,因为某些 makesystem 会因此失败。接下来,解压 SDK 并 cd 进入其中。
执行
```
echo "src-git youtubeUnblock https://github.com/Waujito/youtubeUnblock.git;openwrt" >> feeds.conf
./scripts/feeds update youtubeUnblock
./scripts/feeds install -a -p youtubeUnblock
make package/youtubeUnblock/compile
```
现在包已构建,您可以将其导入路由器。在 `bin/packages//youtubeUnblock/youtubeUnblock-.ipk` 中找到它。
### 使用工具链构建
预编译的工具链位于 SDK 附近。例如,它名为 `openwrt-toolchain-23.05.3-ramips-mt76x8_gcc-12.3.0_musl.Linux-x86_64.tar.xz`。下载工具链后,将其解压到某处。现在我们准备好进行编译了。我的 cross gcc 要求我为它创建一个 staging dir 并将其作为环境变量传递。此外,您应该注意 toolsuite 软件包并用您的替换我的 make 命令。
```
STAGING_DIR=temp make CC=/usr/bin/mipsel-openwrt-linux-gcc LD=/usr/bin/mipsel-openwrt-linux-ld AR=/usr/bin/mipsel-openwrt-linux-ar OBJDUMP=/usr/bin/mipsel-openwrt-linux-objdump NM=/usr/bin/mipsel-openwrt-linux-nm STRIP=/usr/bin/mipsel-openwrt-linux-strip CROSS_COMPILE_PLATFORM=mipsel-buildroot-linux-gnu
```
看看 `CROSS_COMPILE_PLATFORM`,它是 autotools 要求的,但我认为它不是必需的。无论如何,我在这里放了 `mipsel-buildroot-linux-gnu`。对于您的路由器型号名称,[automake cross-compile 手册](https://www.gnu.org/software/automake/manual/html_node/Cross_002dCompilation.html) 可能会有所帮助。
编译完成后,二进制文件将位于 build 目录中。将其复制到您的路由器。请注意,可能需要 ssh 访问权限才能继续。*sshfs* 在我的型号上不起作用,所以我通过 *Software Upload Package* 页面将应用程序注入路由器。它给了我一个错误,但也给了一个 `/tmp/upload.ipk` 文件,我将其复制到根目录,`chmod +x` 它并运行。
## 内核模块
本节介绍 youtubeUnblock 的内核模块版本。内核模块作为普通模块在内核内运行,并集成在 netfilter 栈中,以无状态地修改通过 Internet 发送的数据包。
您可以使用其标志配置模块:
```
insmod kyoutubeUnblock.ko
echo "--fake_sni=1 --exclude_domains=.ru --quic_drop" | sudo tee /sys/module/kyoutubeUnblock/parameters/parameters
```
您也可以执行
```
cat /sys/module/kyoutubeUnblock/parameters/parameters
```
并检查所有配置的参数。
您可以使用以下命令检查 youtubeUnblock 的统计信息
```
sudo cat /proc/kyoutubeUnblock
```
### 构建内核模块
#### 在宿主系统上构建
要在宿主系统上构建内核模块,您应该安装 `linux-headers`,它将提供构建基本工具和 `gcc` 编译器套件。在宿主系统上,您可以使用以下命令构建模块
```
make kmake
```
#### 在任意内核上构建
要为外部内核构建模块,您应该在本地构建该内核并指向 make例如,使用 `KERNEL_BUILDER_MAKEDIR=~/linux` 标志进行 make:
```
make kmake KERNEL_BUILDER_MAKEDIR=~/linux
```
请注意,内核应该已经配置并构建。有关特定案例的更多信息,请参阅 linux 内核构建手册。
**如果您得到一个非常大的模块,您可以对其进行 strip 处理并显着减小其大小:**
```
strip --strip-debug kyoutubeUnblock.ko
```
#### 使用 openwrt SDK 构建
使用 openwrt SDK 构建并不是一件难事。您唯一需要做的就是获取 sdk。您可以通过查看当前使用的 openwrt 的架构和版本来找到它。您应该使用完全相同的 openwrt 版本,因为那里的内核经常变化。您可以通过两种方式找到 sdk:从他们的站点下载或使用 openwrt sdk docker 容器(推荐)。
如果您决定下载 tar 归档文件,请执行以下步骤:
对我来说,归档文件位于 https://downloads.openwrt.org/releases/23.05.3/targets/ramips/mt76x8/ 并名为 `openwrt-sdk-23.05.3-ramips-mt76x8_gcc-12.3.0_musl.Linux-x86_64`。您需要 [在您的系统上安装 sdk 需求](https://openwrt.org/docs/guide-developer/toolchain/install-buildsystem) 如果您遇到任何问题,请使用 docker ubuntu:24.04 镜像。确保是非 root 用户,因为某些 makesystem 会因此失败。接下来,解压 SDK 并 cd 进入其中。
或者您可以获取内置 sdk 的 docker 镜像:[https://hub.docker.com/u/openwrt/sdk](https://hub.docker.com/u/openwrt/sdk)。在我的例子中,镜像标签为 `ramips-mt76x8-23.05.3`。这里的一个好处是您不需要在 docker 容器内安装任何依赖项。此外,如果您不确定哪个标签对应您的设备,docker hub 有完美的标签搜索功能。
当您解压/安装 sdk 后,您就可以开始构建内核模块了。
执行
```
echo "src-git youtubeUnblock https://github.com/Waujito/youtubeUnblock.git;openwrt" >> feeds.conf
./scripts/feeds update youtubeUnblock
./scripts/feeds install -a -p youtubeUnblock
make defconfig
make package/kyoutubeUnblock/compile V=s
```
当命令完成时,模块就准备好了。使用 `find bin -name "kmod-youtubeUnblock*.ipk"` 找到它,复制到您的主机并通过 gui 软件界面安装到路由器。模块应立即启动。如果不行,请执行 `modprobe kyoutubeUnblock`。
## Padavan
YoutubeUnblock 也可以在 Padavan 上运行。[在此处查看手册 [俄语]](Padavan.md)
标签:DNS 反向解析, DNS解析, iptables, IPv6, Linux内核网络, NAT, nftables, OpenWRT, Padavan, PowerShell, QUIC, SNI绕过, YouTube解锁, 内核模块, 安全资源, 客户端加密, 嵌入式系统, 底层编程, 开源项目, 抗封锁工具, 流量混淆, 深度包检测, 网络安全, 网络安全, 网络安全分析, 网络审查规避, 网络工具, 网络流量劫持, 路由器插件, 透明代理, 防火墙配置, 隐私保护, 隐私保护