92-ICMP 协议(基础)

本文介绍了ICMP协议的基本概念,包括其在网络层中的作用、ICMP报文的分类及首部格式。并列举了一些常见的ICMP报文类型,如ICMP回显与应答等。

ICMP 协议(Internet Control Messages Protocol,网际控制报文协议)是网络层最重要的协议之一。前面的实验我们也看到了,它由 IP 协议承载,封装在 IP 协议的数据部分。


这里写图片描述
图1 ICMP 被封装在 IP 数据报的数据部分

1. ICMP 报文的作用

网络上经常会出现一些错误,比如目标主机不存在,目标端口不存在什么的,那么你要怎么知道呢?ICMP 的功能之一就是将错误反馈给你,这种 ICMP 报文通常被称为差错报文,表示网络出问题啦!

当然,ICMP 还有其它的功能,比如你发送一个时间戳请求 ICMP 报文给一台主机,那台主机知道这是请求时间的,就会把自己的时间放在 ICMP 报文中,然后再发回去给你,像这种 ICMP 报文称为 ICMP 查询报文和 ICMP 应答报文。

还有一种就是用于控制网络行为的,比如路由重定向啊等等。

当然啦,上面只是粗略的分类,后面我们写程序来练习。

2. ICMP 首部

2.1 ICMP 首部格式


这里写图片描述
图2 ICMP 首部格式

任何 ICMP 报文的首 4 字节的格式都是一样的,如图 2 所示。我们程序在收到了 ICMP 报文的时候,可以根据 ICMP 的类型,代码号来判断这个 ICMP 报文是哪个类别。

比如类型号是 3,表示这是差错报文,具体到是哪种差错报文,还要看 8 位代码号。如果类型号是 13 表示这是一个时间戳请求报文等等。

2.2 ICMP 结构体

按照图 2 中给出的首部,我们很容易写了 ICMP 的结构体。该结构体定义在系统的头文件 /usr/include/netinet/ip_icmp.h 中。为了方便学习,我在 unp/program/include/icmp.h 中重新定义了它,以后我们写程序的时候,包含 include/icmp.h 即可。

// icmp 头部
struct icmp {                  
  uint8_t icmp_type;           
  uint8_t icmp_code;           
  uint16_t icmp_cksum;         
  // 不同类型的 icmp 报文,后面都不一样
};

3. 常见的 ICMP 报文类型

我列举的几个,是我们将要学习的几种(用 type 表示类型,code 表示代码号):

  • ICMP 回显与应答(type = 8或0,code = 0)
  • ICMP 地址掩码请求与应答(type = 17或18,code = 0,已废弃,如今已使用 DHCP 协议取代,参考 RFC 6918 的 2.4 和 2.5 小节.)
  • ICMP 时间戳请求与应答(type = 13或14,code = 0)
  • ICMP 端口不可达差错报文(type = 3,code = 3)

还有很多其它类型的 ICMP 报文,这里就不细讲了。《TCP/IP 详解》一书的第 6 章对此描述的非常清楚,大家可以去看。

4. 总结

  • 掌握 ICMP 首部格式
  • 知道 ICMP 报文是根据什么分类的

练习:尝试着解析一个 ICMP 报文,并打印它的 type、code 和 cksum 字段。

<think>我们遇到了一个关于防火墙规则设置的问题,具体是当尝试在Ubuntu上允许ICMPv6流量时,命令`sudo ufw allow proto ipv6-icmp from any to any`可能返回错误提示“未被支持的协议ipv6-icmp”。这是因为UFW(Uncomplicated Firewall)在某些版本中可能不支持直接使用`ipv6-icmp`作为协议名称。 ### 原因分析 在UFW中,对于IPv6的ICMP协议(即ICMPv6),需要使用`ipv6-icmp`作为协议名称,但是某些较旧的UFW版本可能不支持这个关键字。另外,也有可能是因为命令格式不正确。 ### 解决方案 #### 方法1:使用ICMPv6的类型编号 ICMPv6可以通过指定类型(type)来允许特定的ICMPv6消息。对于ping(echo请求)和pong(echo应答),我们通常需要允许类型128(echo请求)和129(echo应答)。但为了允许所有ICMPv6流量(包括邻居发现等),我们可以允许所有类型。 ```bash # 允许所有ICMPv6流量(包括ping) sudo ufw allow in proto ipv6 from any to any app name "All ICMPv6" # 或者更精确地指定类型(可选,如果上面不行,可以尝试下面指定类型) sudo ufw allow in proto ipv6 from any to any port 0 app name "ICMPv6 Echo Request" type 128 sudo ufw allow in proto ipv6 from any to any port 0 app name "ICMPv6 Echo Reply" type 129 ``` 但是,如果上述方法仍然报错,我们可以尝试使用更底层的iptables命令。 #### 方法2:直接使用iptables(IPv6) 因为UFW底层使用的是iptables,我们可以直接使用iptables命令来添加规则(注意:UFW管理规则可能会覆盖手动添加的规则,所以最好通过UFW的配置文件添加)。 ```bash # 允许所有ICMPv6 sudo ip6tables -A INPUT -p ipv6-icmp -j ACCEPT ``` 但是,为了确保规则持久化,并且不被UFW覆盖,我们可以将规则添加到UFW的配置文件中。 ##### 步骤: 1. 编辑UFW的IPv6规则文件(如果不存在则创建): ```bash sudo nano /etc/ufw/before6.rules ``` 2. 在`COMMIT`行之前添加以下规则: ``` # 允许ICMPv6 -A ufw6-before-input -p ipv6-icmp -j ACCEPT ``` 3. 重启UFW: ```bash sudo ufw reload ``` #### 方法3:升级UFW 如果是因为UFW版本过旧,可以考虑升级UFW到最新版本: ```bash sudo apt update sudo apt upgrade ufw ``` ### 验证 添加规则后,使用以下命令检查规则是否生效: ```bash sudo ip6tables -L ``` 或者使用UFW的状态检查: ```bash sudo ufw status verbose ``` ### 注意事项 - 允许所有ICMPv6流量对于IPv6网络是必要的,因为IPv6的邻居发现等基础功能都依赖ICMPv6。 - 如果只希望允许ping,可以只允许类型128和129。 §§相关问题§§ 1. 如何在Ubuntu中查看当前UFW版本并确定其是否支持ipv6-icmp协议? 2. 除了UFW,还有哪些方法可以配置Ubuntu系统的IPv6防火墙规则? 3. 如何通过UFW配置文件允许特定类型的ICMPv6消息(如邻居发现)? 4. 在直接使用ip6tables命令后,如何确保规则在系统重启后仍然有效?</think>### 解决 "未被支持的协议 ipv6-icmp" 错误 当在 Ubuntu 防火墙 (UFW) 中配置 IPv6 规则时遇到 "未被支持的协议 ipv6-icmp" 错误,这是因为 UFW 的语法限制。以下是三种解决方案: --- ### **解决方案 1:使用正确的协议名称** UFW 要求使用 **`icmp6`** 而非 `ipv6-icmp`: ```bash # 正确写法 sudo ufw allow proto icmp6 from any to any ``` --- ### **解决方案 2:使用 ICMP 类型编号** 更精确地指定 ICMPv6 类型(推荐): ```bash # 允许所有 ICMPv6 流量 sudo ufw allow in proto ipv6 from any to any app name "All ICMPv6" # 或仅允许 ping 相关类型: sudo ufw allow in proto ipv6 from any to any port 0 app name "ICMPv6 Echo Request" type 128 sudo ufw allow in proto ipv6 from any to any port 0 app name "ICMPv6 Echo Reply" type 129 ``` --- ### **解决方案 3:直接修改 iptables 规则** 绕过 UFW 直接配置底层防火墙: ```bash # 允许所有 ICMPv6 sudo ip6tables -A INPUT -p ipv6-icmp -j ACCEPT # 或仅允许 ping sudo ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-request -j ACCEPT sudo ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-reply -j ACCEPT ``` > **永久保存规则**: > 安装 `iptables-persistent` 并保存规则: > ```bash > sudo apt install iptables-persistent > sudo netfilter-persistent save > ``` --- ### **验证配置** 1. 检查 UFW 状态: ```bash sudo ufw status verbose | grep icmp6 ``` 2. 测试 ping 连通性: ```bash ping6 -c 4 ::1 # 测试本地 ping6 -c 4 2001:4860:4860::8888 # 测试 Google DNS ``` --- ### **关键注意事项** 1. **协议名称差异**: - UFW 使用 `icmp6` - iptables 使用 `ipv6-icmp` - 两者等效但语法不同 2. **必要流量类型**: | ICMPv6 类型 | 编号 | 作用 | |-------------------|------|----------------------| | Echo Request | 128 | Ping 请求 | | Echo Reply | 129 | Ping 响应 | | Neighbor Solicitation | 135 | 邻居发现(必需) | | Neighbor Advertisement | 136 | 邻居发现(必需) |
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值