Linuxのネットワークネームスペースを仮想イーサネット(veth)で接続する
Linuxのネットワークネームスペースは、ネットワークに関連するシステムリソースの分離を提供するカーネル機能です。この記事では、Linuxで2つのネットワークネームスペースを作成して接続する方法をご紹介します。この記事は、Linuxのネットワークネームスペースのさまざまな側面を探求しようと試みた個人プロジェクトの一部です。さあ、始めましょう。
注意
ルートユーザーとしてログインしていない場合は、次のコマンドに
sudo
をつけて実行してください。
早速、ターミナル(ターミナル1
と呼びます)を使って2つの新しいネットワークネームスペースns1
とns2
を作成しましょう。
ip netns add "ns1"
ip netns add "ns2"
/抜ける
次のコマンドで既存のネームスペースをリストアップできます。ここではns1
とns2
が表示されるはずです。
ip netns list
/抜ける
次に、n1e
とn2e
という2つのインターフェースを持つveth
ケーブルを作成しましょう。
ip link add "n1e" type veth peer name "n2e"
/抜ける
次のコマンドでインターフェースの詳細を確認できます。
ip addr list
/抜ける
さて、veth
を使用して2つのネームスペースを接続しましょう。
ip link set "n1e" netns "ns1"
ip link set "n2e" netns "ns2"
/抜ける
注目すべき点は、もし今ip addr list
をターミナルで入力しても、n1e
とn2e
はリストされないことです!どこに行ったのでしょうか?インターフェースは、割り当てられたネームスペースの中に入ったのです。そこで、インターフェースを再び見るためには、ネームスペースの中に入る必要があります。ns1
から始めましょう。
これで、次のコマンドを使ってns1
の中に入ることができます。
ip netns exec "ns1" bash
/抜ける
入りました!今、もしip addr list
をタイプすると、DOWN
状態のlo
とn1e
の2つのインターフェースが表示されます。ping localhost
を試すと「ping: connect: Cannot assign requested address」というエラーメッセージが出ます。このピング接続を動作させるためには、以下のように状態をUP
に設定する必要があります。
ip link set dev lo up
/抜ける
これでping localhost
が動き始めます。
それでは、veth
ケーブルの両端のインターフェースにIPアドレスを割り当てましょう。n1e
から始めます。アドレスにはCIDR表記を用いて指定する必要があります。そして、n1e
インターフェースをUP
にしましょう。
ip addr add 10.10.1.1/32 dev "n1e"
ip link set dev "n1e" up
/抜ける
次に、新しいターミナル(ターミナル2
と呼びます)を開き、次のようにns2
ネームスペースに入りましょう。
ip netns exec "ns2" bash
/抜ける
今度は、lo
とn2e
インターフェースを起動して、n2e
にIPを割り当てましょう。
ip link set dev lo up
ip addr add 10.10.2.1/32 dev "n2e"
ip link set dev "n2e" up
/抜ける
すると、ターミナル1
からping -I n1e 10.10.2.1
を実行して、ターミナル2
でtcpdump -v -i n2e
を使用してリクエストを監視すると、「IP 10.10.1.1 > 10.10.2.1 : ICMP エコーリクエスト」というメッセージが表示されます。これは、リクエストがns2
に到達していることを確認しています。しかし、ターミナル1
では何も表示されません。つまり、ns2
ネームスペースからパケットが外部に出ていないことを意味しています。これは、ns2
が応答をどこに送信すればよいか、つまりパケットをどのようにルーティングすればよいのかを知らないためです。これを解決するには、ns2
のルートテーブル
にエントリを追加します。
ルートテーブル
を指定するには以下のように実行します。
ip route add default via 10.10.2.1 dev "n2e"
/抜ける
これでターミナル1
に応答が表示されるようになります。
ここで質問ですが、ICMPリクエストを行う際にインターフェースを明示的に定義せず、つまりping 10.10.2.1
とすると、「ping: connect: Network is unreachable」と表示されます。これもルーティングの問題です。これを解決するためには、ns1
で以下を追加します。
ip route add default via 10.10.1.1 dev "n1e"
/抜ける
これで、インターフェースを明示的に定義せずにpingができるようになります。素晴らしいことですね?
ネットワークネームスペースで遊んでみて、読んでくださってありがとう。
こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/umarfchy/connecting-linux-network-namespaces-with-veth-4cfk