起因
一直在用nps做内网转发,各个web端口管理比较乱也比较难记,没有一点安全措施。凑着阿里云的活动整了个域名,用子域名统一下入口接入雷池waf,非web类的用IPS处理下。
由于没有一个类似雷池的免费带web管理的成品IPS,只能用Snort或Suricata来自己整了。考虑弱鸡cpu,用Suricata来做IPS也许会好点。
翻遍全网都是拿来跑数据包的,没有一个可用的IPS配置,chatgpt领歪十万八千里,全靠浏览器翻译官网文档整了出来。记录下来作为一个敲门砖,也作为博客的第一篇文章。
安装
内网环境
一张带俩网卡的主板,跑着众多虚拟机。由于宽带没公网IPv4,IPv4流量由vps内网穿透转到内网;IPv6可以直连内网。
IPS实现方式
Suricata配置一个直通物理网卡和两个虚拟网卡,一个虚拟网卡负责ssh管理(可能的web管理)和规则更新。物理网卡和另一个一个虚拟网卡负责建立透明网桥,iptables将经过网桥流量转发到NFQUEUE队列交由Suricata处理。
Suricata安装
Ubuntu可以直接apt install suricata
安装,安装完成后先systemctl stop suricata.service
和systemctl disable suricata.service
先停掉suricata的服务,以防万一配置错误还有的救(这个等下再说 TAT全是泪)。
配置
系统层面
使用以下配置,经Suricata处理流量的设备是无法访问安装Suricata的机器中的docker的(仅限非host模式,需要写路由,不会!)。
modprobe br_netfilter #加载内核网桥转发
echo "br_netfilter" > /etc/modules-load.d/br_netfilter.conf #内核网桥转发持久化
sysctl -w net.bridge.bridge-nf-call-iptables=1 #开启内核网桥转发
echo "net.bridge.bridge-nf-call-iptables=1" > /etc/sysctl.d/99-bridge.conf
sysctl --system #开启内核网桥转发持久化
ip link set dev enp6s19 promisc on
ip link set dev enp6s16 promisc on
ip link add name br0 type bridge
ip link set enp6s19 master br0
ip link set enp6s16 master br0
ip link set br0 up
ip link set dev br0 down
#添加网桥,把入口网卡和隔离区网卡添加到网桥,不要给网桥和这两个网卡配置任何ip
iptables -I FORWARD -o br0 -j NFQUEUE --queue-num 0
iptables -I FORWARD -i br0 -j NFQUEUE --queue-num 0
#网桥流量转发到NFQUEUE队列,队列id 0
Suricata配置
先贴一下配置文件/etc/suricata/suricata.yaml
:
%YAML 1.1
---
# ============================================
# Suricata 7.0.10 优化版配置 - IPS模式 (NFQUEUE队列 双网卡桥接)
# 规则路径:/var/lib/suricata/rules
# ============================================
runmode: workers
runmode-threads: 4 #线程配置
vars:
address-groups: #地址分组
HOME_NET: "[192.168.0.0/16,10.0.0.0/8,172.0.0.0/8,127.0.0.0/8]"
EXTERNAL_NET: "!$HOME_NET"
HTTP_SERVERS: "$HOME_NET"
SMTP_SERVERS: "$HOME_NET"
SQL_SERVERS: "$HOME_NET"
DNS_SERVERS: "$HOME_NET"
TELNET_SERVERS: "$HOME_NET"
AIM_SERVERS: "$EXTERNAL_NET"
DC_SERVERS: "$HOME_NET"
DNP3_SERVER: "$HOME_NET"
DNP3_CLIENT: "$HOME_NET"
MODBUS_CLIENT: "$HOME_NET"
MODBUS_SERVER: "$HOME_NET"
ENIP_CLIENT: "$HOME_NET"
ENIP_SERVER: "$HOME_NET"
port-groups:
HTTP_PORTS: "80,5000,8000,25500,8096"
HTTPS_PORTS: "443,8443,8006"
SHELLCODE_PORTS: "!80"
ORACLE_PORTS: 1521
SSH_PORTS: "22,222,2222,22222"
DNP3_PORTS: 20000
MODBUS_PORTS: 502
FILE_DATA_PORTS: "[$HTTP_PORTS,110,143]"
FTP_PORTS: 21
GENEVE_PORTS: 6081
VXLAN_PORTS: 4789
TEREDO_PORTS: 3544
default-rule-path: /var/lib/suricata/rules
rule-files:
- "*.rules" # 可匹配所有规则文件
##############↓重点区域↓##############
nfq:
mode: accept #表示 Suricata 接受 NFQUEUE 中的包,由Suricata判断是否丢弃,drop 丢弃所有
fail-open: yes #当Suricata崩溃时放行所有包
queue: 0 #NFQUEUE队列id
batchcount: 20 #每次处理包个数,根据系统负载可以调整
copy-mode: packet #Suricata处理所有包数据,metadata仅五元组
copy-range: 0 #packet的配置,0表示处理全部数据长度
##############↑重点区域↑##############
detect-engine: #性能配置
- profile: medium
custom-values:
toclient-groups: 3
toserver-groups: 25
sgh-mpm-context: auto
inspection-recursion-limit: 3000
outputs:
- fast: #告警输出
enabled: yes
filename: /var/log/suricata/fast.log
- eve-log: #日志内容配置
enabled: yes
filetype: regular
filename: /var/log/suricata/eve.json
types:
- alert:
payload: yes
metadata: yes
tags: yes
#- dns:
#query: yes
#answer: yes
- ssh
- http
- anomaly
#- stats:
# totals: yes
# threads: no
- drop:
alerts: yes # 是否包含与drop相关的alert(建议开启)
flows: start
logging:
default-log-level: info
outputs:
- file:
enabled: yes
filename: /var/log/suricata/suricata.log
stats: #状态信息,包含当前处理包数量
enabled: yes
interval: 10 # 每10秒输出一次统计信息
app-layer: #协议识别
protocols:
tls:
enabled: yes
http:
enabled: yes
dns:
enabled: yes
smtp:
enabled: yes
ssh:
enabled: yes
ftp:
enabled: yes
stream:
memcap: 128mb
checksum-validation: yes
reassembly:
memcap: 512mb
depth: 1mb
toserver-chunk-size: 2560
toclient-chunk-size: 2560
midstream: true
prealloc-sessions: 20480
inline: auto
host-mode: auto
unix-command:
enabled: yes # 启用 suricatasc 命令接口
filename: /var/run/suricata-command.socket
运行
添加一条测试的规则,运行suricata
echo 'alert icmp any any -> any any (msg:"ICMP Detected"; sid:1000001; rev:1;)' >> /var/lib/suricata/rules/local.rules
suricata -c /etc/suricata/suricata.yaml -q 0
ping下隔离区主机验证下:
ping 192.168.31.x
如果配置没问题,ping不通且web、ssh等可以正常访问,能在/var/log/suricata/fast.log
看到告警信息:
[**] [1:1000001:1] ICMP Detected [**] [Classification: (null)] [Priority: 3] {ICMP} 192.168.31.14:8 -> 192.168.31.x:0
规则
贴上几个吧:
https://xz.aliyun.com/spa/#/news/13362
https://github.com/al0ne/suricata-rules
没搞明白的
上述配利用的是iptables的NFQUEUE队列,将网桥流量转交suricata处理,在官网还有另一种方式,由suricata直接替代网桥连接两个网卡。
逻辑是:网卡1的流量suricata处理后转发到网卡2,网卡2的流量suricata处理后转发到网卡1
配置如下:
af-packet:
- interface: enp6s16
threads: auto
cluster-id: 99
cluster-type: cluster_flow
copy-mode: tap
copy-iface: enp6s19
defrag: yes
use-mmap: yes
tpacket-v3: yes
buffer-size: 65535
block-size: 262144
block-timeout: 1000
use-emergency-flush: yes
bypass: yes
- interface: enp6s19
threads: auto
cluster-id: 100
cluster-type: cluster_flow
copy-mode: tap
copy-iface: enp6s16
defrag: yes
use-mmap: yes
tpacket-v3: yes
buffer-size: 65535
block-size: 262144
block-timeout: 1000
use-emergency-flush: yes
bypass: yes
小问题:
- 网络风暴:两个网卡相互转发会把网卡1转到网卡2的数据原封不动的转到网卡1上。每次转发到网卡2对应的隔离区,服务器都会返回新的syn-ack,导致俩网卡间数据指数级增长,直接内网崩掉,谁都出不了外网。
- 在路由器能看到客户端的syn、隔离区的syn-ack,就是没有客户端的ack
有没有大佬给解释下啊!
暂无评论 IP地址位置数据由 纯真CZ88 提供支持