Linuxのネットワークネームスペースを仮想イーサネット(veth)で接続する

カバー画像 for Linuxのネットワークネームスペースを仮想イーサネット(veth)で接続する

Linuxのネットワークネームスペースは、ネットワークに関連するシステムリソースの分離を提供するカーネル機能です。この記事では、Linuxで2つのネットワークネームスペースを作成して接続する方法をご紹介します。この記事は、Linuxのネットワークネームスペースのさまざまな側面を探求しようと試みた個人プロジェクトの一部です。さあ、始めましょう。

注意

ルートユーザーとしてログインしていない場合は、次のコマンドにsudoをつけて実行してください。

早速、ターミナル(ターミナル1と呼びます)を使って2つの新しいネットワークネームスペースns1ns2を作成しましょう。

ip netns add "ns1"
ip netns add "ns2"

/抜ける

次のコマンドで既存のネームスペースをリストアップできます。ここではns1ns2が表示されるはずです。

ip netns list

/抜ける

次に、n1en2eという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をターミナルで入力しても、n1en2eはリストされないことです!どこに行ったのでしょうか?インターフェースは、割り当てられたネームスペースの中に入ったのです。そこで、インターフェースを再び見るためには、ネームスペースの中に入る必要があります。ns1から始めましょう。

これで、次のコマンドを使ってns1の中に入ることができます。

ip netns exec "ns1" bash

/抜ける

入りました!今、もしip addr listをタイプすると、DOWN状態のlon1eの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

/抜ける

今度は、lon2eインターフェースを起動して、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を実行して、ターミナル2tcpdump -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