刚刚整完 Nginx 四层反向代理,突然想到,iptables 也可以在三四层做网络地址及端口转换(此处可参考 【iptables 系列】),那它肯定也能完成反向代理的功能呀~~
干说无用,赶紧来试试。
在 【Nginx(7)之四、七层反向代理实例】中,我们实现了如下架构配置。
那本篇文章我们就基于这个配置继续测试 iptables 啦~~~
在这里我们要使用 iptables 做网络地址转换来顶替原来 A 主机的 Nginx 服务来完成四层反向代理的功能,但是这里有一个问题,在上图中 A 主机完成了 B、C 两个主机的请求调度功能,那按我们之前学习的 【iptables 网络地址转换】的知识,我们也只能把指定的请求分配到单个的目标主机上。
由于这个问题的存在,所以我们先来测试一下代理单个主机试试,下面就先以代理 B 主机为例。
1、停止 A 主机中的 Nginx 服务。
$ systemctl stop nginx
2、开启 A 主机的核心转发功能:
$ sysctl -w net.ipv4.ip_forward=1
3、添加如下规则,将目标地址为 10.0.1.200:80
的请求转发到 B 主机(172.16.1.201:80
):
$ iptables -t nat -A PREROUTING -d 10.0.1.200 -p tcp --dport 80 -j DNAT --to-destination 172.16.1.201:80
4、完成上述操作后,我们发往 A 主机 80 端口的请求就能到达 B 主机了,但是 B 主机的响应报文还是走默认网关,所以我们这里就需要将 B 主机的默认网关修改为 A 主机的 172.16.1.200
了,如下:
$ ip route add default via 172.16.1.200
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.1.200 0.0.0.0 UG 0 0 0 eth0
172.16.1.0 0.0.0.0 255.255.255.0 U 101 0 0 eth0
5、此时使用浏览器访问 10.0.1.200
,会发现已经正常代理 B 主机了:
现在 A 主机已经能正常代理 B 主机了,现在就是要想办法让 A 主机能同时代理 B、C 主机并且具有分流功能。
有想法就有办法,继续往下看。。
1、我们先将 C 主机的默认网关也改为 A 主机的 172.16.1.200
:
$ ip route add default via 172.16.1.200
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.1.200 0.0.0.0 UG 0 0 0 eth0
172.16.1.0 0.0.0.0 255.255.255.0 U 101 0 0 eth0
2、在 A 主机中添加如下规则:
$ iptables -t nat -A PREROUTING -d 10.0.1.200 -p tcp --dport 80 -m statistic --mode nth --every 2 --packet 0 -j DNAT --to-destination 172.16.1.201:80
$ iptables -t nat -A PREROUTING -d 10.0.1.200 -p tcp --dport 80 -m statistic --mode nth --every 1 --packet 0 -j DNAT --to-destination 172.16.1.202:80
3、此时我们再多次使用浏览器访问 10.0.1.200
,会发现也实现了负载均衡的功能。
如果此时你观察 B 主机和 C 主机的访问日志,会发现每隔一段时间它们会轮流被访问,即实现了分流的功能。
我们知道 iptables 是可以查看匹配报文的统计信息的,那我们就看一下我们刚刚添加的两条规则的匹配情况:
$ iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 14 packets, 956 bytes)
pkts bytes target prot opt in out source destination
30 1920 DNAT tcp -- * * 0.0.0.0/0 10.0.1.200 tcp dpt:80 statistic mode nth every 2 to:172.16.1.201:80
30 1920 DNAT tcp -- * * 0.0.0.0/0 10.0.1.200 tcp dpt:80 statistic mode nth every 1 to:172.16.1.202:80
会发现,不论我们如何访问,它们匹配的报文数(pkts
)逐渐趋于持平状态,是不是很神奇~~~
这里我们使用了一个陌生的模块,那就是 statistic
(-m statistic
):
- 指定模块的模式是
nth
(--mode nth
); - 如果有数据包计数器的话,
—every n
指的是每 n 个数据包被当前规则匹配,在上述示例中就是第偶数个数据包被第一条规则匹配,第奇数个数据包被第二条规则匹配; —packet 0
指的是第一个数据包;
所以我们就通过此种方式完成了 iptables 四层分流负载均衡的功能。
该模块详细使用请参考 【statistical packet distribution with iptables】。
评论区