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

Mar*_*ark 12 linux ssh iptables forwarding

我有一个 Linux 网关为我的家庭网络执行 NAT。我有另一个网络,我想透明地将数据包转发到,但只能转发到/来自特定的 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
Run Code Online (Sandbox Code Playgroud)

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

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

ssh -L 5000:192.168.50.50:5000 1.2.3.4
Run Code Online (Sandbox Code Playgroud)

这适用于路由器,它现在可以本地连接到端口 5000。因此“telnet localhost 5000”将按预期连接到 192.168.50.50:5000。

现在我想通过现在建立的 ssh 隧道重定向来自 Source 和漏斗的流量。我为此尝试了 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
Run Code Online (Sandbox Code Playgroud)

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

-A POSTROUTING -s 192.168.1.0/24 -o eth1 -j MASQUERADE
Run Code Online (Sandbox Code Playgroud)

本网站或其他地方的大多数问答似乎都涉及转发服务器端口或发夹式 NAT,我在其他地方都可以正常工作,但都不适用于这种情况。我当然可以 DMZ 通过远程网关转发远程目标端口,但我不希望这些端口可以通过互联网访问,我希望它们只能通过安全的 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
Run Code Online (Sandbox Code Playgroud)

由于我没有使用环回,因此可以避免火星拒绝。

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

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

我有兴趣将我的问题和解决方法贡献给一般搜索,以节省其他人的搜索时间,我只是想出了死胡同,并希望有人回答我的问题的回送/火星部分仍然开放对我来说。

Jos*_*din 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 目标不可达),则就外部世界而言,它与没有任何内容侦听该地址:端口组合的情况在很大程度上相同。