简介
此文章主要参考了一篇文章和FortiWeb Guide文档,原理也是和chatgpt沟通得到的,具体链接放到了最后.
注意事项
- 此文章会涉及到网桥、iptables等配置,使用时可能会影响正常的网络通信,不当的使用可能会导致网络故障或安全问题。因此,此文章需要的服务器网络全都是独立的,不要把他们接入公司或者你正在使用的网络中,避免引发网络问题。
- 服务器最好先进行时间同步,确保这些服务器全都是一样的时间
准备工作
- 三台Centos7服务器, 分别做客户端(网关)、WAF服务器(透明桥)、WEB服务器。
- WAF服务器要有多个网口,其中有2个接口要做桥接,还有1个管理口。
- 2条网线,以及其他线材和外设保证服务器能正常运行和操作。
- 显示器, 需要直连服务器。或者用PC可以远程操作这些服务器,但这个要防止网络异常,最好是直连服务器操作。
实现客户端和WEB服务器正常通信
首先在没有WAF透传的情况下要保证客户端和WEB服务器通信是正常的。
客户端服务器最好有界面,可以用firefox浏览器。配置客户端其中一个网口的IP地址和子网掩码, 比如
IP: 172.16.0.1 子网掩码: 255.255.255.0, 网关不要填写
WEB服务器安装WEB服务,可以用nginx搭建一个HTTP服务,此处不细说,后续会假定HTTP服务为80端口提供。 配置WEB服务器其中一个网口的IP地址和子网掩码, 比如:
IP: 172.16.0.3 子网掩码: 255.255.255.0, 网关: 172.16.0.1
用一根网线直连这2台服务器的对应网口,然后可以用ping命令测试是否联通,也可以直接在客户端通过浏览器访问 172.16.0.3:80, 看看响应是否正常。
WAF服务器配置桥接
- 比如WAF服务器有6个网口,服务器中显示的网卡分别是enp2s0、enp3s0….enp6s0、enp7s0。
首先确定管理口,提供给PC或者远程连接操作,目前也可以用显示器直连服务器操作,比如用enp2s0做管理口。 - 确定桥接的2个接口,比如用enp6s0和enp7s0
- 关闭centos 7自带防火墙
1
2systemctl stop firewalld.service
systemctl disable firewalld.service - 安装ifconfig 和网桥工具包
1
2yum -y install net-tools.x86_64
yum -y install bridge-utils - 关闭和禁用 NetworkManager 服务,启用 network 服务
1
2
3
4chkconfig NetworkManager off
chkconfig network on
service NetworkManager stop
service network start - 添加网桥
1
2
3
4/sbin/modprobe bridge
/usr/sbin/brctl addbr br0(设置网桥名为br0)
/sbin/ifup enp6s0 (要加入网桥的网卡,通过ifconfig查看, 启动此网卡)
/sbin/ifup enp7s0 (要加入网桥的网卡) - 将 enp6s0 和 enp7s0 网络接口添加到名为 br0 的网桥设备中
1
2/usr/sbin/brctl addif br0 enp6s0
/usr/sbin/brctl addif br0 enp7s0 - 设置网桥IP (例:172.16.0.2 设置一个在内网网段的IP)
1
ifconfig br0 172.16.0.2 netmask 255.255.255.0
- 开启网桥
1
/sbin/ip link set br0 up
- 查看网桥如果以上步骤都正常,则会显示如下内容
1
sudo brctl show
1
2
3bridge name bridge id STP enabled interfaces
br0 8000.4062311c9132 no enp6s0
enp7s0 - 如果上述步骤网桥IP之类设置错误,可以删掉重新设置。如果正常不要执行此步骤内容。
1
2
3
4
5# 关闭网桥
ifconfig br0 down
# 删除br0
sudo brctl delbr br0
# 然后重新添加网桥br0,然后将enp6s0、enp7s0加入网桥,设置br0的Ip和掩码,再启动 - 这时候就用2条网线,1条连接客户端网口和enp6s0网络接口,另1条连接enp7s0和WEB服务器网口。
在客户端使用浏览器访问 172.16.0.3:80 ,如果正常则会显示WEB服务器HTTP的响应界面。 此时已经桥接成功。
将流量导向WAF服务
现在2个接口桥接可以使网络通信正常,而且没有更改客户端和WEB服务器配置,把刚刚的网线拿掉,连接客户端和WEB服务器还可以正常通信。
但是我们目的还是要经过WAF处理请求数据,所以还需要将请求导入WAF处理,WAF是7层的,所以需要利用iptables做NAT转换,让WAF插入中间做透明代理。
安装iptables 并开启
1
2
3yum -y install iptables
yum -y install iptables-services
service iptables start在/etc/sysctl.conf下添加内容, 也就是编辑此文件,在最后添加相关配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# 启用 IPv6 数据包的防火墙过滤功能。当网桥设备转发 IPv6 数据包时,可以使用防火墙规则对数据包进行过滤和控制
net.bridge.bridge-nf-call-ip6tables = 1
# 启用 IPv4 数据包的防火墙过滤功能。当网桥设备转发 IPv4 数据包时,可以使用防火墙规则对数据包进行过滤和控制。
net.bridge.bridge-nf-call-iptables = 1
# 启用 ARP 数据包的防火墙过滤功能。当网桥设备转发 ARP 数据包时,可以使用防火墙规则对数据包进行过滤和控制。
net.bridge.bridge-nf-call-arptables = 1
# 启用 Linux 操作系统的 IP 转发功能。当网桥设备转发数据包时,可以使用 IP 转发功能将数据包转发到其他网络。
net.ipv4.ip_forward = 1
# 启用 Linux 操作系统的端口绑定功能。当网桥设备绑定端口时,可以使用端口绑定功能将端口绑定到非本地 IP 地址。
net.ipv4.ip_nonlocal_bind = 1
# 禁用 Linux 操作系统的反向路径过滤功能。反向路径过滤是一种网络安全功能,用于检查数据包的源地址是否合法。禁用反向路径过滤可以提高网桥设备的网络性能和灵活性。
net.ipv4.conf.default.rp_filter = 0
# 禁用 Linux 操作系统的反向路径过滤功能。同上。
net.ipv4.conf.all.rp_filter = 0
# 禁用网桥设备 br0 的反向路径过滤功能。同上。
net.ipv4.conf.br0.rp_filter = 0执行命令使生效
1
sysctl -p
如果报错:
1
2
3
4
5
6
7sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: 没有那个文件或目录
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: 没有那个文件或目录
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-arptables: 没有那个文件或目录
# 执行
modprobe br_netfilter
# 再次执行
sysctl -p添加路由, 这个步骤是上述文章提到,我还没明白这个作用
1
2
3
4# 添加一个 IP 路由规则,将标记为 1 的数据包转发到 ID 为 100 的路由表中。这个命令可以实现基于标记的流量控制,例如将特定的数据包流量转发到指定的网络接口或网关中。
/sbin/ip -f inet rule add fwmark 1 lookup 100
# 添加一个本地路由规则,将本地流量转发到 ID 为 100 的路由表中。这个命令可以实现本地流量的负载均衡,例如将本地流量分散到多个网络接口或网关中,从而提高网络性能和可靠性。
/sbin/ip -f inet route add local default dev lo table 100首先检查是否有其他iptables规则,如果有,则需要先删除
1
2
3
4
5
6
7# 检查iptables NAT规则
sudo iptables -t nat -L -n --line-numbers
# 这个命令将列出当前iptables的nat表中的PREROUTING和POSTROUTING规则,以及它们的行号。
# 删除PREROUTING规则
sudo iptables -t nat -D PREROUTING [行号]
# 删除POSTROUTING规则
sudo iptables -t nat -D POSTROUTING [行号]添加DNAT规则, 其中前面的172.16.0.3和80端口是WEB服务器的IP和HTTP服务端口,后面的172.16.0.2:8080,则是WAF服务器网桥IP和WAF服务的端口,8080是WAF提供的代理HTTP服务端口
1
iptables -t nat -A PREROUTING -d 172.16.0.3 -p tcp --dport 80 -j DNAT --to-destination 172.16.0.2:8080
保存iptables规则,重启服务
1
2service iptables save
service iptables restart以上,系统透明模式需要的设置已完成,WAF可以自行安装,参考上述文章的shareWAF或者自己准备其他WAF服务,也可以简单装一个nginx,打开access.log,看是否有请求转到nginx。如果一切正常,此时在客户端请求172.16.0.3:80, 是通过了WAF转发的,WAF可以看到请求,而且客户端和WEB端都无需修改配置,还正常响应
抓包
现在功能是正常了,但是还可以进一步研究网络是如何通信的,那就需要抓包看数据了,分别使用如下命令在客户端、WAF、和WEB服务器抓包, 网卡替换成对应网卡
1 | tcpdump -n -X -i enp2s0 -w client.pcap |
然后用客户端浏览器发送请求,等响应正常后可以ctrl+c停止抓包,将抓包文件导出到windows中,利用wireshark研究数据
客户端数据
- 红圈中的这条数据就是ARP协议数据,ARP是通过IP地址找MAC地址的,这条数据是客户端(172.16.0.1)发送一个 ARP Announcement 消息到局域网中,以通知其他主机更新自己的 ARP 缓存表, 客户端发送给ff:ff:ff:ff:ff:ff 是广播地址,用于将数据包发送到网络中的所有主机。参数就是自己的mac地址(40:8d:5c:d7:49:ed)
- 这条数据也是arp协议数据,是客户端(172.16.0.1)询问WEB服务器(172.16.0.3)的mac地址,然后收到了回复。可以看到客户端也是发送到广播地址,然后收到了WEB服务器的mac地址(40:8d:5c:f2:aa:6f)
- 客户端和WEB服务器的http通信,直接看图, 展示了3次握手和http通信数据,HTTP 状态码 304 Not Modified 表示客户端发送的请求的资源没有发生修改,因为我前面请求了几次,所以服务器没有返回资源的内容,而是返回一个空的响应体,告诉客户端可以使用缓存中的资源。
从上面图可以看到客户端(172.16.0.1)一直和WEB服务器(172.16.0.3)通信,并没有感受到WAF的存在。
WEB服务器数据
先看WEB服务器数据,因为WAF的稍微有点绕,可以先理解WEB服务器通信,如下图所示
- ARP相关的和客户端一样,都是广播自己的mac,然后收到了客户端(172.16.0.1)询问WEB服务器(172.16.0.3)的mac地址,然后返回自己的mac
- 可以看到3次握手,和http请求响应数据
- 多了个四次挥手
这个就看出问题了,WEB服务器不是和客户端直接通信的,因为看他的ip地址是 172.16.0.2:31515和172.16.0.3:80 通信,这个是WAF和WEB服务器通信的。在客户端我们看到的截图是172.16.0.1:50635和172.16.0.3:80通信的。
还有就是多了四次挥手,客户端并没有看到。
这2个不同点就说明中间是有WAF劫持了流量,而且WAF后续和WEB服务器进行了通信
WAF数据
- 可以看到ARP协议数据,不再多说,和上面一样
- 三次握手有2部分,这个就特殊了,先解释为什么会有2个TCP三次握手,因为iptables做了DNAT也就是改了数据包的目标IP地址,上面那条iptables命令检测到发往WEB服务器172.16.0.3:80 的数据,就会将目标IP和端口改为172.16.0.2:8080。这也就是可以看到第一次握手是客户端发给WAF的,因为被iptables改了,这就相当于客户端和WAF做了TCP连接。又因为WAF做的桥接,对客户端是透明的,所以syn+ack显示的是172.16.0.3和172.16.0.1。
- 后面是客户端发的http请求,然后就是WAF和WEB服务器做的TCP握手(第二部分三次握手),这也就是WEB服务器抓包看到的三次握手。
- 握手成功后WAF转发HTTP请求到WEB服务器,然后收到WEB服务器的响应,之后就断开和WEB服务器的TCP连接,最后把响应转发给客户端
对客户端来说,他是不知道有WAF存在的,抓包可以看到与客户端通信的都是WEB服务器的IP。对WEB服务器来说,与他通信的是WAF的网桥IP,所以对WEB服务器没有做到真正的透明。
总结
由于中间的设备加了iptables转发的步骤,才能让WAF可以处理经过的流量,WAF会和WEB服务器做TCP连接,这样也不算完全的透明,如果没有iptables做转发,那么对客户端和WEB服务器都只会显示对方的IP,无法感知到WAF存在。
但是这个也是透明部署,因为无需修改客户端和WEB服务器配置。当然实际部署情况应该是WAF前面有一个网关或者网络防火墙,然后另一端是WEB服务器,同样不需要修改两端的配置,只需要修改WAF配置即可。如果用bypass网卡,在WAF设备出故障时也可以实现透明传输,更稳定。
参考内容
- chatgpt
- npm 设置代理_高端操作:DIY一台硬件WAF!透明代理
- FortiWeb Guide WAF文档
- FortiWeb Guide WAF透明部署示意图: