tcpdump可快速识别icmpsh流量:捕获大于74字节icmp包,筛出含windows路径、命令关键字等明文载荷;其固定64字节、非默认填充、高频递增序列号及无连接特性是关键特征。

Linux怎么用tcpdump快速识别icmpsh流量特征
直接抓包看数据载荷是否异常,比等规则告警更早发现问题。icmpsh的ICMP数据段明显偏离系统默认填充内容,且固定64字节(不含IP/ICMP头),这是最易观察的突破口。
- 执行
tcpdump -i any icmp and greater 74 -w icmp.pcap捕获所有大于默认Windows ping包(74字节总长)的ICMP包,避免被正常探测淹没 - 用
tcpdump -r icmp.pcap -A | grep -E "(Micro|C:\\|Desktop|ipconfig|whoami)"快速筛出含Windows路径、命令关键字或典型shell提示符的载荷 - 注意:icmpsh默认不加密,载荷里常出现明文ASCII字符串,比如
"C:UsersAdministratorDesktop>"或"Microsoft Windows [6.1.7601]",这类内容在正常ping中绝不会出现 - 若发现大量连续64字节ICMP echo request(type=8),且payload十六进制呈现无规律、非默认填充(如不是
61626364...或08090a0b...),基本可判定为隧道行为
Suricata规则怎么写才能捕获icmpsh类ICMP隧道
靠单一 dsize 阈值容易误报,必须结合载荷内容、频率和序列号行为三重判断。官方规则库里的 sid:5621006(dsize:>100; threshold:count 50/5s)对icmpsh无效——它压根不用那么大载荷。
- 真正有效的规则要匹配“小载荷 + 高频 + 非标准内容”,例如:
alert icmp any any -> $HOME_NET any (msg:"ICMP tunnel likely - non-default payload"; content:"C:\\"; depth:10; fast_pattern; sid:900001; rev:1;)
- 加一条序列号检测:icmpsh的sequence字段会持续递增(不像正常ping是随机或固定),可用
itype:8; byte_test:2,>,0,4,big; byte_jump:2,4,big; content:"|00 01|"; offset:4;粗筛异常递增模式(需Suricata 6.0+) - 禁用
flowint类状态跟踪规则——icmpsh通信无连接状态,这类规则几乎不触发 - 别忘了排除已知合法工具:fscan的ICMP末32字节恒为零,可在规则中加
isdataat:32,relative; content:"|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|"; distance:0;避免误杀
怎么定位发出icmpsh流量的进程(Linux端)
icmpsh服务端是Python脚本,但实际发包的是内核ICMP socket,lsof -i icmp 或 netstat 都看不到。得从socket创建源头入手。
- 先用
ss -uapn | grep :0查UDP监听——虽然ICMP不走UDP,但很多ICMP隧道工具(如icmptunnel)会伪造UDP套接字做伪装,漏掉就白查了 - 用
strace -f -e trace=socket,sendto,sendmsg -p $(pgrep -f "icmpsh_m.py") 2>&1 | grep -i icmp实时跟踪目标进程的socket调用,确认是否真在构造ICMP包 - 更彻底的方法:用
auditctl -a always,exit -F arch=b64 -S socket -F a0=10 -k icmp_socket(10=AF_INET)审计所有IPv4 socket创建,再配合aureport -k icmp_socket --start recent定位调用进程 - 注意:若攻击者改用
python3 -c "import socket;..."一行式启动,pgrep -f可能漏掉,此时必须依赖auditd或eBPF工具(如bpftrace)捕获原始socket事件
为什么单纯禁用 net.ipv4.icmp_echo_ignore_all 不够
这个内核参数只控制是否响应echo reply,对icmpsh这类主动外发echo request的客户端完全无效——它根本不需要系统回包,自己构造并发送即可。
- 真正该关的是ICMP raw socket权限:
echo 1 > /proc/sys/net/ipv4/conf/all/secure_redirects作用有限,但sysctl -w net.ipv4.conf.all.rp_filter=1可抑制部分伪造源IP的ICMP包 - 更有效的是限制非root用户创建raw socket:
echo 1 > /proc/sys/net/ipv4/ping_group_range改为0 0,让只有root能调用socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) - 如果业务确实需要普通用户ping,至少用
setcap cap_net_raw+ep /bin/ping替代全局放开,避免Python脚本随意调用raw socket - 最关键的盲点:icmpsh_m.py本身不发包,它通过
socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)创建套接字后调用sendto()。只要Python进程有CAP_NET_RAW能力,禁用系统ping响应毫无意义
实际环境中,ICMP隧道最棘手的不是检测不到,而是它混在海量正常ping里难以分离。载荷内容指纹比包长、频率更可靠,而进程级溯源必须绕过“内核处理ICMP”的表象,盯住socket创建那一刻的调用栈。











