如何从 Python 中的原始套接字接收数据?
How to receive data from a raw socket in Python?
我正在尝试使用套接字库创建一个端口扫描器(使用 SYN 数据包)(是的,我知道 scapy 会使这更容易,但我这样做主要是为了学习练习。)我制作了数据包并成功发送,但是我在接收和解析后续响应时遇到了麻烦。
到目前为止,我已经尝试了 s.recv(1024)
和 4096,以及 recvfrom()
.
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.sendto(packet, (dstip, 80))
r = s.recv(1024)
print(r)
但是,我在接收响应时遇到问题,我可以看到数据包正在通过 Wireshark 正确发送,并且 SYN-ACK 已发送到我的机器,但是我无法正确接收和打印它。有没有更好的方法可以使用 s.recv()
函数进行此类输入?还是我使用了错误的功能?
感谢任何帮助,我是套接字库的新手。谢谢。
以下是我最近在各种资源的帮助下为套接字 IO 编写的一个模块,您可以从中获取您想要的内容。
import socket
import threading
import time
import pygogo as gogo
from icentralsimulator.bridgeio.read_packets import PacketFactory
from icentralsimulator.bridgeio.write_packets import WritePacket
from icentralsimulator.configurations.interfaces import IServerInfoProvider
logger = gogo.Gogo(__name__).logger
send_lock = threading.Lock()
class BridgeConnection:
def __init__(self, bridge_info_provider: IServerInfoProvider):
info = bridge_info_provider.get_bridge_server_info()
self.callback = None
self.bridge_ip = info.IpAddress
self.bridge_port = info.Port
self._connection = None
self._terminate_wait_for_incoming = False
@property
def is_connected(self):
return self._connection is not None
def connect(self, callback):
"""
The purpose of this method is to create (and hold) a connection to the server. At the same time,
it creates a new thread for the purpose of waiting on incoming packets.
"""
if self._connection is not None: return
self._connection = socket.create_connection((self.bridge_ip, self.bridge_port))
self._connection.settimeout(0.5)
self.callback = callback
t = threading.Thread(target=self._wait_for_incoming)
t.start()
time.sleep(5)
def disconnect(self):
"""
Breaks existing connection to the server if one is currently made and cancels the thread that is waiting
for incoming packets. If the connection is not currently open, simply returns silently -- thus it is safe
to call this method repeatedly.
"""
self._terminate_wait_for_incoming = True
while self._terminate_wait_for_incoming:
time.sleep(0.1)
self._connection.close()
self._connection = None
def send_packet(self, packet: WritePacket):
"""
Sends an arbitrary packet to the server.
"""
with send_lock:
logger.debug(f"Sending packet: {packet.payload_plain_text}")
payload = packet.payload
self._connection.sendall(payload)
def _wait_for_incoming(self):
"""
Continually runs a loop to wait for incoming data on the open socket. If data is received, it is converted
to a receive packet and forwarded to the consumer as part of a callback.
"""
self._terminate_wait_for_incoming = False
buf_len = 4096
try:
while not self._terminate_wait_for_incoming:
data = None
try:
_cnx = self._connection
if _cnx is None: break
data = _cnx.recv(buf_len)
if data is not None and len(data) > 0:
while True:
new_data = _cnx.recv(buf_len)
if new_data is None or len(new_data) == 0:
break
data = data + new_data
except socket.timeout:
if data is not None and self.callback is not None:
packet = PacketFactory.get_packet(data)
self.callback(packet)
logger.debug(f"Received packet: {data}")
time.sleep(0.5)
except OSError: # Happens when stopping the application
logger.info("Application aborted")
return
finally:
self._terminate_wait_for_incoming = False
请注意,我没有在此处包括 IServerInfoProvider 或 PacketFactory。这些对我的应用程序来说是非常定制的。您将需要根据到达您的特定用例的数据包数据来解释数据包。
Black Hat Python 一书有使用套接字库创建扫描器的示例,不幸的是不是端口扫描器。他们检查主机是否启动,并使用原始套接字接收数据。代码可用 here.
他们在新线程中使用一个套接字 object 发送 SYN-packets,并使用另一个套接字 object 嗅探回复。
在示例中,他们使用 socket.IPPROTO_IP
或 socket.IPPROTO_ICMP
而不是 socket.IPPROTO_RAW
,具体取决于它是否 Windows。
对于嗅探器,他们使用函数 setsockopt(socket.IPPROTO_IP,
socket.IP_HDRINCL, 1)
进行嗅探,其中 IPPROTO_IP
是 TCP 的 dummy-protocol,IP_HDRINCL
是在IP包中包含headers,1映射到代码中的ICMP-protocol。
祝你好运!
我正在尝试使用套接字库创建一个端口扫描器(使用 SYN 数据包)(是的,我知道 scapy 会使这更容易,但我这样做主要是为了学习练习。)我制作了数据包并成功发送,但是我在接收和解析后续响应时遇到了麻烦。
到目前为止,我已经尝试了 s.recv(1024)
和 4096,以及 recvfrom()
.
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.sendto(packet, (dstip, 80))
r = s.recv(1024)
print(r)
但是,我在接收响应时遇到问题,我可以看到数据包正在通过 Wireshark 正确发送,并且 SYN-ACK 已发送到我的机器,但是我无法正确接收和打印它。有没有更好的方法可以使用 s.recv()
函数进行此类输入?还是我使用了错误的功能?
感谢任何帮助,我是套接字库的新手。谢谢。
以下是我最近在各种资源的帮助下为套接字 IO 编写的一个模块,您可以从中获取您想要的内容。
import socket
import threading
import time
import pygogo as gogo
from icentralsimulator.bridgeio.read_packets import PacketFactory
from icentralsimulator.bridgeio.write_packets import WritePacket
from icentralsimulator.configurations.interfaces import IServerInfoProvider
logger = gogo.Gogo(__name__).logger
send_lock = threading.Lock()
class BridgeConnection:
def __init__(self, bridge_info_provider: IServerInfoProvider):
info = bridge_info_provider.get_bridge_server_info()
self.callback = None
self.bridge_ip = info.IpAddress
self.bridge_port = info.Port
self._connection = None
self._terminate_wait_for_incoming = False
@property
def is_connected(self):
return self._connection is not None
def connect(self, callback):
"""
The purpose of this method is to create (and hold) a connection to the server. At the same time,
it creates a new thread for the purpose of waiting on incoming packets.
"""
if self._connection is not None: return
self._connection = socket.create_connection((self.bridge_ip, self.bridge_port))
self._connection.settimeout(0.5)
self.callback = callback
t = threading.Thread(target=self._wait_for_incoming)
t.start()
time.sleep(5)
def disconnect(self):
"""
Breaks existing connection to the server if one is currently made and cancels the thread that is waiting
for incoming packets. If the connection is not currently open, simply returns silently -- thus it is safe
to call this method repeatedly.
"""
self._terminate_wait_for_incoming = True
while self._terminate_wait_for_incoming:
time.sleep(0.1)
self._connection.close()
self._connection = None
def send_packet(self, packet: WritePacket):
"""
Sends an arbitrary packet to the server.
"""
with send_lock:
logger.debug(f"Sending packet: {packet.payload_plain_text}")
payload = packet.payload
self._connection.sendall(payload)
def _wait_for_incoming(self):
"""
Continually runs a loop to wait for incoming data on the open socket. If data is received, it is converted
to a receive packet and forwarded to the consumer as part of a callback.
"""
self._terminate_wait_for_incoming = False
buf_len = 4096
try:
while not self._terminate_wait_for_incoming:
data = None
try:
_cnx = self._connection
if _cnx is None: break
data = _cnx.recv(buf_len)
if data is not None and len(data) > 0:
while True:
new_data = _cnx.recv(buf_len)
if new_data is None or len(new_data) == 0:
break
data = data + new_data
except socket.timeout:
if data is not None and self.callback is not None:
packet = PacketFactory.get_packet(data)
self.callback(packet)
logger.debug(f"Received packet: {data}")
time.sleep(0.5)
except OSError: # Happens when stopping the application
logger.info("Application aborted")
return
finally:
self._terminate_wait_for_incoming = False
请注意,我没有在此处包括 IServerInfoProvider 或 PacketFactory。这些对我的应用程序来说是非常定制的。您将需要根据到达您的特定用例的数据包数据来解释数据包。
Black Hat Python 一书有使用套接字库创建扫描器的示例,不幸的是不是端口扫描器。他们检查主机是否启动,并使用原始套接字接收数据。代码可用 here.
他们在新线程中使用一个套接字 object 发送 SYN-packets,并使用另一个套接字 object 嗅探回复。
在示例中,他们使用 socket.IPPROTO_IP
或 socket.IPPROTO_ICMP
而不是 socket.IPPROTO_RAW
,具体取决于它是否 Windows。
对于嗅探器,他们使用函数 setsockopt(socket.IPPROTO_IP,
socket.IP_HDRINCL, 1)
进行嗅探,其中 IPPROTO_IP
是 TCP 的 dummy-protocol,IP_HDRINCL
是在IP包中包含headers,1映射到代码中的ICMP-protocol。
祝你好运!