nstatコマンドの使い方
- 1 nstatコマンドとは?
- 2 検証環境
- 3 パッケージのインストール方法
- 4 オプション一覧
- 5 単純な使い方(オプション指定なし)
- 6 カウンタが0の統計情報も表示する方法(-z)
- 7 OS起動時からの累積値を表示する方法(-a)
- 8 特定の統計情報を表示する方法
- 9 統計情報をjson形式で表示する方法
- 10 その他
- Z 参考情報
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
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技術ブログ