私はIPSetを使用して、IPTablesルールにリンクされる数万のIPv4 CIDR /ネットマスク範囲を管理しています。この設定はうまく機能していますが、クライアントのレポート作成のためにIPSetが作用するIPホストアドレスの概要を正確に把握したいと思います。
IPSetエントリのフォーマットは、一貫して次のようになります。
123.456.0.0/16 timeout 86400
したがって、timeout
を持つ行をgrepして、エントリに含まれるCIDR /ネットマスク範囲に作用する値を取得できます。
たとえば、IPSet出力を(ipset -L -n > ipset-20181228.txt
経由で)ipset-20181228.txt
という名前のテキストファイルに保存してから、次のようにgrep
とwc -l
の組み合わせを実行するとします。
grep "timeout" ipset-20181228.txt | wc -l
39,000以上のCIDR /ネットマスク範囲に相当する39,000以上のアイテムの数を取得します。ただし、これは(もちろん)CIDR /ネットマスク範囲のみをカウントし、その範囲内のIPホストアドレスの完全なカウントはカウントしません。
prips
(CIDR /ネットマスク値をBashの実際のIPアドレスに展開します)をgrepで使用して、次のようなCIDR /ネットマスク範囲のアイテムのみを選別しようとしました。
grep -oE '(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([0-9]{1,2})' ipset-20181228.txt | awk 'NF { system( "prips " $0) }' | wc -l
そして、2018 MacBook Airで(ファンがキックインして)なんと20〜30分(!!!)した後、私が得たカウントは736,000,000+でした。これは、私が目指していることです…しかし、20〜30分は長すぎます。 。これをできるだけスクリプト化可能で邪魔にならないようにし、リソースを消費せずに本番サーバーで実行するようなコマンドを信頼することはできません。私のローカル2018MacBookAir開発セットアップでどのように動作するかを見てください。
単にCIDR /ネットマスク値に基づいてCIDR /ネットマスク範囲カウントを計算する方法はありますか?コマンドラインツール(または使用している既存のツールのオプション)があれば、それが役立つことに気づいていないことを願っています。
grep
コマンドが_123.456.0.0/16
_のような行を出力する場合は、それらをにパイプする必要があります
_awk -F / '{ count[$2]++ } END { for (mask in count) total+=count[mask]*2^(32-mask); print total }'
_
このコマンドは、マスク(つまり、_/
_の後にあるもの)のみを抽出し、各マスクの発生をカウントします。最後に、検出されたマスク(2^(32-mask)
)ごとにホストの数が計算され、発生数が乗算されて合計されます。
ノート:
1.2.3.4/40
_のような入力が受け入れられ、非整数出力が計算されます。必要に応じて、予備のgrep
フィルターを改善します。prips
での試行はこれで良くなかったと思います)。元のポスターはtimeout
の行からCIDRを取得するためにgrepを実行しているので、このようなものが機能すると思いました。
awk -F'[ /]' '/timeout/ {hosts+=2^(32-$2)};ENDFILE{print "Hosts number in "FILENAME": "hosts;total+=hosts;hosts=0};END {print "Total: "total}' ipset*.txt
編集-上記のawk
プログラムは、GNU awk
でのみ正常に実行されます。 ENDFILE
はGNU拡張子です。
BSD awk
はENDFILE
を無視し、メインプログラムセクションの一部である場合はそのセクションを実行すると思います。
これはGNUおよびBSDawkと互換性があります。
awk -F'[ /]' '{if (filename != FILENAME) hosts=0};/timeout/ {hosts+=2^(32-$2)};{filename=FILENAME;file_total[filename]=hosts};END{for (i in file_total) {print "Hosts number in "i": "file_total[i];total+=file_total[i]};{print "Total: "total};}' ipset*.txt