从实时 tcpdump 抓取中提取唯一的 IP

8

我正在使用以下命令从实时tcpdump捕获中输出IP地址:

sudo tcpdump -nn -q ip -l | awk '{print $3; fflush(stdout)}' >> ips.txt

我得到了以下输出。
192.168.0.100.50771
192.168.0.100.50770
192.168.0.100.50759

需要两件事情:

  1. 只提取IP地址,不包括端口。
  2. 生成一个文件,其中IP地址唯一,不存在重复,并且如果可能的话按顺序排列。

提前感谢您的帮助。


从输出中获取$3可以得到源IP,但它可能不在您的网络上;它可能是从某个地方发送的数据包,并最终路由到您的网络中。除非源或目标地址与您的机器位于同一网络中,否则无法百分之百确定哪些IP是本地的,因此无法确定从tcpdump输出中使用源地址还是目标地址。如果这是一个给定的条件,您需要将该检查(IP是否与我的IP之一位于同一子网中)编码到awk脚本中,然后开始担心解析端口和唯一性问题。 - JCCyC
4个回答

19

从tcpdump中提取唯一的IP地址,您可以使用以下方法:

awk '{ ip = gensub(/([0-9]+.[0-9]+.[0-9]+.[0-9]+).*/,"\\1","g",$3); if(!d[ip]) { print ip; d[ip]=1; fflush(stdout) } }' YOURFILE

查看唯一IP地址的实时命令如下:

sudo tcpdump -nn -q ip -l | awk '{ ip = gensub(/([0-9]+.[0-9]+.[0-9]+.[0-9]+)(.*)/,"\\1","g",$3); if(!d[ip]) { print ip; d[ip]=1; fflush(stdout) } }'

这将会在每个IP出现时立即将其打印到输出中,因此无法对其进行排序。如果您想要对它们进行排序,可以将输出保存到文件中,然后使用sort工具:

sudo tcpdump -nn -q ip -l | awk '{ ip = gensub(/([0-9]+.[0-9]+.[0-9]+.[0-9]+)(.*)/,"\\1","g",$3); if(!d[ip]) { print ip; d[ip]=1; fflush(stdout) } }' > IPFILE
sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4  IPFILE

示例输出:

34.216.156.21
95.46.98.113
117.18.237.29
151.101.65.69
192.168.1.101
192.168.1.102
193.239.68.8
193.239.71.100
202.96.134.133

注意:确保您正在使用gawk。它无法与mawk一起使用。


非常好的回答!在代码的这一部分中,如果(!d[ip]),我能否添加一个awk条件来检查IP是公共的还是私有的?为了仅输出公共IP地址。使用grep将类似于grep -E '^(192.168|10.|172.1[6789].|172.2[0-9].|172.3[01].)',但如何使用awk完成呢? - Carlos
1
当处理非本地IP时,在您的AWK脚本开头添加$0!~/^(192\.168|10\.|172\.1[6789]|172\.2[0-9]\.|172\.3[01]\.)/,而对于本地IP,则添加$0~/^(192\.168|10\.|172\.1[6789]|172\.2[0-9]\.|172\.3[01]\.)/。因此,AWK命令的开头将类似于:awk '$0~/^(192\.168|10\.|172\.1[6789]|172\.2[0-9]\.|172\.3[01]\.)/ { ip = ... }' - Andriy Makukha
sudo tcpdump -nn -q ip -l | gawk '$0!~/^(192\.168|10\.|172\.1[6789]|172\.2[0-9]\.|172\.3[01]\.)/ { ip = gensub(/([0-9]+.[0-9]+.[0-9]+.[0-9]+)(.*)/,"\\1","g",$3); if(!d[ip]) { print ip; d[ip]=1; fflush(stdout) } }' 输出所有 IP 而不进行过滤。你能帮我吗? - Carlos
1
哦,抱歉,您需要将“$0”更改为“$3”。 - Andriy Makukha
@AndriyMakukha:你能解释一下如何只捕获唯一的IP地址吗?这与d[IP]有关,但我很难理解。谢谢! - aj8080
1
@aj8080,d[IP]=1会将键值对(IP, 1)添加到关联数组d中(在某些语言中也称为“字典”)。因此条件if (!d[IP])将防止处理任何先前观察到的IP。 - Andriy Makukha

6
虽然我非常喜欢Awk,但是有一些替代方案也值得考虑。请看以下使用cut命令的示例:
  tcpdump -n ip | cut -d ' ' -f 3 | cut -d '.' -f 1-4 | sort | uniq

您的命令没有输出任何IP地址。这里是基于您的解决方案:sudo tcpdump -n ip | cut -d ' ' -f 3 | cut -d '.' -f 1-4 | awk '!x[$0]++' - Arkadiy Bolotov

2
这是一个使用match的示例(在macOS中运行)。
sudo tcpdump -nn -q ip -l | \
    awk '{match($3,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/); \
    ip = substr($3,RSTART,RLENGTH); \
    if (!seen[ip]++) print ip }'

如果想要预先过滤输入内容,你可以使用类似以下的方法:

sudo tcpdump -nn -q ip -l | \
    awk '$3 !~ /^(192\.168|10\.|172\.1[6789]|172\.2[0-9]\.|172\.3[01]\.)/ \
    {match($3,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/); \
    ip = substr($3,RSTART,RLENGTH); \
    if (!seen[ip]++) print ip }'

1

sudo tcpdump -n ip | cut -d ' ' -f 3 | cut -d '.' -f 1-4 | awk '!x[$0]++'

这个命令对我很有用。简单而优雅。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接