WAF 实现透明部署-原理及操作步骤
2023-04-26 00:00:00

简介

此文章主要参考了一篇文章和FortiWeb Guide文档,原理也是和chatgpt沟通得到的,具体链接放到了最后.

注意事项

  1. 此文章会涉及到网桥、iptables等配置,使用时可能会影响正常的网络通信,不当的使用可能会导致网络故障或安全问题。因此,此文章需要的服务器网络全都是独立的,不要把他们接入公司或者你正在使用的网络中,避免引发网络问题
  2. 服务器最好先进行时间同步,确保这些服务器全都是一样的时间

准备工作

  • 三台Centos7服务器, 分别做客户端(网关)、WAF服务器(透明桥)、WEB服务器。
  • WAF服务器要有多个网口,其中有2个接口要做桥接,还有1个管理口。
  • 2条网线,以及其他线材和外设保证服务器能正常运行和操作。
  • 显示器, 需要直连服务器。或者用PC可以远程操作这些服务器,但这个要防止网络异常,最好是直连服务器操作。

实现客户端和WEB服务器正常通信

首先在没有WAF透传的情况下要保证客户端和WEB服务器通信是正常的。

  1. 客户端服务器最好有界面,可以用firefox浏览器。配置客户端其中一个网口的IP地址和子网掩码, 比如

    IP: 172.16.0.1 子网掩码: 255.255.255.0, 网关不要填写

  2. WEB服务器安装WEB服务,可以用nginx搭建一个HTTP服务,此处不细说,后续会假定HTTP服务为80端口提供。 配置WEB服务器其中一个网口的IP地址和子网掩码, 比如:

    IP: 172.16.0.3 子网掩码: 255.255.255.0, 网关: 172.16.0.1

  3. 用一根网线直连这2台服务器的对应网口,然后可以用ping命令测试是否联通,也可以直接在客户端通过浏览器访问 172.16.0.3:80, 看看响应是否正常。

WAF服务器配置桥接

  1. 比如WAF服务器有6个网口,服务器中显示的网卡分别是enp2s0、enp3s0….enp6s0、enp7s0。
    首先确定管理口,提供给PC或者远程连接操作,目前也可以用显示器直连服务器操作,比如用enp2s0做管理口。
  2. 确定桥接的2个接口,比如用enp6s0和enp7s0
  3. 关闭centos 7自带防火墙
    1
    2
    systemctl stop firewalld.service
    systemctl disable firewalld.service
  4. 安装ifconfig 和网桥工具包
    1
    2
    yum -y install net-tools.x86_64
    yum -y install bridge-utils
  5. 关闭和禁用 NetworkManager 服务,启用 network 服务
    1
    2
    3
    4
    chkconfig NetworkManager off
    chkconfig network on
    service NetworkManager stop
    service network start
  6. 添加网桥
    1
    2
    3
    4
    /sbin/modprobe bridge
    /usr/sbin/brctl addbr br0(设置网桥名为br0)
    /sbin/ifup enp6s0 (要加入网桥的网卡,通过ifconfig查看, 启动此网卡)
    /sbin/ifup enp7s0 (要加入网桥的网卡)
  7. 将 enp6s0 和 enp7s0 网络接口添加到名为 br0 的网桥设备中
    1
    2
    /usr/sbin/brctl addif br0 enp6s0
    /usr/sbin/brctl addif br0 enp7s0
  8. 设置网桥IP (例:172.16.0.2 设置一个在内网网段的IP)
    1
    ifconfig br0 172.16.0.2 netmask 255.255.255.0
  9. 开启网桥
    1
    /sbin/ip link set br0 up
  10. 查看网桥
    1
    sudo brctl show
    如果以上步骤都正常,则会显示如下内容
    1
    2
    3
    bridge name     bridge id               STP enabled     interfaces
    br0 8000.4062311c9132 no enp6s0
    enp7s0
  11. 如果上述步骤网桥IP之类设置错误,可以删掉重新设置。如果正常不要执行此步骤内容
    1
    2
    3
    4
    5
    # 关闭网桥
    ifconfig br0 down
    # 删除br0
    sudo brctl delbr br0
    # 然后重新添加网桥br0,然后将enp6s0、enp7s0加入网桥,设置br0的Ip和掩码,再启动
  12. 这时候就用2条网线,1条连接客户端网口和enp6s0网络接口,另1条连接enp7s0和WEB服务器网口。
    在客户端使用浏览器访问 172.16.0.3:80 ,如果正常则会显示WEB服务器HTTP的响应界面。 此时已经桥接成功。

将流量导向WAF服务

现在2个接口桥接可以使网络通信正常,而且没有更改客户端和WEB服务器配置,把刚刚的网线拿掉,连接客户端和WEB服务器还可以正常通信。
但是我们目的还是要经过WAF处理请求数据,所以还需要将请求导入WAF处理,WAF是7层的,所以需要利用iptables做NAT转换,让WAF插入中间做透明代理。

  1. 安装iptables 并开启

    1
    2
    3
    yum -y install iptables
    yum -y install iptables-services
    service iptables start
  2. 在/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
  3. 执行命令使生效

    1
    sysctl -p
  4. 如果报错:

    1
    2
    3
    4
    5
    6
    7
    sysctl: 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
  5. 添加路由, 这个步骤是上述文章提到,我还没明白这个作用

    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
  6. 首先检查是否有其他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 [行号]
  7. 添加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
  8. 保存iptables规则,重启服务

    1
    2
    service iptables save
    service iptables restart
  9. 以上,系统透明模式需要的设置已完成,WAF可以自行安装,参考上述文章的shareWAF或者自己准备其他WAF服务,也可以简单装一个nginx,打开access.log,看是否有请求转到nginx。如果一切正常,此时在客户端请求172.16.0.3:80, 是通过了WAF转发的,WAF可以看到请求,而且客户端和WEB端都无需修改配置,还正常响应

抓包

现在功能是正常了,但是还可以进一步研究网络是如何通信的,那就需要抓包看数据了,分别使用如下命令在客户端、WAF、和WEB服务器抓包, 网卡替换成对应网卡

1
2
3
tcpdump -n -X -i enp2s0 -w client.pcap
tcpdump -n -X -i br0 -w waf.pcap
tcpdump -n -X -i enp2s0 -w server.pcap

然后用客户端浏览器发送请求,等响应正常后可以ctrl+c停止抓包,将抓包文件导出到windows中,利用wireshark研究数据

客户端数据

  1. 红圈中的这条数据就是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
  2. 这条数据也是arp协议数据,是客户端(172.16.0.1)询问WEB服务器(172.16.0.3)的mac地址,然后收到了回复。可以看到客户端也是发送到广播地址,然后收到了WEB服务器的mac地址(40:8d:5c:f2:aa:6f)
  3. 客户端和WEB服务器的http通信,直接看图, 展示了3次握手和http通信数据,HTTP 状态码 304 Not Modified 表示客户端发送的请求的资源没有发生修改,因为我前面请求了几次,所以服务器没有返回资源的内容,而是返回一个空的响应体,告诉客户端可以使用缓存中的资源。

从上面图可以看到客户端(172.16.0.1)一直和WEB服务器(172.16.0.3)通信,并没有感受到WAF的存在。

WEB服务器数据

先看WEB服务器数据,因为WAF的稍微有点绕,可以先理解WEB服务器通信,如下图所示

  1. ARP相关的和客户端一样,都是广播自己的mac,然后收到了客户端(172.16.0.1)询问WEB服务器(172.16.0.3)的mac地址,然后返回自己的mac
  2. 可以看到3次握手,和http请求响应数据
  3. 多了个四次挥手

这个就看出问题了,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数据

  1. 可以看到ARP协议数据,不再多说,和上面一样
  2. 三次握手有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。
  3. 后面是客户端发的http请求,然后就是WAF和WEB服务器做的TCP握手(第二部分三次握手),这也就是WEB服务器抓包看到的三次握手。
  4. 握手成功后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设备出故障时也可以实现透明传输,更稳定。

参考内容