Zxilly
Try to be 1%
Zxilly's Blog

校园网路由器多设备伪装指北

请不要给 admin@learningman.top 发邮件,那个邮箱我一年检查一次的

因为近期的更新,此文章的内容已经部分失效,可以参照 https://sunbk201public.notion.site/sunbk201public/OpenWrt-f59ae1a76741486092c27bc24dbadc59 ,或者自行阅读源码

起因

因为工信部对大学生们的监督,国内的校园网有了一人一号的限制。在某些企业的变本加厉之下,甚至已经演变为了一设备一号。

但是我有一堆智能设备,没有一个网络环境无法使用。

调察

查了一些资料,加上自己的测试。基本可以确定我校所用的Dr.Com检测多设备的方式基本上就是检测 HTTP报文 里的 User-Agent 字段 。目前来说,现成的解决方案有Privoxy 或者由CHN-beta 开发的

但是以上都有一个缺点:他们只能处理从80端口发送的HTTP请求。无论是 Privoxyiptables 转发,还是 xmurp-ua 的挂载netfilter链,他们都没有考虑过对于HTTP 的识别,而是处理所有通过 80 端口的流量。

但是事实上,并不是所有的 HTTP 流量都是通过 80 端口发送的。比如手机 QQ 的图片传送,使用的是 HTTP 协议的同时,走的是 8080 端口。你可能会想,那我把那些端口也处理了不就好了吗?但是在非标端口上的行为并没有规定,这些端口上并不是只有 HTTP 流量。如果你把非 HTTP 的 TCP 流量转发到了代理服务器,结果就是这些连接都被阻断了(比如小爱同学)。

我曾经想过用一个叫做 sslh 的程序完成流量识别,作为代理服务器的前置代理,将识别出的 HTTP 流量转发到代理服务器。但是事实上这样效率很低,而且手动抓包,然后在防火墙里写上几十个端口,看起来也很蠢。

这样看来只有一个办法了——作为一个软件工程专业的学生,就应该自己写一个应用来处理这件事。

于是,就有了 UA2F

实验性项目
UA2F仍然是一个实验性项目,我不对此程序带来的可能的硬件损坏和人身伤害负责。

开源

技术细节

根据我日常生活的经验,学校使用的检测设备并不真正的去识别一个ua字符串,而是仅仅检测其中是否含有某个特定的子串。比如 Android 或者 iPhone 之类。所以我们只需要把所有的 UA 脱敏。在这里我选择将整个字符串全部替换成 F。

框架

我之所以没有使用 xmurp-ua 还有一个原因,这个程序在我的路由器上会随机引起内核挂起,只有强行重启路由器才能解决。这是因为这个程序是一个内核模块,他的任何错误都会连累到整个内核。

UA2F 解决了这个问题,因为它并不是一个内核模块。作为一个普普通通的用户程序,系统并不关心他的死活。

在防火墙中有一个 target 被称作 NFQUEUE,可以将防火墙接收到的包交由用户态程序进行处理。而它的参数 --queue-bypass,允许在用户态程序无响应时,直接放行所有的包。UA2F 使用这个来获取相应的包并进行处理。

当然这也是有代价的,在内核与用户态程序之间的通讯是需要时间和计算力的。我原本以为这会是一笔很大的开销,但是在实际的运行中看起来并没有那么糟糕。而且我相信,使用这种技术限制学生的上网行为的学校,大概也不会给校园网太高的带宽(逃)。

处理方式

在 TCP 连接建立起来以后,期望应该是第 1 个 TCP 报文中包含 HTTP 报文的首部。也就是说,我们只需要判断一个TCP包是否以 HTTP method 开头(如GETPOST),就可以得知这是不是一个 HTTP 报文。

事实上,这是一个极度简化的模型,有非常多的意外情况没有考虑到。但是他现在看起来工作良好。而且因为我们替换的是同等长度的字符串,所以服务端返回的 ACK 是可以接受的。这也就让我们可以不需要追踪整个连接来修改所有返回的 ACK。

当判断一个 TCP 包是一个 HTTP 报文以后,程序将会向下解析所有的头部字段,直到找到 UA 并替换为止。

修改后的包将会被放回防火墙队列中,继续进行原本应该进行的处理。

使用

写了一大堆东西,终于要讲到这个程序应该怎么用了。

首先,你要拥有一个你自己的路由器的编译环境。理论上 SDK 也是可以的。但是我推荐使用源码编译,这样可以免去很多无谓的小问题。

如果你已经把编译好的系统刷到你的路由器里了。你执行ua2f --version的时候,应该会看到版本号和编译配置,而不是 command not found

随后执行service ua2f start来将程序在后台启动。这个时候你应该可以通过路由器访问HTTP的网页,并且注意到自己的 User-Agent 已经被修改了。

推荐执行service ua2f enable来将ua2f设为开机启动。

这里提供一个查看自己UA的HTTP网址:http://ua.233996.xyz/

不是我搭的,不保证服务质量。但是就算想自己搭一个也非常简单。

大部分使用流量识别的校园网系统应该都是网页登录的(不排除特别惨的)。抓包写一个脚本,应该不会太难。

目前就我自己的使用体验来说,应该还算是比较稳定。之前只拦截 80 端口的时候,大概是半个小时登录一次。但是现在已经三个小时都没有再次登录过了。

额外规则

根据一些相关的论文,可以发现能够被检测到的流量特征并不只有 UA 这一项。事实上有很多流量特征,甚至是统计学上的方法,都可以发现路由器后的多设备。

下面这几条规则解决了 NTP,DNS 和 TTL 的问题,据说还能解决深信服的劫持问题。我向我们学校的网络中心咨询过,我们学校应该也是部署了深信服的设备的。但是我在实际中并没有见到被劫持的现象。
在实际使用中,我发现深信服防劫持依赖的字符串解析对性能的影响还是比较大的,是否使用自行斟酌。

其余规则期望的性能开销并不大,不会影响流量的转发。注意,其中的 ntp 规则,需要你在服务器本地有一个 ntp 服务器。而 DNS 规则也需要本地的Dnsmasq的相应配置。

不要照抄,至少先把路由器IP换成你自己的。

iptables -t nat -N ntp_force_local
iptables -t nat -I PREROUTING -p udp --dport 123 -j ntp_force_local
iptables -t nat -A ntp_force_local -d 0.0.0.0/8 -j RETURN
iptables -t nat -A ntp_force_local -d 127.0.0.0/8 -j RETURN
iptables -t nat -A ntp_force_local -d 192.168.0.0/16 -j RETURN
iptables -t nat -A ntp_force_local -s 192.168.0.0/16 -j DNAT --to-destination 192.168.3.1

iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53
iptables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53

iptables -t mangle -A PREROUTING -j TTL --ttl-set 64
# iptables -I FORWARD -p tcp --sport 80 --tcp-flags ACK ACK -m string --algo bm --string " src=\"http://1.1.1." -j DROP

你可以在上文提到过的 CHN-Beta 的 Github 中找到一个修改 IPID 的软件包 rpk-ipid

缺点

这个程序有很多缺点。

之于xmurp-uaUA2F最大的改进就是它是一个用户态程序,可以方便的完成灾难恢复。

但是具体的灾难恢复机制呢?没写。

这个程序是一个单进程,单线程程序,所以期望性能非常非常低,路由器的羸弱性能更是雪上加霜。

非常理想化的 HTTP 检测机制。

这个程序是照着样例代码写的,我甚至没有完整地理解整个处理流程,应该有一些处理是不必要的。

结尾

在这里我想再一次感谢校园网,如果不是校园网,我可能不会有机会如此抓狂的去读一些底层的代码。

感谢 libmnllibnetfilter-quene 的开发者们,感谢 openwrt 社区,顺便 %Linus 。是他们慷慨地开放出这些源码,才让我们这些普通人有了能够进行这些操作的能力。

Zxilly

文章作者

回复 corpa 取消回复

textsms
account_circle
email

  • Cool_Loong

    这是我之前用的固件,我把它克隆到了我的仓库https://github.com/CoolLoong/AutoBuild-Actions,编译完成后运行ua2f提示mnl_cb_run: Not supported,可是我明明已经修改内核添加NETFILTER_NETLINK_GLUE_CT了,在Scripts/x64.sh中完成,请大佬你帮我看看到底是哪出问题了

    3年前 回复
  • Zepto

    草,我在被 itsc 封锁之后竟然搜到了您的文章

    3年前 回复
  • 星念

    ua.zhezhiyu.xyz域名要过期了,我换成了ua.233996.xyz,十年域名+甲骨文白嫖,应该可以一直用下去了

    3年前 回复
    • learningman博主

      @星念: xmsl,我甲骨文死活不给过,两张卡都不行

      3年前 回复
      • 星念

        @learningman: 老玄学了哈哈哈,我可以给你一个arm的服务器当玩具,韩国首尔的服务器,只要不把我上面的V2ray关掉就行(

        3年前 回复
  • 凡凡爱吃毛豆

    请问有直接刷入即食的K2P的固件吗 不是计科专业 确实有点难以下手呀 感谢作者大大的付出~~

    3年前 回复
  • Y_R

    我开启ua2f后会出现断流现象,是ua2f的bug还是我配置问题,还是说学校有什么新的检测方式?

    2年前 回复
    • learningman博主

      @Y_R: 我们需要先来定义一下什么叫做断流。。。

      2年前 回复
      • Y_R

        @learningman: 我个人理解是短时间断网,一般突然断网几十秒到几分钟会自动连回去。

        2年前 回复
        • learningman博主

          @Y_R: 先syslog看日志,如果是UA2F挂了抓包给我我看下怎么修,如果不是那就说明你们学校还部署了别的检测方式,UA2F只负责处理UA

          2年前
  • PianCat

    Q:为什么默认UA要使用IE8兼容的Mozilla/4.0?
    是为了与某些上古的,没有HTTPS的网站保证兼容性的同时不影响访问吗?

    2年前 回复
  • Cool_Loong

    最近更新了一下固件,然后使用同样的防火墙规则,出现了腾讯系软件的图片加载不了的情况,例如QQ里面的图片,把防火墙规则删除之后又正常访问,这是什么情况

    2年前 回复
    • learningman博主

      @Cool_Loong: QQ的问题,没有计划解决

      2年前 回复
      • Cool_Loong

        @learningman: QQ图片显示慢,是否是因为我使用了UCI命令,然后又在防火墙里面添加了规则,重复导致的原因。我刚刚把防火墙规则删除了之后,图片加载速度正常了,在ua检测网站上,标准80端口的UA并没有被修改,非标准1234端口上的UA显示正常被修改了,我查看日志显示mnl_cb_run: Operation not permitted,这样是正常运行的情况吗。

        2年前 回复
        • learningman博主

          @Cool_Loong: Operation not permitted是重复运行了,不正常
          最新版uci那些规则不是我写的,我也不太明白

          2年前
  • dfa

    怎么学的

    2年前 回复
    • Zxilly博主

      @dfa: 逼急了就会了

      2年前 回复
      • dfa

        @Zxilly: 细琐细琐(

        2年前 回复
        • Zxilly博主

          @dfa: 有需求,没现成的,那不就逼急了现学现搓一个

          2年前
      • dfa

        @Zxilly: 非钩

        2年前 回复
        • Zxilly博主

          @dfa: 就是知道了有这个api,那就研究下就写了呗。。。能说啥

          2年前
        • dfa

          @Zxilly: 老哥开个门,指条路)

          2年前
        • dfa

          @Zxilly: 同专业完全不知道要怎么开始

          2年前
        • Zxilly博主

          @dfa: 这个一两句话不可能说的清,你学校里找个靠谱点的社团就行

          2年前
        • dfa

          @Zxilly: 谢谢

          2年前
  • 本源

    只能写进固件里面嘛,我编译完安装ua2f的ipk需要三个依赖导致安装失败。

    2年前 回复
    • Zxilly博主

      @本源: ua2f本身是不需要的,但是它依赖特定的内核特性,所以最好还是一起编译

      2年前 回复
      • 本源

        @Zxilly: 可是我现在的固件我挺舍不得的,也是为了ua2f去学openwrt编译,一开始一直出错连make menuconfig都进不去,具体自定义编译成我想要的固件还是有点难度,我的软路由加装了usb网卡驱动和风扇,如果在make menuconfig界面我就完全不知道怎么加了

        2年前 回复
        • Zxilly博主

          @本源: 这只能慢慢学了。。。网卡和风扇加驱动嘛,找找就好

          2年前
        • 本源

          @Zxilly: 我想问问,如果我是软路由做主路由,下级路由是安装了ua2f的,可以配置能用嘛

          2年前
        • Zxilly博主

          @本源: 你能把防火墙配明白就行,所有流量要流经ua2f才能被修改

          2年前
        • ko_teiru

          @本源: 如果有 .config 或者 buildinfo 的话倒是可以打开研究研究,没有的话那就得从头来过了

          2年前
  • ffyuanda

    tql

    2年前 回复
  • QX

    请问可以放行指定的域名吗,有些app改了UA后不能正常使用。

    2年前 回复
  • AUEN2333

    获取的UA是FFFFFF…而不是文章里说的IE8的UA是那里配置错了吗,

    2年前 回复
  • l

    家里有ipv6,学校也有,直接v回去

    2年前 回复
  • ko_teiru

    感谢哥们写的文章,帮助很大。一人一设备真的纯纯脑瘫。

    2年前 回复
  • kiki

    很棒,非常支持!

    12月前 回复
  • kiki

    ua2f是不是对校园网说:u are too fuck

    12月前 回复
  • 似梦如花

    大佬,按照上述操作编译完了,但是UA并没有更改,没有起任何作用。编译期间也没有任何报错

    11月前 回复
    • Zxilly博主

      @似梦如花: 用uci启用了吗

      11月前 回复
      • 似梦如花

        @Zxilly: 启用了,然后直接导致无法上网,只能关闭uci才行

        11月前 回复
      • 似梦如花

        @Zxilly: 启用了,但是启用之后直接无法上网,只能关闭才能正常,不知道为什么

        11月前 回复
        • Zxilly博主

          @似梦如花: 如果你有能力可以抓个包,然后github发个issue,否则我帮不了你什么

          11月前
        • 似梦如花

          @Zxilly: 好的,非常感谢大佬,我再试试

          11月前
        • 似梦如花

          @Zxilly: 您好,想问一下uci里这一条 uci set ua2f.firewall.handle_fw=1防火墙规则最后的fw、tls、mmtls、intranet这四种有什么区别呀,不会选

          11月前
  • 似梦如花

    大佬 启用这一条之后部分网站就无法打开了,应该怎么解决呢
    # 自动配置防火墙(默认开启)(建议开启)
    uci set ua2f.firewall.handle_fw=1
    Windows疑难解答给出的检测是:网站处于联机状态,但未对连接尝试做出响应。

    11月前 回复
    • Zxilly博主

      @似梦如花: 提供日志,抓包文件,去github开个issue,你现在提供的这些信息我帮不了你

      11月前 回复

Zxilly's Blog

校园网路由器多设备伪装指北
如何在一个部署了流量识别设备的校园网中使用路由器?
扫描二维码继续阅读
2020-11-29