如何使用RAW-SOCKETS打开端口?



我正在Python3中使用AF_PACKET进行RAW-Sockets。

如果我发送这个dns查询包->我得到了一个答案,但是:

  • linux内核发送一个ICMP目的不可达(端口不可达)因为我没有打开源端口57799

如何使用AF_Packet和RAW_SOCKETS打开端口?

#!/usr/bin/python3.9
# -*- coding: utf-8 -*-
import socket
import time
from struct import pack
ETH_P_ALL = 3
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ETH_P_ALL))
def dns_query():
s.bind(("enp4s0", 0))
frame = [
### Ether Frame ###
pack('6B', *(0x10, 0xfe, 0xed, 0x57, 0xef, 0xdc)),
s.getsockname()[4],
pack('!H', 0x0800),
#########################
### IPv4 Header ###
pack('B', 0x45),
pack('B', 0x00),
pack('!H', 0x003C),
pack('!H', 0xcdaf),
pack('B', 0x00),
pack('B', 0x00),
pack('B', 0x40),
pack('B', 0x11),
pack('!H', 0xea55),
pack('4B', *(0xc0, 0xa8, 0x00, 0x02)),
pack('4B', *(0x01, 0x01, 0x01, 0x01)),
### UDP ###
# Source-Port
pack('!H', 0xe1c7),  # Port 57799
# Destination-Port
pack('!H', 0x0035),  # Port 53
pack('!H', 0x0028),
pack('!H', 0x0000),
### DNS ###
pack('!H', 0x26d9),
pack("!H", 0x0120),
pack("!H", 0x0001),
pack("!H", 0x0000),
pack("!H", 0x0000),
pack("!H", 0x0000),
pack("B", 0x03),
pack("!3B", *(0x77, 0x77, 0x77)),
pack("B", 0x07),
pack("!7B", *(0x6f, 0x72, 0x65, 0x69, 0x6C, 0x6C, 0x79)),
pack("B", 0x02),
pack("!H", 0x6465),
pack("B", 0x00),
pack("!H", 0x0001), # A-Record
pack("!H", 0x0001)
]
s.sendall(b''.join(frame))
time.sleep(1)
s.close()

dns_query()

无法使用AF_PACKET&quot打开端口。这里的问题是,您告诉远程系统您正在从端口UDP 57799调用,但您的本地操作系统内核知道没有这样的端口打开。

可以使用AF_INET数据报(UDP)套接字单独打开端口,bind以获得端口号,然后在您的AF_PACKET代码中使用该端口号。如果您在操作时保持其他UDP套接字打开,这应该可以防止ICMP错误,但是DNS响应数据报很可能会堆积在您的UDP套接字的队列中,等待您将它们取出(因为内核本身也会看到它们,并且知道它们是针对您的UDP套接字的)。这是完全可以的,因为你这样做是为了教育/探索的目的,但不是一个可行的生产机制。

底线是你试图像内核一样工作,但是没有办法告诉内核你正在为它做它的工作。

最新更新