如何配置与协议无关的双向端口转发?

如何配置与协议无关的双向端口转发?

我正在尝试解决以下问题:


我有一个系统,以后将其称为“本地”,该系统在端口 80 和端口 443 上托管服务,并依赖于在端口 25 上发送传出请求。它还在端口 22 上托管一个单独的服务。我将其称为“Global”,它具有全局可访问的静态 IP 地址并为其配置了 DNS,并且能够接受端口 80、443、25 和 222 上的传入请求。

本地和全局在保留子网 10.0.0.0/24 上连接(通过 VPN 接口,如果重要的话)

我希望全局端口 80 和 443 上的所有传入请求分别重定向到端口 80 和 443 上的本地。我还希望全局端口 222 上的传入请求重定向到端口 22 上的本地端口(是的,这是一个故意不同的端口)。此外,我希望所有从本地到端口 25 的传出请求都重定向到端口 25 上的全局。

Local 和 Global 都是现代 Linux 系统,具有 apt、iptables、nftables 和 ufw 可用。
我尝试了多种 iptables 配置,但没有成功。

据我所知,/应该/工作(但不工作!)的配置如下:

Global:
    /etc/ufw/before.rules (excerpt)
        *nat
        :PREROUTING ACCEPT [0:0]

        # forward port 222 to Local:22
         -A PREROUTING -p tcp --dport 222 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:22

        # forward port 80 to Local:80
         -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:80

        # forward port 443 to Local:443
         -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:443

        # and forward the responses the other direction
         -A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j MASQUERADE

        COMMIT

Local:
    /etc/ufw/before.rules (excerpt)
        *nat
        :PREROUTING ACCEPT [0:0]

        # forward outgoing port 25 to Global:25
        -A OUTPUT -p tcp --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 Subnet>:25

        COMMIT

我意识到传入的 HTTP 请求可以使用 nginx 或 apache 配置进行路由,但我想要一个不依赖于协议且可用于 ssh 或其他协议的通用解决方案,因为此流量不一定总是 HTTP。

有谁知道如何做到这一点?
是否有某种原因导致这种类型的配置无法实现?

答案1

好吧,经过一番惊愕之后,我能够解决我原来的问题,因此可以在这里为将来可能遇到此问题的任何人发布正确的解决方案。应用程序层配置超出了原始问题的范围。

首先,如果您设置了 ufw,则需要允许应用这些规则而不被防火墙阻止。这需要在两个都主机,如果他们都有 ufw。这是通过以下描述的步骤完成的https://help.ubuntu.com/lts/serverguide/firewall.html在“IP 伪装”部分下,总结如下

0) edit /etc/default/ufw to set DEFAULT_FORWARD_POLICY="ACCEPT"
1) edit /etc/ufw/sysctl.conf to set net/ipv4/ip_forward=1 and net/ipv6/conf/default/forwarding=1
2) put the desired iptables rules in /etc/ufw/before.rules using ufw's syntax, starting with *nat and ending with COMMIT
3) restart ufw 

要重定向传入数据包并将其代理到本地,请在全球的:

 #ensure forwarding is enabled, just for sanity's sake (for ufw sysctl.conf covers this)
 sysctl -w net.ipv4.ip_forward=1

 #rewrite incoming port 222 to Local:22
 iptables -t nat -A PREROUTING -p tcp --dport 222 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:22

 #having rewritten the destination, also rewrite the source for all packets that now have a destination of Local:22
 #rewriting the source means that the ACKs and other bidirectional data gets sent back to Global instead of attempting to go from Local directly to the originator
 iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 22 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>

 #repeat the above for ports 80 and 443, as in the original question
 iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:80
 iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 80 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>

 iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:443
 iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 443 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>

这涵盖了传入的代理连接。对于传出连接,我们需要以下配置当地的:

 #rewrite outgoing port 25 to Global:25, UNLESS it's meant for localhost (assumes lo is set up for ipv4, and not just ipv6)
 iptables -t nat -A OUTPUT -p tcp '!' -d 127.0.0.1/32 --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 subnet>:25

 #having rewritten the destination, also rewrite the source for all packets that now have a destination of Global:25
 iptables -t nat -A POSTROUTING -p tcp '!' -d 127.0.0.1/32 --dport 25 -j SNAT --to-source <Local IP on 10.0.0.0/24 subnet>

我们需要允许 localhost,以便可以连接到该端口上的本地服务器,因为这就是 SMTP 和许多其他在协议级别进行代理的程序(包括 DNS)需要运行的方式。因此,我们转发了所有未绑定到本地主机的内容。

就是这样!这是该堆栈级别的完整配置,它将把您的数据包发送到需要的位置。应用程序级别配置超出了这个问题的范围。

相关内容