プロセスに基づいて IP トラフィックを異なるデフォルト ルート/インターフェイスにルーティングする

プロセスに基づいて IP トラフィックを異なるデフォルト ルート/インターフェイスにルーティングする

プロセスまたはプロセス グループからの IP パケットを特定のインターフェイス経由で選択的にルーティングし、他のすべてのパケットを別のインターフェイス経由でルーティングできるかどうかを調べています。つまり、からのすべてのトラフィックを 経由で/usr/bin/testappルーティングしeth1、他のすべてのパケットを 経由でルーティングしたいのですeth0。この場合のパケットは TCP、UDP、ICMP などであり、エンド ユーザーがさまざまなポートを使用するように設定できます。

問題のプロセスを特定のインターフェースにバインドするように強制することは簡単にできないため、ルーティングを介して同じ結果を達成しようとしています。これは可能ですか?

- - 編集 - -

ここで、そして他の多くの場所で、UIDに基づいてパケットをマークするという有益な提案がありますが、それは本当の目的ではありません。目標はプロセスに基づいてマーク/フィルタリング/ルーティングすることです。ユーザーに関係なくつまり、、およびがすべて独自の のインスタンスを実行する場合alicebob3charlie/usr/bin/testappのインスタンスからのすべてのパケットが通過しeth1、システムからのその他のすべてのパケットは を通過する必要がありますeth0

testappさまざまなユーザーが実行し、独自に異なるポートを設定する可能性があるため、送信元/宛先ポート、ユーザー名/UID などでマークするだけでは不十分であることに注意してください~/.config/testapp.conf。質問はプロセスによるフィルタリングに関するものです。

/bin/(ba|z)?sh利用できるオプションの 1 つは、ネイティブ バイナリを ベースのラッパーで囲むことですが、これがどれほど役立つかはわかりません。

- - 編集 - -

ここでは、最新の Linux カーネル (4.0 以上) を実行しているシステムでのルーティングについて言及しています。、、iproute2およびnftables同様conntrackのツール以外のソフトウェア依存関係がある場合は、オープン ソース ソリューションを検討しても構いませんが、基本的なツールが望ましいです。

答え1

パケットをeth1またはeth0のいずれかにルーティングします。テーブルマングルはこれに対処する必要があります。そのためには、パケットをマークし、それを処理するためのルールを設定する必要がありました。まず、2でマークされたパケットをカーネルがテーブルにルーティングするようにルールを追加します。

ip rule add fwmark 2 table 3

ゲートウェイが 10.0.0.1 であると仮定して、別のインターフェース経由でトラフィックをリダイレクトするためのルートを追加します。

ip route add default via 10.0.0.1 table 3

ルーティング キャッシュをフラッシュします。

ip route flush cache

次に、指定されたパケットをマークするためのファイアウォール ルールを設定します。

iptables -t mangle -A OUTPUT -p tcp --dport 465 -j MARK --set-mark 2

最後に、リバース パス ソース検証を緩和します。0 に設定することを提案する人もいますが、 によると 2 のほうが適切な選択のようですhttps://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt。これをスキップすると、パケットは受信されます ( を使用して確認できますtcpdump -i tap0 -n) が、パケットは受け入れられません。パケットが受け入れられるように設定を変更するコマンド:

sysctl -w net.ipv4.conf.tap0.rp_filter=2

参照 :http://serverfault.com/questions/345111/iptables-target-to-route-packet-to-specific-interface

答え2

特定のユーザーでプロセスを実行し、パケットを iptable のowner拡張子と一致させることができます。一致したら、それをマークして別のルーティング テーブルで使用したり、POSTROUTING任意のソリューションを使用したりできます。

これこの投稿では、 を使用したパケット マッチングについてより詳しく説明していますowner

答え3

これは、ネットワーク名前空間を使用してプロセスを分離し、そのネットワーク名前空間をメインの名前空間に接続するための仮想イーサネット接続を使用することで可能になります。その後、iptables を使用して、そのソースに基づいてルーティングできます。

ここに例があります。私はいくつかのコマンドにネットワークマネージャを使用していますが、そのまま実行することもできます。

# Create a namespace
ip netns add ns1

# create a bridge between them
nmcli connection add type veth ifname virt0 peer virt1
ip link set virt1 netns ns1
ip addr add 192.168.69.1/24 dev virt0
ip netns exec ns1 ip addr add 192.168.69.2/24 dev virt1
ip netns exec ns1 ip link up virt1
echo 1 > sudo tee /proc/sys/net/ipv4/ip_forward

# At this point traffic from ns1 will appear in your main network namespace as coming from ip 192.168.69.2 dev virt0, so you can handle it from there.  You will need NAT to make it go somewhere useful.
# In this case I want the traffic to go out through interface vpn1, which is not a default route on my system.

# Add your process-specific routing rules in a non-default table (12345 in this case)
ip route add default dev vpn1 table 12345 proto static scope link metric 50
# Set up a rule to use that table for the traffic coming from that IP, with lower priority than the default table's rule.
ip rule add priority 30000 from 192.168.69.0/24 lookup 12345
# Add the nat, so that the traffic can actually exist on your outbound interface
iptables -t nat -A POSTROUTING -o vpn1 -j MASQUERADE

# At this point traffic from ns1 will go out through interface vpn1. Now you can run command sin that netns to utilize this.

nsenter  --net=/var/run/netns/ns1 your_program

答え4

さて、あなたが私たちに言ったことを考えると:

問題のプロセスを特定のインターフェースにバインドするように強制することは簡単にできないため、ルーティングを介して同じ結果を達成しようとしています。これは可能ですか?

この点から、私たちはあなたを助けることができます。かつて FreeBSD では、jailプロセスまたはプロセス グループをシステム リソースのサブセクションに制限する目的でシステム コールが登場しました。特に、これらの「分離された」プロセスがネットワーク アクティビティに使用する IP アドレスを指定できました。これは非常に便利だったので、Linux でこの機能が本当に恋しかったです。しかし、Linux にも同様の結果が得られる方法がいくつかあります。

または、最も軽量な方法は、名前空間を手動で調整するだけです。https://unix.stackexchange.com/questions/155446/linux-is-there-there-handy-way-to-exec-a-program-binding-it-to-ip-address-of-choice です

関連情報