ifconfig がもう古いと聞いてイラっとした時に

# はじめに
Linux のネットワークは ifconfig コマンドで設定する時代が長く続きましたが、現在は ip コマンドへ置き換わりつつあります。慣れた方法が NG となるとイラっとするものです。メリットあるんだろうけど、今は手元の Linux に IP アドレスを設定できれば十分。ググると Qiita にあんちょこが見つかり事なきを得る（例えば[こちら](https://qiita.com/suzutsuki0220/items/dc72df23f1e1b1cda5f2)）。私もそんな風に過ごしてきました。ではメリットは何だろう、を簡単にまとめたのがこの記事です。

# 結論から

結論をひとことで言うと、ip（より正確には [iproute2](https://wiki.linuxfoundation.org/networking/iproute2)）はモダンネットワークを構成でき、ifconfig (より正確には net-tools) はできません。

ではモダンネットワークとは？
厳密な定義はさておき、大きな利点のひとつは図のような[ネットワークの仮想化](https://paulgorman.org/technical/linux-iproute2-cheatsheet.html)です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104747/5efa46c4-aaaf-10e1-1c7c-eeed0c4aedc4.png)
ifconfig 時代のモダンでない Linux は「ネットワーク機能（ネットワークスタック）はカーネルに一つ」の前提で構築されていました。それも今や昔の話。今日 Linux を構築するならば、論理的・物理的に複数のインターフェイスを持つのが一般的です。単純にインターフェイスの数だけでなく、ネットワークスタックを1台の Linux に複数持たせられます。これをネットワークの仮想化と呼びます。つまり、ハイパーバイザーが無くても Linux の機能だけでネットワーク仮想化を実現できます。

なお、この記事では取り上げませんが、iproute2 はその他にも[ルーティング、フィルタリング、クラシフィケーションの強化を目指して開発された経緯があります](https://tldp.org/HOWTO/Adv-Routing-HOWTO/lartc.intro.linux.html)。

# 試して理解を深める

## ネットワーク名前空間の作成

ネットワーク仮想化の実現に重要な概念が「ネットワーク名前空間（Network Namespace）」です。新しくネットワーク名前空間を作ると、[ネットワークスタックが複製されます](https://man7.org/linux/man-pages/man8/ip-netns.8.html)。これには、ルーティングテーブル・ファイアウォール・インターフェイスを含みます。

実際にネットワーク名前空間を作るのは簡単です。ここでは例として２つの名前空間 NS1 と NS2 を作成してみます。

```
# ip netns add NS1     # ネットワーク名前空間 NS1 を作成
# ip netns add NS2     # ネットワーク名前空間 NS2 を作成
# ip netns list        # ネットワーク名前空間の一覧を表示（list は省略可）
NS1
NS2
```

作成した名前空間 NS1 に対してコマンドを実施するには ip netns exec NS1 の後に実行したいコマンドを記載します。例として、ネットワークの基本情報を確認してみます：

```
# ip netns exec NS1 ip link    # ip link はインターフェイスを確認するコマンド
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
```

インターフェイスは２つ登録されていることがわかります。

```
# ip netns exec NS1 ip route    # ip route はルーティングテーブルを確認するコマンド
#
```

ルーティングテーブルは空です。

```
# ip netns exec NS1 ip neigh    # ip neigh は ARP テーブルを確認するコマンド
#
```

ARPテーブルも空です。

## ２つのネットワーク名前空間を接続する設定

設定は図の3ステップです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104747/4092b52b-9e9a-fa05-8063-7d8389f03519.png)

```
# ip link add VETH1 netns NS1 type veth peer name VETH2 netns NS2
# ip netns exec NS1 ip addr add 10.0.0.1/24 dev VETH1
# ip netns exec NS2 ip addr add 10.0.0.2/24 dev VETH2
# ip netns exec NS1 ip link set VETH1 up
# ip netns exec NS2 ip link set VETH2 up
```

1行目はもしかすると奇異に見えるかもしれません。リンクと仮想インターフェイスを同時に作成しています。これは次のような事情によります。

タイプとして veth を指定していますが、その名前から推測できるように仮想イーサネットインターフェイスです。veth 作成時には[必ず２つのペアとして作成する必要があります](https://man7.org/linux/man-pages/man4/veth.4.html)。片方のインターフェイスへ送信したパケットは直ちにもう一方のインターフェイスから出てきます。このような事情から veth の作成は必ずペアで行います。

上記で設定は完了しています。疎通確認をします：

```
$ sudo ip netns exec NS1 ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.038 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.027 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.030 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.032 ms
```

再びルーティングテーブルと ARP テーブルを確認してみます：

```
# ip netns exec NS1 ip route
10.0.0.0/24 dev VETH1 proto kernel scope link src 10.0.0.1
# ip netns exec NS1 ip neigh
10.0.0.2 dev VETH1 lladdr d2:a1:3a:33:a9:b8 REACHABLE
```

# おわりに

勘の良い方は既にお気づきのようにネットワーク名前空間はコンテナのネットワーク実現に不可欠な要素です。Docker を使っているのに ifconfig を使う、というのはどうも具合が悪そうです。Mac 等個人端末として使う場合には まだまだ ifconfig で十分かもしれません。

なお、モダンネットワークに対する厳密な定義は無さそうなので、ネットワーク仮想化以外にも着目すべき機能があるかもしれません。ご意見頂けるとうれしいです。

# 使用したバージョン

Ubuntu 18.04.3 LTS