【发布时间】:2017-06-04 22:16:51
【问题描述】:
我正在实现一个简单的用户空间网络堆栈以用于自学目的。我正在用 Python 编写它,在 Linux(Ubuntu 16.04.2 LTS)中运行它。我正在使用a Python TAP device 接收第 2 层帧(例如以太网)。从那里,我根据标题字段提取标题和处理帧。
问题: TAP 设备接收到几种类型的帧,但不接收 ICMP 数据包(例如 ICMP 回显请求)。我也希望它接收 ICMP 回显请求。
详细信息:为了测试我正在运行的堆栈的行为ping 10.0.0.4在同一台机器上。我的 Ubuntu 环境在 VM 上运行,因此我也尝试从主机运行ping 10.0.0.4 (在向路由表添加适当的条目之后)。即使 TAP 设备没有看到任何回显请求,我也总是收到 ICMP 回显回复:
PING 10.0.0.4 (10.0.0.4): 56 data bytes
64 bytes from 10.0.0.4: icmp_seq=0 ttl=64 time=0.451 ms
64 bytes from 10.0.0.4: icmp_seq=1 ttl=64 time=0.530 ms
这是数据包处理代码(为本问题的目的而简化):
from pytun import TunTapDevice, IFF_TAP, IFF_NO_PI
tap_dev = TunTapDevice(flags = (IFF_TAP | IFF_NO_PI))
tap_dev.persist(True)
tap_dev.addr = '10.0.0.4'
tap_dev.netmask = '255.255.255.0'
tap_dev.up()
while (1):
frame = tap_dev.read(1500)
# extract the Ethernet header from the raw frame
# (assume this is working correctly)
eth_frame_hdr = unpack_eth_hdr(frame)
# check if it is an IPv4 packet
if eth_frame_hdr.type == 0x0800:
ipv4_hdr = unpack_ipv4_hdr(frame)
# check if an icmp packet
if ipv4_hdr.proto == 0x01:
process_icmp(frame)
我的诊断:我认为正在发生的事情是 Linux 内核正在直接处理 ICMP 回显请求,并且 (1) 甚至没有将数据包“在线上”或 (2 ) 不会将 ICMP 数据包传递给用户空间。
(失败)解析尝试:我已经尝试了几种方法来获取 TAP 设备上的 ICMP 数据包,但都没有导致 TAP 设备接收到 ICMP 回显请求:
-
忽略 ICMP 回显处理:
echo 1 | sudo tee /proc/sys/net/ipv4/icmp_echo_ignore_all -
添加 iptables 规则以丢弃 ICMP 回显请求:
sudo iptables -I INPUT -p icmp --icmp-type echo-request -j DROP -
添加一个“跳转”到
QUEUE目标的 iptables 规则(想法是将 ICMP 数据包传递到用户空间):sudo iptables -I INPUT -p icmp --icmp-type echo-request -j QUEUE -
使用原始套接字作为处理 ICMP 数据包的特殊情况:
from socket import * icmp_listener_sock = socket(AF_PACKET, SOCK_RAW, IPPROTO_ICMP) icmp_listener_sock.bind((tap_dev.name, IPPROTO_ICMP)) (icmp_ipv4_dgram, snd_addr) = icmp_listener_sock.recvfrom(2048) process_icmp(icmp_ipv4_dgram)
您能否指出让 Python TAP 设备接收 ICMP 回显请求的正确方法?
【问题讨论】:
-
你真的在使用 python-pytun 0.2 吗?我看到 they have 发布的版本号更具吸引力。
-
嗨,不:我使用的是 python-pytun 2.2.1,这只是我在 Google 上找到的第一个链接(现已更正)。
标签: python linux sockets network-programming iptables