Linuxのプロセスの特定のインターフェイスを介してトラフィックをルーティングする


20

プロセスが使用するトラフィックを特定のインターフェイスにルーティングすることは可能ですか?

たとえば、ダウンロードアプリケーションごとのネットワークトラフィックは常にインターフェイスを使用する必要がありますwlan0が、マシン上の他のすべてのアプリケーションはを使用する必要がありますeth0

Linuxでこの種のルールを使用することは可能ですか?

回答:


22

Linux Network Namespacesを使用して実行できます。

以下にその方法を説明する記事があります。基本的に、異なるデフォルトルートでネットワーク名前空間を作成し、そこで必要なプロセスを実行します。新しく作成したネットワーク名前空間をブリッジを使用して物理アダプターに接続します(もちろん、他のソリューションも可能です)。

更新:カーネル3.14から、この記事で説明されているように、コントロールグループの使用がさらに簡単になりました。必ず:

1)net_cls制御グループを定義して、特定のプロセスからのパケットにclassid(またはプロセスのグループ、それらの間に親子関係はないことに注意してください)の注釈を付けます

2)iptables cgroupモジュール(Linux 3.14で追加)を使用してパケットをfwmarkする

3)ポリシールーティング(ip rule add fwmark ....)を使用して、マークされたパケットの新しいルーティングテーブルを作成します。

利点は、ブリッジングを行う必要がなく、すべてがcgroupのおかげではるかに動的になることです。


14

私はすっかりこれに苦労しているので、ここに完全なソリューションがあります。Ubuntu 15および16でテストされています。特にOpenVPNで使用して、特定のアプリをVPNトンネルインターフェース外にルーティングできます。

完全な「cgroup」ソリューション

どのように機能しますか?

  • Linuxカーネルは、アプリをコントロールグループに入れます。このcgroup内のアプリからのネットワークトラフィックは、ネットワークコントローラーレベルでクラスIDによって識別されます。
  • iptablesはこのトラフィックをマークし、正しいIPで強制的に終了します
  • ip routeは、必要なゲートウェイIPへのデフォルトルートを使用して、異なるルーティングテーブルでマークされたトラフィックを処理します。

自動化されたスクリプト

依存関係のインストールと実行を自動化するnovpn.shスクリプトを作成しました。Ubuntuでテスト済み。

最初にVPNを起動します。

wget https://gist.githubusercontent.com/kriswebdev/a8d291936fe4299fb17d3744497b1170/raw/cf8b37fbe6c3f50a0be825eb77cafa3e0134946f/novpn.sh
# If you don't use eth0, edit the script setting.
sudo chmod +x novpn.sh
./novpn.sh traceroute www.google.com
./novpn.sh --help

マニュアルHowTo

まず、cgroupサポートとツールをインストールします。

sudo apt-get install cgroup-lite cgmanager cgroup-tools

再起動します(必要ではない場合があります)。

iptables 1.6 .0+ が必要です。iptables 1.6.0リリースソースを取得して抽出し、--disable-nftablesiptablesソースディレクトリからこれを実行します(フラグはエラーを回避します)。

sudo apt-get install dh-autoreconf bison flex
./configure --prefix=/usr      \
            --sbindir=/sbin    \
            --disable-nftables \
            --enable-libipq    \
            --with-xtlibdir=/lib/xtables
make
sudo make install
iptables --version

さて、本当の設定。という名前の制御グループを定義しnovpnます。このcgroupのプロセスには、classidが0x00110011(11:11)になります。

sudo su
mkdir /sys/fs/cgroup/net_cls/novpn
cd /sys/fs/cgroup/net_cls/novpn
echo 0x00110011 > net_cls.classid

ここで、特定のアプリに使用するインターフェイスがeth0、ゲートウェイIPであると仮定します10.0.0.1。これらを本当に必要なものに置き換えます(から情報を取得しますip route)。ルートとしてまだ実行します。

# Add mark 11 on packets of classid 0x00110011
iptables -t mangle -A OUTPUT -m cgroup --cgroup 0x00110011 -j MARK --set-mark 11

# Force the packets to exit through eth0 with NAT
iptables -t nat -A POSTROUTING -m cgroup --cgroup 0x00110011 -o eth0 -j MASQUERADE

# Define a new "novpn" routing table
# DO THIS JUST ONCE !
echo 11 novpn >> /etc/iproute2/rt_tables

# Packets with mark 11 will use novpn
ip rule add fwmark 11 table novpn

# Novpn has a default gateway to the interface you want to use
ip route add default via 10.0.0.1 table novpn

# Unset reverse path filtering for all interfaces, or at least for "eth0" and "all"
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $i; done

最後に、特定のインターフェイスでアプリを実行します。

exit
sudo cgcreate -t $USER:$USER -a $USER:$USER -g net_cls:novpn
cgexec -g net_cls:novpn traceroute www.google.com
# Close all Firefox windows first
cgexec -g net_cls:novpn firefox

または、すでに実行中のプロセスをcgroupに移動したい場合は、できません。これは、NAT(マスカレード)機能によるものと思われますiptables -nvL -t nat。cgroupが切り替えられたときに一致しませんが、iptables -nvL -t mangle一致します。

# Get PID of the process (we'll then suppose it's 1234)
pidof firefox
# Add to cgroup - THIS DOESN'T WORK! Silently fails to produce the final result.
sudo echo 1234 > /sys/fs/cgroup/net_cls/novpn/tasks
# Remove - but this works...
sudo echo 1234 > /sys/fs/cgroup/net_cls

クレジット:無回答が期待通りに動作しなかったが、それらのミックスはなかった:evolware記事答えるchripell ルーティングのcgroup、iptablesのとポリシーを使用して:テイク2をルーティングプロセス毎の私は特定のプロセスは、OpenVPNの接続を介してつもりはない作るにはどうすればよいですか?iptablesに基づいてOpenVPNのスイッチを強制終了


すばらしい答えをありがとう、どのようにApacheで動作させるのですか?cgexec -g net_cls:novpn apache2変数の未定義のエラーの全リストを試してみました!
-razzak

2
apache2ターミナルから直接実行すると、同じエラーが発生します。これapache2は、通常、サービスとして起動されるためですsystemctl start apache2。ただし、それはで動作しませんcgexec。呼び出されたプログラムはapache2、net_cls cgroupが伝播するために必要な()プロセスの親である必要があります。そのため、起動スクリプトを見つける必要があります。この場合、それはsudo cgexec -g net_cls:novpn /usr/sbin/apache2ctl startです。で確認してください./novpn.sh --list
KrisWebDev

ubuntu 16.04ではもう機能しません!
-razzak

2
Ubuntu 16.04で使用していますが、問題なく機能しています。Ubuntu 16ではインターフェイス名が変更されました。代わりeth0にのようなものに置き換える必要があるかもしれませんenp7s0ifconfigコマンドから情報を取得します。
KrisWebDev

ありがとうございました。ただし、systemdとの競合によりcpmanagerが削除されたため、Ubuntu 18.04では動作しません
skonsoft


3

mariusmatutiaeとKrisWebDevの優れた回答を組み合わせて、大幅に修正されたバージョンのKrisWebDevの優れたnovpn.shスクリプトを作成しました。KrisWebDevのスクリプトは、より具体的なかゆみ(VPNの内外でプロセスを実行および移動する)をスクラッチするように設計されていますが、私のバージョンでは、指定したネットワーク環境で基本的にすべてのコマンドを実行できます。バインドするインターフェイス、デフォルトルート、独自のiptablesルール、静的ルートを指定し、「テスト」を指定して、コマンドを実行する前にすべてが希望どおりに動作していることを確認できます...など)。複数の設定ファイルを使用できるため、内部でコマンド/プロセスを実行できる特定のネットワーク環境をいくつでも定義できます。

ここに要点として投稿しました:https : //gist.github.com/level323/54a921216f0baaa163127d960bfebbf0

後でcgroup / iptables / routingテーブルをクリーンアップすることもできます!

フィードバックを歓迎します。

PS-Debian 8(Jessie)用に設計されています


こんにちは@ allnatural、altnetworking.shスクリプトを使用したいのですが、構成ファイルに何を入れるべきですか?
Cris70

0

アプリケーションごとではありません。ポートごとまたはIPアドレスごとに実行できます。または、アプリケーション自体が特定のネットワークカードにバインド(および使用)できます。

ただし、ルールを設定することはできません。


私はJavaアプリケーションを持っていますが、そのアプリをインターフェースにバインドすることは可能ですか?
スレシュ

ソースコードを持っているJavaアプリケーションで、内部を再プログラミングできますか?
マジェンコ

Apache HTTPライブラリを使用するJavaアプリケーションのソースコードがあります。
-Suresh

それから、私はstackoverflow.comに行き、そこでプログラマーにあなたのプログラムを変更する方法を尋ねます。Javaでプログラミングしたことはありません。
マジェンコ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.