TCP接続を集約表示するlstfにプロセス情報を表示するオプションを追加

lstfとは、Linuxサーバ上でホスト間コネクションを集約表示するツール lstf をつくった - ゆううきメモ で紹介しているように、netstatやssコマンドで大量のネットワーク接続情報が表示されるときに、オペレーターが目視できないという課題に対して、接続を集約して表示するツールになる。

今回,lstf v0.5.3にて、lstfが出力する接続フローに、接続をもつプロセスの情報(プロセスグループIDとプロセス名)を付与するオプションを追加した。 実際の出力は次のようになる。

$ sudo lstf -n -p
Local Address:Port      <-->    Peer Address:Port       Connections     Process
10.0.0.10:80            <--     10.0.0.11:many          4047            ("nginx",pgid=748)
10.0.0.10:22            <--     10.0.0.1:many           1               ("sshd",pgid=5217)
10.0.0.10:many          -->     52.196.35.56:443        1

このオプションにより,各集約フローがどのプロセスに紐づくものなのかをひと目で確認できるようになった. ("nginx",pgid=748)のようなプロセスの表記形式は、ssコマンドの--processesオプションの出力を真似した。

実装

基本的には、LinuxでTCP/UDPコネクション状態にプロセス情報を紐付ける方法 - ゆううきメモ で書いたように、TCP/UDPのコネクションリストとプロセスリストの2つのリストを突き合わせ、socket inodeをキーとして結合する。 ただし、次のようにsocket inodeが0となるソケットにはプロセス情報を紐付けられないため、ssコマンドでは単にプロセス情報の表示を諦める挙動になっている。

ただし、TCPコネクションのステートがTIME_WAITなど、ソケットをcloseした後のステートでは、ssコマンドでinodeが0となり、プロセス情報を取得できない。 また、まれにステートがESTABであっても、inodeが0となっていることがある。

そこで、lstfでは、passive openの接続の場合、接続の宛先ポート番号と、そのポートを待ち受けるプロセスを紐付けることは可能であるため、 例えば、宛先ポート番号が80の接続であれば、LISTENステートのソケット一覧を取得して、ポート80で待ち受けているソケットを絞り込み、socket inodeからプロセス情報を取得する。 しかし、active openの接続の場合、inodeが0だと、プロセスの特定のしようがないため、プロセスの取得を諦める。

ただし、lstfの接続の集約時に、1つでもinodeが0でないソケットがあれば、そのソケットから取得するプロセスこそが、その集約フロー全体のプロセスである、というようにする。 これにより、プロセス情報を取得できないケースをなるべく削減している。