Linuxで子プロセスを「オフライン」(外部ネットワークなし)で実行するコマンド


15

実際のネットワークを停止せずにオフラインモードでテストしたいプログラムがあります。このプログラムは、Unixドメインソケットとループバックを含むローカルソケットに接続する必要があります。また、ループバックでリッスンし、他のアプリに表示される必要があります。

ただし、リモートマシンへの接続は失敗します。

strace/ unshare/のように機能sudoし、インターネット(およびLAN)を隠した状態でコマンドを実行し、他のすべてがまだ機能しているユーティリティが必要です。

$ offline my-program-to-test

この質問には答えがあります:プロセスのネットワークアクセスをブロックしますか?

他のユーザーとして実行してからiptablesを操作するなど、いくつかの提案がありunshare -nます。しかし、どちらの場合も、UNIXドメインソケットとループバックをメインシステムと共有するための呪文はわかりません。その質問に対する答えはネットワーク全体の共有を解除する方法を教えてくれるだけです。

私がテストしているプログラムは、まだXサーバーとdbusに接続し、システム上の他のアプリからの接続をループバックでリッスンできる必要があります。

ネットワークケーブルを抜くのと同じくらい迷惑になるので、理想的には、chrootやユーザー、VMなどを作成しないようにします。すなわち質問のポイントはどのように私はこれをaのように簡単にすることができるかsudoです。

非ローカルアドレスを指定するネットワークコールが失敗することを除いて、通常どおりに100%実行するプロセスが必要です。理想的には、同じuid、同じhomedir、同じpwd、...を除くすべてをオフラインに保つ。

私はFedora 18を使用しているので、移植性のないLinuxの答えは問題ありません(予想される、でも)。

それが関係しているのであれば、Cプログラムを書くことでこれを解決できてうれしいので、Cを書くことに関係する答えは問題ありません。ローカルネットワークを維持しながら、Cプログラムが外部ネットワークアクセスを取り消すために必要なsyscallがわからないだけです。

「オフラインモード」をサポートしようとする開発者は、おそらくこのユーティリティに感謝するでしょう!

回答:


9

従来の答えは、プログラムを別のユーザーとして実行して使用することiptables -m ownerです。これにより、ネットワーク構成が共有されます。ただし、名前空間の出現により、より簡単な方法があります。

ネームスペースを使用すると、ネットワークの共有を解除し、制限されたネットワークアクセスが必要な場合は仮想ネットワークリンクを作成します。

UNIXドメインソケットを共有するために必要なのは、この2010パッチの後に最新の十分なカーネルが必要なため、2.6.36以上です(これは、RHEL / CentOSを除く執筆時点の現在のすべてのディストリビューションに当てはまります)。

独自のIP名前空間でプログラムを実行します。プログラムを開始する前に、仮想イーサネットインターフェイスを確立します。多くのドキュメントはないようです。いくつかのブログで正しい呪文を見つけました。

以下のスニペットでは、manページにリストされてns_execいるこのラッパーsetnsを使用して、制限された名前空間で実行されているプロセスからネットワークリンクのホスト側を呼び出します。これは実際には必要ありません。制限された名前空間の外部からリンクのホスト側を設定できます。内部からそれを行うと、フロー制御が容易になります。それ以外の場合は、リンクが確立された後、プログラムを開始する前にリンクを設定するために同期が必要です。

unshare -n -- sh -c '
  # Create a virtual ethernet interface called "confined",
  # with the other end called "global" in the namespace of PID 1
  ip link add confined type veth peer name global netns 1

  # Bring up the confined end of the network link
  ip addr add 172.16.0.2/30 dev confined
  ip link set confined up

  # Bring up the global end of the network link
  ns_exec /proc/1/ns/net ifconfig global 172.16.0.1 netmask 255.255.255.252 up

  # Execute the test program
  exec sudo -E -u "$TARGET_USER" "$0" "$@"
' /path/to/program --argument

これらすべてをルートとして実行する必要があります。カーネル3.8でのユーザー名前空間導入により、ネットワークリンクのグローバルエンドを設定することを除いて、特別な権限なしでこれを実行可能にすることができます

2つの名前空間間でlocalhostを共有する方法がわかりません。仮想イーサネットインターフェイスは、ポイントツーポイントブリッジを作成します。iptables転送ルールを使用してlo、必要に応じてトラフィックをリダイレクトできます。


良い追加情報、ありがとう。vethは名前空間の「外部」へのリンクを提供すると思いますが、新しい名前空間は、同じネットワークノードから非ローカルインターフェイスを引いたものではなく、別のネットワークノードになります。意味:(?):Unixドメイン/抽象ソケットは依然として失敗し、ループバックはiptablesを介して転送できますが、転送では共有が達成されません-つまり、元のネームスペースと制限されたネームスペースの両方がループバックと(動的に-changeing)ポートは両方の名前空間で表示される必要があります...私が望むものを推測し始めることはここでは不可能です:-/
Havoc P

1

これは、cgroupに一致するiptablesルールでも実現できます。手順を抽象化するツールを作成しました。初期セットアップにはルート権限が必要ですが、それ以外はsetuidバイナリですが、問題の問題に対処するためのかなり簡単な方法を提供すると思います。十分に新しいiptablesバージョンが必要で、適切なnetfilterモジュールが利用可能である必要があります。

https://github.com/quitesimpleorg/qsni


0

/ !! \これはおそらく、1つのPIDのトラフィックだけでなく、すべてのトラフィックをダウンさせるため、有効な答えではありません。

使用していませんが、Comcastを使用できる可能性があると思います。

https://github.com/tylertreat/Comcast

100%のパケット損失に設定

繰り返しますが、私はこれをテストしていませんが、理論的には、実行可能なreadmeから変更しました。


Linux

Linuxでは、iptables着信パケットと発信パケットをドロップするために使用できます。

$ iptables -A INPUT -m statistic --mode random --probability 1 -j DROP
$ iptables -A OUTPUT -m statistic --mode random --probability 1 -j DROP

または、tcいくつかの追加オプションをサポートするを使用できます。

$ tc qdisc change dev eth0 root netem reorder 0 duplicate 0 corrupt 1

リセットするには:

$ tc qdisc del dev eth0 root netem
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.