仕事:ローカルLAN(192.168.1.xタイプのクラスCアドレスを使用)以外のすべての(IPv4)IPアドレスを含むファイルから行を見つけて印刷します。私は次のようないくつかのパイプラインを使用してsed
これをかなり効率的に行いました(さまざまなオンライン検索からコンテンツを取得しました) 。
sed -rn '/([0-9]{1,3}\.){3}[0-9]{1,3}/p' logfile.txt | sed '/192\.168\.[[:digit:]]\.[[:digit:]]\{,3\}/d'
質問:代替ユーティリティを使用してこれを実行できる他の方法またはより良い方法はありますか?それとも私が思いついた注文を改善できますか?
背景:目的は、システム以外の(Void Linux)システムでSSH接続情報を含むシステムログファイルを毎日取得し、ローカルLAN上のホストに加えて誰がSSH接続/クエリの設定を試みたかを確認することです。 dailyを使用して宛先情報を含むファイルを生成し、上記のsvlogtail
コマンドを実行します。その後、システムは結果を私に電子メールで送信します。
入力データの例:
2020-06-21T08:28:04.56472 auth.err: sshd[21813]: error: Bind to port 22 on 192.168.2.16 failed: Cannot assign requested address.
2020-06-23T11:12:59.04698 auth.info: Jun 23 06:12:59 sshd[25036]: banner exchange: Connection from 194.61.24.4 port 1565: invalid format
2020-07-14T14:53:30.54107 auth.info: Jul 14 09:53:30 sshd[30149]: banner exchange: Connection from 31.207.47.114 port 1848: invalid format
2020-09-06T15:25:19.32385 auth.info: Sep 6 10:25:19 sshd[18826]: banner exchange: Connection from 193.142.146.216 port 30884: invalid format
2021-01-30T16:03:43.39251 auth.info: Jan 30 10:03:43 sshd[32208]: rexec line 80: Unsupported option GSSAPIAuthentication
2021-02-05T12:24:30.42762 auth.info: Feb 5 06:24:30 sshd[27489]: banner exchange: Connection from 94.232.47.170 port 107: invalid format
2021-02-19T15:48:10.29592 auth.info: Feb 19 09:48:10 sshd[2924]: Disconnected from user 192.168.1.10 port 33732
希望の出力sed
(この許容可能な出力は、上記のコマンドを実行した後に得られた結果です。)
2020-06-23T11:12:59.04698 auth.info: Jun 23 06:12:59 sshd[25036]: banner exchange: Connection from 194.61.24.4 port 1565: invalid format
2020-07-14T14:53:30.54107 auth.info: Jul 14 09:53:30 sshd[30149]: banner exchange: Connection from 31.207.47.114 port 1848: invalid format
2020-09-06T15:25:19.32385 auth.info: Sep 6 10:25:19 sshd[18826]: banner exchange: Connection from 193.142.146.216 port 30884: invalid format
2021-02-05T12:24:30.42762 auth.info: Feb 5 06:24:30 sshd[27489]: banner exchange: Connection from 94.232.47.170 port 107: invalid format
後で要約この種のタスクを実行する最もエレガントな方法は確かにですgrepcidr
。これを行う前にこれについて知っていたのであれば、明らかに使用していたでしょう。sed
同じ目標を達成するためのいくつかの方法(私が投稿したコマンドとパイプを含む)がありますが、これを回答に応じて使用するよう提案していきます。このコマンドは、またはを使用するよりも複数のアドレス範囲を簡単に指定できるため、grepcidr
このタイプの操作に適応性があります。sed
grep
grep
ちなみに、次のように一緒にパイプすると、同じ結果を与えるいくつかのコマンドも見つかりました。
grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' logfile.txt | grep -v 192.168.[[:digit:]].[[:digit:]]
答え1
192.168.0.0/16
ブロックにアドレスを含む行をフィルタリングしたいようです。次の方法でこれを実行できますgrepcidr
。
$ grepcidr -v '192.168.0.0/16' file
2020-06-23T11:12:59.04698 auth.info: Jun 23 06:12:59 sshd[25036]: banner exchange: Connection from 194.61.24.4 port 1565: invalid format
2020-07-14T14:53:30.54107 auth.info: Jul 14 09:53:30 sshd[30149]: banner exchange: Connection from 31.207.47.114 port 1848: invalid format
2020-09-06T15:25:19.32385 auth.info: Sep 6 10:25:19 sshd[18826]: banner exchange: Connection from 193.142.146.216 port 30884: invalid format
2021-02-05T12:24:30.42762 auth.info: Feb 5 06:24:30 sshd[27489]: banner exchange: Connection from 94.232.47.170 port 107: invalid format
または、「192.168.1.0と192.168.2.255の間」などの特定の範囲を使用する場合:
$ grepcidr -v '192.168.1.0-192.168.2.255' file
2020-06-23T11:12:59.04698 auth.info: Jun 23 06:12:59 sshd[25036]: banner exchange: Connection from 194.61.24.4 port 1565: invalid format
2020-07-14T14:53:30.54107 auth.info: Jul 14 09:53:30 sshd[30149]: banner exchange: Connection from 31.207.47.114 port 1848: invalid format
2020-09-06T15:25:19.32385 auth.info: Sep 6 10:25:19 sshd[18826]: banner exchange: Connection from 193.142.146.216 port 30884: invalid format
2021-02-05T12:24:30.42762 auth.info: Feb 5 06:24:30 sshd[27489]: banner exchange: Connection from 94.232.47.170 port 107: invalid format
すべてのプライベートIPv4ブロックをフィルタリングするには、次のようにします。
grepcidr -v '10.0.0.0/8,172.16.0.0/12,192.168.0.0/16' file
grepcidr
IPv6も理解しなければならないのに分からないので、例を見せません。
答え2
私はこの種の仕事に最適なツールだとgrep
思います。PCRE
grep -Po "(?<=from )(\d{1,3}\.){3}\d{1,3}(?= port)" file | grep -Ev "^192\.168\.1\.[[:digit:]]{1,3}$"
ネットワークに基本クラスCマスクがあるとします/24
。
より良いアプローチは、あなたの場合、LANホストなどの必須ホストへのロギングをスキップすることです。
また、ロガーの出力は理想的ではなく、解析できません。ファイアウォールのロギングモジュールなどのより良いロガーは、iptables
より洗練された方法で解析できます。
Feb 27 00:32:33 hostname kernel: [181663.827178] [HTTPS-ATTEMPT]IN=eno1 OUT= MAC=aa:bb:cc:dd:ee:ff:ff:ee:dd:cc:bb:aa:08:00 SRC=X.X.X.X DST=X.X.X.X LEN=40 TOS=0x00 PREC=0x00 TTL=242 ID=54321 PROTO=TCP SPT=42717 DPT=443 WINDOW=65535 RES=0x00 SYN URGP=0
ローカルLANホストへのロギングをスキップできる場合、パイプなしでgrep
2番目のラウンドが最初のラウンドで停止する可能性があります。
python
@Praveen Kumar BSは仕事をするのに良いモジュールを考えさせました。ipaddrress
#!/usr/bin/python3
import ipaddress
import re
lan = ipaddress.IPv4Network("192.168.1.0/24")
with open("stack.log", 'r') as log:
for line in log:
curr_ip = re.search(r'(?<=from )(\d{1,3}\.){3}\d{1,3}\b', line)
if curr_ip and not ipaddress.IPv4Address(curr_ip.group()) in lan:
print(curr_ip.group())
私の例では、正規表現キャプチャを介してアドレスを作成し、ipaddress
そのアドレスが特定のネットワークにあることを確認できます。lan
答え3
GNUgrep
または同様の正規表現サポート機能をgrep
使用すると、perl
否定予測演算子を使用できます。
grep -P '\b(?!192\.168\.)(\d{1,3})(\.(?1)){3}\b'
または直接使用してくださいperl
。
perl -ne 'print if /\b(?!192\.168\.)(\d{1,3})(\.(?1)){3}\b/'
これらのレポートには、開始IPアドレスを4進数で割った行が含まれています。この行にはIPアドレス192.168.
も含まれています。192.168.x.y
IP アドレスのより緊密な一致のために、次のRegexp::Common::net
モジュールを使用できます。
perl -MRegexp::Common=net -ne '
print if m{
\b$RE{net}{IPv4}{-keep}\b
(?(?{$2 == 192 && $3 == 168}) (*FAIL))
}x'
答え4
注文する:
awk '!/192.168.*.*/{for(i=1;i<=NF;i++){if($i ~ /^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$/){print $i}}}' filename
出力
194.61.24.4
31.207.47.114
193.142.146.216
94.232.47.170
Python
#!/usr/bin/python
import re
k=re.compile(r'192.168.*.*')
c=re.compile(r'^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*')
m=open('p.txt','r')
for i in m:
if not re.search(k,i):
z=i.split(' ')
for v in range(0,len(z),1):
if re.search(c,z[v]):
print z[v]
出力
194.61.24.4
31.207.47.114
193.142.146.216
94.232.47.170