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

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

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

ただし、リモートコンピュータに接続しようとすると失敗します。

strace私は//のように動作し、他のすべてはまだうまくいきますが、インターネット(およびLAN)を隠すコマンドを実行するユーティリティが欲しいですunsharesudo

$ offline my-program-to-test

この質問はすでに答えを示唆しています。プロセスへのネットワークアクセスをブロックしますか?

別のユーザーとして実行してからiptablesを操作するかunshare -n、 。共有をキャンセルする方法を教えてください。みんなネットワーク。

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

理想的には、chroot、ユーザー、VMなどを生成することは、ネットワークケーブルを抜くのと同じくらい面倒なので避けたいと思います。つまり、質問の要点は、どうすれば同じように作れるかということですsudo

ローカルでないアドレスを指定するネットワーク呼び出しが失敗することを除いて、プロセスは100%動作して実行されることを望みます。理想的には、同じuid、同じhomedir、同じパスワード、オフラインを除くすべてのアイテムを同じにしてください。

私はFedora 18を使用しているので、移植性のないLinuxの答えは大丈夫です(予想もします)。

私はCプログラムを書くことによってこの問題を喜んで解決します。それがCプログラムの作成に関連する答えならば。ローカルネットワークを維持しながら外部ネットワークへのアクセスを取り消すために、Cプログラムがどのシステムコールを行う必要があるのか​​わかりません。

「オフラインモード」をサポートしたい開発者なら誰でもこのユーティリティを高く評価します!

答え1

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

名前空間を使用すると、ネットワーク共有を削除し、限られたネットワークアクセスが必要なときに仮想ネットワークリンクを作成できます。

Unixドメインソケットを共有するために必要なのは、新しいカーネルだけです。今回の2010パッチしたがって、これは2.6.36以上です(この記事を書いている時点では、RHEL / CentOSを除くすべての現在のディストリビューションに対応しています)。

独自のIP名前空間でプログラムを実行します。プログラムを開始する前に、仮想イーサネットインタフェースを作成してください。ドキュメントがあまりないようです。いくつかのブログで正しい真言を見つけました。

以下のコードスニペット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

これらすべてを実行するには、root権限が必要です。これカーネル3.8で導入されたユーザーネームスペースこれを行うために、ネットワークリンクのグローバルエンドを設定する以外に特別な権限は必要ありません。

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

答え2

これは、cgroupに一致するiptablesルールを介しても達成できます。私はこれらのステップを抽象化するツールを書いた。初期設定にはroot権限が必要で、setuidバイナリですが、問題の問題を処理するためのかなり簡単な方法を提供すると思います。これには、十分に最新バージョンのiptablesと適切なnetfilterモジュールが必要です。

https://github.com/quitesimpleorg/qsni

答え3

最近この問題が発生しました。 usergroupを使用してこの問題を解決しました。

  1. 「no-external-internet」グループを追加し、ここにユーザーを追加します。

    sudo addgroup no-external-internet
    sudo adduser $USER no-external-internet
    
  2. 発信トラフィックを iptables許可し、他のすべてのアウトバウンド接続を拒否するルールを追加します。{HOST}{PORT}

    sudo iptables -A OUTPUT -m owner --gid-owner no-external-internet -s {HOST} -p tcp --sport {PORT} -j ACCEPT; 
    sudo iptables  -A OUTPUT -m owner --gid-owner no-external-internet -j REJECT; 
    sudo ip6tables -A OUTPUT -m owner --gid-owner no-external-internet -j REJECT; 
    
  3. ユーザーグループを使用して子プロセスを実行します。

    sg no-external-internet "your command to run child process"
    

答え4

/!!\これは単一の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

関連情報