hana_shinのLinux技術ブログ

Linuxの技術情報を掲載しています。特にネットワークをメインに掲載していきます。

pingコマンドの使い方



1 pingコマンドとは

宛先までIPパケットが到達するかどうかを確認するために使うコマンドです。

2 検証環境

サーバとクライアントの2台構成です。図中のens33はNICの名前です。

                          192.168.2.0/24
client(ens33) -------------------------------------(ens33) server
        .105                                       .120

2.2 版数

サーバ、クライアントともに下記版数です。

[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

カーネル版数は以下のとおりです。

[root@server ~]# uname  -r
3.10.0-1160.el7.x86_64

2.3 pingの版数

pingの版数は以下のとおりです。

[root@server ~]# ping -V
ping utility, iputils-s20160308

3 オプション一覧

[root@server ~]# ping -h
Usage: ping [-aAbBdDfhLnOqrRUvV64] [-c count] [-i interval] [-I interface]
            [-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos]
            [-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option]
            [-w deadline] [-W timeout] [hop1 ...] destination
Usage: ping -6 [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface]
             [-l preload] [-m mark] [-M pmtudisc_option]
             [-N nodeinfo_option] [-p pattern] [-Q tclass] [-s packetsize]
             [-S sndbuf] [-t ttl] [-T timestamp_option] [-w deadline]
             [-W timeout] destination

4 基本的な使い方

クライアントからサーバまでIPパケットが到達するかどうか確認をしてみます。 クライアントでpingを実行します。終了するときは、Ctrl + cを押下します。

[root@client ~]# ping 192.168.2.100
PING 192.168.2.100 (192.168.2.100) 56(84) bytes of data.
64 bytes from 192.168.2.100: icmp_seq=1 ttl=64 time=1.98 ms
64 bytes from 192.168.2.100: icmp_seq=2 ttl=64 time=0.655 ms
64 bytes from 192.168.2.100: icmp_seq=3 ttl=64 time=0.602 ms
^C
--- 192.168.2.100 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.602/1.081/1.987/0.641 ms

5 ICMP echo requestパケットの送信回数の指定方法(-c)

pingを実行すると、ICMP echo requestパケットが送信されます。 -cオプションは、送信するICMP echo requestパケット数を指定します。

ICMP echo requestパケットを1つだけ送信してみます。

[root@client ~]# ping -c 1 192.168.2.100
PING 192.168.2.100 (192.168.2.100) 56(84) bytes of data.
64 bytes from 192.168.2.100: icmp_seq=1 ttl=64 time=2.24 ms

--- 192.168.2.100 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 2.240/2.240/2.240/0.000 ms

次に、ICMP echo requestパケットを2つ送信してみます。

[root@client ~]# ping -c 2 192.168.2.100
PING 192.168.2.100 (192.168.2.100) 56(84) bytes of data.
64 bytes from 192.168.2.100: icmp_seq=1 ttl=64 time=0.886 ms
64 bytes from 192.168.2.100: icmp_seq=2 ttl=64 time=0.790 ms

--- 192.168.2.100 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.790/0.838/0.886/0.048 ms

5 タイムスタンプを表示する方法(-D)

タイムスタンプ(マイクロ秒単位)を表示してみます。 1秒間隔でサーバ(192.168.2.100)から応答を受信していることがわかります。

[root@client ~]# ping -D 192.168.2.100
PING 192.168.2.100 (192.168.2.100) 56(84) bytes of data.
[1639998814.956947] 64 bytes from 192.168.2.100: icmp_seq=1 ttl=64 time=1.13 ms
[1639998815.960743] 64 bytes from 192.168.2.100: icmp_seq=2 ttl=64 time=0.709 ms
[1639998816.966041] 64 bytes from 192.168.2.100: icmp_seq=3 ttl=64 time=0.771 ms
-snip-

6 ICMP echo requestパケットの送信間隔を指定する方法(-i)

ICMP echo requestを200ミリ秒間隔で送信してみます。 サーバ(192.168.2.100)から200ミリ秒間隔で応答を受信していることがわかります。

[root@client ~]# ping -D -i 0.2 192.168.2.100
PING 192.168.2.100 (192.168.2.100) 56(84) bytes of data.
[1639998927.370328] 64 bytes from 192.168.2.100: icmp_seq=1 ttl=64 time=0.816 ms
[1639998927.585093] 64 bytes from 192.168.2.100: icmp_seq=2 ttl=64 time=0.664 ms
[1639998927.799582] 64 bytes from 192.168.2.100: icmp_seq=3 ttl=64 time=0.710 ms
-snip-

次に、ICMP echo requestを500ミリ秒間隔で送信してみます。 サーバ(192.168.2.100)から500ミリ秒間隔で応答を受信していることがわかります。

[root@client ~]# ping -D -i 0.5 192.168.2.100
PING 192.168.2.100 (192.168.2.100) 56(84) bytes of data.
[1639998972.566876] 64 bytes from 192.168.2.100: icmp_seq=1 ttl=64 time=1.32 ms
[1639998973.082046] 64 bytes from 192.168.2.100: icmp_seq=2 ttl=64 time=1.08 ms
[1639998973.595965] 64 bytes from 192.168.2.100: icmp_seq=3 ttl=64 time=0.794 ms
-snip-

7 パケットサイズを指定する方法(-s)

ICMPパケットは以下の構成になります。

|<- IP header(20byte) ->|<- ICMP header(8byte) ->|<------- Payload -------->|
+-----------------------+------------------------+--------------------------+
|                       |                        |                          |
|                       |                        |                          |
|                       |                        |                          |
+-----------------------+------------------------+--------------------------+

本オプションを使うと、ICMP echo requestのPayload長を指定することができます。 オプション未指定の場合、Payload長が56(byte)になります。 つまり、IPヘッダを含めたパケットサイズが84(byte)になります。

次に、pingを実行します。 このとき表示される56(84)は、56がICMPペイロード長を表します。 84はICMPペイロード長に、IP/ICMPヘッダ長を加えた値を表しています。

[root@server ~]# ping 192.168.2.1
PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data.
64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=7.57 ms
-snip-

次に、Payload長に0を指定してみます。 ICMPペイロード長が0、IP/ICMPヘッダにICMPペイロードを加えたサイズを表していることがわかります。

[root@server ~]# ping -s 0 192.168.2.1
PING 192.168.2.1 (192.168.2.1) 0(28) bytes of data.
8 bytes from 192.168.2.1: icmp_seq=1 ttl=64
-snip-

最後に、ちょうどMTU長(本環境は1500byte)になるICMPパケットを送信してみます。

[root@server ~]#  ping -s 1472 192.168.2.1
PING 192.168.2.1 (192.168.2.1) 1472(1500) bytes of data.
1480 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=3.15 ms
-snip-

8 送信インタフェースを指定する方法(-I)

ICMP echo requestパケットの送信インタフェースを指定するときに使います。 複数のインタフェースを持つサーバ等で使用します。

[root@server ~]# ping -I ens33 192.168.2.1
PING 192.168.2.1 (192.168.2.1) from 192.168.2.100 ens33: 56(84) bytes of data.
64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=33.9 ms
64 bytes from 192.168.2.1: icmp_seq=2 ttl=64 time=5.38 ms
-snip-

9 Flood pingを実行する方法(-f)

Flood pingは、単位時間に大量のICMP echo requestパケットを送信する機能です。 クライアントからサーバに対してFlood pingを実行してみます。 そのときの様子をstraceコマンドを使って確認してみます。 1ミリ秒程度でsendtoシステムコールを繰り返し実行して、クライアントからサーバに、 ICMP echo requestが100(packet/s)程度送信されていることがわかります。 なお、straceの使い方は、ここ(straceコマンドの使い方)を参照してください。

[root@client ~]# strace -tt -s 0 -e trace=sendto ping -c 10 -f 192.168.2.100
PING 192.168.2.100 (192.168.2.100) 56(84) bytes of data.
19:15:45.246809 sendto(3, ""..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.2.100")}, 16) = 64
19:15:45.249444 sendto(3, ""..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.2.100")}, 16) = 64
19:15:45.251079 sendto(3, ""..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.2.100")}, 16) = 64
19:15:45.252611 sendto(3, ""..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.2.100")}, 16) = 64
19:15:45.253581 sendto(3, ""..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.2.100")}, 16) = 64
19:15:45.255097 sendto(3, ""..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.2.100")}, 16) = 64
19:15:45.256587 sendto(3, ""..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.2.100")}, 16) = 64
19:15:45.258229 sendto(3, ""..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.2.100")}, 16) = 64
19:15:45.258846 sendto(3, ""..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.2.100")}, 16) = 64
19:15:45.259518 sendto(3, ""..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.2.100")}, 16) = 64

10 応答を待たずにICMP Echo Requestパケットを送信する方法(-l)

ICMP echo requestに対する応答を受信してから、次のICMP echo requestを送信します。 しかし、本オプションを指定すると、応答を待たずに、次のICMP echo requestを送信できます。 本オプションは、応答を待たずに送信できるICMP echo requestのパケット数を指定します。

以下の例では、5つ目までは短い間隔でICMPパケットを受信していますが、 6つ目からは1秒間隔でICMPパケットを受信していることがわかります。

[root@client ~]# ping -D -l 5 192.168.2.100
PING 192.168.2.100 (192.168.2.100) 56(84) bytes of data.
[1640255841.972294] 64 bytes from 192.168.2.100: icmp_seq=1 ttl=64 time=0.706 ms
[1640255841.972329] 64 bytes from 192.168.2.100: icmp_seq=2 ttl=64 time=0.536 ms
[1640255841.972338] 64 bytes from 192.168.2.100: icmp_seq=3 ttl=64 time=0.848 ms
[1640255841.972345] 64 bytes from 192.168.2.100: icmp_seq=4 ttl=64 time=0.770 ms
[1640255841.972352] 64 bytes from 192.168.2.100: icmp_seq=5 ttl=64 time=0.701 ms
[1640255842.986215] 64 bytes from 192.168.2.100: icmp_seq=6 ttl=64 time=0.796 ms
[1640255843.979614] 64 bytes from 192.168.2.100: icmp_seq=7 ttl=64 time=0.699 ms
[1640255844.976921] 64 bytes from 192.168.2.100: icmp_seq=8 ttl=64 time=0.705 ms
[1640255845.983677] 64 bytes from 192.168.2.100: icmp_seq=9 ttl=64 time=0.731 ms
[1640255846.976107] 64 bytes from 192.168.2.100: icmp_seq=10 ttl=64 time=0.504 ms

11 ペイロードのパターンを指定する方法(-p)

ICMP Echo Requestパケットのペイロードを確認するため、サーバ側でtcpdumpを実行します。 なお、tcpdumpの使い方は、tcpdumpの使い方(基本編) - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# tcpdump -i ens33 icmp -x

クライアントからサーバに対してpingを1回実行します。 このとき、ペイロードを0xffで埋めたICMP Echo Requestパケットを送信してみます

[root@client ~]# ping -c 1 -p ff 192.168.2.100
PATTERN: 0xff
PING 192.168.2.100 (192.168.2.100) 56(84) bytes of data.
64 bytes from 192.168.2.100: icmp_seq=1 ttl=64 time=0.648 ms

--- 192.168.2.100 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.648/0.648/0.648/0.000 ms

サーバ側で受信したICMP Echo Requestパケットの中身を確認します。 ペイロードが0xffのICMP Echo Requestパケットを受信し、その応答としてICMP Echo Replyパケットを返信しているのがわかります。

[root@server ~]# tcpdump -i ens33 icmp -x
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
18:34:49.006655 IP 192.168.2.105 > server: ICMP echo request, id 1922, seq 1, length 64
        0x0000:  4500 0054 78f5 4000 4001 3b96 c0a8 0269
        0x0010:  c0a8 0264 0800 f4b7 0782 0001 b942 c461
        0x0020:  0000 0000 7e20 0000 0000 0000 ffff ffff
        0x0030:  ffff ffff ffff ffff ffff ffff ffff ffff
        0x0040:  ffff ffff ffff ffff ffff ffff ffff ffff
        0x0050:  ffff ffff
18:34:49.006721 IP server > 192.168.2.105: ICMP echo reply, id 1922, seq 1, length 64
        0x0000:  4500 0054 586e 0000 4001 9c1d c0a8 0264
        0x0010:  c0a8 0269 0000 fcb7 0782 0001 b942 c461
        0x0020:  0000 0000 7e20 0000 0000 0000 ffff ffff
        0x0030:  ffff ffff ffff ffff ffff ffff ffff ffff
        0x0040:  ffff ffff ffff ffff ffff ffff ffff ffff
        0x0050:  ffff ffff

12 タイムアウトを指定する方法(-W)

存在しないホストに対してpingを実行してみます。 pingコマンドがタイムアウトするまで3秒(★)かかっていることがわかります。

[root@server ~]# date;ping -c 1 192.168.2.200;date
2021年 12月 22日 水曜日 ★19:27:26 JST
PING 192.168.2.200 (192.168.2.200) 56(84) bytes of data.
From 192.168.2.36 icmp_seq=1 Destination Host Unreachable

--- 192.168.2.200 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

2021年 12月 22日 水曜日 ★19:27:29 JST

次に、1秒のタイムアウトを指定してみます。 コマンドが1秒(★)で完了していることがわかります。

[root@server ~]# date;ping -W 1 -c 1 192.168.2.200;date
2021年 12月 22日 水曜日 ★19:28:43 JST
PING 192.168.2.200 (192.168.2.200) 56(84) bytes of data.

--- 192.168.2.200 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

2021年 12月 22日 水曜日 ★19:28:44 JST

13 pingの実行結果を簡潔に表示する方法(-q)

pingの実行結果(統計情報)だけを表示します。 ここでは、デフォルトルータにpingを10回実行してみます。

[root@server ~]# ping -q -c 10 192.168.2.1
PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data.

--- 192.168.2.1 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9073ms
rtt min/avg/max/mdev = 2.220/3.224/5.763/1.309 ms

14 IPv6アドレスに対するping

検証環境のIPv6は以下のとおりです。ともに、リンクローカルアドレスです。

client(ens33) ---------------------------------------------------(ens33) server
fe80::3e2:a9c0:9fa6:a8ad/64                        fe80::174:936a:8876:8055/64

クライアントでpingを実行します。 pingに指定する宛先IPv6アドレスは、サーバのIPv6リンクローカルアドレスです。 このとき、IPv6パケットを送信するデバイス名を-Iオプションで指定します。

[root@client ~]# ping -6 -I ens33 fe80::174:936a:8876:8055
PING fe80::174:936a:8876:8055(fe80::174:936a:8876:8055) from fe80::3e2:a9c0:9fa6:a8ad%ens33 ens33: 56 data bytes
64 bytes from fe80::174:936a:8876:8055%ens33: icmp_seq=1 ttl=64 time=0.640 ms
64 bytes from fe80::174:936a:8876:8055%ens33: icmp_seq=2 ttl=64 time=0.781 ms
-snip-

15 Path MTU Discoveryの使い方(-M)

-Mオプションを使うと、宛先までの経路上で最小のMTUを見つけることができます。

15.1 環境構築

作成したネットワークは以下のようになります。 r1,r2間のMTUは1000になります。

          192.168.100.0/24             192.168.110.0/24           192.168.120.0/24
            MTU=1500                       MTU=1000                    MTU=1500
   h1 ------------------------ r1 ------------------------ r2 ------------------------ h2
   (veth1-h1)        (veth1-r1)  (veth2-r1)      (veth1-r2)   (veth2-r2)     (veth1-h2)
     .10                    .20   .10                   .20   .10                   .20

15.2 フラグメント禁止の指定方法(-M do)

1500(byte)のICMPパケットを送信してみます。1500(byte)の内訳は以下のとおりです。

・IPヘッダ:20(byte)

・ICMPヘッダ:8(byte)

・ICMPペイロード:1472(byte)

フラグメントを禁止にすることで、パケット長がMTUを超える場合、ICMP Packet Too Bigが返信されます。

[root@client ~]# ping -M do -s 1472 192.168.120.20
PING 192.168.120.20 (192.168.120.20) 1472(1500) bytes of data.
From 192.168.100.20 icmp_seq=1 Frag needed and DF set (mtu = 1000)
ping: local error: Message too long, mtu=1000
ping: local error: Message too long, mtu=1000
ping: local error: Message too long, mtu=1000
ping: local error: Message too long, mtu=1000
-snip-

オプションを指定していないと、途中のルータがパケットを分割して宛先まで転送していることがわかります。

[root@client ~]# ping -s 1472 192.168.120.20
PING 192.168.120.20 (192.168.120.20) 1472(1500) bytes of data.
1480 bytes from 192.168.120.20: icmp_seq=1 ttl=62 time=0.054 ms
1480 bytes from 192.168.120.20: icmp_seq=2 ttl=62 time=0.056 ms
1480 bytes from 192.168.120.20: icmp_seq=3 ttl=62 time=0.058 ms
-snip-

なお、宛先までの経路上の最小MTUは、tracerouteコマンドでも調べることができます。 tracerouteコマンドは、tracerouteコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

Z 参考情報

私が業務や記事執筆で参考にした書籍を以下のページに記載します。 Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ