安装 Suricata

OS: Ubuntu 18.04.2 LTS

可以源码安装、二进制安装、从源安装,为了方便选择从源安装

sudo add-apt-repository ppa:oisf/suricata-stable # 添加 suricata PPA源
sudo apt-get update # 更新源
sudo apt-get install suricata # 安装 suricata

安装完后 dpkg 查看 suricata

➜  ~ dpkg -L suricata | grep -v 'doc\|log\|python' | xargs file | grep -v directory
/etc/default/suricata:                      ASCII text
/etc/init.d/suricata:                       POSIX shell script, ASCII text executable
/etc/suricata/classification.config:        ASCII text
/etc/suricata/reference.config:             ASCII text
/etc/suricata/rules/app-layer-events.rules: ASCII text
/etc/suricata/rules/decoder-events.rules:   ASCII text
/etc/suricata/rules/dnp3-events.rules:      ASCII text
/etc/suricata/rules/dns-events.rules:       ASCII text
/etc/suricata/rules/files.rules:            ASCII text
/etc/suricata/rules/http-events.rules:      ASCII text
/etc/suricata/rules/ipsec-events.rules:     ASCII text
/etc/suricata/rules/kerberos-events.rules:  ASCII text
/etc/suricata/rules/modbus-events.rules:    ASCII text
/etc/suricata/rules/nfs-events.rules:       ASCII text
/etc/suricata/rules/ntp-events.rules:       ASCII text
/etc/suricata/rules/smb-events.rules:       ASCII text
/etc/suricata/rules/smtp-events.rules:      ASCII text
/etc/suricata/rules/stream-events.rules:    ASCII text
/etc/suricata/rules/tls-events.rules:       ASCII text, with very long lines
/etc/suricata/suricata.yaml:                ASCII text
/etc/suricata/threshold.config:             ASCII text
/usr/bin/suricata:                          ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=09bf1a65bedfe2a69d3fa39cd8d0cd5852d43ddc, stripped
/usr/bin/suricata-update:                   a /usr/bin/python script, ASCII text executable
/usr/bin/suricatactl:                       a /usr/bin/python script, ASCII text executable
/usr/bin/suricatasc:                        a /usr/bin/python script, ASCII text executable
/usr/share/man/man1/suricata.1.gz:          gzip compressed data, max compression, from Unix

可以看到配置文件在 /etc/suricata/suricata.yaml

配置 Suricata

编辑 /etc/suricata/suricata.yaml 文件:

修改 vars.address-groupsHOME_NET 值为 本机 IP 地址

例如

➜  ~ ifconfig eth0 | grep inet\ 
        inet 172.16.1.180  netmask 255.255.255.0  broadcast 172.16.1.255
➜  ~ grep -v '#' /etc/suricata/suricata.yaml | grep . | head -n 10
%YAML 1.1
---
vars:
  address-groups:
    HOME_NET: "[172.16.1.180]"
    EXTERNAL_NET: "!$HOME_NET"
    HTTP_SERVERS: "$HOME_NET"
    SMTP_SERVERS: "$HOME_NET"
    SQL_SERVERS: "$HOME_NET"
    DNS_SERVERS: "$HOME_NET"

然后在修改以下属性的值:

default-rule-path: /etc/suricata/rules

rule-files:
 - test.rules

搭建测试环境

为了模拟真实的存在 IDS 的环境,使用 iptables 把安装了 Suricata 的 Ubuntu 系统配置为网关

第一步修改 /etc/sysctl.conf 文件

sudo vim /etc/sysctl.conf

启用 IPv4 流量转发

net.ipv4.ip_forward=1

启用配置

sudo sysctl -p 

配置 iptables 规则

sudo iptables -P FORWARD ACCEPT
sudo iptables --table nat -A POSTROUTING -o eth0 -j MASQUERADE

这时该 Ubuntu 系统成为了一个网关,能转发 eth0 interface 上的流量

我们需要配置另外一台 Ubuntu 系统的的网关为该系统

➜  ~ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.16.1.2      0.0.0.0         UG    100    0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eth0
172.16.1.0      0.0.0.0         255.255.255.0   U     100    0        0 eth0
➜  ~ sudo route add default gw 172.16.1.180
➜  ~ sudo route delete default gw 172.16.1.2
➜  ~ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.16.1.180    0.0.0.0         UG    0      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eth0
172.16.1.0      0.0.0.0         255.255.255.0   U     100    0        0 eth0

测试是否生效

➜  ~ 
➜  ~ traceroute baidu.com 
traceroute to baidu.com (123.125.114.144), 30 hops max, 60 byte packets
 1  _gateway (172.16.1.180)  1.316 ms  1.231 ms  1.168 ms
 2  172.16.1.2 (172.16.1.2)  1.085 ms  0.995 ms  0.934 ms
 3  * * *
 4  * * *
 5  * * *
 6  * * *
 7  * * *
 8  * * *
 9  * * *
10  * * *
11  * * *

...

此时的网络环境为

---------       -----------------------------       -----
Internet| <---> | Suricata IDS: 172.16.1.180|  <--> |LAN|
---------       -----------------------------       -----

编写 Suricata 规则

编辑 /etc/suricata/rules/test.rules 文件为以下内容

alert icmp any any -> any any (msg:"ICMP connection attempt"; sid:1000002; rev:1;) 
alert tcp any any -> any 23 (msg:"TELNET connection attempt"; sid:1000003; rev:1;)

现在是时候让 Suricata 跑起来了,但在这之前还有一个步骤需要去完成

当你使用 pcap 捕获模式的时候,强烈建议关闭 Suricata 监听网卡上的任何的包卸载(例如 LRO/GRO)功能,这些功能会干扰包的实时捕获行为

按照以下方法关闭 eth0 接口的 LRO/GRO 功能

sudo ethtool -K eth0 gro off lro off

这里要注意,在使用某些网卡的情况下,你会看到如下警告信息

Cannot change large-receive-offload

忽略它们就行了,这些信息只不过告诉你你的网卡不支持 LRO 功能而已

然后运行 suricata

➜  ~ sudo suricata -c /etc/suricata/suricata.yaml -i eth0 --init-errors-fatal -v
30/5/2019 -- 14:24:56 - <Notice> - This is Suricata version 4.1.4 RELEASE
30/5/2019 -- 14:24:56 - <Info> - CPUs/cores online: 1
30/5/2019 -- 14:24:56 - <Info> - fast output device (regular) initialized: fast.log
30/5/2019 -- 14:24:56 - <Info> - eve-log output device (regular) initialized: eve.json
30/5/2019 -- 14:24:56 - <Info> - stats output device (regular) initialized: stats.log
30/5/2019 -- 14:24:56 - <Info> - Running in live mode, activating unix socket
30/5/2019 -- 14:24:56 - <Info> - 1 rule files processed. 2 rules successfully loaded, 0 rules failed
30/5/2019 -- 14:24:56 - <Info> - Threshold config parsed: 0 rule(s) found
30/5/2019 -- 14:24:56 - <Info> - 2 signatures processed. 2 are IP-only rules, 0 are inspecting packet payload, 0 inspect application layer, 0 are decoder event only
30/5/2019 -- 14:24:56 - <Info> - Going to use 1 thread(s)
30/5/2019 -- 14:24:56 - <Info> - Running in live mode, activating unix socket
30/5/2019 -- 14:24:56 - <Info> - Using unix socket file '/var/run/suricata/suricata-command.socket'
30/5/2019 -- 14:24:56 - <Notice> - all 1 packet processing threads, 4 management threads initialized, engine started.
30/5/2019 -- 14:24:56 - <Info> - All AFP capture threads are running.

从日志中可以看到已加载 1 条规则

在另外一个 Ubuntu 系统中 ping baidu.com

➜  ~ ping -c 3 baidu.com
PING baidu.com (220.181.57.216) 56(84) bytes of data.
64 bytes from 220.181.57.216 (220.181.57.216): icmp_seq=1 ttl=127 time=69.0 ms
64 bytes from 220.181.57.216 (220.181.57.216): icmp_seq=2 ttl=127 time=74.8 ms
64 bytes from 220.181.57.216 (220.181.57.216): icmp_seq=3 ttl=127 time=71.7 ms

--- baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2304ms
rtt min/avg/max/mdev = 69.051/71.896/74.841/2.364 ms
➜  ~ 

这时查看 suricata 的日志

开启另一个 Terminal

查看日志文件

➜  ~ tail -f /var/log/suricata/fast.log
05/30/2019-15:21:42.636988  [**] [1:1000002:1] ICMP connection attempt [**] [Classification: (null)] [Priority: 3] {ICMP} 220.181.57.216:0 -> 172.16.1.180:8
05/30/2019-15:21:42.636985  [**] [1:1000002:1] ICMP connection attempt [**] [Classification: (null)] [Priority: 3] {ICMP} 220.181.57.216:0 -> 172.16.1.180:8

编写的规则成功检测获到 ping 的 ICMP 请求

这时在随便找一个开放23端口的主机 TELNET 一下

➜  ~ telnet 125.76.238.80
Trying 125.76.238.80...
Connected to 125.76.238.80.
Escape character is '^]'.


User Access Verification

Password: 
Password: 
Password: 
% Bad passwords
Connection closed by foreign host.
➜  ~ 

suricata 的日志又多两条

➜  ~ tail -f /var/log/suricata/fast.log

05/30/2019-15:21:42.636988  [**] [1:1000002:1] ICMP connection attempt [**] [Classification: (null)] [Priority: 3] {ICMP} 220.181.57.216:0 -> 172.16.1.180:8
05/30/2019-15:21:42.636985  [**] [1:1000002:1] ICMP connection attempt [**] [Classification: (null)] [Priority: 3] {ICMP} 220.181.57.216:0 -> 172.16.1.180:8

05/30/2019-15:29:16.622272  [**] [1:1000003:1] TELNET connection attempt [**] [Classification: (null)] [Priority: 3] {TCP} 172.16.1.182:41410 -> 125.76.238.80:23
05/30/2019-15:29:16.622425  [**] [1:1000003:1] TELNET connection attempt [**] [Classification: (null)] [Priority: 3] {TCP} 172.16.1.180:41410 -> 125.76.238.80:23

Suricata 规则解析

拿上面的 ICMP 协议检测规则举例

alert icmp any any -> any any (msg:"ICMP connection attempt"; sid:1000002; rev:1;)
Action Protocol Source Port Direction Destination Port Options
alert icmp any any -> any any (msg..)

Action 可选值:

  • pass
  • drop
  • reject
  • alert

Protocol 可选值:

  • http
  • ftp
  • tls (this includes ssl)
  • smb
  • dns
  • dcerpc
  • ssh
  • smtp
  • imap
  • msn
  • modbus (disabled by default)
  • dnp3 (disabled by default)
  • enip (disabled by default)
  • nfs (depends on rust availability)
  • ikev2 (depends on rust availability)
  • krb5 (depends on rust availability)
  • ntp (depends on rust availability)
  • dhcp (depends on rust availability)

Source 和 Destination 编写规则

操作 说明
../.. IP范围(CIDR 格式)
! 除了/非
[.., ..]
例子 意思
!1.1.1.1 除了 1.1.1.1的所有IP
![1.1.1.1, 1.1.1.2] 除了 1.1.1.1 和 1.1.1.2 的所有IP
$HOME_NET yaml 配置文件里的 HOME_NET
[$EXTERNAL_NET, !$HOME_NET] EXTERNAL_NET and not HOME_NET
[10.0.0.0/24, !10.0.0.5] 10.0.0.0/24 除掉 10.0.0.5
[…, [….]]  
[…, ![…..]]  

Ports (source and destination)

操作 说明
: 端口区间
! 除了/非
[.., ..]
例子 意思
[80, 81, 82] port 80, 81 and 82
[80: 82] Range from 80 till 82
[1024: ] From 1024 till the highest port-number
!80 Every port but 80
[80:100,!99] Range from 80 till 100 but 99 excluded
[1:80,![2,4]] Range from 1-80, except ports 2 and 4  
[.., [..,..]]  

Direction 可选值

  • source -> destination
  • source <> destination (both directions)

Options 选项

规则的其余部分由选项组成,用圆括号括起来,用分号隔开。

有些选项具有设置(例如msg),这些设置由选项的关键字指定,后跟冒号,然后是设置的值。有些选项没有值,只有关键字(如nocase):

<keyword>: <settings>;
<keyword>;

;" 在 Suricata 规则语言中具有特殊含义并且当在规则选项中出现时必须转义,例如

msg:"Message with semicolon\;";