Iptebales提供的功能中其中一个是NAT网络地址转换,网络地址转换使用的场景通常是一个公网IP情况下供内网中多台主机连接外网,但是在极少数情况下会用在一台主机内网络流量重定向,比如将在本机回环设备中的数据包强行转发到另一台主机上。结果发现原本在正常的NAT场景中生效的iptables规则在loopback数据包的转发中并不起作用,原因是如果想要转发lo设备中的网络流量需要修改一个内核参数route_localnet值为1,该参数位于:
#echo 1 > /proc/sys/net/ipv4/conf/<NET_DEV>/route_localnet
该参数指定一个网络设备是否允许转发目的或源地址为127/8的数据包,也就是来自或去往lo设备的数据包,通常情况下Linux系统中的每个网络设备都有自己的参数配置。
Note:内核参数的修改是立即生效的但是重启后丢失。
接下来就可以按照正常的NAT一样来定义Iptables规则,以转发连接自己的SSH数据包到一台外部主机为例:
1.首先匹配到127.0.0.1:22套接字地址的数据包,将其目的地址强行修改为一个外部主机:
#iptables -t nat -A OUTPUT -d 127.0.0.1 -p tcp -m tcp --dport 22 -j SNAT --to-destination 16.186.74.32
该规则在OUTPUT链上修改数据包的传递路径,此时Routing Subsystem不会影响该数据包的流向。
此时数据包的目的地址已经由原先的127.0.0.1修改为了16.186.74.32,但是源地址还是原先的127.0.0.1,这样数据包是无法正常返回本机的,so需要将数据包的源地址改为本机连接局域网的设备IP地址。
2.源地址的修改有两种方法,一种是手动修改数据包源地址为本机地址:
#iptables -t nat -A POSTROUTING -d 16.186.74.32 -p tcp -m tcp --dport 22 -j SNAT --to-source 16.186.75.195
此处在POSTROUTING链上进行,匹配经过了前一条规则修改的目的地址数据包,将其源地址强行修改为本机的地址(使用地址16.186.75.195)。
还有一种简单的修改方法是利用Iptables提供的地址伪装功能MASQUERADE,该功能能够自动帮我们完成NAT功能:
#iptables -t nat -A POSTROUTING -o ens32 -j MASQUERADE
此处要在实际链接外网的网络设备(本机为ens32)启用MASQUERADE规则。
此时尝试链接:ssh 127.0.0.1,结果:
发现在尝试ssh连接本机时实际连接的是另一台主机,至此成功实现了loopback流量的转发。
但是根据标准A router SHOULD NOT forward, except over a loopback interface, any packet that has a source address on network 127.
route_localnet
该参数可以实现网络设备转发lo设备数据包的功能,默认值为0-False,此处我们的数据包需要经过ens32转发到外部网络,所以可以修改/proc/sys/net/ipv4/conf/ens32/route_localnet,也可以修改/proc/sys/net/ipv4/conf/all/route_localnet对所有网络设备生效。链接
ip_forward
该参数对lo设备数据包的转发没有影响,因为在OUTPUT链中的NAT已经不会再进行Routing决策,只能称为Redirect而不是Forward。
localhost
使用localhost在本例中可能无效。localhost本质上不能等于127.0.0.1,虽然大多数情况下他们都可以代表同一个目的地,但是路径不完全一致。localhost通过UNIX域套接字而不会经过TCP/IP协议栈,所以不会被NETFILTER处理。
这篇博客介绍了如何使用iptables在Linux系统中重定向loopback接口(lo)的网络流量到外部主机。通过修改内核参数route_localnet,允许转发127/8网络的数据包,并设置iptables规则进行NAT转换,实现从127.0.0.1:22到外部主机的SSH连接。同时,文章强调了route_localnet和ip_forward参数的区别以及localhost在本过程中的特殊性。

66

被折叠的 条评论
为什么被折叠?



