UDP 反向隧道
UDP reverse tunneling
我遇到了一个很难解决的问题,如果有人能提供帮助,我将不胜感激。
我在防火墙后面的本地网络中有一个 VPN 服务器,只允许出站连接。
我的目标是进行“UDP 性别更改”,并通过创建反向隧道使 VPN UDP 端口可用于我可以转发端口的外部服务器。使用 TCP 隧道执行此操作很简单,并且可以使用 socat、nc 甚至 ssh 隧道等工具轻松完成。但是,VPN 应始终由 UDP 数据包承载以避免 TCP 崩溃问题(TCP over TCP)。
使用 socat/nc 创建的 UDP 反向隧道不起作用,因为 UDP 是无连接协议。这意味着“client client”和“listen listen”配置将仅在客户端先发送数据包时才允许数据传输(在反向连接中不可能)。
我错过了什么吗?是否有任何实用程序可以在不使用第二个 VPN 连接的情况下完成此任务(例如,通过使用某些 headers 建立面向 UDP 连接)?
非常感谢
我在Python中想到了这样的事情:
import socket
from select import select
# immediately useful parameters are:
# REMOTE_SERVER_NAME other network server (which will be resolved by DNS)
# LOCAL_SERVER_PORT where forward network traffic to
REMOTE_SERVER_NAME = '8.8.8.8'
LOCAL_SERVER_PORT = 20
LOCAL_SERVER_NAME = '127.0.0.1'
REMOTE_PORT = 9990
LOCAL_PORT = REMOTE_PORT + 1
sock_remote = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_remote.bind(('', REMOTE_PORT))
sock_remote.connect((REMOTE_SERVER_NAME, REMOTE_PORT))
sock_local = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_local.bind(('', LOCAL_PORT))
sock_local.connect((LOCAL_SERVER_NAME, LOCAL_SERVER_PORT))
sockets = (sock_remote, sock_local)
for s in sockets:
s.setblocking(0)
# loop forever forwarding packets between the connections
while True:
avail, _, _ = select((sock_local, sock_remote), (), (), timeout=100)
# send a keep alive message every timeout
if not avail:
sock_remote.send(b'keep alive')
continue
for s in avail:
# something from the local server, forward it on
if s is sock_local:
msg = sock_local.recv(8192)
sock_remote.send(msg)
# something from the remote server
if s is sock_remote:
msg = sock_remote.recv(8192)
# don't forward keep alives to local system
if msg != b'keep alive':
sock_local.send(msg)
即运行 这在任一服务器上(更改 REMOTE_SERVER_NAME
以指向适当的位置)并且它将在它们之间转发数据包,每 100 秒发送一个 "keep alive" 数据包。您的本地进程会将 UDP 数据包发送到 LOCAL_PORT
,这些数据包将被转发到远程服务器,远程服务器将接收这些数据包并将它们发送到另一端的 LOCAL_SERVER_PORT
。有 8 个流需要担心,因此命名变得尴尬:
DMZ <=> VPN <=> python <=> NAT <=> internet <=> NAT <=> python <=> VPN <=> DMZ
您也许可以使用 sock_local.recvfrom
检测 LOCAL_SERVER_NAME
和 LOCAL_SERVER_PORT
并将地址信息隐藏起来,但我想我会把它们留在里面以便于理解
希望您理解Python!但我很难用语言表达出来
我改编了 Sam Mason 的答案来执行 UDP 反向连接。
这是配置:
HOST UDP-LISTEN <=> python cc <=> NAT <=> internet <=> server <=> python ll UDP-LISTEN
主机侦听一个 UDP 端口。您可以通过 python 脚本使用反向连接从有权访问服务器的任何第三方客户端访问主机。
第一部分是 listen 脚本。它将在 CC_PORT 上侦听客户端脚本并在 SERVICE_PORT 上转发任何内容。它还会丢弃来自 cc 脚本的 keepalive。
import socket
from select import select
CC_PORT = 8881
SERVICE_PORT = 8880
LISTEN_IP='x.x.x.x'
sock_cc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_cc.bind((LISTEN_IP,CC_PORT))
sock_serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_serv.bind((LISTEN_IP,SERVICE_PORT))
sockets = (sock_cc, sock_serv)
for s in sockets:
s.setblocking(0)
client_serv=None
client_cc=None
# loop forever forwarding packets between the connections
while True:
avail, _, _ = select((sock_cc, sock_serv), (), (), 1)
# send a keep alive message every timeout
if not avail:
continue
for s in avail:
# something from the local server, forward it on
if s is sock_cc:
msg = sock_cc.recvfrom(8192)
client_cc=msg[1]
if client_serv is not None:
if msg[0] != b'keep alive':
sock_serv.sendto(msg[0], client_serv)
# something from the remote server
if s is sock_serv:
msg = sock_serv.recvfrom(8192)
client_serv=msg[1]
if client_cc is not None:
sock_cc.sendto(msg[0], client_cc)
客户端客户端脚本
import socket
from select import select
DEST_IP = 'x.x.x.x'
DEST_PORT = 8881
LOCAL_IP = '127.0.0.1'
LOCAL_SERVICE = 8800
sock_remote = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock_remote.connect((DEST_IP,DEST_PORT)) sock_local = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock_local.connect((LOCAL_IP,LOCAL_SERVICE)) sockets = (sock_remote, sock_local) for s in sockets:
s.setblocking(0)
# loop forever forwarding packets between the connections while True:
avail, _, _ = select((sock_local, sock_remote), (), (), 1)
# send a keep alive message every timeout
if not avail:
sock_remote.send(b'keep alive')
continue
for s in avail:
# something from the local server, forward it on
if s is sock_local:
msg = sock_local.recv(8192)
sock_remote.send(msg)
# something from the remote server
if s is sock_remote:
msg = sock_remote.recv(8192)
# don't forward keep alives to local system
if msg != b'keep alive':
sock_local.send(msg)
再次感谢 Sam Mason 帮我解决了这个问题。
我遇到了一个很难解决的问题,如果有人能提供帮助,我将不胜感激。
我在防火墙后面的本地网络中有一个 VPN 服务器,只允许出站连接。 我的目标是进行“UDP 性别更改”,并通过创建反向隧道使 VPN UDP 端口可用于我可以转发端口的外部服务器。使用 TCP 隧道执行此操作很简单,并且可以使用 socat、nc 甚至 ssh 隧道等工具轻松完成。但是,VPN 应始终由 UDP 数据包承载以避免 TCP 崩溃问题(TCP over TCP)。
使用 socat/nc 创建的 UDP 反向隧道不起作用,因为 UDP 是无连接协议。这意味着“client client”和“listen listen”配置将仅在客户端先发送数据包时才允许数据传输(在反向连接中不可能)。
我错过了什么吗?是否有任何实用程序可以在不使用第二个 VPN 连接的情况下完成此任务(例如,通过使用某些 headers 建立面向 UDP 连接)? 非常感谢
我在Python中想到了这样的事情:
import socket
from select import select
# immediately useful parameters are:
# REMOTE_SERVER_NAME other network server (which will be resolved by DNS)
# LOCAL_SERVER_PORT where forward network traffic to
REMOTE_SERVER_NAME = '8.8.8.8'
LOCAL_SERVER_PORT = 20
LOCAL_SERVER_NAME = '127.0.0.1'
REMOTE_PORT = 9990
LOCAL_PORT = REMOTE_PORT + 1
sock_remote = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_remote.bind(('', REMOTE_PORT))
sock_remote.connect((REMOTE_SERVER_NAME, REMOTE_PORT))
sock_local = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_local.bind(('', LOCAL_PORT))
sock_local.connect((LOCAL_SERVER_NAME, LOCAL_SERVER_PORT))
sockets = (sock_remote, sock_local)
for s in sockets:
s.setblocking(0)
# loop forever forwarding packets between the connections
while True:
avail, _, _ = select((sock_local, sock_remote), (), (), timeout=100)
# send a keep alive message every timeout
if not avail:
sock_remote.send(b'keep alive')
continue
for s in avail:
# something from the local server, forward it on
if s is sock_local:
msg = sock_local.recv(8192)
sock_remote.send(msg)
# something from the remote server
if s is sock_remote:
msg = sock_remote.recv(8192)
# don't forward keep alives to local system
if msg != b'keep alive':
sock_local.send(msg)
即运行 这在任一服务器上(更改 REMOTE_SERVER_NAME
以指向适当的位置)并且它将在它们之间转发数据包,每 100 秒发送一个 "keep alive" 数据包。您的本地进程会将 UDP 数据包发送到 LOCAL_PORT
,这些数据包将被转发到远程服务器,远程服务器将接收这些数据包并将它们发送到另一端的 LOCAL_SERVER_PORT
。有 8 个流需要担心,因此命名变得尴尬:
DMZ <=> VPN <=> python <=> NAT <=> internet <=> NAT <=> python <=> VPN <=> DMZ
您也许可以使用 sock_local.recvfrom
检测 LOCAL_SERVER_NAME
和 LOCAL_SERVER_PORT
并将地址信息隐藏起来,但我想我会把它们留在里面以便于理解
希望您理解Python!但我很难用语言表达出来
我改编了 Sam Mason 的答案来执行 UDP 反向连接。 这是配置:
HOST UDP-LISTEN <=> python cc <=> NAT <=> internet <=> server <=> python ll UDP-LISTEN
主机侦听一个 UDP 端口。您可以通过 python 脚本使用反向连接从有权访问服务器的任何第三方客户端访问主机。
第一部分是 listen 脚本。它将在 CC_PORT 上侦听客户端脚本并在 SERVICE_PORT 上转发任何内容。它还会丢弃来自 cc 脚本的 keepalive。
import socket
from select import select
CC_PORT = 8881
SERVICE_PORT = 8880
LISTEN_IP='x.x.x.x'
sock_cc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_cc.bind((LISTEN_IP,CC_PORT))
sock_serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_serv.bind((LISTEN_IP,SERVICE_PORT))
sockets = (sock_cc, sock_serv)
for s in sockets:
s.setblocking(0)
client_serv=None
client_cc=None
# loop forever forwarding packets between the connections
while True:
avail, _, _ = select((sock_cc, sock_serv), (), (), 1)
# send a keep alive message every timeout
if not avail:
continue
for s in avail:
# something from the local server, forward it on
if s is sock_cc:
msg = sock_cc.recvfrom(8192)
client_cc=msg[1]
if client_serv is not None:
if msg[0] != b'keep alive':
sock_serv.sendto(msg[0], client_serv)
# something from the remote server
if s is sock_serv:
msg = sock_serv.recvfrom(8192)
client_serv=msg[1]
if client_cc is not None:
sock_cc.sendto(msg[0], client_cc)
客户端客户端脚本
import socket
from select import select
DEST_IP = 'x.x.x.x'
DEST_PORT = 8881
LOCAL_IP = '127.0.0.1'
LOCAL_SERVICE = 8800
sock_remote = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock_remote.connect((DEST_IP,DEST_PORT)) sock_local = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock_local.connect((LOCAL_IP,LOCAL_SERVICE)) sockets = (sock_remote, sock_local) for s in sockets:
s.setblocking(0)
# loop forever forwarding packets between the connections while True:
avail, _, _ = select((sock_local, sock_remote), (), (), 1)
# send a keep alive message every timeout
if not avail:
sock_remote.send(b'keep alive')
continue
for s in avail:
# something from the local server, forward it on
if s is sock_local:
msg = sock_local.recv(8192)
sock_remote.send(msg)
# something from the remote server
if s is sock_remote:
msg = sock_remote.recv(8192)
# don't forward keep alives to local system
if msg != b'keep alive':
sock_local.send(msg)
再次感谢 Sam Mason 帮我解决了这个问题。