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

Python发送原始IP数据包失败,求助排查原因

嘿,我来帮你排查无法发送原始IP数据包的问题!结合你的描述和代码片段,先从几个最常见的原因说起,再给你补全代码的思路:

1. 权限不足(最常见的坑)

原始套接字操作属于系统底层网络操作,必须以root/管理员权限运行脚本:

  • Linux/macOS:运行时加上sudo,比如 sudo python ip.py 192.168.1.100 8.8.8.8 eth0
  • Windows:右键命令提示符/终端,选择「以管理员身份运行」后再执行脚本

2. 操作系统限制

有些系统默认会限制普通用户创建原始套接字:

  • Linux:内核3.17之后普通用户可创建部分原始套接字,但IPPROTO_RAW仍需root权限,无需额外调整内核参数
  • Windows:需要确保系统允许使用原始套接字,若遇到报错,可检查防火墙是否放行原始数据包,一般管理员权限就能解决多数问题

3. 不完整的IP头构造

你的IP_HEADER函数只写了开头,而用IPPROTO_RAW创建的套接字,系统不会自动帮你生成IP头——你必须手动构造完整的IP头,包括版本、IHL、总长度、ID、TTL、协议、校验和、源/目标IP等所有字段。如果头构造不完整或校验和错误,数据包会被系统直接丢弃。

4. 未绑定指定网卡

你的代码里没有绑定到指定网卡的逻辑,系统可能会选择默认路由的网卡发送数据包,导致不符合预期。需要在创建套接字后添加绑定网卡的代码:

# Linux/macOS下绑定网卡
ST.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, sys.argv[3].encode())

补全后的完整示例代码

这里给你补全了IP头构造、校验和计算、网卡绑定和权限检查的完整代码:

#!/usr/bin/python
import socket
import struct
import sys
import os

def Create_SOCKET(interface):
    global ST
    try:
        ST = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
        # 绑定到指定网卡
        ST.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, interface.encode())
        # 明确告知系统我们自己处理IP头
        ST.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
    except socket.error as MSG:
        print "[ERROR] Socket creation error:\n", MSG
        sys.exit()

def calculate_checksum(data):
    # 计算IP头校验和的标准逻辑
    checksum = 0
    data_len = len(data)
    if data_len % 2 != 0:
        data += b'\x00'
        data_len += 1
    for i in range(0, data_len, 2):
        word = (data[i] << 8) + data[i+1]
        checksum += word
    checksum = (checksum >> 16) + (checksum & 0xffff)
    checksum = ~checksum & 0xffff
    return checksum

def IP_HEADER(Source_IP, Destination_IP):
    global IP_PACKET
    IP_VER = 4
    IP_IHL = 5
    IP_TOS = 0
    IP_TOTAL_LENGTH = 20  # 仅IP头,无数据时为20字节
    IP_ID = 54321
    IP_FLAGS = 0
    IP_FRAG_OFFSET = 0
    IP_TTL = 64
    IP_PROTOCOL = socket.IPPROTO_TCP  # 可替换为ICMP/UDP等你需要的协议
    IP_CHECKSUM = 0
    IP_SRC = socket.inet_aton(Source_IP)
    IP_DST = socket.inet_aton(Destination_IP)

    # 先构造不带校验和的临时IP头
    temp_header = struct.pack('!BBHHHBBH4s4s',
                            (IP_VER << 4) | IP_IHL,
                            IP_TOS,
                            IP_TOTAL_LENGTH,
                            IP_ID,
                            (IP_FLAGS << 13) | IP_FRAG_OFFSET,
                            IP_TTL,
                            IP_PROTOCOL,
                            IP_CHECKSUM,
                            IP_SRC,
                            IP_DST)
    # 计算并替换校验和
    IP_CHECKSUM = calculate_checksum(temp_header)
    IP_PACKET = struct.pack('!BBHHHBBH4s4s',
                            (IP_VER << 4) | IP_IHL,
                            IP_TOS,
                            IP_TOTAL_LENGTH,
                            IP_ID,
                            (IP_FLAGS << 13) | IP_FRAG_OFFSET,
                            IP_TTL,
                            IP_PROTOCOL,
                            socket.htons(IP_CHECKSUM),
                            IP_SRC,
                            IP_DST)

def send_packet(dest_ip):
    try:
        # 原始套接字sendto的端口参数无意义,填0即可
        ST.sendto(IP_PACKET, (dest_ip, 0))
        print "[INFO] Packet sent successfully!"
    except socket.error as MSG:
        print "[ERROR] Failed to send packet:\n", MSG

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print "Usage: sudo python ip.py <Source_IP> <Destination_IP> <Interface>"
        sys.exit(1)
    # Linux/macOS下检查root权限
    if os.geteuid() != 0:
        print "[ERROR] Need root privileges to run this script!"
        sys.exit(1)
    src_ip = sys.argv[1]
    dest_ip = sys.argv[2]
    interface = sys.argv[3]
    Create_SOCKET(interface)
    IP_HEADER(src_ip, dest_ip)
    send_packet(dest_ip)

额外排查技巧

如果还是无法发送,可以用tcpdump(Linux/macOS)或Wireshark抓包,查看:

  • 指定网卡是否有数据包发出
  • 发出的IP头格式是否正确(比如校验和、源/目标IP是否符合预期)

内容的提问来源于stack exchange,提问作者D.H

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:38:10