【Linux】TCP/IPを動かす

もくじ

Docker内のubuntuで実行しています。くわしくはこちらをご参考ください。

bonoponz.hatenablog.com

必要なパッケージをインストール

rootでコンテナに入っているのでsudoは不要です。

まずはアップデートします。

root@b6e6b93390bb:/# apt-get update
.
.
.
Fetched 23.1 MB in 23s (997 kB/s)                                                         
Reading package lists... Done

もしrootではないならsudoで実行してください。

root@b6e6b93390bb:/# sudo apt-get update

そして必要なパッケージをインストールしましょう。

root@b6e6b93390bb:/# apt-get -y install \
    bash \
    coreutils \
    grep \
    iproute2 \
    iputils-ping \
    traceroute \
    tcpdump \
    bind9-dnsutils \
    dnsmasq-base \
    netcat-openbsd \
    python3 \
    curl \
    wget \
    iptables \
    procps \
    isc-dhcp-client

ubuntu:18.04だとbind9-dnsutilsがインストールできないかもしれません。

root@b6e6b93390bb:/# apt-get -y install \
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package bind9-dnsutils

これの解決はできませんでした。

apt updateaptをアップデートすれば解決するなどの記事を参考にいろいろ試しましたがインストールは成功しませんでした。

必要になった時にまた調べます。

次項より/#のある行が実際にターミナルで実行するコマンドであり、/#は実際には打ちません。

pingコマンド

/# ping -c 3 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=37 time=50.9 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=37 time=41.5 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=37 time=31.1 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2010ms
rtt min/avg/max/mdev = 31.129/41.210/50.946/8.095 ms

解説

8.8.8.8というIPアドレスを持った通信相手からこの場合3回応答があったことを示しています。
ちなみに8.8.8.8Googleが無償で提供しているGoogle Public DNSIPアドレスです。

-cオプションで3回を指定しているので、応答を要求をするメッセージを3回送るという意味です。なので、3回送って、3回返ってきています。

3 packets transmitted, 3 received, 0% packet lossつまり「3回送った、3回返ってきた、ロスは0(無し)」という結果にも表れています。

IPでデータをやり取りする際の単位がpacketです。

ip address showコマンド

/# ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000
    link/tunnel6 :: brd ::
11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

ここで着目するのはinetの後ろ部分です。上記例で言うと127.0.0.1172.17.0.2が、コンピュータのIPアドレスです。

127.0.0.1は自分自身

127.0.0.1というIPアドレスは「ループバックアドレス」という特殊なIPアドレスで自分自身を表します。

/# ping -c 3 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.049 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.100 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.262 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2042ms
rtt min/avg/max/mdev = 0.049/0.137/0.262/0.090 ms

上記の結果と8.8.8.8の結果を比較してみましょう。先程と実行したコマンド(↓)を再度実行してみます。

/# ping -c 3 8.8.8.8

ふたつを比較した時、応答が返ってくるまでのtimeが短縮されていることがわかります。圧倒的ですね。

IPアドレス 結果
8.8.8.8 64 bytes from 8.8.8.8: icmp_seq=1 ttl=37 time=50.9 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=37 time=41.5 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=37 time=31.1 ms
127.0.0.1 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.049 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.100 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.262 ms

tcpdumpコマンド

新規タブでターミナルでtcpdumpコマンドを実行します。
この新規タブを「タブ2」、元のタブを「タブ1」とします。

今回Dockerに入ってやっているので新規ターミナルでもログインが必要にです。以下のように、ログインしてからtcpdumpコマンドを実行してください。

$ docker exec -it ubuntu-test /bin/bash
root@b6e6b93390bb:/# tcpdump -tn -i any icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes

ここで画面が固まったように見えますが問題ありません。

「タブ1」に戻って以下コマンドを実行します。

/# ping -c 3 8.8.8.8

実行したあと「タブ2」を見ると表示が増えていると思います。

IP 172.17.0.2 > 8.8.8.8: ICMP echo request, id 4151, seq 1, length 64
IP 8.8.8.8 > 172.17.0.2: ICMP echo reply, id 4151, seq 1, length 64
IP 172.17.0.2 > 8.8.8.8: ICMP echo request, id 4151, seq 2, length 64
IP 8.8.8.8 > 172.17.0.2: ICMP echo reply, id 4151, seq 2, length 64
IP 172.17.0.2 > 8.8.8.8: ICMP echo request, id 4151, seq 3, length 64
IP 8.8.8.8 > 172.17.0.2: ICMP echo reply, id 4151, seq 3, length 64

IPは送信元と送信先IPアドレスです。
ICMPPingの通信がIPとICMPの組み合わせで成り立っていることを示しています。

確認が終わったらtcpdumpコマンドをCtrl + Cを押して終了しましょう。

tcpdumpコマンドのオプションについては以下の通りです。

オプション 意味
-t 時刻に関する情報を出力しない
-n IPアドレスを逆引きせずそのまま表示する
-i パケットキャプチャする対象のネットワークインターフェースを指定。anyを指定するとすべてのインターフェースが対象になる

オプションとは別に、今回末尾でicmpを引数に渡すことで、パケットキャプチャの対象をICMPに限定しています。

tracerouteコマンド

tracerouteコマンドはパケットがどのようなルート(経路)を通って目的地まで届くのか確認するのに使われます。

/# traceroute -n 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  172.17.0.1  0.124 ms  0.040 ms  0.049 ms
 2  000.000.000.1  9.932 ms  12.368 ms  12.932 ms
 3  * * *
 4  000.000.000.209  43.713 ms  45.905 ms  46.325 ms
 5  000.000.000.10  40.282 ms  43.116 ms  41.055 ms
 6  * * *
 7  * * *
 8  * * *
 9  000.000.000.253  39.196 ms  42.667 ms  41.732 ms
10  * * *
11  8.8.8.8  28.813 ms  24.858 ms  24.289 ms

表示される内容はインターネット環境によって異なります。一部変更しています。

それぞれの行に表示されているIPアドレスはパケットが通過したルータの持っているIPアドレスです。これらをバケツリレーしながらパケットが運ばれてくるわけです。

参考

Linuxで動かしながら学ぶTCP/IPネットワーク入門 | もみじあめ | 一般・入門書 | Kindleストア | Amazon