【ネットワーク】Network Namespace 関連のコマンドメモ

# はじめに

以下を読んでいる途中、コマンドをすぐ忘れるのでメモ。

https://www.amazon.co.jp/dp/B085BG8CH5

# コマンドメモ

- Network Namespace 一覧を確認

```shell
$ ip netns list
ns2 (id: 2)
router (id: 1)
ns1 (id: 0)
```

- 特定の Network Namespace を削除

```shell
$ sudo ip netns delete ns1
```

- Network Namespace をすべて削除

```shell
$ sudo ip --all netns delete
```

- Network Namespace を作成

```shell
$ sudo ip netns add ns1
```

- veth インターフェースを作成

```shell
$ sudo ip link add ns1-veth0 type veth peer name gw1-veth0
```

- veth インターフェースを Network Namespace に所属させる

```shell
$ sudo ip link set ns1-veth0 netns ns1
```

- Network Namespace のネットワークインターフェースの状態を UP に変更

```shell
$ sudo ip netns exec ns1 ip link set ns1-veth0 up
```

- Network Namespace のネットワークインターフェース一覧を確認

```shell
$ sudo ip netns exec ns1 ip link show
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
10: ns1-veth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 5a:7d:06:29:bb:d3 brd ff:ff:ff:ff:ff:ff link-netns router1
```

- Network Namespace のネットワークインターフェースに IP アドレスを付与

```shell
$ sudo ip netns exec ns1 ip address add 192.0.2.1/24 dev ns1-veth0
```

- Network Namespace にデフォルトルートを追加
  - 特定のルートが他に定義されていない場合、`192.0.2.254` にルーティングする

```shell
$ sudo ip netns exec ns1 ip route add default via 192.0.2.254
```

- Network Namespace のルーティングテーブルを確認

```shell
$ sudo ip netns exec ns1 ip route show
default via 192.0.2.254 dev ns1-veth0
192.0.2.0/24 dev ns1-veth0 proto kernel scope link src 192.0.2.1
```

- Network Namespace のルータの IP フォワーディングを有効化

```shell
$ sudo ip netns exec router1 sysctl net.ipv4.ip_forward=1
```

- Network Namespace のルータの IP フォワーディングを確認

```shell
$ sudo ip netns exec router1 sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
```

- Network Namespace の `192.0.2.1` から `198.51.100.1` に `ping` を 3 回送信

```shell
$ sudo ip netns exec ns1 ping -c 3 198.51.100.1 -I 192.0.2.1
```

- Network Namespace のルータに静的ルーティングによりルートを追加
  - `198.51.100.0/24` 向けのトラフィックを `203.0.113.2` に送信

```shell
$ sudo ip netns exec router1 ip route add 198.51.100.0/24 via 203.0.113.2
```

- Network Namespace のパケットキャプチャを行う
  - `-t` : タイムスタンプを表示しない
  - `-n` : ホスト名を解決せずにIPアドレスをそのまま表示
  - `-i any` : すべてのネットワークインターフェース上のパケットをキャプチャ
  - `icmp` : ICMPトラフィックのみをフィルタリングしてキャプチャ

```shell
$ sudo ip netns exec ns1 tcpdump -tn -i any icmp
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
ns1-veth0 Out IP 192.0.2.1 > 198.51.100.1: ICMP echo request, id 16122, seq 1, length 64
ns1-veth0 In  IP 198.51.100.1 > 192.0.2.1: ICMP echo reply, id 16122, seq 1, length 64
ns1-veth0 Out IP 192.0.2.1 > 198.51.100.1: ICMP echo request, id 16122, seq 2, length 64
ns1-veth0 In  IP 198.51.100.1 > 192.0.2.1: ICMP echo reply, id 16122, seq 2, length 64
ns1-veth0 Out IP 192.0.2.1 > 198.51.100.1: ICMP echo request, id 16122, seq 3, length 64
ns1-veth0 In  IP 198.51.100.1 > 192.0.2.1: ICMP echo reply, id 16122, seq 3, length 64
```

- Network Namespace のネットワークインターフェースに MAC アドレスを指定

```shell
$ sudo ip netns exec ns1 ip link set dev ns1-veth0 address 00:00:5E:00:53:01
```

- Network Namespace のパケットキャプチャを行う
  - `-e` : イーサネットのヘッダ情報を表示
  - `-i ns1-veth0` : インターフェース ns1-veth0 上のパケットをキャプチャ

```shell
$ sudo ip netns exec ns1 tcpdump -tne -i ns1-veth0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ns1-veth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 22439, seq 1, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 22439, seq 1, length 64
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 22439, seq 2, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 22439, seq 2, length 64
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 22439, seq 3, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 22439, seq 3, length 64
```

- Network Namespace の MAC アドレスのキャッシュ（ネイバーテーブル）を確認

```shell
$ sudo ip netns exec ns1 ip neigh
192.0.2.2 dev ns1-veth0 lladdr 00:00:5e:00:53:02 REACHABLE
```

- Network Namespace の MAC アドレスのキャッシュ（ネイバーテーブル）をクリア

```shell
$ sudo ip netns exec ns1 ip neigh flush all
```

- Network Namespace のパケットキャプチャを行う
  - `arp` : ARP トラフィックをフィルタンリングしてキャプチャ

```shell
$ sudo ip netns exec ns1 tcpdump -tne -i ns1-veth0 icmp or arp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ns1-veth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
00:00:5e:00:53:01 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.0.2.2 tell 192.0.2.1, length 28
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype ARP (0x0806), length 42: Reply 192.0.2.2 is-at 00:00:5e:00:53:02, length 28
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 62258, seq 1, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 62258, seq 1, length 64
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 62258, seq 2, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 62258, seq 2, length 64
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype IPv4 (0x0800), length 98: 192.0.2.1 > 192.0.2.2: ICMP echo request, id 62258, seq 3, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype IPv4 (0x0800), length 98: 192.0.2.2 > 192.0.2.1: ICMP echo reply, id 62258, seq 3, length 64
00:00:5e:00:53:02 > 00:00:5e:00:53:01, ethertype ARP (0x0806), length 42: Request who-has 192.0.2.1 tell 192.0.2.2, length 28
00:00:5e:00:53:01 > 00:00:5e:00:53:02, ethertype ARP (0x0806), length 42: Reply 192.0.2.1 is-at 00:00:5e:00:53:01, length 28
```

- Network Namespace にブリッジインターフェースを作成

```shell
$ sudo ip netns exec bridge ip link add dev br0 type bridge
```

- Network Namespace のブリッジインターフェースを UP に変更

```shell
$ sudo ip netns exec bridge ip link set br0 up
```

- Network Namespace の veth インターフェースの片側をブリッジインターフェースに接続

```shell
$ sudo ip netns exec bridge ip link set ns1-br0 master br0
```

- Network Namespace のブリッジインターフェースの MAC アドレステーブルを確認
  - `fdb` は FDB（フォワーディングデータベース）を意味し、FDB は MAC アドレスとその対応するポート（インターフェース）の情報を保持する。これにより、ブリッジは受信したフレームを適切なポートに転送する

```shell
$ sudo ip netns exec bridge bridge fdb show br br0
...
00:00:5e:00:53:01 dev ns1-br0 master br0
...
00:00:5e:00:53:02 dev ns2-br0 master br0
...
00:00:5e:00:53:03 dev ns3-br0 master br0
...
```

- Network Namespace で DHCP サーバを起動
  - `--dhcp-range` : `192.0.2.100` から `192.0.2.200` の範囲で IP アドレスを付与。`255.255.255.0` はネットワークアドレス
  - `--interface` : DCHP リクエストを受け付けるネットワークインターフェース
  - `--port 0` : DNS 機能を無効にする
  - `--no-resolv` : /etc/resolv.conf ファイルを無視して、外部DNSサーバを使用しない
  - `--no-daemon` : フォアグラウンドで実行し、デーモン化しない

```shell
$ sudo ip netns exec server dnsmasq \
    --dhcp-range=192.0.2.100,192.0.2.200,255.255.255.0 \
    --interface=s-veth0 \
    --port 0 \
    --no-resolv \
    --no-daemon
```

- Network Namespace で DHCP クライアントを起動し、IPアドレスを取得する
  - `-d` :  デバッグモードで実行し、フォアグラウンドで実行

```shell
$ sudo ip netns exec client dhclient -d c-veth0
...
DHCPREQUEST for 192.0.2.180 on c-veth0 to 255.255.255.255 port 67 (xid=0x11e56f05)
DHCPACK of 192.0.2.180 from 192.0.2.254 (xid=0x56fe511)
...
bound to 192.0.2.180 -- renewal in 1425 seconds
```

- Network Namespace の DHCP クライアントに割り当てられた IP アドレスを確認

```
$ sudo ip netns exec client ip address show dev c-veth0 | grep "inet "
    inet 192.0.2.180/24 brd 192.0.2.255 scope global dynamic c-veth0
```

- Network Namespace `router` の NAT（ネットワークアドレス変換）テーブルに SNAT ルールを追加
  - `-t nat` : NAT テーブルを指定
  - `-A POSTROUTING` : POSTROUTING チェーンを指定。ルーティングが終わりパケットがインターフェースから出ていく直前にルールを適用する
  - `-s 192.0.2.0/24` : ソースアドレス範囲
  - `-o gw-veth1` : ルールを適用する出力先インターフェース
  - `-j MASQUERADE` : 該当するパケットに対して適用するルール。ここではマスカレード（送信元アドレスの変換）を指定

```shell
$ sudo ip netns exec router iptables \
    -t nat \
    -A POSTROUTING \
    -s 192.0.2.0/24 \
    -o gw-veth1 \
    -j MASQUERADE
```

- Network Namespace `router` の NAT（ネットワークアドレス変換）テーブルのルールを表示
  - `-L` : リスト表示
  - `target` : ルールが適用された場合に取るアクション
  - `prot` : プロトコル。tcp、udp、icmp など、どのプロトコルにルールが適用されるかを示す
  - `opt` : オプション
  - `source` : ルールが適用される送信元アドレス
  - `destination` : ルールが適用される送信先アドレス

```shell
$ sudo ip netns exec router iptables -t nat -L
...
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  192.0.2.0/24         anywhere
```

- Network Namespace `router` の NAT（ネットワークアドレス変換）テーブルに DNAT ルールを追加
  - `-p tcp --dport 54321 -d 203.0.113.254` : ルール適用対象のトラフィック
  - `--to-destination 192.0.2.1` : ルール適用後のアドレス

```shell
$ sudo ip netns exec router iptables \
    -t nat \
    -A PREROUTING \
    -p tcp \
    --dport 54321 \
    -d 203.0.113.254 \
    -j DNAT \
    --to-destination 192.0.2.1
```

- DNAT ルール追加後の NAT テーブル確認

```shell
$ sudo ip netns exec router iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT       tcp  --  anywhere             203.0.113.254        tcp dpt:54321 to:192.0.2.1
...
```

# 参考

https://www.amazon.co.jp/dp/B085BG8CH5