如何使用 RAW-SOCKETS 打开端口?
How can I open a Port with RAW-SOCKETS?
我正在 Python3 中使用 AF_PACKET 处理 RAW-Sockets。
如果我发送此 DNS 查询数据包 -> 我会得到答复,但是:
- Linux-Kernel 发送一个 ICMP Destination unreachable(Port unreachable) 因为我没有打开 Source-Port 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 打开一个端口”。这里的问题是你告诉远程系统你正在从端口 UDP 57799 调用,但你的本地 OS 内核知道没有打开这样的端口。
你可以用AF_INET数据报(UDP)套接字单独打开一个端口,bind
它获得一个端口号,然后使用那个AF_PACKET 代码中的端口号。如果您在操作时保持另一个 UDP 套接字打开,这应该可以防止 ICMP 错误,但 DNS 响应数据报很可能会堆积在 UDP 套接字的队列中,等待您将它们拉下来(因为内核本身也会看到它们并且知道它们是针对您的 UDP 套接字的)。这非常好,因为您这样做是为了教育/探索目的,但不是可行的生产机制。
最重要的是,您正试图表现得像内核,但没有办法告诉内核您正试图为它完成它的工作。
我正在 Python3 中使用 AF_PACKET 处理 RAW-Sockets。
如果我发送此 DNS 查询数据包 -> 我会得到答复,但是:
- Linux-Kernel 发送一个 ICMP Destination unreachable(Port unreachable) 因为我没有打开 Source-Port 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 打开一个端口”。这里的问题是你告诉远程系统你正在从端口 UDP 57799 调用,但你的本地 OS 内核知道没有打开这样的端口。
你可以用AF_INET数据报(UDP)套接字单独打开一个端口,bind
它获得一个端口号,然后使用那个AF_PACKET 代码中的端口号。如果您在操作时保持另一个 UDP 套接字打开,这应该可以防止 ICMP 错误,但 DNS 响应数据报很可能会堆积在 UDP 套接字的队列中,等待您将它们拉下来(因为内核本身也会看到它们并且知道它们是针对您的 UDP 套接字的)。这非常好,因为您这样做是为了教育/探索目的,但不是可行的生产机制。
最重要的是,您正试图表现得像内核,但没有办法告诉内核您正试图为它完成它的工作。