我如何将所有应用程序的所有传出数据包从其各自的源端口路由到端口 x,以便它们看起来都好像来自端口 x。 可能吗?
我不太了解 iptables,但我尝试了这些规则,但它们的语法不正确:
iptables --table nat --append POSTROUTING --protocol TCP --source-port 1:65534 --jump REDIRECT --to-port 9999
# copy and paste exact rule but for UDP :
iptables --table nat --append POSTROUTING --protocol UDP --source-port 1:65534 --jump REDIRECT --to-port 9999
答案1
目标REDIRECT
不是您想要的。 REDIRECT
适用于您想要拦截通常会通过您的盒子路由的连接并将其重定向到本地端口的情况。这通常在实施某种透明代理解决方案时使用。在此模型中,您将有一个服务侦听目标端口(在您的示例中为 9999),该服务将响应流量。
(源SNAT
NAT) 和MASQUERADE
目标更接近您想要的,但我不确定其中任何一个是否适用于本地生成的流量(即,来自您正在实施此 iptables 规则的同一系统上的连接)...
...正如 Kyle 在评论中指出的那样,即使您能够实施“成功”的解决方案,如果您一次运行多个应用程序,您也会破坏一切。
如果您能提供有关您正尝试解决的问题的更多详细信息,我们也许能够提出更好的解决方案。
答案2
我不知道这是否可行。我怀疑即使可行你也不应该使用它,因为它本身就打破了 TCP/IP 模型对应用层的假设(IP+端口 = 套接字 = 1 个应用程序守护进程)。这与您无法仅使用 NAT 将防火墙上的单个端口转发到多个主机上的多个端口的原因相同(除非您正在对同一个应用程序进行负载平衡,但我认为您需要比 NAT 和 iptables 更复杂的东西来实现这一点)。
应用程序通常绑定到给定端口,这将阻止其他应用程序绑定到同一端口的尝试。通过此绑定,操作系统的网络代码可以知道哪个应用程序获取了数据包。这就是为什么您不能同时在端口 80 上运行 Apache 和 lighttpd。想想数据包。传输层需要处理的只是 IP 地址、源和目标的端口号(加上会话 ID,但如果会话已经建立,它也是无用的)。如果两者都绑定到一个端口,哪个守护进程可以获取它?
你可以“伪造”这种事情,如果你有一个超级服务器守护进程(如 inetd 或 xinetd)或远程命令中继(如 RPC 和 WMI),但每个客户端应用程序都必须知道它需要在应用程序层指定目的地,或者请求必须是特定于协议的。
答案3
根据你具体想做什么,我会研究如何设置“源 NAT”。一个很好的参考似乎是netfilter 指南第 6.1 节。在这里,netfilter 框架会跟踪更改,并将响应答案重写/重新路由到正确的发送端口。
例子:
polaris:~# iptables -t nat -A POSTROUTING -d qew -p tcp --destination-port 1444 -j SNAT --to :2347
polaris:~# telnet qew 1444
Trying 10.23.1.9...
Connected to qew.
Escape character is '^]'.
hello world
另一边:
qew:~# nc -l -p 1444
hello world
在另一个 shell 中显示从 polaris 到 qew 的数据包的源端口实际上已经改变。
qew:~# netstat -n |grep 1444
tcp 0 0 10.23.1.9:1444 10.23.1.10:2347 ESTABLISHED
如果您不希望连接奇迹般地保持活动状态,您也可以尝试直接修改数据包。我找不到针对端口执行此操作的目标,但有一个扩展允许更改 TTL 字段,所以我可能只是没有仔细查看。
最后的手段是使用 QUEUE 目标将您的数据包路由到用户空间,修改它们,更新所有校验和,然后将它们返回到内核。