Linux iptables ssh 端口转发(火星人拒绝)

Linux iptables ssh 端口转发(火星人拒绝)

我有一个为我的家庭网络执行 NAT 的 Linux 网关。我有另一个网络,我想透明地将数据包转发到该网络,但仅限于特定 IP/端口(即不是 VPN)。以下是一些可使用的 IP 和端口示例:

Source          Router          Remote Gateway     Remote Target
192.168.1.10 -> 192.168.1.1 ->  1.2.3.4        ->  192.168.50.50:5000

我希望源计算机能够与远程目标上的特定端口通信,就好像它可以直接从路由器路由一样。在路由器上,eth0 是专用网络,eth1 是面向互联网的。远程网关是另一台我可以通过 ssh 连接的 Linux 机器,它可以直接路由到远程目标。

我尝试的一个简单的解决方案是在路由器上设置 ssh 端口转发,例如:

ssh -L 5000:192.168.50.50:5000 1.2.3.4

这对于路由器来说效果很好,它现在可以本地连接到端口 5000。因此“telnet localhost 5000”将按预期连接到 192.168.50.50:5000。

现在我想通过现已建立的 ssh 隧道重定向来自源和漏斗的流量。我为此尝试了 NAT 规则:

iptables -t nat -D PREROUTING -i eth0 -p tcp -s 192.168.1.10 --dport 5000 -d 1.2.3.4 -j DNAT --to-destination 127.0.0.1:5000

由于路由器已经是我的 NAT 网关,因此它已经具有所需的后路由规则:

-A POSTROUTING -s 192.168.1.0/24 -o eth1 -j MASQUERADE

这个网站或其他地方的大多数问答似乎都涉及转发服务器端口或发夹 NAT,这两个我在其他地方都工作得很好,但都不适用于这种情况。我当然可以通过远程网关转发远程目标端口,但我不希望这些端口可通过互联网访问,我希望它们只能通过安全 SSH 隧道访问。

我能找到的最佳答案与 Linux 内核中的 Martian 数据包拒绝相关:

iptables,如何从环回重定向端口?

我已经启用了火星人的日志记录,并确认内核将这些数据包作为火星人拒绝。但它们不是:我确切地知道这些数据包的用途、它们来自哪里以及它们要去哪里(我的 ssh 隧道)。

那里提出的“迂回”解决方案适用于原来的问题,但不适用于我的情况。

然而,在编写/研究这个问题时,我通过使用 SSH 源 IP 绑定解决了我的问题,如下所示:

ssh -L 192.168.1.1:5000:192.168.50.50:5000 1.2.3.4
iptables -t nat -D PREROUTING -i eth0 -p tcp -s 192.168.1.10 --dport 5000 -d 1.2.3.4 -j DNAT --to-destination 192.168.1.1:5000

由于我没有使用环回,这可以避免火星人的拒绝。

我仍然在这里发布这个问题有两个原因:

  1. 希望将来尝试做类似事情的人可以在他们的搜索中找到这一点,并且此解决方法可能会对他们有所帮助。
  2. 我仍然更喜欢将 ssh 端口转发连接仅绑定到环回并能够通过 iptables 路由到它们的想法。既然我确切地知道这些数据包是什么以及它们要去哪里,我是否应该有某种方法来标记它们,以便 Linux martian 过滤不会拒绝它们?我对这个主题的所有搜索都会导致 rp_filter,这对我的测试没有任何帮助。即使它确实有效,它也不是特定于我试图允许的确切数据包。

我有兴趣将我的问题和解决方法贡献给一般搜索,以节省其他人的搜索时间,我所做的只是想出死胡同,并希望有人回答我的问题中仍然悬而未决的环回/火星部分大部头书。

答案1

对 127.0.0.1:5000 进行 DNAT 的问题是,当远程端响应时,这些数据包返回到路由引擎,就好像它们是本地发起的(来自 127.0.0.1),但它们具有外部目标地址。与外部接口匹配的 SNAT/MASQUERADE 会捕获它们并重写它们,但必须首先做出使数据包到达该接口的路由决策,并且默认情况下它们不允许这些伪造的数据包。路由引擎不能保证您稍后会记得进行重写。

您应该能够做的事情是使用源地址规范!之前的参数拒绝 iptables INPUT 处到 192.168.1.1:5000 的任何外部连接,除了来自 192.168.1.10 的连接。-s如果您使用 TCP 重置作为拒绝机制(-j REJECT --reject-with tcp-reset,而不是默认的 ICMP 目标不可达),则就外部世界而言,它与没有任何内容侦听该地址:端口组合的情况在很大程度上相同。

答案2

我将使用 openVPN 创建从路由器到 RemoteGateway 的隧道。

然后我会在路由器上添加一条路由:

路由添加-主机RemoteTarget gw RemoteGateway-VPN地址

使用简单的 iptables 规则来限制允许 Source 访问的端口。

相关内容