在文件中查找不包括本地 IP 的 IP 地址

在文件中查找不包括本地 IP 的 IP 地址

任务:从文件中查找并打印包含本地 LAN(本地 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'

问题:是否有其他或更好的方法可以使用替代实用程序来执行此操作,或者我可以对我想出的咒语进行改进?

背景:目的是,在非 systemd (Void Linux) 系统上,每天搜寻包含 ssh 连接信息的系统日志文件,以查看除本地 LAN 上的主机之外的哪些人一直在尝试建立 ssh 连接/查询。每天使用 生成包含目标信息的文件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

我认为grepPCRE是此类工作的最佳工具:

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第二轮可能会在没有管道的情况下在第一轮停止。

@Praveen Kumar BS 让我想到一个很好的python模块来完成这项工作: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 地址的四进制十进制表示形式的行192.168.,即使这些行也包含192.168.x.yIP 地址。

为了更严格地匹配 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

相关内容