将 TCP 数据包路由到本地 UDP 端口

将 TCP 数据包路由到本地 UDP 端口

第三方服务器将 UDP 数据包发送到我们设置的 EC2 实例,我正尝试将这些数据包路由到我的本地机器。

客户端将这些数据包发送到端口 8975

为此,我首先建立了到我的 ec2 实例的 ssh 隧道

ssh -4 -L 10000:localhost:10000 -i ~/.ssh/xxxx.pem [email protected]

在我的远程机器上 - 我使用此命令将端口 8975 上收到的数据包路由到 10000

netcat -l -u -p 8975 > /tmp/udp2tcp | netcat -l -p 10000 < /tmp/udp2tcp

udp2tcp是一个 fifo 文件

在我的本地机器上 - 我正在获取tcp收到的数据包并将它们转换回 UDP

netcat localhost 10000 > /tmp/tcp2udp | netcat -l -u -p 8975 < /tmp/tcp2udp

当我运行时netcat localhost 10000- 我可以看到数据包流入我的本地机器

但出于某种原因,没有数据包以 udp 形式路由到端口 8975 - 我不确定我到底需要做什么

当我跑步时sudo tcpdump -i any -S -vvv port 10000

这显示了数据包登录

15:39:10.053013 IP (tos 0x0, ttl 64, id 64725, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.48974 > localhost.webmin: Flags [.], cksum 0xfe28 (incorrect -> 0x5674), ack 1261213200, win 10567, options [nop,nop,TS val 1064223053 ecr 1064223053], length 0

但是当我运行 sudo 时tcpdump -i any -S -v port 8975我什么也没看到

答案1

作为 SSH 端口转发的替代,您可以使用点对点隧道设备、SSH 和下面解释的过程将这些 UDP 数据包转发到本地机器。

在 EC2 实例中,执行以下操作:

  1. /etc/ssh/sshd_config文件中,将配置参数设置PermitTunnelpoint-to-pointyes

  2. 创建一个点对点隧道设备,用于接收来自公共网络的 UDP 数据包:

    $ sudo ip tuntap add dev tun8975 mode tun user ubuntu
    $ sudo ip addr add dev tun8975 172.16.19.22 peer 172.16.19.21
    $ sudo ip link set dev tun8975 up
    
  3. 配置 IPTABLES 或 NFTABLES 将此类 UDP 数据包转发到隧道设备

    $ sudo iptables -t nat -A PREROUTING '!' -i tun8975 -p udp --dport 8975 -j DNAT --to-destination 172.16.19.21:8975
    
    $ sudo nft add rule ip nat PREROUTING iifname '!=' "tun8975" udp dport 8975 dnat to 172.16.19.21:8975
    
  4. 确保内核允许网络接口之间的 IP 数据包转发:

    $ sudo sysctl -w net.ipv4.ip_forward=1
    

然后,在本地机器上执行以下操作:

  1. 创建 SSH 将用于输出转发的 UDP 数据包的点对点隧道设备:

    $ sudo ip tuntap add dev tun8975 mode tun
    $ sudo ip addr add dev tun8975 172.16.19.21 peer 172.16.19.22
    $ sudo ip link set dev tun8975 up
    
  2. 请求 SSH 通过其安全通道转发隧道设备之间的流量:

    $ sudo ssh -4 -o Tunnel=point-to-point -w 8975:8975 -i ~/.ssh/xxxx.pem [email protected]
    

答案2

我发现你解决沟通问题的方法存在两个问题。

第一个问题出现在本地机器上运行的命令中。我认为应该删除命令管道-l的 UDP 部分的标志netcat,并且本地机器中的另一个进程(可能是另一个netcat)应该监听 UDP 端口 8975 并接收发送到该端口的数据报。netcat在这种情况下,将以客户端模式运行并生成此类数据报。

第二个问题与这些命令行的构造方式有关:

  • 在远程机器上
    $ netcat -l -u -p 8975 > /tmp/udp2tcp | netcat -l -p 10000 < /tmp/udp2tcp
    
  • 在本地机器上
    $ netcat localhost 10000 > /tmp/tcp2udp | netcat -l -u -p 8975 < /tmp/tcp2udp
    

它们混合了重定向和管道。虽然我确实读过管道重定向来自的部分Bash 手册页并发现管道将在重定向之前被处理,我无法理解 shell 如何使用这种语法连接标准流。

netcat它的工作原理是将数据从其标准输入转发到套接字的发送端,并将数据从套接字的接收端转发到其标准输出。无论此类套接字是连接到远程服务器的客户端套接字还是接受来自远程客户端的连接的服务器套接字,它都会这样做。因此,为了在 TCP 和 UDP 套接字之间转发数据,您需要适当地连接标准流,也就是说,您需要同时将 TCP 的 STDOUT 连接netcat到 UDP 的 STDIN netcat,并将 UDP 的 STDOUTnetcat连接到 TCP 的 STDIN 。netcat

也许你正在运行的命令行已经实现了这个目标。尽管如此,我建议使用以下命令进行更明确的数据转发:

  • 在远程机器上

    $ cat /tmp/udp2tcp | netcat -l -u -p 8975 | netcat -l -p 10000 > /tmp/udp2tcp
    
  • 在本地机器上

    $ cat /tmp/tcp2udp | netcat localhost 10000 | netcat -u localhost 8975 > /tmp/tcp2udp
    

在这两种情况下,匿名管道都会将第一个netcat的 STDOUT 连接到第二个netcat的 STDIN,而命名管道(fifo)会将第二个netcat的 STDOUT 连接回第一个netcat的 STDIN。

考虑netcat通过在命令行参数中添加标志来指示仅使用 IPv4 堆栈-4。如果监听 UDP 端口 8975 的进程与 IPv6 不兼容,这可能会有所帮助。

相关内容