web-dev-qa-db-ja.com

信頼性の低いネットワークを介した高度なLinuxルーティングを備えた冗長OpenVPN接続

私は現在、多くのWebサイトをブロックし、外界へのネットワーク接続の信頼性が低い国に住んでいます。 Linuxサーバー上に2つのOpenVPNエンドポイント(たとえば、vpn1とvpn2)があり、ファイアウォールを回避するために使用しています。私はこれらのサーバーに完全にアクセスできます。これは、VPN接続でのパッケージ損失が大きいことを除けば、非常にうまく機能します。このパケット損失は、時間に応じて1%から30%の間で変動し、相関が低いように見えます。ほとんどの場合、ランダムに見えます。

両方のエンドポイントへのOpenVPN接続を維持し、すべてのパケットを両方のエンドポイントに2回送信するホームルーター(Linuxでも)をセットアップすることを考えています。 vpn2は、すべてのパケットをホームからvpn1に送信します。リターントラフィックは、vpn1からホームに直接送信されるか、vpn2を介して送信されます。

       +------------+
       |    home    |
       +------------+
        |          |
        | OpenVPN  |
        |  links   |
        |          |
     ~~~~~~~~~~~~~~~~~~ unreliable connection
        |          |
+----------+   +----------+
|   vpn1   |---|   vpn2   |
+----------+   +----------+
        |
       +------------+
       | HTTP proxy |
       +------------+
             |
         (internet)

明確にするために、ホームとHTTPプロキシ間のすべてのパケットは複製され、異なるパスを介して送信され、そのうちの1つが到着する可能性が高くなります。両方が到着した場合、最初の2番目のものは黙って破棄できます。

ホーム側とエンドポイント側の両方で、帯域幅の使用は問題ではありません。 vpn1とvpn2は互いに近く(3ms ping)、信頼性の高い接続があります。

Linuxで利用可能な高度なルーティングポリシーを使用してこれをどのように達成できるかについての指針はありますか?

9
konrad

@ user48116から提供された回答を使用しましたが、それは魅力のように機能します。セットアップは実際には非常に簡単です!

[〜#〜] note [〜#〜]:これはすでに問題を解決しているので、1つのサーバーへの2つの接続でこれを実装しました。 2台のサーバーでセットアップを試したい場合、最も簡単な方法は、ポート転送を使用して2番目のサーバーから最初のサーバーにUDPポートを転送し、ここで説明したのと同じレシピを使用することです。私はこれを自分でテストしていません。

まず、ボンディングをサポートする2.6カーネル(最新のすべてのディストリビューションではデフォルト)があり、ifenslaveがインストールされていることを確認してください。

次に、これを/etc/rc.localまたはその他の任意の場所に配置しますが、実行されていることを確認してくださいbefore 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パッケージに対してfour応答が表示されます。パッケージはローカル側で複製され、これら2つのパッケージへの応答はリモート側で再び複製されます。 TCPはすべての重複を単に無視するため、これはTCP接続では問題になりません。

重複を処理するのはソフトウェア次第であるため、これはUDPパケットの問題です。たとえば、DNSクエリは、予想される2つではなく4つの応答を生成します(応答には、2回ではなく通常の4倍の帯域幅を使用します)。

# 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)

幸運を!

7
konrad

「ホーム」側と「vpn1」側でボンディングインフラストラクチャを使用します。具体的には、ボンドに属するすべてのインターフェイスでトラフィックをブロードキャストするmode = 3設定を使用します。

ボンディングの構成方法の詳細については、 http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.37.y.git;a)の優れたマニュアルを参照してください。 = blob; f = Documentation/network/bonding.txt; h = 5dc638791d975116bf1a1e590fdfc44a6ae5c33c; hb = HEAD

8
jap