为了 保障校园网的营运利润 维护校园网络安全,学校在规定上是不允许校园网再设置路由器进行后续共享的。而实际上也在防火墙进行了相关验证,对检测出的有共享嫌疑的账号会给予临时封禁。
所谓的临时封禁也就是屏蔽所有网络流量,并对 HTTP 报文构造一个虚假的 301 跳转,将用户的浏览器跳转到 http://1.1.1.3/remind/proxy_remind.htm?tm=8 这个网址。但是可能由于配置上的失误,这个网址也是并不能正确显示的。从 URL 我们可以推断出应该是一个用户友好的一个检测到共享行为的提示页面。此外这个 URL 是已知的出现在深信服防火墙上面过的,可以假设学校使用的就是深信服的设备。
这一规定的出发点可以理解,但是对于广大学子的日常生活确实造成了诸多不便。尤其是计算机相关专业的同学,由于专业学习的需要,多设备组建局域网,乃至虚拟机多开等都是非常常见的需求,但这些行为同时也是构成了事实上的 “共享”,会被封火墙检测并封禁,极大的阻碍了有此类需求的相关专业同学的学习。
鉴于学校也不可能为我们这些专业的同学开绿灯,那么我们只能自行动手,从技术上解决矛盾了。
通过一段时间的观察,可以得到我校校园网前端的计费系统采用城市热点的 Dr.COM 的计费系统,这是一套非常常见的计费系统;BRAS 终端是锐捷的设备,采用 POE 方式连接锐捷的 AP,似乎没有参与认证。
我将校园网分为三大类接入方式,无线,办公区有线,学生公寓有线。
前两者都是 DHCP+Portal 验证,网页表单提交账号即可完成验证。学生公寓区域的有线设备有两种认证方法,要么使用学校提供的 Dr.COM6.0.0D 客户端登陆,要么直接在系统中 PPPoE 拨号,账号信息就是校园网账号本身。两个方式应该本质上是同一个,都是 PPPoE。
因此路由的接入方式便确定了。宿舍的有线直接 PPPoE 认证就可以正常上网了。对于 Portal 的要麻烦一些,若无法连接外网则判断 Portal 能否访问,能访问的话提交一个构造好的 POST 包登录即可。
但是共享检测的问题还没有解决,此时虽然已经可以通过路由上网了,但是还是没法共享。
查询相关资料,检测共享主要有两个思路,一个是通过流量的特征来识别,另一个是深度包内容检测。
前者比较好理解就是寻找经过 NAT 后的流量有什么不同的地方(比如经过 NAT 后的包 TTL 会加一)。后者则是通过分析流量的内容从逻辑上证明有共享行为。比如同一个账户既连接了小米的服务器,又连接了苹果的服务器,那么一定程度上就可以认为存在小米与苹果设备的共享。这种检测一方面要有足够强大的数据库,对于流量要有准确识别、标记的能力,另一方面这种方式也存在相当的误杀率,实施时要有足够精明的策略。这种检测往往是由防火墙企业统一进行维护,不断下发数据来维持的。
针对前者我们需要在 NAT 设备上修改相关特征使其看起来正常;后者如果是简单的策略针对性处理即可,如果是成体系的数据库对流量进行统计,那基本没辙,基本只有所有流量加密穿透出去这一条路可走。
经过一段时间摸索发现如下规律:
- 两台小米手机(不同型号)可以正常同时上网。
- Mi 6+MiPad 2(Windows 10 系统),在较短时间内会被封禁网络。
- 封禁时手机 QQ 的消息可以正常接收,但群聊中的图片无法显示。不知道是什么问题,可能是 QQ 推送用的长连接是在阻断前建立的,防火墙没有阻断。
- 初步判断,平板使用 HTTPS 协议上网时不会被检测。一旦连接 HTTP 协议的网站,就会触发。
- 被封禁后,重新登录校园网就可以解除。
- 浏览器时常提示 “等待 1.1.1.3 …”,疑似 HTTP 劫持插入了 js 或者 Flash,不排除利用 js 与 Flash 拿到更多设备信息的可能。
可以初步确定,应该就是通过 HTTP 报文中的 UA 来进行识别的。太复杂的规则学校是不敢部署的,即使是 0.01%的误杀率都意味着每天都可能有人去投诉。
那我们就可以得到初步方案了:尽可能处理掉明显的包特征,同时针对 HTTP 内容替换为统一的 UA。
下面的实施方案都基于 OpenWRT 的路由器,由于部分处理需要特定的内核模块支持,需要有适配的源码。
包特征处理
设备发出的数据包有一个默认的 TTL 值,且不同系统也有不同(Windows 为 128,安卓与 iOS 默认为 64)。
在路由上修改数据包的 TTL 为同一个值即可。
Ref: TTL modification for outgoing traffic with OpenWRT
注意,筛选规则用了 ipopt 模块,ipopt 在编译时不会默认勾选,记得在内核的防火墙模块处勾选 ipopt
iptables -t mangle -I POSTROUTING -o br-lan -j TTL --ttl-set 65
|
TCP 的 SYN 包会泄露主机的时间戳,不同的主机时间造成时间戳不同。
有两个方案,一个是劫持各设备的 NTP 服务到路由统一时间,但手机与基站通信时可能会同步基站时间,所以影响准确度;另一个是直接删掉 SYN 包中的时间戳,但暂无成熟的实现。先暂时使用前者。
在 Openwrt 系统设置,设置正确的 NTP 服务器后,勾选 “作为 NTP 服务器提供服务” 并保存。
设置以下防火墙规则劫持 NTP 到路由(192.168.1.1)
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.1.1
|
IPID 检测:各设备的起始值不同,并随着包数量的上升而上升,若有多个设备长时间使用后会呈现出多条上升序列。
因需要的检测时间较长,通常为数天,所以定时重新拨号即可打断检测过程。
也可以修改 IPID 为随机值,但网上的现有方法似乎过于古老,无法使用。
设置如下 crontab 即可在每天凌晨三点重新拨号。
0 3 * * * ( ifdown wan; sleep 5; ifup wan )
|
以上规则来自网友分享。
侵入流量屏蔽
深信服侵入式检测,Android 和 iOS 不要一起连
如果不给连手机的话,手机也不要连,手机和电脑通过 UA 检测
电脑和电脑检测通过 HTTP 劫持检测,屏蔽 TTL 为 127、189 的包就好,把防火墙加入路由器
iptables -I FORWARD -p tcp -m tcp –sport 80 -m u32 –u32 “5&0xFF=0x7F” -j DROP
iptables -I FORWARD -p tcp -m tcp –sport 8000 -m u32 –u32 “5&0xFF=0x7F” -j DROP
iptables -I FORWARD -p tcp -m tcp –sport 8080 -m u32 –u32 “5&0xFF=0x7F” -j DROP
iptables -I FORWARD -p tcp -m tcp –sport 80 -m u32 –u32 “5&0xFF=0x80” -j DROP
iptables -I FORWARD -p tcp -m tcp –sport 8000 -m u32 –u32 “5&0xFF=0x80” -j DROP
iptables -I FORWARD -p tcp -m tcp –sport 8080 -m u32 –u32 “5&0xFF=0x80” -j DROP
这一条规则来自 V2EX 的网友。
在 Openwrt 防火墙的流量规则设置如下规则:
源区域 WAN,源地址 1.1.1.3,目标区域设备,动作拒绝
源区域 WAN,源地址 1.1.1.1,目标区域设备,动作拒绝
iptables -I FORWARD -p tcp --sport 80 --tcp-flags ACK ACK -m string --algo bm --string " src=\"http://1.1.1." -j DROP iptables -I FORWARD -p tcp --sport 80 --tcp-flags ACK ACK -m string --algo bm --string " value=\"http://18.20.18." -j DROP
|
此规则来自校友的博客。
HTTP UA 处理
网上有很多利用 Proxy 来实现的教程,这里不推荐,主要是太影响速度。
现有其他大学的前辈开发出的内核级处理插件,CHN-beta/xmurp-ua @GitHub,直接使用该插件即可。
断线重启
若发现意外被封禁,自动重启拨号。
#!/bin/sh DATE=`date +%Y-%m-%d-%H:%M:%S` tries=0 while [[ $tries -lt 3 ]] do if /bin/ping -c 1 8.8.8.8 >/dev/null then echo --- exit --- exit 0 fi tries=$((tries+1)) sleep 2 done
echo $DATE network restart >>my_watchdog.log
ifdown wan sleep 2 ifup wan
|
将其保存到路由的/home 目录,并设置如下 crontab 每 15 秒运行一次
* * * * * ( sleep 15 ; sh /root/my_watchdog.sh ) * * * * * ( sleep 30 ; sh /root/my_watchdog.sh ) * * * * * ( sleep 45 ; sh /root/my_watchdog.sh ) * * * * * sh /root/my_watchdog.sh
|
DNS 处理
这么操作完后,外网可以正常使用,但是学校的内网资源反而全部没法正常访问了,发现是路由无法解析出正确的 IP 地址。
暂时没弄清楚原因,直接人工提供预解析的地址列表给 Dnsmasq 算了。
xk.csust.edu.cn [10.255.252.1] pt.csust.edu.cn [10.255.65.85] yktfw.csust.edu.cn [10.255.197.207] htp.csust.edu.cn [10.255.193.63] my.csust.edu.cn [10.255.193.63] www.csust.edu.cn [10.255.196.28] oss.csust.edu.cn [10.255.195.22] glis.csust.edu.cn [210.43.188.8] bw.csust.edu.cn [10.255.194.29] cwcx.csust.edu.cn [10.22.14.252] lx.csust.edu.cn [10.255.193.63] jwc.csust.edu.cn [210.43.177.10] xg1.csust.edu.cn [10.255.193.63] yktwd.csust.edu.cn [10.255.197.218] cxwx.csust.edu.cn [10.255.198.50] opac.csust.edu.cn [10.255.198.50] nginx.csust.edu.cn [10.255.198.50] app.csust.edu.cn [10.255.196.35] acm.csust.edu.cn [10.64.70.166]
|