某大学校园网共享检测机制和破解过程

作者提醒: 本文不是一篇水文,需要一定的技术功底阅读,我会尽量写的通俗易懂. 如果你不是一个爱研究的人, 那么你大可不必阅读本文, 直接出门右转有淘宝, 直接搜索校园网和路由器, 你会发现新大陆的

本文章使用知识共享协议 CC 4.0 BY-SA 授权. 这篇文章的部分内容直接或间接的引用的他人的带有此协议的文章, 故使用本协议.

前记

我的大学坐标位于辽宁锦州一个不算有名的大学(至少我是这样想的), 前身是一个师范专科学校, 分为两个校区, 我在靠近锦州港的那个校区.

据我所知,从2022年9月份开学前校园网进行过一次大改造, 用上的深澜家的计费服务(虽然以前也是深澜认证,但是上网的方式有了一些变化,由原来的校园主干网变成了现在的代理拨号服务. 不要问我怎么知道的, 后面有讲). 校园网也比较抠门,一个学期大几百, 一个账户只能登陆两台设备,而且只允许企业微信登录深澜认证的界面,学校没有提供账号和密码 ,无奈作为一名软件工程专业的学生, 居然要忍受这等糟糕的网络体验服务(学校但凡把设备限制数量限制在3台就不会出现这边文章了)

所以我搜集各种各样的资料, 终于算是找到了一个解决方案, 在此感谢那些为了苦逼大学狗们上网做过贡献的人, 是你们为互联网带来了如此优秀的内容, 在此将参考的文章链接贴在下面:

  1. UA2F 的作者: Zxilly 以及他的食用教程 校园网路由器多设备伪装指北 – Zxilly's Blog (learningman.top)

  2. 为啥我的路由器会被检测到(chn.moe)

  3. 全新方案-懒人福音-无需手动编译修改UA-校园网防检测 (sunbk201.site)

  4. OpenWrt 编译与防检测部署教程 (notion.so)

你可以参考这些文章, 毕竟我方案和上面这些文章写的基本上没有相差多少

不可高攀的墙

我没有学JS, 看不懂JavaScript脚本, 所以通过企业微信token截取用户名密码的方法没有尝试, 下面贴了几张图, 有兴趣的大神可以自己了解一下(仅展示了一部分)

下面的代码部分可以不看

// main.js

// 定制认证
    $('#login-custom-sso').click(function () {
        var username = $('#username').val().replace(/ /g, '');
        var password = $('#password').val();
        // 对账号进行非空校验
        if (!portal.fieldCheck(username, 'blank')) return $('#username').focus();
        // 对密码进行非空校验
        if (!portal.fieldCheck(password, 'blank')) return $('#password').focus();

        // 写入用户信息
        portal.userInfo.username = username;
        portal.userInfo.password = password;
        portal.userInfo.domain   = '';

        // 发送请求
        portal.ajax.post({
            url: '/v1/srun_portal_sso',
            params: {
                username: username,
                password: password,
                ac_id: portal.portalInfo.acid,
                theme: portal.getUrlParams('theme')
            },
            success: function (res) {
                if (res.data.oauth_url) return location.href = res.data.oauth_url
                // Portal 认证方法
                portal.login({
                    // 认证方式为账号认证
                    type: 'account',
                    // 认证成功
                    success: function () {
                        // 若勾选记住密码
                        if ($('#remember').prop('checked'))  portal.remember(true);
                        // 若未勾选记住密码 或 不存在记住密码功能
                        if (!$('#remember').prop('checked')) portal.remember(false);
                        // 重定向至成功页
                        portal.toSuccess();
                    }
                });
            },
            error: function (res) {
                portal.confirm(portal.translate(res))
            }
        })
    });
// Portal.js

        _encodeUserInfo.set(_assertThisInitialized(_this), {
            writable: true,
            value: function value(info, token) {
                // 克隆自 $.base64,防止污染
                var base64 = _this.clone($.base64); // base64 设置 Alpha


                base64.setAlpha('LVoJPiCN2R8G90yg+hmFHuacZ1OWMnrsSTXkYpUq/3dlbfKwv6xztjI7DeBE45QA'); // 用户信息转 JSON

                info = JSON.stringify(info);

                function encode(str, key) {
                    if (str === '') return '';
                    var v = s(str, true);
                    var k = s(key, false);
                    if (k.length < 4) k.length = 4;
                    var n = v.length - 1,
                        z = v[n],
                        y = v[0],
                        c = 0x86014019 | 0x183639A0,
                        m,
                        e,
                        p,
                        q = Math.floor(6 + 52 / (n + 1)),
                        d = 0;

                    while (0 < q--) {
                        d = d + c & (0x8CE0D9BF | 0x731F2640);
                        e = d >>> 2 & 3;

                        for (p = 0; p < n; p++) {
                            y = v[p + 1];
                            m = z >>> 5 ^ y << 2;
                            m += y >>> 3 ^ z << 4 ^ (d ^ y);
                            m += k[p & 3 ^ e] ^ z;
                            z = v[p] = v[p] + m & (0xEFB8D130 | 0x10472ECF);
                        }

                        y = v[0];
                        m = z >>> 5 ^ y << 2;
                        m += y >>> 3 ^ z << 4 ^ (d ^ y);
                        m += k[p & 3 ^ e] ^ z;
                        z = v[n] = v[n] + m & (0xBB390742 | 0x44C6F8BD);
                    }

                    return l(v, false);
                }

                function s(a, b) {
                    var c = a.length;
                    var v = [];

                    for (var i = 0; i < c; i += 4) {
                        v[i >> 2] = a.charCodeAt(i) | a.charCodeAt(i + 1) << 8 | a.charCodeAt(i + 2) << 16 | a.charCodeAt(i + 3) << 24;
                    }

                    if (b) v[v.length] = c;
                    return v;
                }

                function l(a, b) {
                    var d = a.length;
                    var c = d - 1 << 2;

                    if (b) {
                        var m = a[d - 1];
                        if (m < c - 3 || m > c) return null;
                        c = m;
                    }

                    for (var i = 0; i < d; i++) {
                        a[i] = String.fromCharCode(a[i] & 0xff, a[i] >>> 8 & 0xff, a[i] >>> 16 & 0xff, a[i] >>> 24 & 0xff);
                    }

                    return b ? a.join('').substring(0, c) : a.join('');
                }

                return '{SRBX1}' + base64.encode(encode(info, token));
            }
        });
        
        
        _getToken.set(_assertThisInitialized(_this), {
            writable: true,
            value: function value(host, ip, callback) {
                _this.ajax.jsonp({
                    host: host,
                    url: _classPrivateFieldGet(_assertThisInitialized(_this), _api).token,
                    params: {
                        username: _this.userInfo.username + _this.userInfo.domain,
                        ip: _this.portalInfo.doub && host ? '' : _this.userInfo.ip
                    },
                    success: function success(res) {
                        return callback(res.challenge);
                    },
                    // 获取 Token 失败给出弹框
                    error: function error(res) {
                        return _this.confirm(_this.translate(res));
                    }
                });
            }
        });

        _getSign.set(_assertThisInitialized(_this), {
            writable: true,
            value: function value(params, callback) {
                _this.ajax.get({
                    url: _classPrivateFieldGet(_assertThisInitialized(_this), _api).sign,
                    params: params,
                    success: function success(res) {
                        return callback(res.Token, res.Sign);
                    },
                    // 获取 Token 失败给出弹框
                    error: function error(res) {
                        _this.running = {};

                        _this.confirm(_this.translate(res));
                    }
                });
            }
        });
        
       _createWeworkQr.set(_assertThisInitialized(_this), {
            writable: true,
            value: function value(obj) {
                _this.ajax.get({
                    url: _classPrivateFieldGet(_assertThisInitialized(_this), _api).authWework,
                    params: {
                        ac_id: _this.portalInfo.acid
                    },
                    success: function success(res) {
                        _this.qrCode({
                            el: '#wework_qrcode',
                            text: res.data.url,
                            background: CREATER.weworkBackground,
                            foreground: CREATER.weworkForeground,
                            size: CREATER.size
                        });

                        $('.panel-notice').height($('.panel-login').height());

                        _classPrivateFieldGet(_assertThisInitialized(_this), _polling).call(_assertThisInitialized(_this), 3, res.data.expire_time);
                    },
                    error: function error(res) {
                        _this.confirm(_this.translate(res));
                    }
                });
            }
        });

这里简单总结一下, 企业微信扫码认证后来了一个token, 然后经过浏览器获取的校园网网页中的JavaScript脚本翻译加密之后, 在转发给认证服务器 (我大概理解就是这样)

只可惜不会JS, 不然我肯定就写一个不停认证的脚本来解决问题了

困难重重

我刚开始的打算的是绕过校园网, 方案是使用53,67,68等端口走OpenV*N的方式, 在公网上购买一个云服务器, 让所有的流量走我的服务器代理, 即可“免费”使用学校搭建好的宿舍网络环境.

PS: 这个时候我还没有发现网络结构是下面这样的, 直到我发现使用使用特殊端口的方式根本出不了外网, 重新收集信息时才看到了这个ppt, 得知防火墙把所有的流量都进行了隔离, 意味着走特殊端口这种方式不可行!

我还想过通过一些特殊手段获取到PPPoE的账号和密码, (联通宽带需要提供用户地址才能查询用户名和密码, 当然这些信息只有学校那边的人知道) ,然后不用学校的代理拨号系统转而自己拨号, 因为本人技术实在有限, 涉及到破解数据库等等工作(我怕进局子), 这一条路也被我放弃了, 如果正在看本文的你有人脉, 那么或许不会像我这样做(毕竟找一个认识的人问一下密码什么的要简单的多)

转机

值得高兴的是, 我在收集数据的时候发现深澜软件将我们学校的校园网作为一个示范项目挂在了他们的官网上, 这也让我了解了校园网的网络结构, 也为后来的伪装数据包埋下伏笔









从图中可以看到校园网主要认证方式是Srun4000, 通过Srun4000 AAA与运营商交换机进行数据对接, H3C-CR16K作为Portal对接核心交换机, 然后通过防火墙移交给代理拨号服务器, 然后通过的PPPoE代理拨号最后交给联通运营商

穿上伪装的外衣

既然从外部的打入不可行, 那么我们换一种方式, 通过正常的渠道上网, 然后将数据包伪装成“一台设备”的普通流量不就好了吗, 我们就对症下药, 他们怎么检测, 我们就怎么防.

下面的内容需要拥有一个正常使用的校园网账户!!

先说一个结论: NAT 无法被外侧检查到

因为我是一个正常的校园网用户,不需要分析登录状态等等东西, 我们只需要让管设备限制的那套服务器认为只有一台设备在使用校园网就可以了

如果你想要了解为什么这样做, 请参考这篇文章: 为啥我的路由器会被检测到

绝大多数家用路由器的上网方式是 NAT + DHCP的方式上网的[默认的上网方式也是这个](除了路由器桥接模式), 相当于其他的设备经过路由器上网的时候经过处理,变成了一台上网设备(一台上网设备指的是路由器), 只是这一台上网设备有一些漏洞, 让学校的上网行为管理知道了你通过一台上网设备上网并映射到了多台设备. 一般来说, 学校在你使用校园网服务之前会将你的路由器以人工的方式更改为桥接模式, 这样你的路由器变成了一个”AP”(相当于wifi天线), 与整个校园网的线路直接连接, 这样从学校就从源头解决了多台设备共享的问题(因为这样桥接根本不可能实现共享)

关于某大学校园网共享上网检测机制的研究与解决方案 (sunbk201.site) 这篇文章详细介绍了校园网是如何检测NAT环境下存在多用户

总之归类下面几个大类:

  • 基于 IPv4 数据包包头内的 TTL 字段的检测

  • 基于 HTTP 数据包请求头内的 User-Agent 字段的检测

  • DPI (Deep Packet Inspection) 深度包检测技术

  • 基于 IPv4 数据包包头内的 Identification 字段的检测

  • 基于网络协议栈时钟偏移的检测技术

  • Flash Cookie 检测技术 (过时的技术)

我们需要做的就是将这几项伪装起来,这样校园网就不会将我们踢下线(我们在校园网眼里就是一个正常的用户,只是流量用的有亿点多)

因为普通的路由器根本没有提供上述功能, 所以我们需要一个带有这样功能的设备来帮助我们实现,(淘宝上的校园网专用路由器和“这样功能的设备”原理上是一样的,只是淘宝上的路由器比裸机贵很多), 这里选择软路由系统的大哥——OpenWrt: Welcome to the OpenWrt Project

实践出真知

下面的步骤可能对成手有些繁琐, 对于计算机小白来说更加困难, 不过这些是必经之路

编译OpenWrt

编译OpenWrt会从网上拉取一些代码, 然而这些代码可能在当下的互联网环境下(GFW)不能够正常拉取

所以:

请务必保证互联网环境处于全局代理模式!!!

请务必保证互联网环境处于全局代理模式!!! 懂得都懂!

这里我选择编译lean大的OpenWrt: coolsnowwolf/lede: Lean's LEDE source (github.com)

当然你也可以选择OpenWrt官方的仓库: [OpenWrt Wiki] Welcome to the OpenWrt Project

先说一下我的环境:

Windows10 21H2 with WSL(Linux子系统)

AMD Ryzen5 4600 with Graphis + NVDIA GeForce 1650ti + 32GB内存(8GB以上也可以)

如果你没有开启WSL,请自行百度, 并切换到WSL2

这里推荐使用Ubuntu进行编译

1. 环境配置

禁用windows环境变量对WSL中编译的影响

提示: 你可以在WSL中 新建/etc/wsl.conf 并使用下面的代码以禁用windows环境变量

[interop]
appendWindowsPath = false

提示: 你可以在windows宿主主机中的 ~/.wslconfig (对应 %USERPROFILE%\.wslconfig) 写入配置, 指定wsl的核心数量, 内存, 交换分区的大小

[wsl2]
processors=12
memory=10GB
swap=4GB
localhostForwarding=true

然后使用 wsl --shutdown 关闭WSL, 然后重新开启即可

之后你可以使用htop命令查看核心数量, 内存和交换分区大小

2. 拉取源码

更新系统并安装编译依赖

sudo apt update -y
sudo apt full-upgrade -y
sudo apt install -y ack antlr3 aria2 asciidoc autoconf automake autopoint binutils bison build-essential bzip2 ccache cmake cpio curl device-tree-compiler fastjar flex gawk gettext gcc-multilib g++-multilib git gperf haveged help2man intltool libc6-dev-i386 libelf-dev libglib2.0-dev libgmp3-dev libltdl-dev libmpc-dev libmpfr-dev libncurses5-dev libncursesw5-dev libreadline-dev libssl-dev libtool lrzsz mkisofs msmtp nano ninja-build p7zip p7zip-full patch pkgconf python2.7 python3 python3-pip libpython3-dev qemu-utils rsync scons squashfs-tools subversion swig texinfo uglifyjs upx-ucl unzip vim wget xmlto xxd zlib1g-dev

进入一个目录, 这里以家目录为例:

cd ~
git clone https://github.com/coolsnowwolf/lede.git
cd lede
./scripts/feeds update -a
./scripts/feeds install -a

添加需要的组件

# 我将组件放在了package中新创建的目录中
mkdir ~/lede/package/aquawius
cd ~/lede/package/aquawius

# 加入的组件
git clone https://github.com/Zxilly/UA2F.git
git clone https://github.com/CHN-beta/rkp-ipid.git

# 我一共添加了以下组件, (上面的两个已经满足正常的伪装需要)
# OpenClash  UA2F  helloworld  luci-theme-argon  openwrt-passwall  rkp-ipid
3. 开始编译
cd ~/lede
make menuconfig
# 默认lede是luci中文

# LuCI
#		--> 1. Collections
#				--> luci
#			--> luci-compat
#		--> 2. Modules
#				--> Translations
# Base system
#		--> Customize busybox options
#				--> dnsmasq-full (取消dnsmaq,两者冲突)
# Network -> ipset
# network -> Routing and Redirection -> ua2f
# Firewall -> iptables-mod-conntrack-extra
# kernel-modules->Other modules -> ipid
# 选上两个模块: iptables-mod-ipopt, kmod-ipt-ipopt,搜索就能找到

# 这一步时间比较长
make kernel_menuconfig

# 然后将
# Networking support -> 
# Networking options -> 
# Network packet filtering framework (Netfilter) -> 
# Core Netfilter Configuration -> 
# 	Netfilter NFNETLINK interface
# 	Netfilter LOG over NFNETLINK interface
# 	Netfilter connection tracking support
# 	Connection tracking netlink interface
# 	NFQUEUE and NFLOG integration with Connection Tracking 打开
# 有一些选项必须在打开上一个选项的时候才能开启
# 还有一个替代方案, 编辑.config文件,其中加入 CONFIG_NETFILTER_NETLINK_GLUE_CT=y

# 预下载编译所需的软件包
make download -j$(nproc) V=s

# 正式开始编译, 可能持续很长很长时间
make -j$(nproc) V=s 
# 编译后的固件文件在:openwrt/bin/targets 下面。

将输出的文件刷入路由器/软路由中

建议使用Etcher软件,进行烧录

默认的软路由地址是 192.168.1.1, 密码是password, 默认开启了DHCP服务

你需要尝试每个每一个接口, 直到你的网络设备得到了IP地址

4. 配置OpenWrt

登录OpenWrt的LUCI配置页面 192.168.1.1

成品大概像我这样(被我加入了主题), 只要能进入, 还有和我类似的界面就算成功了

开始配命令之前,请检查所有的服务中的所有项目为关闭状态, 还有网络中的Turbo ACC网络加速一定为关闭状态(对UA2F有影响)

这个时候你可以进行校园网认证了

进入 OpenWRT 系统设置, 勾选 Enable NTP client(启用 NTP 客户端)和 Provide NTP server(作为 NTP 服务器提供服务)

NTP 服务器使用lede自带的就可以

将wan口的DHCP名字改成一个像电脑的名字,比如LAPTOP-*******

进入 网络 -> 防火墙 -> 自定义规则

将原来的命令直接删除, 使用文章提供的命令

注意: 使用上面的命令添加到自定义规则的方法可能会造成iptables规则重复!! (暂时没有发现可能会影响性能)

iptables配置

# This file is interpreted as shell script.
# Put your custom iptables rules here, they will
# be executed with each firewall (re-)start.

# Internal uci firewall chains are flushed and recreated on reload, so
# put custom rules into the root chains e.g. INPUT or FORWARD or into the
# special user chains, e.g. input_wan_rule or postrouting_lan_rule.

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
# 如果你有ipv6, 加上这些
# [ -n "$(command -v ip6tables)" ] && ip6tables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53
# [ -n "$(command -v ip6tables)" ] && ip6tables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53

# 通过 rkp-ipid 设置 IPID
# 若没有加入rkp-ipid模块,此部分不需要加入
iptables -t mangle -N IPID_MOD
iptables -t mangle -A FORWARD -j IPID_MOD
iptables -t mangle -A OUTPUT -j IPID_MOD
iptables -t mangle -A IPID_MOD -d 0.0.0.0/8 -j RETURN
iptables -t mangle -A IPID_MOD -d 127.0.0.0/8 -j RETURN

# 由于本校局域网是 A 类网,所以我将这一条注释掉了,具体要不要注释结合你所在的校园网内网类型
# iptables -t mangle -A IPID_MOD -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A IPID_MOD -d 172.16.0.0/12 -j RETURN
iptables -t mangle -A IPID_MOD -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A IPID_MOD -d 255.0.0.0/8 -j RETURN
iptables -t mangle -A IPID_MOD -j MARK --set-xmark 0x10/0x10

# ua2f 改UA
# ua2f 最新版本已实现自动配置,无需手动配置防火墙, 下面的内容属于手动配置, 如果UA2F工作正常, 即使没有通过iptables向内核发送过滤, 出口流量的User-Agent也会正常的被修改为FFFFFFFFF.....
> 现在的最新版的已经可以自定义UA, 不一定非得是FFFFFFF.....,  iptables/nftables默认的情况下ua2f也可以正确的配置(通过init.d/ua2f.service脚本实现)

iptables -t mangle -N ua2f
#由于本校局域网是 A 类网,所以我将这一条注释掉了,具体要不要注释结合你所在的校园网内网类型
# iptables -t mangle -A ua2f -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A ua2f -d 127.0.0.0/8 -j RETURN
iptables -t mangle -A ua2f -d 192.168.0.0/16 -j RETURN # 不处理流向保留地址的包
iptables -t mangle -A ua2f -p tcp --dport 443 -j RETURN # 不处理 https
iptables -t mangle -A ua2f -p tcp --dport 22 -j RETURN # 不处理 SSH 
iptables -t mangle -A ua2f -p tcp --dport 80 -j CONNMARK --set-mark 44
iptables -t mangle -A ua2f -m connmark --mark 43 -j RETURN # 不处理标记为非 http 的流 (实验性)
iptables -t mangle -A ua2f -m set --set nohttp dst,dst -j RETURN
iptables -t mangle -A ua2f -j NFQUEUE --queue-num 10010
iptables -t mangle -A FORWARD -p tcp -m conntrack --ctdir ORIGINAL -j ua2f
iptables -t mangle -A FORWARD -p tcp -m conntrack --ctdir REPLY

# 防时钟偏移检测
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

# 通过 iptables 修改 TTL 值
iptables -t mangle -A POSTROUTING -j TTL --ttl-set 64

# iptables 拒绝 AC 进行 Flash 检测(Flash 时代已经过去), 你可以不用输入.
# iptables -I FORWARD -p tcp --sport 80 --tcp-flags ACK ACK -m string --algo bm --string " src=\"http://1.1.1." -j DROP

执行重启防火墙

状态 -> 防火墙中 应该出现这些规则

UA2F 配置

下面的命令需要在终端配置, 或者你可以使用SSH连接

# 开机自启
uci set ua2f.enabled.enabled=1
# 自动配置防火墙(默认开启)(建议开启)
uci set ua2f.firewall.handle_fw=1
# 处理内网流量(默认开启),防止在访问内网服务时被检测到。(建议开启)
uci set ua2f.firewall.handle_intranet=1
# 处理 443 端口流量(默认关闭),443 端口出现 http 流量的概率较低
uci set ua2f.firewall.handle_tls=1
# 处理微信的 mmtls(默认开启)(建议关闭)
uci set ua2f.firewall.handle_mmtls=0

# 提交规则
uci commit ua2f

# 启动ua2f
service ua2f start

# 开机自启ua2f
service ua2f enable

到现在你就可以正常上网了

5. 检查是否工作

检查是否工作的最好方式就是抓包, 如果你会抓包, 我觉得都不用我来写了…….是吧

如果你不会的话, 还有一个简单的方式, 打开这个网站UA检测-HTTP (233996.xyz) (这个时候科XUE上网环境需要关闭)

如果你的显示结果是这样的

那么你可能中间除了问题

如果是这样的

恭喜!!

如果出现了bilibili直播打不开(黑屏)的情况, 请开启 网络 -> DHCP/DNS -> 重绑定保护 关闭

这个原因不明, 我也不清楚具体折腾了个什么就好了, 我觉得大概率是DNS解析造成的
原因已经查明, 因为学校的垃圾DNS解析, 导致解析实在是太慢, 出现了bilibili直播反应极其迟钝的情况, 现在学校的DNS解析情况已经有所改善.

另外几种思路

这里就是几种设想, 我认为没有必要这样做, 因为这种方案最终需要客户端运行代理软件, 还是写一下吧:

  1. 使用NGINX或者Privoxy等代理软件修改UA
  2. 将所有80端口的流量通过clash等代理
  3. 在国内买一个服务器, 使用https + tls走全局代理 (富有的人的选择)

后记

目前来说, 主流的检测方法是TTL, ID , UA 和时钟偏移 , 只要这几点你能够做好伪装, 基本上就不会被强制踢下线

这个方案我已经使用了一小段时间,总的来说非常稳 (稳到3天没掉过线的那种), 还是非常NB的

理论上来说, 你可以使用两个物理接口作为WAN口, 分别绑定不同的mac地址, 这样可以实现带宽速度的叠加, 但是由于我软路由是被我改造的, 只有两个物理接口(一个WAN,一个LAN), 所以这个方法我没有尝试

如果你看到了这个教程并成功的“破解”了校园网限制, 我希望你遵守一个约定: 请给我引用过文章的这些大佬们点个赞, 或者在github上给他们一个star, 这些拥有高技术力而又无私的大佬们值得被你点赞, 没有人监督你遵守这个约定, 全看你自己.

文章中可能会有不严谨或者错误的地方, 如果你发现了希望能够告诉我

就到这里吧……

2022/10/7 晌记毕


2023/03/05 更新

哈哈, 想不到吧, 这东西居然还有更新.

因为UA2F更新之后如果开启了

# 自动配置防火墙(默认开启)(建议开启)
uci set ua2f.firewall.handle_fw=1

那么ua2f将会读取你的iptables并且自动帮助你进行配置防火墙, 所以说上文中有关与UA2F的iptables命令可以不用输入!

还有一个坑, 因为openwrt-22+ 版本已经放弃使用iptables, 所以请在编译固件的时候选择适当的分支!

aquawius@aquawius:~/openwrt$ git checkout
HEAD                   v17.01.1               v18.06.9               v21.02.0-rc4
lede-17.01             v17.01.2               v19.07.0               v21.02.1
master                 v17.01.3               v19.07.0-rc1           v21.02.2
openwrt-18.06          v17.01.4               v19.07.0-rc2           v21.02.3
openwrt-19.07          v17.01.5               v19.07.1               v21.02.4
openwrt-21.02          v17.01.6               v19.07.10              v21.02.5
openwrt-22.03          v17.01.7               v19.07.2               v22.03.0
origin/HEAD            v18.06.0               v19.07.3               v22.03.0-rc1
origin/lede-17.01      v18.06.0-rc1           v19.07.4               v22.03.0-rc2
origin/master          v18.06.0-rc2           v19.07.5               v22.03.0-rc3
origin/openwrt-18.06   v18.06.1               v19.07.6               v22.03.0-rc4
origin/openwrt-19.07   v18.06.2               v19.07.7               v22.03.0-rc5
origin/openwrt-21.02   v18.06.3               v19.07.8               v22.03.0-rc6
origin/openwrt-22.03   v18.06.4               v19.07.9               v22.03.1
reboot                 v18.06.5               v21.02.0               v22.03.2
v17.01.0               v18.06.6               v21.02.0-rc1           v22.03.3
v17.01.0-rc1           v18.06.7               v21.02.0-rc2
v17.01.0-rc2           v18.06.8               v21.02.0-rc3

# 这里建议使用 openwrt-21.02
git checkout openwrt-21.02

# 然后从 `./script/feeds update -a` 开始向后执行就好

至于多网口分流, 我曾经过使用macvlan创建多个虚机接口进行多播, 虽然能够正常使用网络速度叠加, 但是似乎在多个ip之间跳转, 并不能一劳永逸. 具体反应出来的问题就是网络奇慢, 登录态不能保持, 只有速度能够上去, 体验提托大便……

近期, 我又尝试了一下, 将系统从lede换成了openwrt21.02, 并且购买了一个usb 88179网卡(没错, 就是绿联的那个88179网卡), 使用3个物理网口(2wan,1lan)进行多播, 居然可以了, 目前不清楚是mwan3UA2F 有冲突还是 openwrt血统比较纯正的原因(雾), 总之就是现在不可用.

我会再试试使用原来编译好的固件重新手动分配一下mwan3的策略接口啥的, 我依稀记得当时使用lede的时候似乎使用的是syncdial分流助手帮助我进行的分流和创建虚拟接口, 这几天我会重新验证一下: 是不是mwan3本来就可用, 但是由于我的错误配置, 导致了mwan3的工作不正常.

2023/3/8 补充: 已经查明 mwan3 与 ua2f 有冲突, 意味着通过ua2f+mwan3的方式彻底失败, 但是我又看到了另一位大佬的ua2f改, 地址放在这里, 有想要折腾的可以自己研究研究, 在issue中提到了有关mwan3共存.
UA2F-cpp: Change User-agent for privacy protection

当然, 有技术力的玩家可以使用虚拟机套娃的方式, 使用分流效果更好的IKuai(你需要处理有关于网卡直通方面的问题), 我相信这样处理可能遇到的坑更小, 毕竟每一个系统都有他自己擅长的地方, 不一定都需要交给openwrt处理.

2023/3/8 补充: 已经通过这种方式实现带宽叠加, 还是虚拟机省事......

最后还是想说一下, 目前的检测系统在性能和能效等等方面做了平衡, 仅仅是检测UA,ipid等等相关的信息. (而且如果你愿意完全可以将UA2F自己复刻一份,变成UA2Any(变成随意定制的UA头), 当然, 不是说如果你这些检测方式都做了就一定好用), 如果你的学校真的想要恶心你, 在网管那边仅仅就是开启一个选项(检测的方式严格一点), 目前的方式就很有可能失效.

道高一尺, 魔高一丈, 如果有更加牛逼的检测方式, 一定就会有更nb的解决方式, 打开你的思维, 多多自我实践.

2023/03/06 09:33:47 正在上课的时候更新(反正老子也不听课 233333)
posted @ 2022-10-07 13:41  QU头  阅读(10040)  评论(6编辑  收藏  举报