通過不可靠的網路使用高級 Linux 路由的冗餘 OpenVPN 連接
我目前生活在一個阻止許多網站並且與外界的網路連接不可靠的國家。我在用於繞過防火牆的 Linux 伺服器上有兩個 OpenVPN 端點(例如:vpn1 和 vpn2)。我可以完全訪問這些伺服器。這工作得很好,除了我的 VPN 連接上的高包失去。這種丟包率在 1% 到 30% 之間變化,具體取決於時間,並且似乎具有低相關性,大部分時間它似乎是隨機的。
我正在考慮設置一個家庭路由器(也在 Linux 上),它維護到兩個端點的 OpenVPN 連接,並將所有數據包發送兩次,到兩個端點。vpn2 會將所有數據包從家裡發送到 vpn1。返回流量將直接從 vpn1 發送到家中,也可以通過 vpn2 發送。
+------------+ | home | +------------+ | | | OpenVPN | | links | | | ~~~~~~~~~~~~~~~~~~ unreliable connection | | +----------+ +----------+ | vpn1 |---| vpn2 | +----------+ +----------+ | +------------+ | HTTP proxy | +------------+ | (internet)
為了清楚起見:家庭和 HTTP 代理之間的所有數據包都將被複製並通過不同的路徑發送,以增加其中一個到達的機會。如果兩者都到達,則可以靜默丟棄第一個第二個。
無論是在家庭端還是端點端,頻寬使用都不是問題。vpn1 和 vpn2 彼此靠近(3ms ping)並且連接可靠。
關於如何使用 Linux 中可用的高級路由策略來實現這一點的任何指示?
我使用了@user48116 提供的答案,它就像一個魅力。設置其實很簡單!
注意:我通過兩個連接到一台伺服器來實現這一點,因為這已經解決了我的問題。如果您想嘗試使用兩台伺服器進行設置,最簡單的方法可能是使用埠轉發將 UDP 埠從第二台伺服器轉發到第一台,並使用與此處所述相同的方法。我自己還沒有測試過。
首先,確保你有一個支持綁定的 2.6 核心(在所有現代發行版中都是預設的)並且你已經安裝了 ifenslave。
接下來,將其放入您的 /etc/rc.local 或您喜歡的任何其他位置,但請確保它在 openvpn 啟動之前執行(因為它會嘗試綁定到 bond0):
客戶:
modprobe bonding mode=broadcast ifconfig bond0 10.10.0.2 netmask 255.255.255.0 up
如果需要,您可以在此處添加一些路由,但請確保您也從另一側執行所有正確的路由。
route add -net 10.7.0.0/24 gw 10.10.0.1
伺服器:
modprobe bonding mode=broadcast ifconfig bond0 10.10.0.1 netmask 255.255.255.0 up
創建 /etc/openvpn/tap-up.sh 腳本(不要忘記使用 chmod a+x tap-up.sh 將其標記為可執行):
#!/bin/sh # called as: cmd tap_dev tap_mtu link_mtu ifconfig_local_ip ifconfig_netmask [ init | restart ] ifenslave bond0 "$1"
接下來,將 bridge0a.conf 和 bridge0b.conf 添加到 /etc/openvpn/ 以及共享密鑰。a 和 b 的文件相同,但埠不同(例如,b 使用 3002)。將 11.22.33.44 替換為您伺服器的公共 IP。
客戶:
remote 11.22.33.44 dev tap port 3001 rport 3001 secret bridge.key comp-lzo verb 4 nobind persist-tun persist-key script-security 2 up /etc/openvpn/tap-up.sh
伺服器:
local 11.22.33.44 dev tap port 3001 lport 3001 secret bridge.key comp-lzo verb 4 script-security 2 up /etc/openvpn/tap-up.sh
不要忘記編輯 /etc/defaults/openvpn 以確保您的新 VPN 配置已啟動。重啟你的機器,或者載入 rc.local 並手動重啟 openvpn。
現在您已準備好測試您的設置:
# ping 10.10.0.1 PING 10.10.0.1 (10.10.0.1) 56(84) bytes of data. 64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=50.4 ms 64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=51.1 ms (DUP!) 64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=51.1 ms (DUP!) 64 bytes from 10.10.0.1: icmp_req=1 ttl=64 time=51.1 ms (DUP!) 64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=52.0 ms 64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=52.2 ms (DUP!) 64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=53.0 ms (DUP!) 64 bytes from 10.10.0.1: icmp_req=2 ttl=64 time=53.1 ms (DUP!) --- 10.10.0.1 ping statistics --- 2 packets transmitted, 2 received, +6 duplicates, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 50.428/51.786/53.160/0.955 ms
如果一切順利並且線路良好,您將看到每個 ICMP 包的四個回复:您的包在本地端複製,而對這兩個包的回复在遠端端再次複製。這對於 TCP 連接來說不是問題,因為 TCP 將簡單地忽略所有重複項。
這是 UDP 數據包的問題,因為處理重複數據取決於軟體。例如,DNS 查詢將產生四個回复,而不是預期的兩個(並且使用正常頻寬的四倍而不是兩倍):
# tcpdump -i bond0 -n port 53 listening on bond0, link-type EN10MB (Ethernet), capture size 65535 bytes 13:30:39.870740 IP 10.10.0.2.59330 > 10.7.0.1.53: 59577+ A? serverfault.com. (33) 13:30:40.174281 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49) 13:30:40.174471 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49) 13:30:40.186664 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49) 13:30:40.187030 IP 10.7.0.1.53 > 10.10.0.2.59330: 59577 1/0/0 A 64.34.119.12 (49)
祝你好運!
在“home”和“vpn1”端使用綁定基礎設施,特別是使用 mode=3 設置,在屬於綁定的所有介面上廣播流量。
有關如何配置綁定的更多資訊,請參閱http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.37.y.git;a=blob;f上的優秀手冊=文件/網路/bonding.txt;h=5dc638791d975116bf1a1e590fdfc44a6ae5c33c;hb=HEAD