
2つの異なるサブネットに接続されている2つのインターフェースを持つサーバーがありますdhcp
。これら2つの異なるサブネットは、2つの異なるインターフェイスを介して同じスイッチに接続されます。
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
23: enp10s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether c4:00:ad:a4:e3:38 brd ff:ff:ff:ff:ff:ff
inet 192.168.201.232/24 brd 192.168.201.255 scope global enp10s0
valid_lft forever preferred_lft forever
25: enp11s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether c4:00:ad:a4:e3:39 brd ff:ff:ff:ff:ff:ff
inet 192.168.203.3/24 brd 192.168.203.255 scope global enp11s0
valid_lft forever preferred_lft forever
inet6 fe80::c600:adff:fea4:e339/64 scope link
valid_lft forever preferred_lft forever
路線:
# ip r
default via 192.168.201.1 dev enp10s0
192.168.201.0/24 dev enp10s0 proto kernel scope link src 192.168.201.232
192.168.203.0/24 dev enp11s0 proto kernel scope link src 192.168.203.3
まず、ノートブックでpingを実行して、そのデバイスのtcpdumpを介して要求と応答を192.168.201.232
表示できます。icmp
# tcpdump -s 0 -i any -vvv -nn 'host 192.168.1.30 and not port 22'
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
11:42:05.240967 IP (tos 0x0, ttl 62, id 53809, offset 0, flags [none], proto ICMP (1), length 84)
192.168.1.30 > 192.168.201.232: ICMP echo request, id 55768, seq 1, length 64
11:42:05.240994 IP (tos 0x0, ttl 64, id 42288, offset 0, flags [none], proto ICMP (1), length 84)
192.168.201.232 > 192.168.1.30: ICMP echo reply, id 55768, seq 1, length 64
pingを実行しても192.168.203.3
応答がありません。 tcpdump 出力は次のようになります。
# tcpdump -s 0 -i any -vvv -nn 'host 192.168.1.30 and not port 22'
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
11:43:57.037535 IP (tos 0x0, ttl 62, id 19363, offset 0, flags [none], proto ICMP (1), length 84)
192.168.1.30 > 192.168.203.3: ICMP echo request, id 55808, seq 1, length 64
11:43:58.060756 IP (tos 0x0, ttl 62, id 19364, offset 0, flags [none], proto ICMP (1), length 84)
192.168.1.30 > 192.168.203.3: ICMP echo request, id 55808, seq 2, length 64
このパケットはどうなりますか?
なぜicmp
答えがないのですか?私のIPは次のようなので、応答がデフォルトのgw()に移動したいと
思います。icmp
192.168.201.1
192.168.1.30
何もなくiptables
、ステッドも上がりませんnetstat -s
。
DHCPを削除しましたが、インターフェイスにenp10s0
IPが付与されていないため、ルートは1つだけ残ります。
# ip r
default via 192.168.203.1 dev enp11s0
192.168.203.0/24 dev enp11s0 proto kernel scope link src 192.168.203.3
私のラップトップからpingを送信すると動作192.168.203.3
します。
答え1
常に追加のルーティングの複雑さが発生するマルチホームサーバーがあります。
ネットワークは多少複雑な場合がありますが、次のように見えます。
┏━━━━━━┓
┃laptop┃
┗━━━━━━┛
192.168.1.30/24
┊
lan1
┊
192.168.1.1/24
┌─────────┐
│ clients │
│ router │
└─────────┘
x.x.x.x
┊
y.y.y.y
┌─────────┐
192.168.201.1/24 servers 192.168.203.1/24
╭┄┄┄┄┄┄┄┄┄┄┄┄┄│ router │┄┄┄┄┄┄┄┄┄┄┄┄┄╮
┆ └─────────┘ ┆
┆ ┆
lan201 lan203
┆ ┆
┆ ┏━━━━━━━━━┓ ┆
╰┄┄┄┄┄┄┄┄┄┄┄┄┄┃ ┃┄┄┄┄┄┄┄┄┄┄┄┄┄╯
192.168.201.232/24 server 192.168.203.3/24
┃ ┃
┗━━━━━━━━━┛
パケットが無視されるのはなぜですか?
問題は、「なりすまし保護」という機能が有効になっているサーバーによって発生した可能性があります。厳格なリバースパスの転送(SRPF).つまり、着信パケットは、応答が同じインターフェイスを使用して再ルーティングされる場合にのみインターフェイスを通過できます。
両方のインターフェイスが設定され、デフォルトパスが192.168.201.1を使用し、ノートブックで192.168.201.232をpingすると、パケットは「左パス」を介してサーバーに移動し、「左パス」を介してサーバーから返されます。サーバーは、カーネルにルーティング決定が何であるかを尋ねることができます。
ラップトップに行く方法:
# ip route get from 192.168.201.232 192.168.1.30
192.168.1.30 from 192.168.201.232 via 192.168.201.1 dev enp10s0 uid 0
cache
使用enpu10s0。
私たちは同じ着信パケットを持っています(enpu10s0)これがサーバーのルーターが何をするのかを知っているからです。
# ip route get from 192.168.1.30 iif enp10s0 192.168.201.232
local 192.168.201.232 from 192.168.1.30 dev lo table local
cache <local> iif enp10s0
発信パケットと同じ側にあるため、着信パケットが許可され、ローカルシステムにルーティングされます。
192.168.203.3をpingすると、パケットがルーティングされ、「正しいパス」に移動し、サーバーのルーティング構成はサーバーを「左パス」に置くようにマークされます。これは非対称パスであり、以前のSRPF検査に失敗しました。別のインターフェイスです。
この状況の決定をカーネルに再要求することができます。応答(存在する場合)は、次のようにルーティングされます。
# ip route get from 192.168.203.3 192.168.1.30
192.168.1.30 from 192.168.203.3 via 192.168.201.1 dev enp10s0 uid 0
cache
デフォルトパスを使用するためenpu10s0、受信データパケット:
# ip route get from 192.168.1.30 iif enp11s0 192.168.203.3
RTNETLINK answers: Invalid cross-device link
着信インターフェイスのためにSRPFによって拒否されました。enpu11s0発信インターフェイスと一致しません。enpu10s0このIPアドレスに応答するために使用されます。
「左パス」を無効にしてデフォルトパスを変更し、「右パス」からDHCPのデフォルトパスを継承すると、すべてが次に変更されます。enpu11s0再び動作します。
どのように機能させるのですか?
あまり役に立たないかもしれないもの
システムに通知できます。障害を負う確認するか安心到着する緩いリバースパスの転送。存在するデフォルトパスの場合、両方の効果は似ていますが(つまり、まったく効果が大きくはありません)、Linuxでこれを軽減する(設定2)ことは、有効にしたときに無効にする(0に設定する)よりも面倒です。このため、他の場所では簡単にこの構成では、最大の値が勝ちます。。システムの起動時に有効にすることができます。
/etc/sysctl.d
(YMMV)そこから編集できます。だから:sysctl -w net.ipv4.conf.enp11s0.rp_filter=2
以前のクエリはもはや失敗しません。
# ip route get from 192.168.1.30 iif enp11s0 192.168.203.3 local 192.168.203.3 from 192.168.1.30 dev lo table local cache <local> iif enp11s0
今2つのtcpdumpがあります。各サーバーインターフェイスに1つずつ着信パケットを表示できる必要があります。enpu11s0と発信応答enpu10s0。
ラップトップが応答を受信すると、作業は完了し、1日で通話できます。
おそらくそうではありません。パスに沿って次のネットワーク要素であるサーバーのルーター返品SRPFを実装します。あるいは、ファイアウォールとしても使用でき、192.168.201.0/24のパケットのみを許可するインターフェイスからのパケット192.168.203.3を疑わしいと見なすことができます(SRPFの目標でもある偽装防止保護)。したがって、パケットは1ステップ後に廃棄される可能性が高くなります。
仕組み:ポリシールーティング
マルチホーミングが含まれるたびに、ポリシーベースのルーティング使用する必要があります。これにより、決定セレクタとして、宛先アドレスだけでなく、さまざまなその他の基準(最も一般的にはソースアドレス)を使用してルーティングを選択できます。これにはソースアドレスも必要です。 Linuxでは、追加のルーティングテーブル(通常はターゲットをセレクタとして使用)を使用し、ルールを使用して適切なルーティングテーブルを選択します(ここではソースをセレクタとして使用)。設定はソースアドレスに依存するため、DHCPなどの動的環境に統合することは困難です。確かに可能ですが、デーモンは次のようになります。dhクライアントまたはネットワーク管理者それぞれにスクリプトに挿入する独自のフックセットがあり、静的IPアドレス設定を使用してこれらのアドレスをDHCPサーバーに予約して宣言することで時間を節約できます。
基本表へのパスは、追加表に部分的にコピーする必要があります。サーバーがルーターでもある場合(たとえば、LXC、Docker、VMの実行など)、より多くのパスを考慮する必要があり、他のルーティングテーブルにコピーすることもできます。もちろん、これらのパスが動的(コンテナの実行中に表示される)の場合、構成はより複雑になります。いつものように、
ip route get
ここにはたくさんの助けがあります。したがって、各エンドに対してルーティングテーブルを作成し(このテーブルにはランダムではない値201と203を使用します)、このエンドに関して必要なものだけをコピーします。追加各デフォルトパスの1つです。それでも、デフォルトのパスは 1 つしか使用できませんが、パステーブルごとに 1 つしか使用できません。ここにデフォルトルートを追加するだけでルーティングの問題を解決できます(実際にはルーティングテーブル203のみが必要です)。レイアウトが変更された場合(パスコンテナなど)、以前に追加する必要がないと思われたパスを再検討する必要があります。また、常に使用されていなくても、デフォルトのルートはデフォルトのルーティングテーブルに保持する必要があります。これが「デフォルト」のデフォルトパスになります。デフォルトパスは、ソースIPアドレスが定義されていない状態でサーバーがクライアントに接続されたときの自動選択に影響します。
ip route add table 201 default via 192.168.201.1 ip route add table 203 default via 192.168.203.1
ソースベースのルールを使用して選択します。
ip rule add from 192.168.201.232 lookup 201 ip rule add from 192.168.203.3 lookup 203
結果:
# ip route get from 192.168.203.3 192.168.1.30 192.168.1.30 from 192.168.203.3 via 192.168.203.1 dev enp11s0 table 203 uid 0 cache
アウトバウンドインターフェイスが次に切り替わります。enpu11s0ルーティングテーブル203を使用する。
# ip route get from 192.168.1.30 iif enp11s0 192.168.203.3 local 192.168.203.3 from 192.168.1.30 dev lo table local cache <local> iif enp11s0
したがって、同じインターフェイスから着信パケットは同じインターフェイス(SRPF)に失敗しません。
サーバールーターが複雑になりません。ノートブックのpingは両方のアドレスで動作します。
サーバーで送信元アドレスを選択できるクライアントアプリケーションは、トラフィックが選択したパスを間接的に変更します(たとえば、通常は
curl --interface 192.168.203.3 192.168.1.30
変更ping -I 192.168.203.3 192.168.1.30
しping -I enp11s0 192.168.1.30
ません)。ただこの設定の理由は、ここで詳しく説明されています。SF Q&A私)それはうまくいくでしょう。
注:UDPサービス
上記の最後の項目の構成により、TCPサービスが正常に機能します。しかし、BSDソケットAPIがデフォルトで動作する方法のため、UDPには十分ではありません。
受信TCPソケットがすべてのアドレス(INADDR_ANY:0.0.0.0)にバインドされ、クライアント接続が許可されているaccept(2)
場合(使用新しいTCPソケットが自動的に作成され、照会された(ローカル)宛先がバインディングアドレスとして選択されます。新しいTCPソケットが適切なアドレスにバインドされるため、応答時間にそのアドレスがルーティングスタックに送信元アドレスとして提供され、上記のように適切なルーティングルールを選択します。 TCP Allが適しています。
UDPは、INADDR_ANYにバインドするときには単純ではありません。新しいソケットは自動的に作成されません。基本的にクエリが作成された場所を通知するメカニズムはありません。したがって、応答はTCPなどの正しいソースアドレスを選択できません。 OP の場合、192.168.1.30 から 192.168.203.3 に照会すると、アプリケーションに使用可能な (ローカル) ターゲット 192.168.203.3 情報がありません。ルーティングスタックのソースアドレスの選択を延期するために、ソースアドレスをバインドせずに応答します(例:INADDR_ANY / 0.0.0.0のまま)。上記のルーティングルールは選択されず、デフォルトルーティングテーブルのデフォルトパスが使用されます。無効なパスは、192.168.203.3 ではなく、192.168.201.232 を応答ソースとして選択します。この応答がラップトップに到達しても(ルーティングの観点とSRPFの観点からは問題ありません)、ラップトップ自体はクエリを実行するために選択したアドレスからのものではないため、これを拒否します。
マルチホーム環境のサーバーアプリケーションは複数のピアで使用でき、UDPに対する特別なサポートが必要です。これを行う2つの一般的な方法があります。
INADDR_ANYの代わりに各サーバーのアドレスに個別にバインド
応答はソケットのバインディングアドレスを使用します。クエリが届いたのでこれソケットとは、ソケットが応答元アドレスとして使用するのと同じ宛先アドレス、つまりクライアントがクエリを実行し、アプリケーションソケットがバインドされているアドレスに送信されることを意味します。
たとえば、DNS サーバーは次のようになります。バインディング9アクション:サーバー上のすべての既存のアドレスに個別にバインドされます。
socat
ポート1313での日付提供の例:socat
バインドする各アドレスに対して1つずつ3つのコマンドを実行します。socat UDP4-LISTEN:1313,bind=127.0.0.1,fork EXEC:date & socat UDP4-LISTEN:1313,bind=192.168.201.232,fork EXEC:date & socat UDP4-LISTEN:1313,bind=192.168.203.3,fork EXEC:date &
ソケットオプションの使用IP_PKTINFO(または一部の* BSDではIP_RCVDSTADDR)INADDR_ANYにバインドするとき
これには特定のアプリケーションサポートが必要です。
connect(2)
あるいは、read(2)
これらのwrite(2)
UDPソケットでは使用できなくなりますが、代わりにソケットオプションによって提供されるセカンダリメッセージを処理し、他の方法を使用してクエリアドレスで使用されている実際の(ローカル)宛先を取得するrecvmsg(2)
機能sendmsg(2)
が必要です。 (に記載されているcmsg(3)
)。例えばこれがDNSサーバーがすることです束縛されていない使用時
interface-automatic
オプション。socat
はい(Linux:ip-pktinfo
、* BSDでは使用ip-recvdstaddr
):socat -u \ UDP4-RECVFROM:1313,ip-pktinfo,reuseport,fork \ SYSTEM:'exec socat -u EXEC\:date UDP4-DATAGRAM\:$SOCAT_PEERADDR\:$SOCAT_PEERPORT\,bind=$SOCAT_IP_DSTADDR\:1313\,reuseport'
1つ目
socat
は受信専用、2つ目はエミッション専用、2番目の分岐は、最初の環境変数socat
で使用できるIP_PKTINFOソケットオプションで取得された正しいソースアドレスで応答します。 (SO_REUSEPORT)は、2つの「関連していない」ソケットが同じポートを共有することを可能にする回避策です(実際のアプリケーションでは、UDPソケットはコピーまたはまったくコピーされずに直接使用されるため、これは必要ありません)。socat
reuseport
fork()
dup2(2)
答え2
すべての非リンクローカルトラフィックを1つのインターフェイスを介して送信しますが、非リンクローカルトラフィックを複数のインターフェイスを介して受信するシステムには2つの問題があります。
(ここで発生した)最初の問題はリバースパスフィルタリング(望むよりsysctl -ar '\.rp_filter'
)。この機能はデフォルトで有効になっており、応答しないトランスポートインターフェイスのパケットは破棄されます(ファイアウォールに到達する前でも)。したがって、0
受信インターフェイスとして設定する必要があります。
もう1つの問題は、ファイアウォールがトラフィックの半分だけを報告し、接続について知らないために応答パケットを破棄することです。この場合、高度なルーティング(ポリシールーティング)が必要です。man ip-rule
とを参照してくださいman ip-route
。追加のルーティングテーブルを設定し、適切なトラフィック(発信パケットの送信元アドレス)がそのルーティングテーブルを使用するようにする必要があります。これが完了すると、リバースパスフィルタリングの問題は自動的に解決されます。