hana_shinのLinux技術ブログ

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

nstatコマンドの使い方



1 nstatコマンドとは?

ネットワークの統計情報を表示するコマンドです。CentOS6までは、ネットワークの統計情報はnetstat -sで取得できました。CentOS7では、netstatコマンドではなくssコマンドを使うことが推奨されているのですが、ssコマンドはnetstat -sに相当する情報が取得できません。しかし、nstatコマンドは、netstat -sに相当する情報を表示することができます。ここでは、nstatコマンドの使い方について説明します。

2 検証環境

2.1 ネットワーク構成

サーバとクライアントの2台構成です。図中のens33はNICの名前です。クライアントからサーバにパケットを送信し、サーバでnstatコマンドを実行します。

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

2.2 版数

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

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

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

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

3 パッケージのインストール方法

iprouteパッケージをインストールします。

[root@server ~]# yum -y install iproute

版数を確認します。

[root@server ~]# nstat -V
nstat utility, iproute2-ss170501

4 オプション一覧

オプションは以下のとおりです。

[root@server ~]# nstat -h
Usage: nstat [OPTION] [ PATTERN [ PATTERN ] ]
   -h, --help           this message
   -a, --ignore         ignore history
   -d, --scan=SECS      sample every statistics every SECS
   -j, --json           format output in JSON
   -n, --nooutput       do history only
   -p, --pretty         pretty print
   -r, --reset          reset history
   -s, --noupdate       don't update history
   -t, --interval=SECS  report average over the last SECS
   -V, --version        output version information
   -z, --zeros          show entries with zero activity

5 単純な使い方(オプション指定なし)

左から2列目が統計情報のカウンタです。カウンタが0以外のものが表示されます。表示されるカウンタは、前回nstatコマンドを実行してからの差分を表します。

[root@server ~]# nstat
#kernel
IpInReceives                    532                0.0
IpInDelivers                    532                0.0
IpOutRequests                   435                0.0
-snip-

IcmpInMsgsは、受信したICMPパケット数を表します。まず、IcmpInMsgsの初期値を確認します。0であることがわかります。

[root@server ~]# nstat IcmpInMsgs
#kernel

クライアントで宛先をサーバにしてpingを実行します。なお、pingコマンドの使い方は、pingコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@client ~]# ping -c 2 192.168.2.100

nstatコマンドを実行します。IcmpInMsgsの値が2になったことがわかります。

[root@server ~]# nstat IcmpInMsgs
#kernel
IcmpInMsgs                      2                  0.0

もう一度、nstatコマンドを実行します。前回のnstatコマンド実行以降、ICMPパケットを受信していないので、IcmpInMsgsの値は0となり、実行結果に表示されないことがわかります。

[root@server ~]# nstat IcmpInMsgs
#kernel

6 カウンタが0の統計情報も表示する方法(-z)

-zは、カウントが0の統計情報も含めて、すべての統計情報を表示するオプションです。カウンタが0のIpInHdrErrorsやIpInAddrErrorsが表示されていることがわかります。

[root@server ~]# nstat -z
#kernel
IpInReceives                    250                0.0
IpInHdrErrors                   0                  0.0
IpInAddrErrors                  0                  0.0
-snip-

7 OS起動時からの累積値を表示する方法(-a)

-aは、OS起動時からの統計情報のカウンタの累積値を表示します。OSを再起動すると0に初期化されます。

[root@server ~]# nstat -a
#kernel
IpInReceives                    358                0.0
IpInDelivers                    358                0.0
IpOutRequests                   341                0.0
-snip-

8 特定の統計情報を表示する方法

IcmpInMsgsの累積値を表示してみます。

[root@server ~]#
[root@server ~]# nstat -a IcmpInMsgs
#kernel
IcmpInMsgs                      22                 0.0

IpInReceivesとIpInDeliversの累積値を表示してみます。

[root@server ~]# nstat -a IpInReceives IpInDelivers
#kernel
IpInReceives                    1610               0.0
IpInDelivers                    1610               0.0

9 統計情報をjson形式で表示する方法

9.1 josn形式で表示する方法(-j)

[root@server ~]# nstat -j
{"kernel":{"IpInReceives":21,"IpInDelivers":21,"IpOutRequests":19,"TcpInSegs":19,"TcpOutSegs":18,"UdpInDatagrams":2,"UdpOutDatagrams":2,"Ip6InReceives":6,"Ip6InDelivers":6,"Ip6OutRequests":6,"Ip6InMcastPkts":3,"Ip6OutMcastPkts":6,"Ip6InOctets":436,"Ip6OutOctets":488,"Ip6InMcastOctets":228,"Ip6OutMcastOctets":576,"Ip6InNoECTPkts":6,"Icmp6InMsgs":6,"Icmp6OutMsgs":6,"Icmp6InGroupMembQueries":3,"Icmp6InNeighborSolicits":2,"Icmp6InNeighborAdvertisements":1,"Icmp6OutNeighborSolicits":1,"Icmp6OutNeighborAdvertisements":2,"Icmp6OutMLDv2Reports":3,"Icmp6InType130":3,"Icmp6InType135":2,"Icmp6InType136":1,"Icmp6OutType135":1,"Icmp6OutType136":2,"Icmp6OutType143":3,"TcpExtDelayedACKs":1,"TcpExtTCPHPHits":6,"TcpExtTCPPureAcks":3,"TcpExtTCPHPAcks":5,"TcpExtTCPOrigDataSent":11,"IpExtInOctets":1500,"IpExtOutOctets":5284,"IpExtInNoECTPkts":21}}

9.2 pretty形式で表示する方法(-p)

[root@server ~]# nstat -jp
{
    "kernel": {
        "IpInReceives": 11,
        "IpInDelivers": 11,
        "IpOutRequests": 7,
        "TcpInSegs": 11,
        "TcpOutSegs": 7,
        "TcpExtTCPHPHits": 1,
        "TcpExtTCPPureAcks": 3,
        "TcpExtTCPHPAcks": 3,
        "TcpExtTCPOrigDataSent": 7,
        "IpExtInOctets": 672,
        "IpExtOutOctets": 1588,
        "IpExtInNoECTPkts": 11
    }
}

10 その他

ここでは、クライアントからサーバに様々なパケットを送信して、統計情報のカウンタがカウントアップする様子を確認してみます。

10.1 TcpInCsumErrors

TcpInCsumErrorsは、TCP層でカウントする統計情報で、TCPチェックサム異常となったTCP受信パケット数を表します。

TCPチェックサム値をチェックする処理は、TCP層だけでなく、ファイアウォール(netfiler)にもあります。その処理にひっかかってTCPパケットが廃棄されないようにするため、firewalldサービスを停止しておきます。

[root@server ~]# systemctl stop firewalld.service

TcpInCsumErrorsのカウンタを確認します。

[root@server ~]# nstat TcpInCsumErrors
#kernel

TCPヘッダのチェックサム値を不正な値に変更したTCPパケットをサーバに送信します。なお、hping3コマンドの使い方は、hping3コマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@client ~]# hping3 -I ens33 -c 1 -b -S -s 22222 -p 11111 192.168.2.100

TcpInCsumErrorsのカウンタを確認します。カウンタが1になったことがわかります。つまり、TCPチェックサム異常のTCPパケットを1つ受信したことを意味しています。

[root@server ~]# nstat TcpInCsumErrors
#kernel
TcpInCsumErrors                 1                  0.0

10.2 TcpExtTCPAbortOnClose

カーネル受信バッファから受信データを全て読み出さずにプロセスが終了すると、パケット送信元にRSTパケットが送信されます。そのとき、本統計情報のカウンタがアップされます

TcpExtTCPAbortOnCloseのカウンタを確認します。

[root@server ~]# nstat  TcpExtTCPAbortOnClose
#kernel

ncプロセスがTCPの11111番ポートでListenするようにします。ncコマンドのインストール、使い方はncコマンドの使い方(ネットワーク実験の幅が広がるなぁ~) - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# nc -kl 11111

サーバの11111番ポートを解放します。firewall-cmdのインストール、使い方は、firewall-cmdの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# firewall-cmd --add-port=11111/tcp
success

クライアントでncコマンドを実行して、サーバとの間でTCPコネクションを確立します。

[root@client ~]# nc 192.168.2.100 11111

サーバでCtrl+zを押下して、ncプロセスを停止します。

[root@server ~]# nc -kl 11111
^Z
[1]+  停止                  nc -kl 11111

クライアントからサーバに改行を含めて6バイト送信します。

[root@client ~]# nc 192.168.2.100 11111
12345

ssコマンドを実行すると、Recv-Qの値が6になっています。この値は、カーネル受信バッファに残っている受信バイト数を表しています。ncプロセスが停止しているため、カーネルの受信バッファからデータを読み出すことができないため、受信データがカーネルの受信バッファに残ったままになっています。なお、ssコマンドの使い方は、ssコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# ss -tn4 'sport == :11111'
State       Recv-Q Send-Q               Local Address:Port                              Peer Address:Port
ESTAB       6      0                    192.168.2.100:11111                            192.168.2.105:57600

ncプロセスを終了します。

[root@server ~]# pkill -SIGKILL nc

TcpExtTCPAbortOnCloseのカウンタを確認すると1になったことがわかります。つまり、カーネル受信バッファのデータを読み出さないままncプロセスが終了したため、サーバからクライアントにRSTパケットが1つ送信されたことを意味しています。

[root@server ~]# nstat TcpExtTCPAbortOnClose
#kernel
TcpExtTCPAbortOnClose           1                  0.0

10.3 TcpExtSyncookiesSent

TcpExtSyncookiesSentは、SYN flood攻撃を受けたときにカウントアップします。

TcpExtSyncookiesSentのカウンタを確認します。

[root@server ~]# nstat -a TcpExtSyncookiesSent
#kernel

サーバでncコマンドを実行します。

[root@server ~]# nc -kl 11111

クライアントでhping3コマンドを実行して、サーバにSYN flooding攻撃を実行してみます。-aで指定するアドレスは、同一サブネット内の存在しないIPアドレスを指定します。

[root@client ~]# hping3 -I eth0 -a 192.168.2.200 -S -p 11111 -i u1000 192.168.2.100

TcpExtSyncookiesSentのカウンタを確認します。1576に増えていることがわかります。

[root@server ~]# nstat TcpExtSyncookiesSent
#kernel
TcpExtSyncookiesSent            1576               0.0

journalctlコマンドを実行します。SYN flooding攻撃を受けている旨のログが出力されていることがわかります。なお、journalctlコマンドの使い方は、journalctlコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。

[root@server ~]# journalctl -f
 3月 06 09:41:13 server kernel: TCP: request_sock_TCP: Possible SYN flooding on port 11111. Sending cookies.  Check SNMP counters.

ssコマンドを実行します。TCPコネクションが確立できず、syn-recv状態のままのソケットが多数存在することがわかります。

[root@server ~]# ss -n4 state syn-recv
Netid Recv-Q Send-Q                  Local Address:Port                                 Peer Address:Port
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:14153
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:1878
tcp   0      0           192.168.2.100%if383362009:11111                               192.168.2.200:15116
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:7245
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:12178
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:7242
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:12045
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:12180
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:12179
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:12181
tcp   0      0           192.168.2.100%if383362009:11111                               192.168.2.200:13754
tcp   0      0              192.168.2.100%if-28152:11111                               192.168.2.200:1888
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:7246
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:1881
tcp   0      0              192.168.2.100%if-28152:11111                               192.168.2.200:1885
tcp   0      0                       192.168.2.100:11111                               192.168.2.200:1874

Z 参考情報

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