网络错误定位案例 ICMP host *** unreachable - admin prohibited

本文记录了一次DHCP服务故障的排查过程,详细介绍了从虚拟机发出BOOTP请求到接收DHCP响应的过程,以及如何通过禁用iptables解决网络不通的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 环境

一台物理服务器 9.115.251.86,上面创建两个虚机,每个虚机两个网卡:

  • vm1:eth0 - 9.*.*.232 eth1:10.0.0.14
  • vm2: eth0 - 9.8.*.219 eth1:10.0.0.10,上面运行DHCP Agent,管理 dnsmasq,提供 DHCP 服务

两块 eth1 连到物理机上的一个 bridge 上:

bridge name     bridge id               STP enabled     interfaces
mgtbr0          8000.fa8013216b56       no              tap0
                                                        vnet1
                                                        vnet12
                                                        vnet13
                                                        vnet14
                                                        vnet16
                                                        vnet18
                                                        vnet2
                                                        vnet5

2. 错误

vm1 上创建一个虚机 vmchild1,启动时发出 BOOTP 请求去向 DHCP Agent 获取 IP 地址。DHCP Agent 管理的 dnsmasq 可以正常收到 BOOTP 请求,而且发回了请求,但是 vm1 无法收到。

vm2 上 tcpdump:

15:30:14.135874 IP (tos 0x0, ttl 64, id 46594, offset 0, flags [none], proto UDP (17), length 401)
    10.0.0.10.40589 > 10.0.0.14.8472: OTV, flags [I] (0x08), overlay 0, instance 1027
IP (tos 0xc0, ttl 64, id 57625, offset 0, flags [none], proto UDP (17), length 351)
    50-0-0-10.static.sonic.net.bootps > 50-0-0-15.static.sonic.net.bootpc: BOOTP/DHCP, Reply, length 323, xid 0x11f7631f, secs 60, Flags [none]
          Your-IP 50-0-0-15.static.sonic.net
          Server-IP 50-0-0-10.static.sonic.net
          Client-Ethernet-Address fa:16:3e:ba:43:4c (oui Unknown)
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: Offer
            Server-ID Option 54, length 4: 50-0-0-10.static.sonic.net
            Lease-Time Option 51, length 4: 86400
            RN Option 58, length 4: 43200
            RB Option 59, length 4: 75600
            Subnet-Mask Option 1, length 4: 255.255.255.0
            BR Option 28, length 4: 50-0-0-255.static.sonic.net
            Domain-Name Option 15, length 14: "openstacklocal"
            Domain-Name-Server Option 6, length 4: 50-0-0-10.static.sonic.net
            Default-Gateway Option 3, length 4: 50-0-0-1.static.sonic.net
            Classless-Static-Route Option 121, length 13: (60.0.0.0/24:0.0.0.0),(default:50-0-0-1.static.sonic.net)
15:30:14.136118 IP (tos 0xc0, ttl 64, id 10816, offset 0, flags [none], proto ICMP (1), length 429)
    10.0.0.100 > 10.0.0.10: ICMP host 10.0.0.14 unreachable - admin prohibited, length 409
        IP (tos 0x0, ttl 63, id 46594, offset 0, flags [none], proto UDP (17), length 401)
    10.0.0.10.40589 > 10.0.0.14.8472: OTV, flags [I] (0x08), overlay 0, instance 1027

而且发现另外的问题:

root@controller:~/s1# ping 10.0.0.13
PING 10.0.0.13 (10.0.0.13) 56(84) bytes of data.
64 bytes from 10.0.0.13: icmp_seq=1 ttl=64 time=0.630 ms
From 10.0.0.13: icmp_seq=2 Redirect Host(New nexthop: 10.0.0.13)
64 bytes from 10.0.0.13: icmp_seq=2 ttl=64 time=0.628 ms
From 10.0.0.13: icmp_seq=3 Redirect Host(New nexthop: 10.0.0.13)

3.定位

初步推断是某处防火墙阻止了 BOOTP 的包,于是将 vm1,vm2 上的防火墙全部关掉,无效。最后,查看物理机 iptables:

[root@rh65 ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     udp  --  anywhere             anywhere            udp dpt:domain
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:domain
ACCEPT     udp  --  anywhere             anywhere            udp dpt:bootps
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:bootps
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:domain
ACCEPT     udp  --  anywhere             anywhere            state NEW udp dpt:domain
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ftp
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:16509
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:16514
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:http
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpts:vnc-server:cvsup
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             192.168.122.0/24    state RELATED,ESTABLISHED
ACCEPT     all  --  192.168.122.0/24     anywhere
ACCEPT     all  --  anywhere             anywhere
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited

发现 FORWARD 阻止了 ICMP 相关的包。

4. 解决

在物理机上运行  service iptables stop 将 iptables 关闭,问题解决。

### 如何发送 ICMP 主机不可达消息 ICMP 协议中的主机不可达消息通常由路由器或网关在网络通信过程中自动生成并返回给源设备,当目标主机无法到达时触发该消息。以下是实现和模拟发送 ICMP 主机不可达消息的方法: #### 使用工具伪造 ICMP 不可达消息 可以通过一些网络测试工具来伪造 ICMP 不可达消息。例如,在 Linux 环境下可以使用 `netwox` 工具完成此操作。 以下是一个具体的命令示例: ```bash netwox 82 -f "host 100.1.1.1 and port 80" -i "192.168.248.2" ``` - `-f`: 指定要伪造的目标服务器 IP 地址以及可选的端口号。 - `-i`: 指定接收伪造 ICMP 不可达消息的被攻击者 IP 地址[^4]。 #### 编程实现 ICMP 不可达消息 如果希望通过编程的方式手动构建并发送 ICMP 不可达消息,则需要了解其数据包结构,并通过底层套接字接口进行开发。下面提供了一个 Python 实现的例子,利用原始套接字发送 ICMP 数据包。 ```python import socket import struct def create_icmp_unreachable_message(original_packet): # 构建 ICMP 不可达消息头部 type = 3 # Destination Unreachable 类型 code = 1 # Code 表示 Host Unreachable 子类型 checksum = 0 # 初始校验和设为 0 # 计算校验和 header = struct.pack('!BBH', type, code, checksum) data = original_packet[:28] # 截取原数据包前 28 字节作为负载部分 pseudo_header = b'\x00' * 4 + header + data checksum = calculate_checksum(pseudo_header) # 更新 ICMP 头部 header = struct.pack('!BBH', type, code, checksum) return header + data def calculate_checksum(data): sum = 0 for i in range(0, len(data), 2): if i + 1 < len(data): word = (data[i] << 8) + data[i+1] else: word = (data[i] << 8) sum += word sum = (sum & 0xFFFF) + (sum >> 16) return ~sum & 0xFFFF # 创建原始套接字 sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) sock.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1) # 发送 ICMP 不可达消息到指定目标 target_ip = '192.168.1.1' original_packet = b'\x00' * 28 # 假设这是截获的数据包的一部分 icmp_msg = create_icmp_unreachable_message(original_packet) sock.sendto(icmp_msg, (target_ip, 0)) ``` 以上代码展示了如何创建一个简单的 ICMP 不可达消息,并将其发送至特定目标地址。需要注意的是,运行此类程序可能需要管理员权限,并且仅限于合法用途下的实验环境[^1]。 #### 防御措施注意事项 为了防止恶意用户滥用 ICMP 不可达消息实施拒绝服务攻击或其他形式的安全威胁,应采取适当防御手段,比如过滤异常流量、启用防火墙规则等。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值