精准过滤IPv4地址需用正则确保每段为0–255,核心表达式为(25[0-5]|20-4|[01]?0-9?),四段以.连接并加\b锚定;结合awk筛选状态码、统计频次可定位攻击源IP;需注意代理头字段、排除内网IP及干扰项。

要精准过滤IP地址,关键不是简单匹配数字和点,而是用正则确保每段是合法的0–255范围,避免匹配到像999.999.999.999或1234.56.78.90这类非法格式。
匹配合法IPv4地址的核心正则
单个字节(0–255)的严谨写法是:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)。它分三部分覆盖所有可能:
-
25[0-5]→ 匹配250–255 -
2[0-4][0-9]→ 匹配200–249 -
[01]?[0-9][0-9]?→ 匹配0–199(含前导零如007,但实际日志中少见;若需严格无前导零,可进一步限制)
四个字节用\.连接,并加词界锚定(\b),防止匹配到长字符串中的子串(比如192.168.1.1234里的前四段):
grep -oE '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b' access.log
结合攻击特征做定向提取
只提取IP不够,要定位攻击源,得叠加行为条件。例如筛选返回403/404且高频访问的IP:
- 先用
awk筛出状态码异常的行:awk '$9 ~ /^(403|404)$/' access.log - 再提取IP并统计频次:
awk '$9 ~ /^(403|404)$/ {print $1}' access.log | grep -oE '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.{3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b' | sort | uniq -c | sort -nr | head -20
这样得到的是“高频触发拒绝响应”的可疑IP列表,比单纯扫全量IP更有效。
处理常见干扰项
日志里常混有IPv6、域名、本地地址或伪造头字段(如X-Forwarded-For)。需注意:
- 默认
$1在Apache日志中是真实客户端IP;若用了CDN或反向代理,真实IP可能在X-Forwarded-For字段,需先用awk -F'"' '{print $2}'或sed提取该字段再过滤 - 排除内网IP(如10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)可用
grep -vE '\b(10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.)' - IPv6地址不适用该正则,如需支持,应单独用
grep -oE '([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}',但多数Web攻击仍以IPv4为主
快速验证与调试技巧
写完正则别直接跑全量日志,先小样测试:
- 准备测试数据:
echo -e "192.168.1.1\n255.255.255.255\n999.1.1.1\n12.34.567.89\n10.0.0.1" > test_ips.txt - 运行命令验证输出是否仅含前两行
- 加
-n显示行号,--color=always高亮匹配部分,便于观察边界是否准确
不复杂但容易忽略细节。

















