想要从内网直接去访问外网的服务器肯定是不可能的,因为互联网中的机器都是公网通信,它看到内网来源后不知道该响应给谁,这就要用到源地址转换。源地址转换实质上就是把要出去的数据包中的源地址做了修改。
Linux 上基于 iptables 可实现源地址转换,即 SNAT。一般情况下一台主机配置一个公网 IP 就可以了,但是在有些场合因为业务需要,机器上要配置多个地址,这些地址可能是连续的,不连续的,一部分连续,一部分不连续,针对不同的情况,做 SNAT 也不同。
网卡上只有一个 IP 直接 SNAT 即可
1 | # eth1 111.161.126.234 |
网卡上有在同一个子网的多个连续的 IP
1 | eth0 111.161.74.179 |
这种情况可以选择其中一个 IP 做 SNAT,但是既然已经有这么多 IP 了就应该充分利用资源。使用 -
可以在 SNAT 的时候指定连续的 IP 范围,这样能够达到某种负载均衡的效果
1 | iptables -t nat -I POSTROUTING -o eth0 -s 192.168.0.0/16 -j SNAT --to 111.161.74.179-111.161.74.183 |
网卡上的 IP 都在同一子网,但是都不连续
1 | eth0 111.32.133.22 |
这种情况在 CentOS 5 上可以使用 SAME
和多个 --to
来达到上面的 SNAT 效果
1 | iptables -t nat -I POSTROUTING -o eth0 -s 192.168.0.0/16 -j SAME --to 111.32.133.22 --to 111.32.133.25 --to 111.32.133.29 |
但是 CentOS 5 的系统已经很少使用了,并且高版本的系统也不支持这种写法了。要解决这个问题,可以使用 state
模块和 statistic
来根据连接状态做负载均衡。既然是 3 个不连续的地址,我们就可以视为 3 个要 SNAT 的对象,根据这个来匹配 NEW 状态的数据包,匹配到的数据包中每 3 个数据包作为一个循环体,其中第 1 个数据包 SNAT 到第 1 个 IP,第 2 个数据包 SNAT 到第 2 个 IP,以此类推,当前循环体操作完之后将操作下一个循环体的 3 个数据包。要注意一下,我们人所说的第 1 个,在计算机上是从 0 开始的。如果到最后还是没有被匹配到,就 SNAT 到其中任意一个 IP ,这个规则就相当于是默认的 SNAT 规则。
1 | iptables -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/16 -m state --state NEW -m statistic --mode nth --every 3 --packet 0 -j SNAT --to 111.32.133.22 |
同一子网部分连续
1 | eth1 42.81.58.226 |
这种情况我们可以把连续的 IP 当做一个 SNAT 对象,这样就是两个 SNAT 对象。同样还是按照上面的方法处理
1 | iptables -t nat -A POSTROUTING -o eth1 -s 192.168.0.0/16 -m state --state NEW -m statistic --mode nth --every 2 --packet 0 -j SNAT --to 42.81.58.226-42.81.58.227 |
不同子网都是连续
1 | eth2 220.181.122.74 |
还是一样,连续的 IP 当做一个 SNAT 对象
1 | iptables -t nat -A POSTROUTING -o eth2 -s 192.168.0.0/16 -m state --state NEW -m statistic --mode nth --every 2 --packet 0 -j SNAT --to 220.181.122.74-220.181.122.78 |