DockerでARPテーブルを確認してみる！

仕事の都合上Linuxやネットワークの勉強をしています。深く関わったことがない領域ですし、字を追っただけでは理解に限界があるなーと思いまして、実際に触って、見て理解しようかと思いました。というわけでこの記事はその記録というわけです。

タイトル通りARPテーブルを見てネットワークの仕組みの一部を覗いてみようかと。環境はDockerを使います。

``` bash
$ docker --version
Docker version 19.03.8, build afacb8b
```

# ARPってなんだっけ

ARP (Address Resolution Protocol）はIPv4アドレスからMACアドレスを解決するために使用される通信プロトコルです。ネットワークに接続されたコンピュータが通信するときには通信相手のIPアドレスに向けてパケットを送信します。しかし、実際にはデータリンク層があるのでIPアドレスとMACアドレスの対応を管理しなくてはいけません。ARPはIPアドレスは分かっているけれど、MACアドレスがわからない場合に単一のサブネットワークの内部で解決を行います。

![arp-overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115251/531249ed-1849-8b4a-ff82-78d1fe3d3916.png)

# まずDockerコンテナを同じネットワークに接続させる

centos1 と centos2 のコンテナをデフォルトのブリッジネットワークに接続させます。

``` bash
$ docker run -dit --name centos1 centos:centos7
6ce3b9540c9eb79a672c4b438f761967f6315068a199c8309b8c7678660c9fcb
$ docker run -dit --name centos2 centos:centos7
6899cf57b849c5f164b26b8b12dd78ebb9ac78679673847cee240855b65a16b7
$ docker network inspect bridge
~（略）~
        "Containers": {
            "6899cf57b849c5f164b26b8b12dd78ebb9ac78679673847cee240855b65a16b7": {
                "Name": "centos2",
                "EndpointID": "cc0278128b0743be739b61567f3831f2371ea2f211182345292876f0c35eecf2",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "6ce3b9540c9eb79a672c4b438f761967f6315068a199c8309b8c7678660c9fcb": {
                "Name": "centos1",
                "EndpointID": "87a14892863da5410cbdd93962540efb796b7a33f99c3ed39c6f96e28c271958",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
~（略）~
```

centos1 でARPテーブルを表示します。ARPテーブルとはそのホストが記憶しているIPアドレスとMACアドレスの対応です。初期状態ではコマンドが入っていないのでインストールしています。（ARPテーブルは <code>arp</code>コマンドで表示できます。）

``` bash
$ docker attach centos1
[root@6ce3b9540c9e /]# yum -y install net-tools
[root@6ce3b9540c9e /]# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
172.17.0.1               ether   02:42:c0:38:4f:cb   C                     eth0
```

まだ何も通信していませんがARPテーブルに一つのエントリがキャッシュされています。このアドレスはルーティングテーブルを見てみるとデフォルトルートになっていることがわかります。デフォルトルートとは簡単に言うと経路制御表でマッチしなかった場合どのIPアドレス宛にパケットを送信するかを表すものです。（ルーティングテーブルは <code>netstat -r</code> コマンドで表示できます。）

``` bash
[root@6ce3b9540c9e /]# netstat -r -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG        0 0          0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 eth0
```

余談になりますがデフォルトルートになっている <code>172.17.0.1</code> アドレスはDockerのデフォルトブリッジで設定されているゲートウェイアドレスと一致します。このあたりの知識整理は機会があればまた後でしておきたいですね。

# コンテナ間で通信してARPテーブルが変わるか確認する

centos1 から centos2 へpingコマンドを使って通信し、ARPテーブルがどのように変わるか確認してみましょう。

``` bash
[root@6ce3b9540c9e /]# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.220 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.113 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.248 ms
64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.116 ms
^C
--- 172.17.0.3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3082ms
rtt min/avg/max/mdev = 0.113/0.174/0.248/0.061 ms
[root@6ce3b9540c9e /]# arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
172.17.0.1               ether   02:42:c0:38:4f:cb   C                     eth0
172.17.0.3               ether   02:42:ac:11:00:03   C                     eth0
```

最後の行に新しいエントリが追加されているのがわかりますね。これは centos2 のIPアドレスとMACアドレスに一致します。つまり、centos1 と centos2 はARPによってIPアドレスとMACアドレスの情報を共有できたということになります。ちなみに、pingコマンドで受信側になった centos2 でも同じようにARPテーブルが更新されます。

# 使用したアイコン

Icons made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon"> www.flaticon.com</a>