【長い前奏曲をお詫びします】途中で質問します。]
VPNサーバーがルートを1つのクライアント(以下「ルーター」と呼びます)にプッシュバックし、サーバーを実行しているマシンとVPNクライアントを実行している他のマシンに独自のサブネットを公開できるOpenVPNセットアップが機能しています。これは、ルーターにSNAT
のiptables
ターゲットを使用させるだけで実現できます。したがって、たとえば、VPNサーバーと他の区別のないクライアントが10.0.77.0/24ネットワーク上にあり、VPNが192.168.252.0/24をカバーする_tun0
_インターフェイスを作成し、プライベートサブネットが192.168.33.0/24であるとします。 OpenVPNサーバーの構成は(とりわけ)
_client-to-client
route 192.168.33.0 255.255.255.0
Push "route 192.168.33.0 255.255.255.0"
_
Linuxの「ルーター」マシンである192.168.33.10がVPNに接続すると、ルートがプッシュされるため、テーブルは次のようになります。
_192.168.33.0 * 255.255.255.0 U 0 0 0 eth1
192.168.252.0 192.168.252.5 255.255.255.0 UG 0 0 0 tun0
192.168.252.5 * 255.255.255.255 UH 0 0 0 tun0
_
そしてそれは実行するように構成されています
_sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 192.168.252.0/24 -j SNAT --to-source 192.168.33.10
_
ファイアウォールを作成するためにいくつかのiptables
ルールを追加することもできますが、OpenVPNサーバー(または別のクライアント)を実行しているマシンがたとえば192.168.33.11に接続できるようにするには、上記で十分です。パケットは_tun0
_をルーターに送信します。ルーターは、SNATを使用して送信元IPを独自の192.168.33.10に設定し、パケットを兄弟マシン192.168.33.11に転送します。応答パケットはルーターに送信され、ルーターはトンネルを介してそれらを転送し、すべて正常に動作します。たとえば、192.168.33.11では
_nc -l localhost 9999
_
そして10.0.77.13(他のVPNクライアント)から私はできます
_nc 192.168.33.11 9999
_
接続します。ここまでは順調ですね。
変更なしいずれかのネットワーク上の物理ルーターマシンに対して行われていることに注意してください。引用符で囲まれた「ルーター」(VPNクライアントを実行しているランダムなマシン)は、ネットワーク上の他のマシンがVPNを介して応答パケットを送り返すことができるようにSNATを使用する必要があります。この質問の目的上、私はどちらのネットワークも「制御」していません。独自のルーティングルールとVPNクライアントまたはサーバーを備えた一部のマシンしか追加できません。
ここで問題があります。2つのネットワーク(どちらもパブリックインターネット上にない)が実際には実際の範囲で重複しているとしましょう。したがって、この例では、プライベートサブネットは192.168.33.11ではなく、10.0.77.0/24です。そして、どちらかのネットワークの番号を付け直すことは単にオプションではないと仮定しましょう。そのため、SNATを使用してルーターがパケットを転送できるようにするだけでなく、OpenVPNサーバーの観点から、ルーターのプライベートネットワークを別のIP範囲に再マッピングする必要があります。仮想ネットワーク範囲として10.0.78.0/24を選択したとしましょう。
_route 10.0.78.0 255.255.255.0
Push "route 10.0.78.0 255.255.255.0"
_
また、OpenVPNサーバーマシンから、10.0.78.11への接続がトンネルを通過し、以前と同様にSNATで処理されるようにしたいが、ルーターのサブネット内の宛先アドレスも10.0.77.11にしたい。これを行うためにiptables
を構成するにはどうすればよいですか?
NETMAP
target looked思った通りでしたが、動作させることができませんでした。
_iptables -t nat -A PREROUTING -i tun0 -j NETMAP --to 10.0.77.0/24
iptables -t nat -A POSTROUTING -s 192.168.252.0/24 -j SNAT --to-source 10.0.77.10
_
NETMAP
ターゲットが追加されると、OpenVPNサーバーマシンから10.0.78.10(つまり、ルーターの再マップされたアドレス)にpingを実行できるため、何かを実行しています。
_tcpdump -i tun0
_
このping中にルーターで実行すると、期待どおりに_ICMP echo request
_と_ICMP echo reply
_が表示されます。しかし、10.0.78.11(つまり、ルーターのサブネット上の兄弟マシンの再マップされたアドレス)にpingを実行しようとすると、応答がなく、ルーターのtcpdump
は要求を表示しますが、応答は表示しません。 10.0.77.11(兄弟マシン)のtcpdump
は、パケットをまったく表示しません。ルーターでも実行中:
_iptables -t nat -L -v
_
NETMAP
によって処理されているパケットを示していますが、SNAT
によって処理されているパケットはありません。それで、NETMAP
ターゲットがどういうわけかSNAT
ターゲットに取って代わっているように見えますか?
基本的に私が欲しいのは、ルーターが_tun0
_でパケットを受信したときです。 10.0.78.11宛ての192.168.252.5(トンネル上のOpenVPNサーバーのアドレス)は、twoの方法で書き換えられます。宛先アドレスは10.0.77.11に変更され、送信元アドレスは10.0に変更されます。 .77.10(SNATがこれがどの接続であるかを追跡できるように、新しい送信元ポートが選択されています)。次に、10.0.77.11が10.0.77.10の偽のポートに応答を送信すると、ルーターはプロセスを逆にして、偽の送信元アドレス10.0.78.11で_tun0
_の192.168.252.5にパケットを送り返す必要があります。 NETMAP
はこれを行うことができますか、それともiptables
の他のターゲットはこれを行うことができますか?
私が成功せずに試した他のこと:プロキシARP用にルーターマシンを構成する。仮想ネットワーク範囲をルーティングテーブルに追加します。しかし、そのようなことは必要ないはずだと感じています。
更新:このコンテキストではDNSはまったく気にしません。接続する必要があるのは「プライベートサブネット」内の少数のマシンだけなので、IPアドレスの使用は許容されます。
これは大きな混乱であり、アドレスが競合する醜いNATのWebを作成するよりも、番号を付け直す方が正直に役立つでしょう。これをサポートするために必要な他のソリューション(たとえば、複数のゾーンを持つスプリットホライズンDNS、場合によっては自動更新)は困難で面倒であり、このネットワークに対処しなければならない後続のすべての人はあなたの名前を永遠に呪い、あなたとあなたのチーム。
それにもかかわらず、あなたが抱えている問題は、NATの片側にあるホストであるように見えます(参照?NATの片側を適切に説明することすらできないため、厄介です)反対側のホストに戻るパスがありません。リターンパスにもNETMAPルールを追加する必要があります(私が推測するeth1から着信するパケット)。
ちょっと待って!これは、事前ルーティングチェーンで行われます。したがって、宛先アドレスはルーティングの決定が行われる前に設定されます。これは、ほぼ同じように機能する必要があります...ただし、ルーターには「競合する」ネットワーク用に2つのルートがあります。そのため、通常の方法で優先順位が付けられ(一致するプレフィックスが最も狭いものが最初になり、タイを解除するメトリック)、一部のパケットはNATを介してルーティングされるのではなく、元のネットワークに反映されます。それらもソースネイトされます。残念ながら、送信元アドレスはルーティングで使用されないため、送信元アドレスを使用することはできません。入力インターフェイスはルーティングでも使用されません。ルーティングの決定が行われると、宛先アドレスを再度書き換えることはできません。
だから、あなたは、これを行うことはできません。 2つのオプションがあります。できれば、ネットワークアドレスが競合するサブネットの1つに番号を付け直します。これは、能力のないネットワークエンジニアではなく、優れたネットワークエンジニアであり、不必要に複雑にならないネットワークを作成するためです。 VPNサブネットの番号の付け直しは、最悪の場合sed
の使用を必要とする単純なタスクになる傾向がありますが、いずれかのサブネットの番号の付け直しが非人道的に難しいタスクであるという奇妙な状況の1つがあるかもしれません。 OK。
何らかの理由でそれができない場合は、スプリットホライズンDNSを使用するために追加のルーターが必要になります。サブネットごとにルーターを設定します(実際には、これはVPNクライアント用に1つのルーターを意味し、ネットワーク上のホスト用に1つのルーターを意味します。残念ながら、VPN用に設定したプレフィックスを使用します)。他のアドレス範囲を選択して(それ以外の場合はサブネットの1つに番号を付け直すことができるものにする必要があります...)、「外部」のものにします。
ここで、VPNホスト側Aのネットワークと、非VPNホスト側Bのネットワークを呼び出すとします。ルーターAで、「外部」プレフィックスを192.0.2.0/24に選択し、ルーターBで、それは198.51.100.0/24です。これらは、そのサブネット上のホストが他のサブネット上の競合するプレフィックスを持つホストに接続するために使用する偽のプレフィックスになります(RFC5737で文書化の目的で予約されているこれらを使用しないでください)。
以下のルールは、POSTROUTINGチェーンの述語として入力インターフェイスを使用できず、ソースサブネットが一意ではないため、複雑です。そのため、フィルタールールを使用してなりすましを防止する必要があります。また、NETMAPは、どのチェーンに含まれているかに基づいて送信元アドレスと宛先アドレスのどちらを変更するかを決定するため、混乱を招きます。
ルーターAとBで、ルーター間のポイントツーポイントリンクでの着信トラフィックのルールを追加します。これをptp0と呼びます。
router-a # iptables -t nat -A PREROUTING -i ptp0 -d 198.51.100.0/24 -j NETMAP --to 10.0.77.0/24
router-a # iptables -t nat -A POSTROUTING -d 10.0.77.0/24 -j NETMAP --to 192.0.2.0/24
router-a # iptables -t filter -A FORWARD -i \!ptp0 -s 10.0.77.0/24 -j DROP
router-b # iptables -t nat -A PREROUTING -i ptp0 -d 192.0.2.0/24 -j NETMAP --to 10.0.77.0/24
router-b # iptables -t nat -A POSTROUTING -d 10.0.77.0/24 -j NETMAP --to 198.51.100.0/24
router-b # iptables -t filter -A FORWARD -i \!ptp0 -s 10.0.77.0/24 -j DROP
これで、ルーティングテーブルに両方のプレフィックスを持つ単一のルーターがなくなったため、問題のこの部分は解決されました。同じルーティングテーブル内の2つの異なるホストを持つ2つの異なるネットワークを参照する同じプレフィックスを持つ必要があるソリューションは機能しません。ルーティングがどのように機能するかにより、本質的に不可能です。
ああ、私はほとんど忘れていました-一致するものがないため、SNATルールは処理されていないと思いますが、接続がNAT状態テーブルに格納されると、処理されなくなることを覚えておくことが重要です。 SNATルールにより、思い出すと統計にカウントされなくなりました。
実際にサブネットを分離する必要がない場合は、レイヤー2ブリッジングを使用してください。それはあなたの人生をずっと楽にしてくれるでしょう。
そこで、Vagrantを使用して自己完結型の snat-routing-demo を作成する作業を行いました。コントロールとして、最初は単純なSNAT
を使用し、VPNクライアントはサービスの実際のIPを直接参照し、OpenVPNのセットアップなどの詳細を明らかにしました。次に、仮想サブネットを導入し、NETMAP
の前にSNAT
をテーブルに追加しました。
iptables -t nat -A PREROUTING -d <virtual-subnet> -j NETMAP --to <actual-subnet>
うまくいった。私は実際の環境でこのかなり単純なルールをすでに試したと思っていましたが、おそらく試していなかったか、何か他のものが壊れていました。とにかく、私は類似のルールを「実際に」機能させることもできます。マークの使用は必要ないようで、
iptables -t nat -L -v
両方のルールが適用されていることが表示されます。
ブリッジされたサブネット内のどのホストとポートにVPNクライアントからアクセスできるかを制限するファイアウォールルールも、実際のIP範囲を使用して、変更されずに機能しているように見えました。
iptables -A FORWARD -p tcp -d <actual-Host> --dport <some-port> -j ACCEPT
iptables -A FORWARD -s <actual-subnet> -j ACCEPT
iptables -P FORWARD DROP
私はあなたの意図を幾分誤解したかもしれない他の答えを信じています、それを考えてみてください。
私があなたを正しく理解していれば、2つのサイト間にVPNリンクがあり、2つのサイト間でトラフィックをルーティングすることになっています。しかし、残念ながら、2つの(以前は独立していた)サイトは両方とも、サブネットに同じRFC1918アドレスを使用することになりましたね。これは、RFC1918の最も厄介な緊急プロパティの1つです。
それでも、最善の解決策は、サブネットの1つに番号を付け直すことです。ただし、それができない場合は、このマッピングを実行しようとしても悪い解決策ではありません。
ただし、ルールにはいくつかのエラーがあります。
SNATルールは、openvpnクライアントルーター自体のパケット以外のものと一致しないため、多くのトラフィックをログに記録していません。 VPNリンクからのパケットの送信元アドレスは10.0.77.0/24の範囲です。したがって、パケットはVPNを通過して反対側に出てきますが、パケットへの応答はVPNを介して返されるのではなく、ローカルセグメントに送信されるため、失われます。
順方向パスの宛先アドレスを区別するためにネットワークプレフィックスのふりを作成する必要があるのとほぼ同じ方法で、逆方向パスアドレスも区別可能である必要があります。これがSNATを使用している理由だと思います。したがって、ルールを修正する必要があります(また、NETMAPの内容についても具体的にして、VPN経由で送信されるすべてのサブネットのすべての宛先アドレスの最初の3オクテットを書き換えないようにします)。
iptables -t mangle -A PREROUTING -i tun0 -j MARK --set-mark 1
iptables -t nat -A PREROUTING -i tun0 -d 10.0.78.0/24 -j NETMAP --to 10.0.77.0/24
iptables -t nat -A POSTROUTING -s 10.0.77.0/24 -m mark --mark 1 -j SNAT --to-source 10.0.77.10
POSTROUTINGルールで入力インターフェイスを述語として使用できないため、マングルルールが必要です。したがって、パケットがVPNリンクから送信され、送信元NATが必要であるかどうかを判断する別の方法が必要です。