使用 iptables 将外部请求重定向到本地主机

使用 iptables 将外部请求重定向到本地主机

我有一个服务在某个 X 端口上的“localhost”地址上运行。不幸的是,我无法将地址更改为“0.0.0.0”以公开该服务。

我可以使用 iptables 在内部将请求从外部重定向到环回/本地主机接口吗?重定向将是 0.0.0.0:X -> localhost:X

谢谢

答案1

由于OP没有提到防火墙的存在,并且为了简单起见,我假设事先没有iptables设置存在:允许任何流量。

DNAT可用于nat/预路由将目标 IP 更改为 127.0.0.1,如下所示(重定向 UDP 端口 5555 的示例):

# iptables -t nat -A PREROUTING -p udp --dport 5555 -j DNAT --to-destination 127.0.0.1

虽然这对于任何 DNAT 目标到 127.0.0.0/8 范围之外的系统任何本地 IP 地址来说已经足够了。对于将目标更改为 127.0.0.0/8 内的 IP 地址的特定情况,这还不够。

必须切换一种特殊设置才能使其正常工作。假设系统的网络接口被称为以太网0这个命令会做到这一点:

# sysctl -w net.ipv4.conf.eth0.route_localnet=1

详细解释见后文。

(可选)特别是如果侦听 127.0.0.1 的应用程序不需要 127.0.0.0/8 之外的源 IP,您还可以更改自然/输入链与网络地址转换。对目标和源进行 NAT 会严重限制并发连接的数量,因此您应该仅在需要时才执行此操作,并且您将不再在日志中获取实际源:

# iptables -t nat -A INPUT -d 127.0.0.1 -m state --ctstate DNAT -j SNAT --to-source 127.0.0.1

关于使用的详细解释route_localnet=1

为了在下面更彻底地说明问题,我将假设:主机的网络接口是以太网0,在此接口上设置的 IP 地址为 192.0.2.100/24,正在接收来自客户端 192.0.2.200 的流量,但route_localnet尚未启用。

必须看一看Netfilter 和通用网络中的数据包流(点击查看完整尺寸):

Netfilter 和通用网络中的数据包流

检查事情发生的顺序:

  • 客户端从 192.0.2.200 发送数据包到 192.0.2.100(UDP 目标端口 5555)

  • nat/预路由发生

    目的地更改为 127.0.0.1(随后将使用相应的 conntrack 条目来恢复回复的此更改)

  • 路由堆栈处理到达的数据包以太网0源地址为 192.0.2.200,目标地址为 127.0.0.1。

  • 路由堆栈认为此数据包无效,因为 127.0.0.1 永远不会出现在lo环回接口之外。数据包被丢弃。

    可以通过以下方式检查ip route get

    # ip route get 127.0.0.1 from 192.0.2.200 iif eth0
    RTNETLINK answers: Invalid argument
    

    除此之外,如果要激活内核火星日志( sysctl -w net.ipv4.conf.eth0.log_martians=1) ,DNAT 时收到的每个数据包都会记录此信息iptables上面的规则正在起作用:

    [728538.240893] IPv4: martian destination 127.0.0.1 from 192.0.2.200, dev eth0
    

在极少数需要这样做的情况下,内核有一个特定的切换来放松这种行为,就像这个特定的情况一样,我们知道数据包中出现 127.0.0.1 的原因是 DNAT 规则:route_localnet

route_localnet - BOOLEAN
  Do not consider loopback addresses as martian source or destination
  while routing. This enables the use of 127/8 for local routing purposes.
  default FALSE

以太网0

# sysctl -w net.ipv4.conf.eth0.route_localnet=1

现在,前面的ip route get命令给出了:

# ip route get 127.0.0.1 from 192.0.2.200 iif eth0
local 127.0.0.1 from 192.0.2.200 dev lo 
    cache <local> iif eth0 

不再掉落了。

这也将以相反的方式放宽相同的限制:作为第一步,回复数据包将遍历路由决策,被 netfilter 取消 DNAT,因此也会被丢弃。之前和之后的路线route_localnet设置为 1:

前:

# ip route get 192.0.2.200 from 127.0.0.1
RTNETLINK answers: Invalid argument

后:

# ip route get 192.0.2.200 from 127.0.0.1
192.0.2.200 from 127.0.0.1 dev eth0 uid 0 
    cache 

答案2

是的,这是可能的。

以下命令序列应该可以做到这一点:

INTERFACE_IP="192.168.0.1"  # IP address of the external interface (e.g. eth0)
INTERFACE_PORT="80"         # external port to forward
LOCAL_IP="127.0.0.1"        # internal ip address to forward to
LOCAL_PORT="8080"           # internal port to forward to
/usr/sbin/iptables -t nat -A PREROUTING -d $INTERFACE_IP --dport $INTERFACE_PORT -j DNAT --to-destination $LOCAL_IP:$LOCAL_PORT

或者稍微不那么动态:

/usr/sbin/iptables -t nat -A PREROUTING -d 192.168.0.1 --dport 80 -j DNAT --to-destination 127.0.0.1:8080

如果目标端口 (:8080) 与传入端口相同,则可以省略。

请注意,您的 iptables 中的其他规则可能会给该规则带来问题!

相关内容