透明代理是個好東西。隨着技術的發展,一些老的工具逐漸體現出各種問題並停止維護,浅羽終於也更換到了基於 Clash 包裝的 OpenClash。雖然 Clash 本身有一些爭議,但配合 OpenClash 使用 LuCI 加上網路上的規則,稍加自定就很獲得不錯的使用體驗,只有一個最大的問題——無論如何都無法連線家中的 VPN 伺服器。
浅羽的 VPN 伺服器並沒有直接架設在 OpenWRT 上,而是位於區域網路內 192.168.0.2
上並透過 port forwarding 接受外部連線。起初浅羽以爲是 port forwarding 及 firewall 設定問題,但幾經調整都無果。偶然查看了 VPN 伺服器的日誌,才發現客戶端其實已經與伺服器取得連線,卻因 TLS handshake timeout
無法成功認證。回想近期對網路的調整,浅羽開始懷疑 Clash 的問題,於是增加了一條 SRC-PORT,1194,DIRECT
規則,並在 Clash 中觀察到也已經直接連線,但客戶端依然提示連線失敗。
透過搜尋工作,浅羽找到並參考了一些相關的問題報告:
- vernesong/OpenClash#525:开启OpenClash之后防火墙的端口转发失效
- vernesong/OpenClash#146:关于 tun 模式和端口转发的问题
- Dreamacro/clash#432:开启clash后,由外网访问内网服务,无法建立连接,connection refused
其中有回覆提到:
@neroanelli 分析的挺对的,就是包来回的路径不一样。SYN 通过主路由直接发到内网机器上,SYN ACK 发给Clash了,除非 Clash 使用 Raw Socket 特别处理这样的数据包,否则 Clash 没有任何办法处理此类 SYN ACK。
同時有幾位評論者都指出:在 mangle
表中增加規則過濾不希望經過 Clash 的流量可以解決問題。那麼按這個思路在 OpenWRT 上的 iptables
增加一條規則,匹配 host 與 port,使相關流量直接從 PREROUTING
鏈 RETURN
:
# iptables -t mangle -I PREROUTING -p udp -s 192.168.0.2 -m multiport --sports 1194,51820 -j RETURN
確認一下規則生效並且排在 Clash 相關規則前:
# iptables -t mangle -L PREROUTING
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
RETURN udp -- 192.168.0.2 anywhere multiport sports openvpn,51820
openclash all -- anywhere
再在客戶端嘗試一下就可以成功連線了,同時訪問區域網路及使用透明代理都沒有問題。
總要一邊一邊地刪除加入防火牆規則非常麻煩,如果遇到不在家中、VPN 又連線不上的情況就更惱火了。那麼有什麼辦法可以在 Clash 重新啓動之後自動修改好防火牆規則呢?
研究一下 OpenClash 包裝的規則,主要的啓動和停止都寫在 luci-app-openclash/root/etc/init.d/openclash
中,其中在 set_firewall()
函式中主要處理了防火牆規則的增加。因此在函式最後添加上幾句:
iptables -t mangle -I PREROUTING -p udp -s 192.168.0.2 --sport 1194 -j RETURN
iptables -t mangle -I PREROUTING -p udp -s 192.168.0.2 --sport 51820 -j RETURN
順便在 revert_firewall()
函數最後也添加相反的指令:
iptables -t mangle -D PREROUTING -p udp -s 192.168.0.2 --sport 51820 -j RETURN
iptables -t mangle -D PREROUTING -p udp -s 192.168.0.2 --sport 1194 -j RETURN
# 爲什麼縮進是三個空格?
這樣最起碼 Clash 重新啓動時不會把自己擋在家門外了。
發佈留言