You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过setsockopt的ICMP_FILTER选项安全过滤ICMP数据包?

如何通过ICMP_FILTER过滤ICMP数据包

首先明确:linux/icmp.h是正确的头文件,其中定义的struct icmp_filter就是用于配置ICMP_FILTER套接字选项的结构。

struct icmp_filter 结构说明

这个结构的核心是__u32 data[8]数组,总共8×32=256位,每一位对应一个ICMP消息类型(0-255):

  • 位为1:过滤该类型的ICMP包,套接字不会接收这类数据包
  • 位为0:允许接收该类型的ICMP包
  • 默认状态下所有位都是0,即接收所有ICMP类型的包

常用操作宏

头文件提供了两个便捷宏来快速初始化过滤器:

  • ICMP_FILTER_SETALL(&filter):将所有位设为1,即过滤所有ICMP类型
  • ICMP_FILTER_CLEARALL(&filter):将所有位设为0,即允许接收所有ICMP类型

实现需求:只接收ICMP_ECHOREPLY(类型0)

你的场景是发送ICMP_ECHO(类型8),只需要接收对应的ICMP_ECHOREPLY(类型0),可以按以下步骤配置:

  1. 初始化过滤器,先过滤所有类型
  2. 单独允许类型0的数据包通过
  3. 调用setsockopt应用过滤器

完整代码示例:

#include <linux/icmp.h>
#include <sys/socket.h>
#include <stdio.h>

// 假设sockfd是已创建的原始套接字:int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

struct icmp_filter filter;

// 第一步:过滤所有ICMP类型
ICMP_FILTER_SETALL(&filter);

// 第二步:清除类型0对应的位,允许接收ICMP_ECHOREPLY
// ICMP_ECHOREPLY的值是0,对应data[0]的第0位
filter.data[ICMP_ECHOREPLY / 32] &= ~(1 << (ICMP_ECHOREPLY % 32));

// 第三步:应用过滤器到套接字
if (setsockopt(sockfd, SOL_RAW, ICMP_FILTER, &filter, sizeof(filter)) == -1) {
    perror("setsockopt ICMP_FILTER failed");
    // 这里添加你的错误处理逻辑,比如关闭套接字、退出等
}

其他场景示例

如果你需要过滤特定类型(比如过滤ICMP_ECHO类型8),可以这样写:

struct icmp_filter filter;

// 先允许所有类型
ICMP_FILTER_CLEARALL(&filter);

// 设置类型8对应的位为1,过滤ICMP_ECHO包
filter.data[ICMP_ECHO / 32] |= (1 << (ICMP_ECHO % 32));

setsockopt(sockfd, SOL_RAW, ICMP_FILTER, &filter, sizeof(filter));

注意事项

  • 操作位时要确保类型值在0-255范围内,避免越界访问data数组
  • setsockopt调用失败时一定要检查返回值,通过perror获取具体错误信息
  • 该过滤器仅对接收的ICMP数据包生效,不影响发送操作

内容的提问来源于stack exchange,提问作者MaPo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 10:25:10