运维知识
悠悠
2026年4月22日

手把手教你落地网络入侵检测系统(NIDS),从选型到上线全记录

说实话,搞安全这块东西,很多运维同学是又爱又恨。爱的是确实能帮你挡住不少事儿,恨的是部署起来各种坑,配不好还一堆误报,搞得你天天看告警看到想吐。

我之前在客户公司负责过一套NIDS的完整落地,从前期调研到最后稳定运行,前前后后折腾了差不多两个月。今天就把这个过程掏出来跟大家聊聊,尽量把踩过的坑和一些实际经验都说清楚。

先搞清楚你到底要监控什么

很多人上来就想装Snort、装Suricata,工具先搞起来再说。我一开始也是这个思路,后来发现这样搞完全是在浪费时间。

你得先坐下来想清楚几个问题:你的网络环境里,哪些流量是需要重点盯着的?敏感数据在哪?常见的威胁类型是什么?

拿我们当时的情况来说,公司有一套对外的Web业务系统,还有内部的OA和数据库集群。对外的业务系统天天被扫描、被尝试SQL注入、XSS什么的,这块肯定是重点。内部的话,主要担心的是横向移动,就是万一有人进来了,在内网里到处乱窜。

我当时列了一个简单的表格:

监控区域流量类型关注的威胁优先级
DMZ区HTTP/HTTPSWeb攻击、扫描探测
核心交换全流量横向移动、C2通信
数据库段DB协议流量异常查询、数据外泄
办公网混合流量恶意软件、钓鱼

这个表看起来简单,但真的很有用。后面选工具、写规则、部署探针的时候,都是围绕这个来的。不然你部署完了发现,关键的地方没覆盖到,不关键的地方一堆告警,那就白忙活了。

工具选型:Snort还是Suricata?

开源的NIDS工具,绕不开这两个。商业的像Palo Alto、FireEye那些,预算够当然好,但大多数公司的安全预算你懂的...所以我们还是聊开源方案。

Snort 是老牌子了,社区大,规则多,文档也全。但它有个问题,单线程。在流量大的环境里,性能瓶颈很明显。我之前在测试环境里跑过,跑到2Gbps左右的流量就开始丢包了。

Suricata 是后来者,天然支持多线程,性能上确实比Snort强不少。而且它兼容Snort的规则格式,也就是说Snort的规则你拿过来基本能直接用。另外Suricata原生支持输出EVE JSON格式的日志,对接ELK那套东西非常方便。

我们最后选的是Suricata,原因很直接:核心交换那个位置的流量峰值能到5Gbps,Snort扛不住。

不过也不是说Snort就不好。如果你的网络规模不大,流量也就几百兆,Snort完全够用,而且上手更简单一些。

还有一个值得提的是 Zeek(以前叫Bro),严格来说它不算传统的IDS,更偏向于网络流量分析和日志生成。它不做实时告警,但生成的连接日志、DNS日志、HTTP日志这些,拿来做事后分析和威胁狩猎非常好用。我们后来也部署了Zeek,和Suricata配合着用,一个管实时告警,一个管深度分析。

硬件和网络架构怎么搞

工具选好了,接下来就是怎么把流量喂给它。

NIDS是旁路部署的,不像防火墙那样串在链路上。它需要的是流量的镜像副本。一般有两种方式:

1. 交换机端口镜像(SPAN/Mirror Port)

这是最常见的方式。在核心交换机上配一个镜像端口,把需要监控的VLAN流量或者特定端口的流量镜像出来,接到NIDS传感器上。

我们用的是华为的交换机,配置大概长这样:

# 创建观察端口(连接NIDS传感器的端口)
observe-port 1 interface GigabitEthernet 0/0/24

# 配置镜像源端口
interface GigabitEthernet 0/0/1
 port-mirroring to observe-port 1 both

如果是思科的设备:

monitor session 1 source interface Gi0/1 both
monitor session 1 destination interface Gi0/24

这里有个坑要注意:镜像端口的带宽要够。如果你镜像的源端口是10G的,但目标端口只有1G,那流量大的时候肯定丢包。我们当时就吃了这个亏,一开始用的1G口做镜像,结果高峰期丢了将近30%的包,好多攻击流量直接漏掉了。后来换成了10G的口才解决。

2. TAP设备

如果预算允许,用网络TAP(Test Access Point)是更好的选择。TAP是一个硬件设备,直接接在链路上,把流量复制一份出来。它的好处是不依赖交换机的镜像功能,也不会因为交换机负载高而丢包。

我们在DMZ区的出口就用了一个TAP,大概花了几千块钱,买的国产的,效果还行。

传感器的硬件配置

跑Suricata的服务器,配置不能太寒酸。我们用的配置是:

  • CPU:Intel Xeon E5-2680 v4(14核28线程)
  • 内存:64GB DDR4
  • 网卡:Intel X710 10GbE(支持多队列)
  • 硬盘:500GB SSD(主要存日志,日志量大的话还得考虑外挂存储)

网卡这块特别说一下,一定要选支持多队列的网卡,这样才能充分利用Suricata的多线程能力。Intel的X710和X520系列都可以。另外,接收镜像流量的网卡不要配IP地址,就让它处于混杂模式(promisc mode),只收不发。

# 设置网卡为混杂模式
ip link set eth1 promisc on

# 关闭网卡的一些offload功能,避免影响抓包
ethtool -K eth1 rx off tx off gro off lro off

关闭offload这一步很重要,不然网卡会在硬件层面对数据包做合并处理,Suricata拿到的就不是原始的包了,可能导致检测失败。

Suricata安装和基础配置

以CentOS 7为例,安装过程记录一下:

# 安装EPEL和依赖
yum install epel-release -y
yum install gcc gcc-c++ make automake autoconf libtool pcre-devel \
    libpcap-devel libyaml-devel file-devel zlib-devel jansson-devel \
    nss-devel libcap-ng-devel libnet-devel lua-devel -y

# 安装Rust(Suricata 6.0+需要)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

# 下载并编译Suricata
wget https://www.openinfosecfoundation.org/download/suricata-6.0.13.tar.gz
tar xzf suricata-6.0.13.tar.gz
cd suricata-6.0.13

./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
    --enable-nfqueue --enable-lua
make -j$(nproc)
make install
make install-conf

当然你也可以直接用包管理器装,省事儿:

# 添加OISF的源
yum install https://copr.fedorainfracloud.org/coprs/jasonish/suricata-stable/repo/epel-7/jasonish-suricata-stable-epel-7.repo
yum install suricata -y

装完之后,主配置文件在 /etc/suricata/suricata.yaml,这个文件巨长,有好几千行。但核心要改的地方其实没几个。

# 定义你的内网地址段
vars:
  address-groups:
    HOME_NET: "[192.168.0.0/16,10.0.0.0/8,172.16.0.0/12]"
    EXTERNAL_NET: "!$HOME_NET"
  port-groups:
    HTTP_PORTS: "80"
    SHELLCODE_PORTS: "!80"
    SSH_PORTS: "22"
    DNS_PORTS: "53"

# 配置监听接口
af-packet:
  - interface: eth1
    cluster-id: 99
    cluster-type: cluster_flow
    defrag: yes
    use-mmap: yes
    tpacket-v3: yes
    ring-size: 2048
    block-size: 32768

# 配置规则文件路径
default-rule-path: /var/lib/suricata/rules
rule-files:
  - suricata.rules

# EVE日志输出配置
outputs:
  - eve-log:
      enabled: yes
      filetype: regular
      filename: eve.json
      types:
        - alert:
            tagged-packets: yes
        - http:
            extended: yes
        - dns:
        - tls:
            extended: yes
        - files:
            force-magic: yes
        - flow

这里 HOME_NET 的配置特别重要,一定要设成你实际的内网地址段。Suricata的很多规则都是基于 "从外到内" 或者 "从内到外" 的方向来判断的,如果HOME_NET配错了,很多规则直接就不生效。

af-packet 是Linux上推荐的抓包方式,性能比libpcap好很多。cluster_flow 模式会把同一个连接的数据包分配到同一个线程处理,避免乱序。

规则管理这块水很深

Suricata自带一个规则更新工具 suricata-update,用起来还挺方便的:

# 更新规则
suricata-update

# 查看可用的规则源
suricata-update list-sources

# 启用ET Open规则集(免费的)
suricata-update enable-source et/open

# 启用后重新更新
suricata-update

ET Open是Emerging Threats提供的免费规则集,质量还可以,覆盖面也比较广。如果你有预算,可以买ET Pro的订阅,规则更全更新也更快。

但说实话,默认的规则集直接用,你会被告警淹没。我们刚上线的时候,一天产生了将近10万条告警,根本看不过来。大部分都是误报或者低价值的告警。

所以规则调优是必须要做的事情。我的做法是分几步走:

第一步:先跑几天,收集数据

不要急着处理告警,先让它跑着,看看告警的分布情况。

# 统计告警按signature排序
cat /var/log/suricata/eve.json | jq -r 'select(.event_type=="alert") | .alert.signature' | sort | uniq -c | sort -rn | head -30

你会发现排在前面的往往就那么几条规则,贡献了80%以上的告警量。

第二步:逐条分析,该禁的禁

比如我们当时排在第一的是一条 ET POLICY GNU/Linux APT User-Agent Outbound likely related to package management 的规则。这条规则检测的是Linux服务器用apt下载软件包的行为,在我们的环境里完全是正常操作,直接禁掉。

# 创建禁用规则列表
echo "2013504" >> /etc/suricata/disable.conf

# 重新更新规则(会自动应用禁用列表)
suricata-update

第三步:针对业务写自定义规则

通用规则集不可能覆盖你所有的业务场景。比如我们有个内部系统,正常情况下只有特定的几台服务器会访问数据库的3306端口,如果其他IP去访问了,那就很可疑。这种就得自己写规则:

alert tcp ![$DB_CLIENT_1,$DB_CLIENT_2,$DB_CLIENT_3] any -> $DB_SERVER 3306 (msg:"Unauthorized MySQL Access Attempt"; flow:to_server,established; sid:1000001; rev:1; classtype:policy-violation;)

写自定义规则的时候有个技巧,sid从1000001开始编号,这样不会和官方规则集冲突。

还有一个我觉得特别实用的规则,检测内网机器对外发起DNS查询到非公司DNS服务器的情况。因为很多恶意软件会用DNS隧道来做C2通信,而且它们通常不会用你公司内部的DNS服务器:

alert udp $HOME_NET any -> !$COMPANY_DNS 53 (msg:"DNS query to non-corporate DNS server"; sid:1000002; rev:1; classtype:policy-violation;)

跟ELK对接,让告警可视化

Suricata产生的eve.json日志,直接看JSON文件肯定不现实。我们用的是经典的ELK方案来做日志收集和可视化。

在Suricata服务器上装Filebeat:

# /etc/filebeat/filebeat.yml
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /var/log/suricata/eve.json
    json.keys_under_root: true
    json.add_error_key: true

output.elasticsearch:
  hosts: ["10.0.0.100:9200"]
  index: "suricata-%{+yyyy.MM.dd}"

setup.template.name: "suricata"
setup.template.pattern: "suricata-*"

然后在Kibana里建个Index Pattern,就能看到所有的告警了。

我建了几个比较实用的Dashboard面板:

  • 告警总览:按时间线展示告警数量趋势,能快速发现异常的告警峰值
  • Top 10告警规则:看哪些规则触发最多,方便持续调优
  • Top 10源IP/目的IP:快速定位可疑的IP地址
  • 告警严重等级分布:饼图展示高中低告警的比例
  • DNS查询Top 20:配合Zeek的DNS日志,看有没有奇怪的域名查询

有了这些面板,每天早上花10分钟扫一眼,心里就有数了。

别忘了HIDS,两者配合才完整

NIDS看的是网络层面的流量,但有些东西它看不到。比如加密流量(HTTPS),NIDS只能看到TLS握手的信息,里面的内容是看不到的。再比如主机上的文件被篡改了、有人用sudo提权了,这些都是网络层面发现不了的。

所以NIDS和HIDS(主机入侵检测系统)应该配合着用。HIDS推荐OSSEC或者它的分支Wazuh,能监控文件完整性、系统日志、rootkit检测这些。

我们的做法是:NIDS负责盯网络流量,发现扫描、攻击尝试、异常连接这些;HIDS负责盯主机层面,发现文件变更、异常登录、可疑进程这些。两边的告警都汇总到ELK里面,做关联分析。

比如NIDS告警说某个外部IP在对Web服务器做SQL注入尝试,然后HIDS告警说同一台Web服务器上的数据库配置文件被修改了,这两个事件关联起来看,那基本就可以确认是被打进来了。单看任何一边都不一定能确定。

威胁情报集成

光靠规则匹配其实是不够的,因为规则都是已知的模式。如果攻击者用了新的手法,规则库里没有,那就检测不到。

引入威胁情报可以弥补一部分。简单来说就是把已知的恶意IP、恶意域名、恶意文件Hash这些信息喂给NIDS,让它去匹配。

Suricata支持加载IP黑名单,你可以从一些免费的威胁情报源获取数据:

  • Abuse.ch 的各种黑名单(SSL黑名单、恶意URL、Botnet C2等)
  • AlienVault OTX 的开放威胁情报
  • CIRCL 的被动DNS数据

我写了个简单的脚本,每天自动拉取这些情报源,转换成Suricata的规则格式,然后reload:

#!/bin/bash
# 下载Abuse.ch的Botnet C2 IP黑名单
wget -q https://feodotracker.abuse.ch/downloads/ipblocklist_recommended.txt -O /tmp/c2_ips.txt

# 转换成Suricata规则
> /var/lib/suricata/rules/threat_intel.rules
while read ip; do
    [[ "$ip" =~ ^#.*$ ]] && continue
    [[ -z "$ip" ]] && continue
    echo "alert ip $ip any -> \$HOME_NET any (msg:\"TI - Known Botnet C2 IP: $ip\"; sid:$((2000000 + RANDOM)); rev:1; classtype:trojan-activity;)" >> /var/lib/suricata/rules/threat_intel.rules
done < /tmp/c2_ips.txt

# 热重载规则
suricatasc -c reload-rules

suricatasc -c reload-rules 这个命令可以在不重启Suricata的情况下重新加载规则,不会中断检测,很实用。

日常运维和持续优化

系统上线之后,不是说就不用管了。NIDS的运维其实是个持续的过程。

规则更新

我设了个crontab,每天凌晨3点自动更新规则:

0 3 * * * /usr/bin/suricata-update && /usr/bin/suricatasc -c reload-rules

性能监控

Suricata自身的性能也要关注。它有个stats日志,记录了丢包率、内存使用等信息:

# suricata.yaml中开启stats
stats:
  enabled: yes
  interval: 30

重点关注 capture.kernel_drops 这个指标,如果丢包率持续上升,说明要么是硬件性能不够了,要么是规则太多导致处理不过来。

我们之前遇到过一次丢包率突然飙升的情况,排查下来发现是有人在内网做大文件传输,流量瞬间冲到了8Gbps,超过了传感器的处理能力。后来的解决办法是在镜像端口上做了过滤,只镜像需要监控的VLAN流量,不相关的大流量传输就不镜像了。

误报处理

这个是永远干不完的活儿。我的经验是建一个误报处理的文档或者wiki,每次处理完一个误报,就记录下来:哪条规则、什么情况触发的、怎么处理的(是禁用规则还是加了例外)。时间长了这就是一份很有价值的知识库。

定期review

每个月抽一天时间,把这个月的告警数据拉出来看一看。哪些规则从来没触发过?是因为确实没有这种威胁,还是因为部署位置不对导致看不到?哪些规则触发太多?是不是需要进一步调优?网络架构有没有变化,需不需要调整探针位置?

关于合规和隐私

这个点很多人会忽略,但其实挺重要的。NIDS抓的是网络流量,里面可能包含用户的个人信息、通信内容这些敏感数据。

我们当时做了几件事:

  1. 明确了NIDS只用于安全检测目的,不会用来监控员工的上网行为
  2. 日志的访问权限做了严格控制,只有安全团队的人能看
  3. 日志保留周期设为90天,过期自动删除
  4. 在员工手册里加了一条关于网络安全监控的说明

这些东西看起来是走形式,但万一真出了事,有没有这些合规措施,差别还是很大的。


写到这里差不多了。整个NIDS的落地过程,说白了就是:想清楚要监控什么 → 选对工具 → 把流量引过来 → 装好配好 → 写规则调规则 → 接上日志平台 → 持续运营优化。每一步都不难,但每一步都有坑。

最关键的其实是最后一步,持续运营。我见过不少公司花了大价钱买了商业IDS/IPS,装上之后就没人管了,告警从来不看,规则从来不更新,跟没装一样。工具再好,没有人去运营,就是个摆设。

希望这篇文章对正在考虑部署NIDS的朋友有些帮助。如果你在部署过程中遇到什么问题,欢迎留言交流。觉得有用的话,帮忙点个赞转发一下,让更多人看到,感谢!


公众号:运维躬行录
个人博客:躬行笔记

文章目录

博主介绍

热爱技术的云计算运维工程师,Python全栈工程师,分享开发经验与生活感悟。
欢迎关注我的微信公众号@运维躬行录,领取海量学习资料

微信二维码