Featured image of post 長沙理工大學:校園網共享指南

長沙理工大學:校園網共享指南

校園網限制一人一終端,但現在的大學生還有幾人是有且只有一台上網裝置的?指望推動學校在短時間做出改變不太現實,只好另闢蹊徑。

2016年11月7日透過的《中華人民共和國網絡安全法》第二十四條規定,「網絡運營者為用戶辦理網絡接入、域名註冊服務,辦理固定電話、行動電話等入網手續,或者為用戶提供資訊釋出、即時通訊等服務,在與用戶簽訂協議或者確認提供服務時,應當要求用戶提供真實身份資訊。用戶不提供真實身份資訊的,網絡運營者不得為其提供相關服務。」

到了教育部這裏落實,就變成了校園網一人一號。再到運營商這裏,就變成了一人一終端,還不準使用路由器。這顯然已經和合規沒有任何關係,學生的需求也擺在這裏,但限制卻還是這個鳥樣。好一點的大學,比如上海交大這種坐擁華東教育骨幹網的學校可以做到校園網免費,為什麼我們甚至不能放開連線裝置數量上的限制呢?

2015年以來……目前,我校IPV4/IPV6總出口頻寬達到47GB,其中電信25GB、聯通10GB、移動10GB、教育網2GB,校園網總註冊用戶數超過4.34萬、活躍用戶數超過2.43萬。辦公賬户(免費)頻寬由2MB升到36MB。宿舍區基本賬户(付費)頻寬由2MB升到12MB,網費不變。……

這套資料應該不是最新的,2022年寒假校園網又進行了一次大擴容,具體擴容了多少不得而知。如果按照這套資料計算,總出口 47GB,活躍用戶數2.43萬,則人均頻寬是$ \dfrac{47GB _ 1000 _ 8}{24300} \approx 15Mbps $。這點可憐的頻寬,還要給學校的官網防 DDoS,加上網安等種種因素,就變成了一人一終端這種限制。

現在的大學生還有幾人是有且只有一台上網裝置的?室友間的一些操作也需要一套區域網環境(檔案共享、聯機遊戲……)指望推動學校在短時間做出這套改變不太現實。但需求總要解決,只能先自己想想辦法,從技術上解決這個矛盾了。

Update 2023/10/7:可能是部署了新裝置,經測試,在敏行軒,本文措施失效——即使部署所有措施,依舊會頻繁被檢測。雖然我的指令碼可以自動讓路由器重新上線,但上網體驗會變得很差,遊戲更是幾乎不可能。那麼,敏行軒大機率是部署了新的檢測方法,基本只剩加密所有流量這一條路可走。

Update 2023/10/16:現在在敏行軒(其他區塊只會更寬鬆),最有效也最簡單的辦法就是用 Clash 代理所有流量(即使全域性直連也可以),具體方法文章後段有詳細説明。

硬件

需要一台可以刷入 OpenWRT 的路由器,我採用的是一台 Nano Pi R2S,最好選擇這種用戶基數大韌體多的產品,也最好能自己編譯韌體。

關於如何為路由器刷入 OpenWRT 請自行在網上搜尋對應的路由器型號+教程。不建議購買所謂的「校園網絡由器」,這種路由器通常價格比同效能路由器貴非常多,而且賣的人還不一定懂技術。

接入路由器

透過一段時間的觀察,可以得到我校校園網前端的計費系統採用城市熱點的 Dr.COM,這是一套非常常見的計費系統;BRAS 終端是鋭捷的裝置,採用 POE 方式連線鋭捷的 AP,似乎沒有蔘與認證。

1
daemon.info pppd[8599]: CHAP authentication succeeded: Welcome to Drcom System:

我將校園網分為三大類接入方式,無線,辦公區有線,學生公寓有線。

前兩者都是 DHCP+Portal 驗證,網頁表單提交賬號即可完成驗證。學生公寓區域的有線裝置透過 PPPoE 認證,賬號資訊就是校園網賬號本身。

因此路由的接入方式便確定了。宿舍的有線直接 PPPoE 認證就可以正常上網了。對於 Portal 的要麻煩一些,若無法連線外網則判斷 Portal 能否訪問,能訪問的話提交一個構造好的 POST 包登入即可。

Portal 認證的指令碼校友已經寫過不少:

https://github.com/linfangzhi/CSUST_network_auto_login

https://github.com/eigeen/csust-cn-login

https://github.com/colawithsauce/csust-network-login

路由器上安好 pythonrequests 庫然後執行這些指令碼即可。如果因無網絡不能安裝,重新編譯一個韌體就行。再不行就寫一個 Shell 指令碼登入。

封鎖狀況

此時已經可以透過路由器上網了,但依然不能全寢共享。

校園網多裝置共享很被檢測到會被臨時遮蔽,此時會遮蔽所有的網絡流量,據説還會強制重定向所有 HTTP 請求到http://1.1.1.3/remind/proxy_remind.htm?tm=8,不過我是沒有遇上。

Update: 會強制重定向到以下網頁:

校園網共享檢測提示

查閲資料發現,檢測是否多裝置共享有兩種思路,一種是透過裝置流量特徵識別:

  • TTL
  • IPID
  • 時間戳
  • UA

另一種是侵入式流量審計,這個可能看學校,不過我校肯定是有的:

增強網絡安全防護能力。……部署出口防火牆、出口行為審計……、IPS(入侵防禦)等安全裝置系統,加固學校網絡和資訊系統的整體安全。

透過一次喊人來寢室修網絡得知肯定是深信服的裝置。

透過路由器裸奔一段時間發現如下規律:

  • 兩台不同平台的產品(如 Windows 電腦和 iPad)同時上網會在較短時間內被封鎖
  • 封鎖時用代理可以連出去,B 站也能看,其他的不行,甚至無法 Ping 通校外 IP
  • 被封鎖後重新認證也無法上網,更換 MAC 地址後才能恢復

得出的結論是大機率透過 UA 識別,檢測到後封禁當前 MAC 地址一段時間。

流量處理

統一 TTL

將這行規則加入路由器的「網絡」-「防火牆」-「自定義規則」(下同),即可統一 TTL 為 65,其中-o br-lan可以視情況更換,如eth0

1
iptables -t mangle -I POSTROUTING -o br-lan -j TTL --ttl-set 65

這條規則用到了 ipopt 模組,在官方編譯的韌體或其他一些極簡的韌體裏預設不會安裝。這種情況下用opkg安裝即可:

1
2
opkg update
opkg install iptables-mod-ipopt

儲存規則並重啓防火牆,在電腦上隨便 Ping 一個網站看 TTL 是否為 65(不要在路由器上 Ping,除非你知道你在幹什麼)。

統一時間戳

接下來先啓用 OpenWrt 自帶的 NTP 伺服器,然後劫持所有區域網內的 NTP 請求到路由器,以達到我們統一時間戳的目的。

這種方法並不完美,因為手機連線基站時會同步到別的 NTP 伺服器,最好的辦法是直接去除 TCP 包的時間戳,但這種方法暫無成熟的實現,只能先採用劫持 NTP 請求的辦法。

只需要在管理頁面中修改幾個設定就可以了。

  • 點選 System -> System(系統)
  • 勾選 Enable NTP client(啓用 NTP 客户端)和 Provide NTP server(作為 NTP 伺服器提供服務)。
  • NTP server candidates(候選 NTP 伺服器)按需設定,可以使用阿里雲的 NTP 伺服器:ntp.aliyun.com
  • 點選 Save & Apply 按鈕。

向防火牆新增以下規則:

1
2
3
4
5
6
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

其中192.168.1.1需要更改成路由器的地址,視韌體而定。

若你的路由器地址不在192.168.0.0/16內,最後兩行都要跟着改,一般的家用路由器都在這個範圍內。

Windows 下確認效果:

1
w32tm /stripchart /computer:baidu.com /dataonly /samples:5

如果能正常同步就證明配置成功了。

統一 UA

網上的解決方案大部分基於代理,比如 Privoxy,甚至 Clash。還有不少是透過XMURP-UA直接在核心層面處理 UA,這幾年又有新的外掛出來,比如UA2F

方案一:UA2F

編譯韌體時自定義加入ua2fluci-app-ua2f,R2S 可以在這裏下載編譯好的。UA2F 與 Turbo ACC 衝突,即使沒有使用 Turbo ACC 也記得要關掉「全雛形 NAT」和「軟件流量分載」這兩個功能。

完成後啓動 UA2F 再開啓ua.233996.xyz就會發現自己的 UA 已經被修改了。

方案二:Privoxy

安裝好 Privoxy 並正確配置,然後將所有 HTTP 流量轉發給 Privoxy 代理,並在 Privoxy 中替換 UA。

安裝 Privoxy
1
2
3
opkg update
opkg install luci-app-privoxy
opkg install luci-app-privoxy-zh-cn
配置 Privoxy

點選 Services -> Privoxy WEB proxy。

  • Files and Directories(檔案和目錄):Action Files 刪除到只剩一個框,填入 match-all.action。Filter files 和 Trust files 均留空。
  • Access Control(訪問控制):Listen addresses 填寫 0.0.0.0:8118,Permit access 填寫 192.168.0.0/16。Enable action file editor 勾選。
  • Miscellaneous(雜項):Accept intercepted requests 勾選。
  • Logging(日誌):全部取消勾選。

點選 Save & Apply。

配置防火牆轉發

向路由器防火牆新增以下規則:

1
2
3
4
5
6
iptables -t nat -N http_ua_drop
iptables -t nat -I PREROUTING -p tcp --dport 80 -j http_ua_drop
iptables -t nat -A http_ua_drop -d 0.0.0.0/8 -j RETURN
iptables -t nat -A http_ua_drop -d 127.0.0.0/8 -j RETURN
iptables -t nat -A http_ua_drop -d 192.168.0.0/16 -j RETURN
iptables -t nat -A http_ua_drop -p tcp -j REDIRECT --to-port 8118

在路由器的區域網中開啓 http://config.privoxy.org/edit-actions-list?f=0,點選 Edit 按鈕。Action 那一列中,hide-user-agent 改選為 Enable(綠色),在右側 User Agent string to send 框中填寫 Privoxy/1.0或任意 UA;其它全部選擇為 No Change (紫色)。點選 Submit 按鈕。

如果打不開這個頁面,説明之前某個地方配置有誤。

確認效果

本地瀏覽器除錯是看不到效果的,因為經過路由器之前 UA 會保持原樣。

訪問 ua.chn.moe 以檢視 UA 是否修改成功。

方案三:Clash

這種方法的思路是使用 Clash 代理/阻止所有發往 80 埠的流量。同時 Clash 也直接接管所有流量,這就意味着無需處理 IPID 和時間戳。

假設你使用的是 OpenClash,方法如下:

OpenClash設定

開啓 OpenClash 外掛面板,進入 覆寫設定 -> 規則設定,勾選自定義規則,將以下規則插入配置:

1
- DST-PORT,80,Proxy

其中Proxy需要視配置檔案的不同而更改,例如我的代理組叫做 HK,也可以直接使用節點名稱。

對於沒有能力加密的同學,則使用以下規則1

1
- DST-PORT,80,REJECT

Update 2023/10/31:經測試,即使不加入這條自定義規則,也足以防止檢測。但必須啓用 Clash,至少設定全域性直連。

防止透過 IPID 檢測

各裝置的 IPID 起始值不同,並隨着包數量的上升而上升,接近一條直線,若有多個裝置長時間使用後會呈現出多條上升序列。這可以用來探測是否是多個裝置。23

由於需要kmod-rkp-ipid,這一步也需要編譯韌體。

編譯好韌體後向防火牆新增以下規則:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
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
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

即可修改所有包的 IPID 為單一遞增曲線。

老辦法

設定如下 crontab 即可在每天凌晨三點重新撥號以打斷檢測過程:

1
0 3 * * * ( ifdown wan; sleep 5; ifup wan )

侵入式流量遮蔽

向路由器防火牆新增以下規則:

1
2
3
4
5
6
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 網友。

這些規則用到了iptablesu32模組,大多數韌體都不會預設安裝,亦需要透過opkg安裝:

1
2
opkg update
opkg install iptables-mod-u32

隨後遮蔽學校的「共享提示」頁面:

1
2
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

在Openwrt防火牆的流量規則設定如下規則:

  • 源區域WAN,源地址1.1.1.3,目標區域裝置,動作拒絕

  • 源區域WAN,源地址1.1.1.1,目標區域裝置,動作拒絕

這些規則來源於校友的部落格(找不到來源,可能已經關閉了)

意外封鎖處理

前面提到學校會封一段時間的 MAC,想要重新上線就需要更換 MAC 地址重新上線。為此我寫了一個 Shell 指令碼:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh
DATE=$(date +%Y-%m-%d-%H:%M:%S)
interface=eth0
current_mac=$(ifconfig ${interface} | grep "HWaddr" | awk '{print$5}')
new_mac=$(dd if=/dev/random bs=1 count=3 2>/dev/null | hexdump -C | head -1 | cut -d' ' -f2- | awk '{ print "34:36:3b:"$1":"$2":"$3 }')
tries=0
while [[ $tries -lt 3 ]]; do
    if /bin/ping -c 1 223.5.5.5 >/dev/null; then
        echo --- exit ---
        exit 0
    fi
    tries=$((tries + 1))
done
echo ${DATE} block detected, replacing mac address >>watchdog.log
ifconfig down ${interface}
sleep 1
ifconfig ${interface} hw ether ${new_mac}
sleep 1
ifconfig up ${interface}
echo ${DATE} old address ${current_mac} has been replaced with ${new_mac} >>watchdog.log

將這個指令碼儲存到路由器的 home 目錄下(用vim貼上儲存以下就可以了),設定如下 Crontab 每分鐘執行一次:

1
* * * * * sh /root/net_watchdog.sh

路由器就會自每隔一分鐘檢測是否線上,如果掉線,則隨機更換 MAC 地址並重新上線,日誌將會記錄在同目錄下的watchdog.log中。

Shell自動檢測是否掉線

DNS 內網解析處理

接上路由器之後,校外資源可以正常訪問,反倒是校內資源全都無法訪問了。經排查發現是路由器下的裝置無法解析出正確的 IP 地址,但路由器本身又沒有問題。

暫時不清楚是什麼原因導致的,但解決起來很簡單,可以直接把已知的內網地址 dnsmasq,但我推薦安裝 SmartDNS 來解決。

SmartDNS 的安裝可以蔘考官方教程

  • 開啓 SmartDNS 並讓其接管路由器的主 DNS
  • 設定 SmartDNS 上游為學校內網提供的 DNS,我校是10.255.255.2510.255.255.26
  • 設定別的上游,可以蔘考這篇部落格

這樣設定下來,內網資源就可以正常訪問了。

蔘考


  1. 這個配置會自動拒絕所有發往 80 埠的連線,對上網體驗影響很大。 ↩︎

  2. 具體可以蔘考這篇論文 ↩︎

  3. 這個方法可行性比較低,沒有已知的部署案例。 ↩︎