任意のTCP応答パケットにfwmark反映を強制的に適用できますか?

任意のTCP応答パケットにfwmark反映を強制的に適用できますか?

TCPソケット接続応答でfwmarkが欠落している問題を解決した人はいますか?

背景:

要求が受信された同じインターフェイスから応答を送信する必要があり、他の手段(ソースベースのルーティングなど)と区別できないネットワークアウトバウンドインターフェイスをサポートする必要があります。この回答ポリシーベースのルーティングについて見てみましょう。最初は私の状況に合わないようでした。別の言葉(tcpdumpを使用してインターフェイスのトラフィックを監視し、iptablesに双方向のパケットメタデータを記録するように指示します)この時点で、私が望むように、着信パケットは実際に着信インターフェイスにタグ付けされていることがわかります。しかし、発信パケットは同じタグを保持しません!ソケット接続から簡単なping(ICMPエコー)でテストケースを簡素化し、fwmarkが欠落していることに気づいたときに、より多くの研究を行って発見しました。"fwmark_reflect" sysctlパラメータ。これを有効にすると、単純化されたテストケースの問題は解決されましたが、もちろんsysctlは「カーネルで生成されたIPパケット、それに関連するユーザーソケットがありません」にのみ影響するため、元の問題には役立ちません。 SSHなどのソケット接続...

追加サポートの詳細:

iptables パケット表示規則:

-A 事前ルーティング-i ens3 -j mark --set-mark 1 -A 事前ルーティング-i ens4 -j MARK --set-mark 2

ルーティングルール(必須ではありません。一部は重複しています):#ipルールリスト0:すべてのローカル検索0:すべてのfwmark 0x1で検索mgmt 0:すべてのfwmark 0x2で検索cust 10:すべてのfwmark 0x1から mgmt 20 検索: すべて fwmark 0x2 で cust 32766 検索: すべてでデフォルト 32767 検索: すべてでデフォルト 65536 検索: すべて fwmark 0x2 oif ens4 で cust 検索

#ip route list table mgmt
  default via 10.100.16.1 dev ens3 
#ip route list table cust

デフォルトでは、221.194.47.243 mark 2 は 10.100.16.1 dev ens4 ip パスを介して取得されます。 221.194.47.243 は 10.100.16.1 dev ens4 src 10.100.16.13 マーク 2 で取得されます。

要求と応答を反映するIptablesのログ出力(完全な往復が完了し、リモートに成功した受信が反映されます):

[27314.322482] pIng IN=ens4 OUT= MAC=00:00:17:01:8c:ff:00:00:17:01:cf:b5:08:00 SRC=10.100.21.143 DST=10.100.16.13 84 TOS=0x00 PREC=0x00 TTL=64 ID=18269 DF PROTO=ICMP タイプ=8 コード=0 ID=14889 SEQ=1 タグ=0x2

[27314.323446] pOng IN= OUT=ens4 SRC=10.100.16.13 DST=10.100.21.143 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=39688 PROTO=ICMP TYPE=0 CODE =0x2

ポート22へのソケット接続を試みると、同様の記録されたメタデータ(リモートfwmarkが失われ、ルーティングテーブルがそれを間違ったインターフェイスに送信しようとしたため、リモートで接続が失敗したと報告しました):

[23305.165235] ens4-PRERT IN=エンス4OUT= MAC=00:00:17:01:8c:ff:00:00:17:23:a9:ae:08:00 SRC=156.151.8.14 DST=10.100.16.13 LEN=60 TOS=0x10 PREC=0x20 TTL=41 ID=45069 DF PROTO=TCP SPT=5874 DPT=22 WINDOW=14600 RES=0x00 SYN URGP=0 MARK=0x2

[23305.169993] 出力 IN= OUT=エンス3SRC=10.100.16.13 DST=156.151.8.14 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=22 DPT=5874 WINDOW=26844 RES=0x00 ACK SYN

この投稿が長くなってすみません。私はこの問題についてしばらく心配してきましたが、関連するすべての詳細を伝えるよりも簡潔な方法を考えることはできません。 「不可能」であっても、誰でも提供できるガイドラインに感謝します。乾杯!

答え1

私の意見によると、これは期待どおりに機能する解決策だと思います。例と順序が反対であることに注意してください。ネットフィルターコマックしかし、着信パケットではなく着信パケットに基づいて決定が下されるので、これは正しい順序です。したがって、前の2つのMARKルールを削除して(ここに再度入れて)、次に置き換えます。

# iptables -t mangle -A INPUT -i ens3 -j MARK --set-mark 1
# iptables -t mangle -A INPUT -i ens4 -j MARK --set-mark 2    
# iptables -t mangle -A INPUT -j CONNMARK --save-mark

# iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark

対称性と明確性のために、INPUT(PREROUTING以降に呼び出されますが、ローカルストリームのみ)を使用します。これは転送ではなくローカル接続用です。 INPUTの代わりにPREROUTINGを使用すると(OUTPUTは維持)、同じ結果が得られます。

これは、すべてのフローを追跡するconntrackを使用してタグを記憶し、それをローカルに生成された発信パケットに戻します。なぜなら、conntrackはタグが同じフローの一部であることを知っているからです。

マングルテーブルでOUTPUTルールを使用すると、パスリダイレクトチェックが開始されます(この内容を参照)。Linuxルーティングおよびnetfilter回路図)、これは指示に従ってトレースをルーティングするために必要です。

別のルールを使用する-t mangle場合やサーバーも渡す場合は、ルールを変更する必要があります。それにもかかわらず、おそらくINPUTでは最後になければならず、OUTPUTでは最初でなければ--save-markなりません。--restore-mark

このフラグはユーザー以外の応答パケット(TCP RSTなど)にも設定されているため、fwmark_reflect不要になったり干渉したりする可能性があるため、テストする必要があります。

関連情報