「匿名」ネットワークネームスペース内の veth デバイスを外部ネットワークネームスペースに接続するには?

「匿名」ネットワークネームスペース内の veth デバイスを外部ネットワークネームスペースに接続するには?

unshare自分だけを含む新しいネットワーク名前空間を作成するプロセス呼び出しがあります。 start bashを呼び出すと、execveipコマンドはデバイスが1つしかないことを示しますlo。ユーザーネームスペースも作成し、そのネームスペース内でプロセスをルートとしてスケジュールすると、そのipコマンドを使用してデバイスを起動して機能します。

このコマンドを使用して、この名前空間にipデバイスを作成することもできます。ただし、期待どおりにvethルートレベルの名前空間には表示されず、ip netns list新しいデバイスもルートレベルの名前空間には表示されません。ルートレベルの名前空間のデバイスをプロセスの名前空間の新しいデバイスに接続するにはveth?このコマンドは、名前空間にコマンドによって割り当てられた名前を持つように要求するようです。私のコマンドは名前空間を作成するために使用していなかったので必要ありません。vethvethipipip netns add

おそらく、netlinkデバイスを使用して設定するプログラムを直接書くことでこれを行うことができます。しかし、私は本当にそうしたくありません。コマンドラインでこれを行う方法はありますか?

Dockerコンテナにも独自のネットワーク名前空間があり、その名前空間にも名前がないため、これを行う方法が必要です。ただし、内部には外部機器vethに接続する機器があります。veth

私の目標は、理想的には、コンテナの外部でルートになる必要なしにプロセス分離コンテキストを動的に生成することです。これを行うには、PIDネームスペース、UIDネームスペース、ネットワークネームスペース、IPCネームスペース、およびマウントネームスペースを作成します。 cgroup名前空間を作成することもできますが、これは新しいものであり、現在サポートされているSLES、RHEL、およびUbuntu LTSのバージョンで実行できる必要があります。

私はこの名前空間を一度に1つずつ作業してきましたが、現在ユーザー、PID、およびマウント名前空間がうまく機能しています。

必要に応じてマウントできますが、/proc/pid/ns/net名前空間の外側のルートになる必要がないように、ユーザーの名前空間内でマウントすることをお勧めします。ほとんどの場合、名前空間のすべてのプロセスが消えると、すべてが消えると予想されます。タスクが完了したら、ファイルシステムで複数の状態をクリーンアップするのは理想的ではありません。コンテナが最初に割り当てられたときに一時的に作成し、すぐに削除することは、コンテナが終了したときにクリーンアップするよりもはるかに優れています。

いいえ、使用できません。ドッカー長沙ククト、または他の既存のソリューションを使用した湿地標準システムユーティリティ(例:アイピー)、次のシステムライブラリglibc、Linuxシステムコール。

答え1

ip linkネットワーク名前空間名に加えて使用できる名前空間オプションがあります。PID参照されるプロセスの名前空間です。もしPID名前空間プロセス間で共有されるため、デバイスを任意の方向に移動できます。これがおそらく最も簡単な方法です。~へ、考えるとPID 1存在する「外部」。別にPID名前空間外部(PID)名前空間から内部名前空間に移動する必要があります。

たとえば、ネットワーク名前空間内で次のように作成できます。veth デバイスペア到着PID 1名前空間:

ip link add veth0 type veth peer name veth0 netns 1

Linuxでネームスペースがどのように機能するか

各プロセスには、その名前空間の参照ファイルがあります/proc/<pid>/ns/。また、このファイルはip netns次の/run/netns/ファイルと関連があります。setnsシステムコールは、実行中のスレッドの名前空間を、このファイルが指す名前空間に変更します。

シェルでは、次を使用して別の名前空間を入力できます。nsenterプログラムは引数に名前空間ファイル(パス)を提供します。

Linux 名前空間の良い概要については、以下を参照してください。実行中の名前空間LWN.netの記事シリーズ。

名前空間の設定

複数の名前空間を設定する場合(マウント、pid、ユーザー、など)、変更前にネットワークネームスペースを設定してください。そしてPID名前空間。共有していない場合またはPID名前空間の場合、外部ネットワーク名前空間を参照するファイルが表示されないため、外部ネットワーク名前空間を指す方法はありません。

コマンドラインユーティリティが提供するよりも柔軟性が必要な場合は、システムコールを使用してプログラムから直接名前空間を管理する必要があります。ドキュメントについては、関連するマニュアルページを参照してください。man 2 setnsman 2 unshareそしてman 7 namespaces

答え2

Aはveth一対のデバイスで構成され、各デバイスを通信するネットワークネームスペース(またはルートネームスペース)に配置します。

これは、新しいネットワークネームスペースを作成し、ルートネームスペースとネットワークネームスペースの間にvetペアを設定するためにルートネームスペースからルートとして呼び出されるスクリプトです。最後の行はその名前空間でxtermを起動します。必要に応じて調整してください。

#!/bin/bash
# Setup network namespace with veth pair, start xterm in it

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi

NS=${1:-ns0}
DEV=${2:-veth0}
DEV_A=${DEV}a
DEV_B=${DEV}b
ADDR=${3-:10.0.0}
ADDR_A=${ADDR}.254
ADDR_B=${ADDR}.1
MASK=${5:-24}
COL=${4:-yellow}

# echo ns=$NS dev=$DEV col=$COL mask=$MASK

ip netns add $NS
ip link add $DEV_A type veth peer name $DEV_B netns $NS
ip addr add $ADDR_A/$MASK dev $DEV_A
ip link set ${DEV}a up
ip netns exec $NS ip addr add $ADDR_B/$MASK dev $DEV_B
ip netns exec $NS ip link set ${DEV}b up
ip netns exec $NS ip route add default via $ADDR_A dev $DEV_B
ip netns exec $NS su -c "xterm -bg $COL &" your_user_id

また、使用することができます

ip link set name_of_if netns name_of_ns

ネットワークネームスペース間でネットワークインターフェイス(物理デバイスへのインターフェイスを含む)を移動します。

編集する

今テストしました。ペアを作成することもできます。以内に新しい名前空間を作成し、エンドポイントをルート名前空間に配置します。秘密は、ルートネームスペースには明らかに名前はありませんが、idでアクセスできるということです1

sudo ip link add veth1b type veth peer name veth1a netns 1

どのように機能するかはわかりませんが、unshare新しく作成されたネットワーク名前空間を何らかの形で見つけることができるようです /proc/<pid>/ns/<type>。名前がない場合は、少なくとも数字IDが必要です。ip netns listヘルプも利用可能です。私はこれすべてです。を使用する代わりに、システムコールを介して実行することも、ip何かを把握するのに役立ちますstraceltrace

編集する

私はman namespaces 7名前空間を調べるだけで十分だと思います(ファイル記述子が1つしかありません)、名前空間を作成してからプログラムを起動する方が良いと思います/proc。あなたが仮定ip netns addip netns execunshareただそれ以外の新しいネットワーク名前空間が必要です。

関連情報