无法使用python将UDP数据包发送到本地端口,无法根据WireShark进行校验和

无法使用python将UDP数据包发送到本地端口,无法根据WireShark进行校验和,python,sockets,networking,udp,socks,Python,Sockets,Networking,Udp,Socks,我一直在为这件事发愁。我正试图用Python编写一个SOCKS5服务器来隧道UDP流量。我绑定到一个端口,并接收数据。然后我解析socks5udp报头(不是典型的UDP报头),并将数据报转发到请求的端点 一切都很好。然后,我侦听端点的响应(如果超时,则重新发送),并获得响应。太好了 这就是我失去理智的地方- 我从端点获取数据报。我根据重新封装返回的数据报,它与以前的UDP报头相同,只是我现在将目标地址和端口更改为原始调用者。我使用: sock_client = socket.socket(soc

我一直在为这件事发愁。我正试图用Python编写一个SOCKS5服务器来隧道UDP流量。我绑定到一个端口,并接收数据。然后我解析socks5udp报头(不是典型的UDP报头),并将数据报转发到请求的端点

一切都很好。然后,我侦听端点的响应(如果超时,则重新发送),并获得响应。太好了

这就是我失去理智的地方-

我从端点获取数据报。我根据重新封装返回的数据报,它与以前的UDP报头相同,只是我现在将目标地址和端口更改为原始调用者。我使用:

sock_client = socket.socket(socket.AF_INET, # Internet
                            socket.SOCK_DGRAM) # UDP
sock_client.sendto(packed_datagram, (self.client_ip, self.client_port))
将数据报发送回客户端。客户从未收到回复!永远

查看WireShark,它说:头校验和:0x0000[不正确,应该是0xcd1f(可能是由“IP校验和卸载”引起的)]


设置了socket.DGRAM的python套接字实现不应该自动将我的数据正确打包到UDP头中并计算适当的校验和吗?为什么设置为0x0000?我用十六进制检查了有效负载,校验和确实设置错误。到底是怎么回事?

校验和计算是由操作系统中的驱动程序完成的。在可能的情况下,计算是由网卡本身完成的。IIRC,Wireshark在本地数据包被传送到网络堆栈之前抓取它们。所有本地生成的数据包都会出现校验和错误。

如果我正确理解了您的代码部分,您可以创建一个新套接字将数据发送回客户端。因此,这将是一个具有随机源IP的新套接字,例如,从客户端的角度来看,您有以下数据包流:

client_ip:client_port  -> socks5_ip:socks_port
client_ip:client_port  <- socks5_ip:random_port
client\u ip:client\u port->socks5\u ip:socks\u port

client_ip:client_port我没有准确地遵循SOCKS5规范的两个部分

UDP关联在UDP连接终止时终止
员工请求已于终止时到达

我在完成UDP中继握手后立即终止TCP套接字。TCP必须保持打开状态,直到来回完成

UDP中继服务器从远程服务器接收应答数据报时 主机,它必须使用上述UDP请求封装该数据报 标头和任何依赖于身份验证方法的封装

我使用客户端的IP和端口作为数据报中的值。它需要是远程服务器的IP和端口,本质上UDP报头封装是客户端传入内容的克隆


解决这两个问题后,SOCKS5服务器将按预期工作。

使用linux命令关闭tx校验和:

ethtool -K eth0 tx off
或者使用此函数计算校验和

def checksum(data):
    s = 0
    n = len(data) % 2
    for i in range(0, len(data)-n, 2):
        s+= ord(data[i]) + (ord(data[i+1]) << 8)
    if n:
        s+= ord(data[i+1])
    while (s >> 16):
        s = (s & 0xFFFF) + (s >> 16)
    s = ~s & 0xffff
    return s
def校验和(数据):
s=0
n=长度(数据)%2
对于范围内的i(0,len(数据)-n,2):
s+=ord(数据[i])+(ord(数据[i+1])>16):
s=(s&0xFFFF)+(s>>16)
s=~s&0xffff
返回s

其中数据是伪头,这很有意义,但意味着我真的不知道本地主机为什么没有接收到我的udp数据包。如果我从一个线程发送它们有关系吗?我在这里真的是在捞救命稻草。这不重要,因为UDP套接字可以想象成孔而不是管道。无论数据的来源是什么,一旦数据被推入孔中,它就会被传递(UDP是无连接的,不像TCP)。也就是说,我按照您的建议重用了接收数据的同一个套接字,但仍然不走运。根据一位同事的建议,我还尝试将SOCKS5服务器和UDP中继服务器绑定到网络上的本地IP,而不是127.0.0.1,并将客户端设置为通过本地IP连接到它。仍然不走运:(请提供客户端和socks服务器之间连接的tcpdump。感谢您的时间,我在回答的问题中解决了我的问题。