Captive Portal 實驗

實作 Wi-Fi 登入畫面實作

相信大家在去如火車站之類的地方都會發現到很多免費的網路,這個時候心動的點下去之後卻跳出了一個登入畫面,一般來說需要輸入身份證之類的資料才能使用。

上面提到的就是所謂的強制門戶(Captive Portal),這個功能是讓使用者驗證的階段改用網頁來進行,因為透過網頁就可以做到同一組帳號密碼在任何地方都能登入的功能,這跟大家在家裡使用的密碼登入的原理不同,前者是先讓使用者連接再驗證而後者是先驗證密碼再讓人連接。

事先聲明

  • 本篇教學提到的任何漏洞僅用於教學,不得用於非法用途
  • 所有的測試不保證在所有的環境皆可使用,僅在我本人的電腦上測試成功

在實驗前我需要準備什麼?

軟體跟硬體在這次的實驗都有需要準備的東西,而且我建議你需要有一定的基礎網路知識再開始學習,因為我不對再對一些基本的知識做解釋。

硬體

  • 一台主機
    • 可以是電腦、樹苺派等,但是我推薦使用 Linux 作業系統,Windows 理論上也做到的但我沒有實驗過
  • 一台可以連接 Wi-Fi 的設備
    • 用於測試,我推薦使用 Android、Windows、iOS 方便測試
  • 一台 AP
    • 可以不用是無線路由器,也可以是無線網卡,但是需要注意在生產環境上我不推薦使用無線網卡

軟體

因為我本人僅在 kali Linux 上實驗,因此我不提供其它作業系統的軟體,如果有需要請自行到網路上尋找

  • iptables
    • 核心部份,用於做 NAT
  • Dnsmasq
    • 因為要觸發 Captive Portal 需要有 DNS 的協助,可以使用其它 DNS 伺服器軟體
    • 本次實驗因為使用了無線網卡,因此在 Linux 需要手動做 DHCP,而 Dnsmasq 剛好有 DHCP 的功能
  • web server
    • 需要準備一個用於驗證使用者的網頁,本次實驗使用 flask
    • 這部分也是最核心的部分,驗證和一般的網頁服務沒有差別
  • hostapd
    • 這次的實驗我使用了 TL-WN722N 這款無線網卡做為熱點,你可以選擇任何可以做到熱點功能的網卡,在生產環境中我不推薦使用無線網卡,應該使用無路路由器

強制門戶是怎麼做到的?

當一台手機連接到帶有 Captive Portal 的 AP 時,手機會先發起一條 DNS 請求,這條 DNS 請求一般來說會解析到一個事先約定好的網站,而當 AP 需要驗證或者不可用的時候則會返回其它的結果,手機也是靠這點做到判斷一個熱點有沒有網路及需不需要驗證。當 DNS 請求被解析後如果網站並非手機預其的網站則會將使用者跳轉到 Captive Portal,此時只需要驗證成功就可以連上網路。

需要注意到提供驗證的網頁不可為 HTTPS,因為手機預期的域名和登入畫面上的憑證不同,因此會出現網站不安全的狀況。

技術細節

上敘提到的 DNS 請求在不同的裝置上也有所不同,下方是常見的 DNS 請求列表:

  • clients3.google.com
  • connectivitycheck.gstatic.com
  • connectivitycheck.android.com
  • detectportal.firefox.com
  • www.msftncsi.com
  • captive.apple.com

上面那些域名就是每個不同的系統用來判斷是否可以連線及是否有 Captive Portal 的基準,因此想要觸發強制門戶的方法就是透過 iptables 的 NAT 表中的 PREROUTING 鏈做到的,因為 DNS 是明文請求,因此只需要目標為 53 號端口的連結指向到 DNS 伺服器就可以做到重定向,而這裡的 DNS 伺服器需要自行架設,這次的實驗使用 Dnsmasq。

開始實驗吧

我假設大家都已經準備好了軟硬體,因此這邊我就直接跳過安裝階段

  1. 將要用來處理驗證的介面卡準備好,可以是無線網卡或者路由器,接著將介面卡指定一個 IP,需要注意這裡的子網域應該要是 /24 才能分配給其它連入的裝置 IP

  2. 先準備好 iptables,下方我提供一個我寫的範例,我強烈建議將註解讀一篇,在理解了之後才能在自己的主機上也做出一樣的效果

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!bin/sh

# 下面兩個是最主要的變數
# INTERFACE 代表的是 AP 的介面,不論這邊使用的是無線網卡還是路由器都是一樣的
# WEBSERVER 代表的是提供驗證的網頁伺服器,要確定是可以連接到的
INTERFACE=wlan0
WEBSERVER=192.168.0.68

# 下面四條會把 filter 和 nat 表完全清空,實驗為了方便才會清空,執行前請特別注意
iptables -t filter -F
iptables -t nat -F
iptables -t filter -X
iptables -t nat -X

# FORWARD 鏈預設設為 DROP
# 這步非常的重要,否則就會發生未經驗證,但是卻可以透過 IP 直接對外連接的狀況。實際上的表現為有些時候可以連接有些時候不行
iptables -P FORWARD DROP

# AUTHORIZED 這條鏈用於新增已經驗證的使用者
iptables -N AUTHORIZED
# 當使用者發送封包的時候先到 AUTHORIZED 檢查,如果未經驗證的話則會往下一條
iptables -A FORWARD -i $INTERFACE -j AUTHORIZED
# 放行所有由介面卡流出的封包,因為在輸入已經做到管制,因此輸出一般來說不就做管制
iptables -A FORWARD -o $INTERFACE -j ACCEPT

# AUTHORIZED 這條鏈用於新增已經驗證的使用者
# 需要注意 filter 和 nat 的鏈不共用
iptables -t nat -N AUTHORIZED
# 將已經驗證的使用者跳過 DNS 重定向
iptables -t nat -A PREROUTING -i $INTERFACE -j AUTHORIZED
# 如果前一翛規則還沒驗證通過則進行 DNS 自定向
iptables -t nat -A PREROUTING -i $INTERFACE -p udp --dport 53 -j DNAT --to-destination $WEBSERVER:53
# 因為實驗中的主要透過 eth0 來連入外網,因此需要做 SNAT 才能連上外網
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
  1. 準備好 Dnsmasq,下面我一樣寫了一個範例,如果你使用自己的 DNS 軟體再自行研究
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 指定介面卡,這裡的介面卡和第一步的介面卡相同
interface=wlan0
# 要監聽哪個 IP,和第一步的指配給介面卡的 IP 相同
listen-address=10.1.0.1
# 設定分配的連入裝置的 IP 子網域
dhcp-range=10.1.0.2,10.1.0.254,1h
# 設定分配的連入裝置的 IP 子網域遮罩
dhcp-option=1,255.255.255.0
# 設定分配的連入裝置的預設 DNS 伺服器,需要注意這裡的 DNS 不可以是用於重定向的伺服器,否則會造成設備強制門戶偵測錯誤
dhcp-option=6,1.1.1.1

# DNS 監聽埠號
port=53

# 下面代表將 Captive Portal 偵測用的域名重定向到自己的 DNS 伺服器
# 下面三個是 Android 的偵測域名,別的廠排可能會有別的域名,這點再自行測試
address=/clients3.google.com/10.1.0.1
address=/connectivitycheck.gstatic.com/10.1.0.1
address=/connectivitycheck.android.com/10.1.0.1
# 下面為 Firefox 瀏覽器的偵測域名
address=/detectportal.firefox.com/10.1.0.1
# 下面為 Windows 的偵測域名
address=/www.msftncsi.com/10.1.0.1
# 下面為 Apple 產品的偵測域名
address=/captive.apple.com/10.1.0.1
  1. 準備用於驗證的網頁伺服器,因為伺服器會有各種需求,以下為簡易的範例,實際上的驗證伺服器並不會這麼簡單
    • 本次實驗使用的網頁後端為 Python 的 Flask,其它框架理論上也可以做到相同的事
    • 驗證伺服器和普通的網頁服務一樣,所有該注意的漏洞一樣也需要注意,而且因為其特殊性更需要注意,下方這個案例就說明了不正確的設定會造成什麼樣的狀況
  1. 確定 Dnsmasq、iptables、熱點、驗證伺服器都已經啟動,此時連線後應該會自動跳轉到驗證伺服器,再輸入帳號密碼後則會連線成功

結論

強制門戶可以在 2024 年已經不在那麼的常見,大部分的學校都已經改為 WAP2-Enterprise 這種驗證方式,雖然這樣的驗證方式在錯誤的配置方式仍然充滿了漏洞,但這還是比強制門戶好了很多,因為強制門戶相對有比較多的漏洞可以繞過驗證。

這次的實驗我花了很多時間在除錯上,也是第一次知道強制門戶是怎麼樣做到在連入的時候跳出登入畫面的,算是解答了我多年前的疑惑。

Licensed under CC BY-NC-SA 4.0
使用 Hugo 建立
主題 StackJimmy 設計