WAF 工作在应用层,对基于 HTTP/HTTPS 协议的 Web 系统有着更好的防护效果,使其免于受到黑客的攻击
操作系统:Linux
指令架构:x86_64
`查询命令:
uname -m
软件依赖:Docker 20.10.14 版本以上
`查询命令:
docker --version
软件依赖:Docker Compose 2.0.0 版本以上
`查询命令:
docker-compose version
最小化环境:1 核 CPU / 1 GB 内存 / 5 GB 磁盘
`查询命令:
cat /proc/cpuinfo # 查看 CPU 信息
cat /proc/meminfo # 查看内存信息
df -h # 查看磁盘信息
在线安装
bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release/latest/setup.sh)"
离线安装
如果你的服务器无法连接互联网环境,或连接 Docker Hub 网络不稳,可以使用镜像包安装方式
这里忽略 Docker 安装的过程
首先,下载 雷池社区版镜像包 并传输到需要安装雷池的服务器上,执行以下命令加载镜像
cat image.tar.gz | gzip -d | docker load
执行以下命令创建并进入雷池安装目录
mkdir -p safeline # 创建 safeline 目录
cd safeline # 进入 safeline 目录
下载 编排脚本 并传输到 safeline 目录中
`编排脚本:
networks:
safeline-ce:
name: safeline-ce # 定义该子网名称
driver: bridge # 定义该子网为桥接模式
ipam:
driver: default
config:
- gateway: ${SUBNET_PREFIX:?SUBNET_PREFIX required}.1 #定义网关为SUBNET_PREFIX.1,若按上文设置,此处为172.22.222.1
subnet: ${SUBNET_PREFIX}.0/24
driver_opts:
com.docker.network.bridge.name: safeline-ce
services:
postgres:
container_name: safeline-postgres # 容器名称
restart: always # #容器启动失败或崩溃时自动重启
image: postgres:15.2 # 镜像名称
volumes: #开启的映射文件夹
- ${SAFELINE_DIR}/resources/postgres/data:/var/lib/postgresql/data
- /etc/localtime:/etc/localtime:ro
environment: #设置容器启动时的环境变量
- POSTGRES_USER=safeline-ce
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?postgres password required}
networks: # 容器网络
safeline-ce:3
ipv4_address: ${SUBNET_PREFIX}.2
cap_drop: # 去除容器中某些不需要的能力
- net_raw
command: [postgres, -c, max_connections=200] #设置 postgres 的最大连接数
redis:
container_name: safeline-redis
restart: always
image: redis:7.0.10
volumes:
- ${SAFELINE_DIR}/resources/redis/data:/data
- /etc/localtime:/etc/localtime:ro
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.3
cap_drop:
- net_raw
sysctls:
net.core.somaxconn: "511" # 设置内核参数
management:
container_name: safeline-mgt-api
restart: always
image: chaitin/safeline-mgt-api:${IMAGE_TAG:?image tag required}
volumes:
- ${SAFELINE_DIR?safeline dir required}/resources/management:/resources/management
- ${SAFELINE_DIR}/resources/nginx:/resources/nginx
- ${SAFELINE_DIR}/logs:/logs
- /etc/localtime:/etc/localtime:ro
ports: # 将容器内部端口映射到宿主机上的端口
- ${MGT_PORT:-9443}:1443 # 使用环境变量$MGT_PORT的值作为宿主机的端口,如果`MGT_PORT`未设置或为空,则默认使用9443
environment:
- MANAGEMENT_RESOURCES_DIR=/resources/management
- NGINX_RESOURCES_DIR=/resources/nginx
- DATABASE_URL=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-postgres/safeline-ce
- MARIO_URL=http://safeline-mario:3335
- DETECTOR_URL=http://safeline-detector:8001
- REDIS_URL=redis://:${REDIS_PASSWORD}@safeline-redis:6379/0
- MANAGEMENT_LOGS_DIR=/logs/management
dns: # 设置DNS地址
- 119.29.29.29
- 223.5.5.5
- 180.76.76.76
- 1.2.4.8
- 114.114.114.114
- 8.8.8.8
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.4
cap_drop:
- net_raw
detector:
container_name: safeline-detector
restart: always
image: chaitin/safeline-detector:${IMAGE_TAG}
volumes:
- ${SAFELINE_DIR}/resources/detector:/resources/detector
- ${SAFELINE_DIR}/logs/detector:/logs/detector
- /etc/localtime:/etc/localtime:ro
environment:
- LOG_DIR=/logs/detector
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.5
cap_drop:
- net_raw
mario:
container_name: safeline-mario
restart: always
image: chaitin/safeline-mario:${IMAGE_TAG}
volumes:
- ${SAFELINE_DIR}/resources/mario:/resources/mario
- ${SAFELINE_DIR}/logs/mario:/logs/mario
- /etc/localtime:/etc/localtime:ro
environment:
- LOG_DIR=/logs/mario
- GOGC=100
- DATABASE_URL=postgres://safeline-ce:${POSTGRES_PASSWORD}@safeline-postgres/safeline-ce
- REDIS_URL=redis://:${REDIS_PASSWORD}@safeline-redis:6379/0
networks:
safeline-ce:
ipv4_address: ${SUBNET_PREFIX}.6
cap_drop:
- net_raw
tengine:
container_name: safeline-tengine
restart: always
image: chaitin/safeline-tengine:${IMAGE_TAG}
volumes:
- ${SAFELINE_DIR}/resources/nginx:/etc/nginx
- ${SAFELINE_DIR}/resources/management:/resources/management
- ${SAFELINE_DIR}/resources/detector:/resources/detector
- ${SAFELINE_DIR}/logs/nginx:/var/log/nginx
- /etc/localtime:/etc/localtime:ro
- ${SAFELINE_DIR}/resources/cache:/usr/local/nginx/cache
- /etc/resolv.conf:/etc/resolv.conf
environment:
- REDIS_URL=redis://:${REDIS_PASSWORD}@${SUBNET_PREFIX}.3:6379/0
- MGT_ADDR=${SUBNET_PREFIX}.4:9002 #配置 mgt-api 的 grpc 服务器地址,用于与 mgt-api 容器通信
ulimits:
nofile: 131072
network_mode: host #Tengine 直接使用宿主机网络 ```
执行以下命令,生成雷池运行所需的相关环境变量
```shell
echo "SAFELINE_DIR=$(pwd)" >> .env # 设置当前路径为雷池社区版本的根路径
echo "IMAGE_TAG=latest" >> .env # 设置镜像的tag
echo "MGT_PORT=9443" >> .env # 管理容器服务使用的端口
echo "POSTGRES_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 > .env
# /dev/urandom是一个很长的随机数文本,tr -dc命令用于删除非字母,非数字的字符,用于生成随机的postgres密码
echo "REDIS_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 > .env
# 同上,用于生成随机的reis密码
echo "SUBNET_PREFIX=172.22.222" >> .env
# 定义docker 虚拟网卡的子网前缀
执行以下命令启动雷池
docker compose up -d
1.容器介绍
名称 | 定义 | 详情 |
---|---|---|
safeline-mgt-api | 管理容器 | 接收管理后台行为,向其他服务或容器推送消息 |
safeline-detector | 检测容器 | 执行检测的容器,从 Tengine 进入的流量会转发到该节点检测 |
safeline-mario | 日志容器 | 记录与统计恶意行为的节点 |
safeline-tengine | 网关 | 转发网关,有简单的过滤功能 |
safeline-postgres | 关系型数据库 | 存储攻击日志、保护站点、黑白名单配置的数据库 |
safeline-redis | 缓存数据库 | - |
2.容器间的通信如下
对于后台管理人员(admin),可以与safeline-mgt-api
直接通信,从而管理服务.该节点负责
safeline-detector
推送postgres
数据库,向后台管理员返回日志,统计和当前配置等而safeline-detector
引擎会将safeline-mgt-api
节点中定好的规则进行接收
对于用户(User),访问目标域名(解析到waf的IP和端口上,反向代理到服务器),请求会达到safeline-tengine
中进行简单的过滤,然后将请求转到safeline-detector
上进行日志检测,查看是否符合条件.如果通过限制,就会将请求转到后端服务器上,然后接收响应返回给用户.如果不符合条件,就会将日志输送给safeline-mario
,记录与统计恶意行为的节点
浏览器打开后台管理页面 https://
。根据界面提示,使用 支持 TOTP 的认证软件或者小程序 扫描二维码,然后输入动态口令登录:
提供一台独立设备部署雷池
`实验环境:
192.168.65.8 --- www.waf.ct
192.168.65.4 --- www.server.ct
`编辑雷池端Nginx配置文件
upstream backend_monitor_servers {
server 192.168.65.4:80;
}
server{
listen 81;
server_name www.waf.ct;
location / {
limit_req zone=five burst=10;
proxy_pass http://backend_monitor_servers ;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Host $host;
add_header Strict-Transport-Security "max-age=31536000";
}
access_log /data/log/nginx/access.log;
error_log /data/log/nginx/error.log;
}
攻击测试:
curl -v "http://www.waf.ct?id=1'union select * from dps"
如果是有域名且具备SSL证书的情况下
不推荐这样部署,这样部署单机负载更高,设备宕机概率更大.非纯净环境下还会提高安装失败的概率,故障排查比较困难
如果能接受这些风险,雷池也可以直接部署在网站服务器上。你需要:
例如:
`1.网站登录服务监听端口为8080
`2.修改Waf监听端口
# 其中端口为Waf开启的端口,默认为80和443
# 上游服务器为要守护的域名
`测试:
在客户端执行命令:curl -H "Host: <域名>" http://<雷池 IP>:<雷池监听端口>
root@WAF:~# curl -H "HOST:192.168.65.8" http://192.168.65.8:80
# 若能获取到业务网站的响应,并且站点上 “今日访问量” 增加,则代表配置成功
雷池作为反代设备,可以在任意位置接入主链路。只要将接入位置的流量指向雷池,并在雷池的 “上游服务器” 处填写请求的下一跳服务器地址即可。例如:
如果按照上文指引部署雷池、配置了站点,但网站仍无法访问,建议按照以下步骤排查:
明确 “网站无法访问” 的具体表现:
如果 502 Bad Gateway tengine
:
大概率是是雷池的上游服务器配置不正确,或者雷池无法访问到上游服务器。请继续按下面步骤排查,重点排查步骤 6、7
如果请求能够返回但是十分缓慢
首先确认服务器负载是否正常
在客户端执行命令,检查雷池服务器与上游服务器的网络:
curl -H "Host: " -vv -o /dev/null -s -w 'time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n' http://<上游服务器地址>
如果不是以上情况,继续下一步
在客户端执行 curl -H "Host: <域名>" http://<雷池 IP>:<雷池监听端口>
。正常情况下,应能获取到业务网站的响应,并且站点的 “今日访问量” +1
http(s)://<雷池 IP>
,恰好业务服务上有 Host 验证,所以拒绝了该请求。这种情况需要修改本机 host,把域名解析到雷池 IP,再访问 http(s)://<域名>
,才能准确测试在雷池设备上执行 curl -H "Host: <域名>" http://<雷池 IP>:<雷池监听端口>
。正常情况下,应能获取到业务网站的响应,并且站点上 “今日访问量” +1
在雷池设备上执行 curl -H "Host: <域名>" http://127.0.0.1:<雷池监听端口>
。正常情况下,应能获取到业务网站的响应,并且站点的 “今日访问量” +1
telnet <雷池 IP> <雷池监听端口>
返回 Unable to connect to remote host: Connection refused
,大概率是被雷池设备上的防火墙拦截了。可能是操作系统本身的防火墙,还有可能是云服务商的防火墙。请根据实际情况逐项排查,开放雷池监听端口的访问在雷池设备上执行 netstat -anp | grep <雷池监听端口>
确认端口监听情况。正常情况下,应该有一个 nginx 进程监听在 0.0.0.0:<雷池监听端口>
。没有的话请通过社群或者 Github issue 提交反馈,附上排查过程。有的话继续下一步
在雷池设备上 curl -H "Host: <域名>" <上游服务器地址>
。正常情况下,应能获取到业务网站的响应
# 最强的防护会将Request和Urlib等请求判定为扫描器会进行拦截
``这是用Python的threading模块进行cc攻击测试就会将IP进行直接封禁
黑名单可以根据 源IP
,路径
,Host
,Header
,Body
五种匹配目标进行匹配,以下是每种匹配目标的匹配方式
`1.配置黑名单为Header 正则匹配
curl -A "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36" www.waf.ct
docker exec -it <container_name> /bin/bash
`Nginx配置生成的文件在:
docker exec -it safeline-tengine /bin/bash
/etc/nginx/sites-enabled/IF-backend* #每配置一个保护站点就会生成一个这样的文件
/etc/nginx/sites-enabled/generated #心跳,健康检查配置
/root/nginx/nginx.conf #与上述两个文件共同构成了 Tengine 的配置
`Nginx的配置文件在:
/etc/nginx
`Nginx的日志文件默认生成在/var/log/nginx ,且默认不生成access.log日志
docker exec -it safeline-mgt-api /bin/bash
#进入容器后
cat /logs/management/nginx.log
cat /logs/management/webserver.log
# 直接docker命令访问mgt日志
docker logs -f safeline-mgt-api
root@WAF:/data# cd safeline/
root@WAF:/data/safeline# tree logs
logs
├── detector
│ └── snserver.log #检测容器的输出日志
├── management
│ ├── nginx.log # Tengine 容器中 nginx 日志输出
│ └── webserver.log # safeline-mgt-api 容器的日志输出
├── mario
│ └── mario.log # 流量日志输出
└── nginx
├── access.log # nginx 的访问日志
├── error.log # nginx 的错误日志
└── tcd.log # tcd 是 Tengine 用于与 safeline-mgt-api 通信的网络代理进程,该文件存储了两者的通信日志