• 开源WAF--Safeline(雷池)测试手册


    长亭科技—雷池(SafeLine)社区版

    在这里插入图片描述

    官方网站:长亭雷池 WAF 社区版 (chaitin.cn)

    WAF 工作在应用层,对基于 HTTP/HTTPS 协议的 Web 系统有着更好的防护效果,使其免于受到黑客的攻击

    在这里插入图片描述

    1.1 雷池的搭建

    1.1.1 配置需求
    • 操作系统:Linux

    • 指令架构:x86_64

      `查询命令:
      uname -m 
      
      • 1
      • 2
    • 软件依赖:Docker 20.10.14 版本以上

      `查询命令:
      docker --version 
      
      • 1
      • 2
    • 软件依赖:Docker Compose 2.0.0 版本以上

      `查询命令:
      docker-compose version
      
      • 1
      • 2
    • 最小化环境:1 核 CPU / 1 GB 内存 / 5 GB 磁盘

      `查询命令:
      cat /proc/cpuinfo        # 查看 CPU 信息
      cat /proc/meminfo        # 查看内存信息
      df -h                    # 查看磁盘信息
      
      • 1
      • 2
      • 3
      • 4
    1.1.2 安装方式
    1. 在线安装

      bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release/latest/setup.sh)"
      
      • 1

    在这里插入图片描述

    1. 离线安装

      如果你的服务器无法连接互联网环境,或连接 Docker Hub 网络不稳,可以使用镜像包安装方式

      这里忽略 Docker 安装的过程

      首先,下载 雷池社区版镜像包 并传输到需要安装雷池的服务器上,执行以下命令加载镜像

      cat image.tar.gz | gzip -d | docker load
      
      • 1

      执行以下命令创建并进入雷池安装目录

      mkdir -p safeline        # 创建 safeline 目录
      cd safeline              # 进入 safeline 目录
      
      • 1
      • 2

      下载 编排脚本 并传输到 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 虚拟网卡的子网前缀
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100
      • 101
      • 102
      • 103
      • 104
      • 105
      • 106
      • 107
      • 108
      • 109
      • 110
      • 111
      • 112
      • 113
      • 114
      • 115
      • 116
      • 117
      • 118
      • 119
      • 120
      • 121
      • 122
      • 123
      • 124
      • 125
      • 126
      • 127
      • 128
      • 129
      • 130
      • 131
      • 132
      • 133
      • 134
      • 135
      • 136
      • 137
      • 138
      • 139
      • 140
      • 141
      • 142

      执行以下命令启动雷池

      docker compose up -d 
      
      • 1
    1.1.3 雷池结构和启动配置

    1.容器介绍

    名称定义详情
    safeline-mgt-api管理容器接收管理后台行为,向其他服务或容器推送消息
    safeline-detector检测容器执行检测的容器,从 Tengine 进入的流量会转发到该节点检测
    safeline-mario日志容器记录与统计恶意行为的节点
    safeline-tengine网关转发网关,有简单的过滤功能
    safeline-postgres关系型数据库存储攻击日志、保护站点、黑白名单配置的数据库
    safeline-redis缓存数据库-

    2.容器间的通信如下

    在这里插入图片描述

    对于后台管理人员(admin),可以与safeline-mgt-api直接通信,从而管理服务.该节点负责

    1. 向Tengine网关容器推送自定义配置并利用Nginx命令进行热部署
    2. 自定义检测规则(黑名单等)并向检测引擎safeline-detector推送
    3. 直接读取postgres数据库,向后台管理员返回日志,统计和当前配置等

    safeline-detector引擎会将safeline-mgt-api节点中定好的规则进行接收

    对于用户(User),访问目标域名(解析到waf的IP和端口上,反向代理到服务器),请求会达到safeline-tengine中进行简单的过滤,然后将请求转到safeline-detector上进行日志检测,查看是否符合条件.如果通过限制,就会将请求转到后端服务器上,然后接收响应返回给用户.如果不符合条件,就会将日志输送给safeline-mario,记录与统计恶意行为的节点

    在这里插入图片描述

    1.2 雷池的使用

    1.2.1 雷池的登录

    在这里插入图片描述

    ​ 浏览器打开后台管理页面 https://:9443。根据界面提示,使用 支持 TOTP 的认证软件或者小程序 扫描二维码,然后输入动态口令登录:

    在这里插入图片描述

    在这里插入图片描述

    1.2.2 雷池配置的两种方式
    1.在单独设备上部署雷池

    提供一台独立设备部署雷池

    1. 将网站所有流量指向雷池.例如将域名解析到雷池
    2. 禁止网站服务器上,除了雷池之外的访问,例如配置防火墙或者将网站服务器放置内网

    在这里插入图片描述

    `实验环境:
    192.168.65.8  --- www.waf.ct
    192.168.65.4  --- www.server.ct
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    `编辑雷池端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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    攻击测试:
    curl -v "http://www.waf.ct?id=1'union select * from dps"
    
    • 1
    • 2

    在这里插入图片描述

    在这里插入图片描述

    如果是有域名且具备SSL证书的情况下

    在这里插入图片描述

    2.直接在网站服务器上部署雷池

    不推荐这样部署,这样部署单机负载更高,设备宕机概率更大.非纯净环境下还会提高安装失败的概率,故障排查比较困难

    如果能接受这些风险,雷池也可以直接部署在网站服务器上。你需要:

    1. 将原本监听 80 或 443/ssl 端口的网站服务改到其他端口,让雷池监听设备的 80 或 443/ssl 端口
    2. 使网站服务仅允许本机访问。例如配置系统防火墙、Iptables

    在这里插入图片描述

    例如:

    `1.网站登录服务监听端口为8080
    
    • 1

    在这里插入图片描述

    `2.修改Waf监听端口
    # 其中端口为Waf开启的端口,默认为80和443
    # 上游服务器为要守护的域名
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    `测试:
    在客户端执行命令:curl -H "Host: <域名>" http://<雷池 IP>:<雷池监听端口> 
    root@WAF:~# curl -H "HOST:192.168.65.8" http://192.168.65.8:80 
    # 若能获取到业务网站的响应,并且站点上 “今日访问量” 增加,则代表配置成功
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    3.和其他反向代理设备一起部署

    ​ 雷池作为反代设备,可以在任意位置接入主链路。只要将接入位置的流量指向雷池,并在雷池的 “上游服务器” 处填写请求的下一跳服务器地址即可。例如:

    在这里插入图片描述

    4.配置后网站无法访问

    如果按照上文指引部署雷池、配置了站点,但网站仍无法访问,建议按照以下步骤排查:

    1. 明确 “网站无法访问” 的具体表现:

      • 如果 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://<上游服务器地址>
          
          • 1
          • 如果 time_namelookup 时间过大,请检查 dns server 配置
          • 如果 time_connect 时间过大,请检查雷池与上游服务器之间的网络状态
          • 如果 time_starttransfer 时间过大,请检查上游服务器状态,是否出现资源过载情况
      • 如果不是以上情况,继续下一步

    2. 在客户端执行 curl -H "Host: <域名>" http://<雷池 IP>:<雷池监听端口> 。正常情况下,应能获取到业务网站的响应,并且站点的 “今日访问量” +1

      • 如果浏览器无法访问,但这一步正常获取到响应,大概率是因为:
        • 测试过程中,网站域名还没有切到雷池,浏览器测试时访问的是 http(s)://<雷池 IP>,恰好业务服务上有 Host 验证,所以拒绝了该请求。这种情况需要修改本机 host,把域名解析到雷池 IP,再访问 http(s)://<域名>,才能准确测试
        • 网站业务做了其他一些特殊处理。例如访问后 301 跳转到了其他地址,需要具体排查网站业务的响应内容
      • 如果不能获取到响应,继续下一步
    3. 在雷池设备上执行 curl -H "Host: <域名>" http://<雷池 IP>:<雷池监听端口>。正常情况下,应能获取到业务网站的响应,并且站点上 “今日访问量” +1

      • 如果步骤 2 失败而这里成功,说明客户端到雷池之间的网络存在问题。请排查网络,保证客户端可访问到雷池
      • 如果不能获取到响应,继续下一步
    4. 在雷池设备上执行 curl -H "Host: <域名>" http://127.0.0.1:<雷池监听端口>。正常情况下,应能获取到业务网站的响应,并且站点的 “今日访问量” +1

      • 如果步骤 3 失败而这里成功,且 telnet <雷池 IP> <雷池监听端口> 返回 Unable to connect to remote host: Connection refused,大概率是被雷池设备上的防火墙拦截了。可能是操作系统本身的防火墙,还有可能是云服务商的防火墙。请根据实际情况逐项排查,开放雷池监听端口的访问
      • 如果不能获取到响应,继续下一步
    5. 在雷池设备上执行 netstat -anp | grep <雷池监听端口> 确认端口监听情况。正常情况下,应该有一个 nginx 进程监听在 0.0.0.0:<雷池监听端口>。没有的话请通过社群或者 Github issue 提交反馈,附上排查过程。有的话继续下一步

    6. 在雷池设备上 curl -H "Host: <域名>" <上游服务器地址>。正常情况下,应能获取到业务网站的响应

      • 如果步骤 4 失败而这里成功,请通过社群或者 Github issue 提交反馈,附上排查过程
      • 如果这步失败,说明雷池和上游服务器之间的网络存在问题。请排查网络,确保雷池可以访问到上游服务器

    1.3 雷池的防护规则

    # 最强的防护会将Request和Urlib等请求判定为扫描器会进行拦截
    
    • 1

    在这里插入图片描述

    在这里插入图片描述

    ``这是用Python的threading模块进行cc攻击测试就会将IP进行直接封禁
    
    • 1

    1.4 配置黑名单

    在这里插入图片描述

    黑名单可以根据 源IP路径HostHeaderBody 五种匹配目标进行匹配,以下是每种匹配目标的匹配方式

    在这里插入图片描述

    `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
    
    • 1
    • 2

    在这里插入图片描述

    在这里插入图片描述

    1.n 可能会用到的配置

    1.n.1 进入某一容器
    docker exec -it <container_name> /bin/bash
    
    • 1
    1.n.2 生成的Nginx配置
    `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日志
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1.n.3 查看mgt-api的日志
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1.n.4 分析safeline下面的日志文件
    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 通信的网络代理进程,该文件存储了两者的通信日志
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    如何部署本地dockers镜像源
    2010年11月10日 Go生态洞察:回顾Go语言的一年发展
    Dubbo API 笔记——Dubbo协议&最佳实践
    【Hello Algorithm】二叉树的递归套路
    力扣 430. 扁平化多级双向链表
    深入理解Docker之:存储卷相关概念详解和分析
    k8s--基础--6.2--环境搭建--单master高可用集群
    计算机组成原理之初识计算机硬件,帮你拆开电脑看看里面的组成!!!
    【Linux私房菜】第七期——尾声
    【计算思维】蓝桥杯STEMA 科技素养考试真题及解析 4
  • 原文地址:https://blog.csdn.net/m0_60981735/article/details/133963298