virtueistheonlygood/siemids
GitHub: virtueistheonlygood/siemids
基于 Suricata 和 ELK 技术栈的开源 SIEM-IDS 集成方案,提供网络流量监控、日志聚合、威胁检测与可视化分析能力。
Stars: 4 | Forks: 0
# 开源 👁 SIEM-IDS 解决方案
本项目专为寻求监控和分析网络基础设施活动、增强隐私控制或应对复杂安全挑战的用户而设计。它支持可扩展部署,可配置为入侵检测系统 (IDS) 或入侵防御系统 (IPS)。集成的安全信息和事件管理 (SIEM) 系统提供集中式日志聚合、实时事件关联和深入的历史分析。IDS 利用基于规则和基于特征的检测机制来识别潜在威胁或异常事件,从而促进主动的威胁管理。
**SIEM-IDS 集成了开源工具,可实时监控、分析、关联网络流量、系统、应用程序和安全事件并发出警报。它提供了每项活动的详细可视化,为您的隐私和安全状况提供可操作的洞察。**
## 开源组件
### [Suricata](https://github.com/OISF/suricata) | [Elasticsearch](https://github.com/elastic/elasticsearch) | [Kibana](https://github.com/elastic/kibana) | [Filebeat](https://github.com/elastic/beats/tree/main/filebeat) | [AdGuard Home](https://github.com/AdguardTeam/AdGuardHome) | [OTX API](https://otx.alienvault.com/)
- Suricata 是一款强大的网络入侵检测系统 (IDS)、入侵防御系统 (IPS) 和网络安全监控 (NSM) 引擎,负责捕获和检查网络流量。
- 捕获的数据采用可扩展事件格式 (EVE) 进行格式化,由 Filebeat 处理、丰富并发送至 Elasticsearch。除了 Suricata 日志外,Filebeat 还收集并转发来自 *auditd*、*auth.log*、*syslog* 以及本项目实际使用的本地 DNS 服务器 [AdGuard Home](https://github.com/AdguardTeam/AdGuardHome) 的 DNS 查询日志。
## 目录
1. [开源组件](#opensource-components)
2. [设置说明](#setup-instructions) (克隆代码仓库,安装 Podman)
3. [配置 Suricata](#configure-suricata)
4. [入门指南](#getting-started) (设备 A:ELK 主机)
- [Podman Compose 配置](#podman-compose-configuration)
- [Podman 容器安全](#podman-container-security)
- [ELK 配置与对象](#elk-configuration-and-objects)
- [检测规则](#detection-rules)
- [ELK 密码与机密](#elk-passwords-and-secrets)
- [Filebeat 日志收集与丰富](#filebeat-log-collection-and-enrichment)
5. [准备就绪](#ready-to-start) (设备 A)
6. [设备 B:Suricata 传感器(例如 Raspberry Pi 路由器)](#device-b-suricata-sensor-eg-a-raspberry-pi-router)
7. [流量流向图](#traffic-flow-map)
8. [OTX 开放威胁交换(开发中)](#otx-open-threat-exchange-under-development)
9. [截图](#screenshots)
10. [贡献](#contributing)
11. [许可证](#license)
## 设置说明
**本项目部署在两台设备上**:**设备 A** 通过 `podman-compose` 运行完整的 ELK 技术栈
(Elasticsearch, Kibana, Filebeat) —— 它需要足够的物理内存来支持
Elasticsearch。**设备 B** 原生运行 Suricata(路由器/AP 级别的设备,例如
Raspberry Pi 就足够了),并通过局域网将其日志发送到设备 A。本项目不支持
单设备(所有组件部署在同一主机)部署设置 —— 将 Elasticsearch 和 Suricata
部署在同一台机器上超出了大多数小型硬件的处理能力,而且这也不是本
项目测试验证的部署方式。
以下步骤(直到 [准备就绪](#ready-to-start))会**先设置设备 A**
—— 设备 B 连接前必须先存在这些 TLS 证书 —— 然后跳转到
[设备 B:Suricata 传感器](#device-b-suricata-sensor-eg-a-raspberry-pi-router) 来
启动第二台设备。
1. **克隆代码仓库**:
```
git clone https://github.com/virtueistheonlygood/siemids
cd siemids
cp .env.example .env
```
`.env` 已被 git 忽略 —— `start.sh` 会在首次运行时将真实、随机生成的密码和
Kibana 的加密密钥写入其中,因此绝不能将其提交。只有
`.env.example`(一个不含机密的模板)会被追踪。
2. **安装 Podman**:
本项目需要 Podman 和 podman-compose 才能运行。
- 请按照 [Podman 官网](https://podman.io/getting-started/installation) 和 [podman-compose GitHub 仓库](https://github.com/containers/podman-compose) 上的说明进行安装。
## 配置 Suricata
无论是在您的架构上作为 IDS 还是 IPS 运行,Suricata 都需要量身定制的配置才能正常工作。请确保配置路径与您的安装路径一致。**本项目原生运行 Suricata,而不是作为容器运行,并且始终在设备 B**(传感器)上运行 —— 完整的部署步骤请参见 [设备 B:Suricata 传感器](#device-b-suricata-sensor-eg-a-raspberry-pi-router);本节仅介绍配置文件本身。
- **我们强烈建议根据您的网络拓扑和监控需求,在您的主机上自定义配置并编译运行 Suricata**。作为参考,您可以使用标准的示例配置文件 `resources/suricata/suricata.yaml`,或者使用 `resources/suricata/suricata-raspberrysrv.yaml` 查看一个完全填充的真实多接口示例(参见 [设备 B:Suricata 传感器](#device-b-suricata-sensor-eg-a-raspberry-pi-router))。
您可以按照 [Suricata 文档](https://suricata.readthedocs.io/en/latest/install.html) 中的说明在您的系统上编译并安装它。
关键配置方面包括:
1. **网络接口**:指定 Suricata 应监控哪些网络接口以进行流量分析。`threads: auto` 会解析为“核心数” *每个接口* —— 在小型、多用途设备上(路由器/AP 同时运行 DNS、VPN、NAT),如果定义了多个接口,很快就会导致 CPU 超载;建议像这里所做的那样,为每个接口硬编码一个较低且合理的线程数:
```
af-packet:
- interface: wlan0
threads: 1
cluster-id: 99
cluster-type: cluster_flow
defrag: yes
use-mmap: yes
mmap-locked: yes
tpacket-v3: yes
ring-size: 2048
block-size: 32768
block-timeout: 10
use-emergency-flush: yes
buffer-size: 32768
disable-promisc: no
checksum-checks: kernel
- interface: wg0
threads: 1
cluster-id: 98
cluster-type: cluster_flow
defrag: yes
use-mmap: yes
mmap-locked: yes
tpacket-v3: yes
ring-size: 2048
block-size: 32768
block-timeout: 10
use-emergency-flush: yes
buffer-size: 32768
disable-promisc: no
checksum-checks: kernel
# Values used for any interface not explicitly listed above.
- interface: default
```
2. **规则集**:指定 Suricata 检测威胁时应使用的规则集。
```
default-rule-path: /usr/local/var/lib/suricata/rules
rule-files:
- suricata.rules
```
3. **日志记录**:配置日志记录选项以捕获并存储警报和其他相关数据。这是 Filebeat 收集 Suricata EVE 日志的路径。
```
default-log-dir: /suricata/
```
## 入门指南
### Podman Compose 配置
`podman-compose.yaml` 文件负责编排部署所需的各种服务。它指定了每个服务的配置,包括安全性、网络设置、环境变量和数据卷挂载,从而确保所有组件的无缝集成。
### Podman 容器安全
容器化服务(Elasticsearch、Filebeat 和 Kibana)之间的通信使用 HTTPS/SSL 进行保护,并通过 'setup_pki' 服务实现了公钥基础设施 (PKI)。PKI 采用一对加密密钥(公钥和私钥)对所涉及的实体进行身份验证,并对传输中的数据进行加密,确保敏感信息得到安全传输且仅能由授权方访问。
```
setup_pki:
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- ./certs:/usr/share/elasticsearch/config/certs
user: "0"
```
- **用于保护容器化服务之间通信安全的证书存储在 `certs/` 目录下**。
- 除了 `elasticsearch`/`localhost`/`127.0.0.1` 之外,`elasticsearch` 证书的 SAN(主体别名)列表还包含了 `ELK_LAN_IP`(在 `.env` 中设置,默认为此主机的局域网 IP),因此通过局域网 IP 连接的远程 Beats 代理(例如 [设备 B:Suricata 传感器](#device-b-suricata-sensor-eg-a-raspberry-pi-router))可以获得完整的 TLS 主机名验证,而不会因为 IP 不匹配而失败。这仅在首次生成证书时生效 —— 如果证书已存在且 `ELK_LAN_IP` 发生变化,请删除 `certs/` 并重新运行 `./start.sh`。
### ELK 配置与对象
可视化和仪表板存储在 `saved.objects/siemids.ndjson` 中,并作为 `./start.sh`/`podman-compose up -d` 的一部分**自动导入** —— 无需手动操作。这由一个专门的专用服务 `setup_kibana` 完成,它会:
1. 在启动前等待 `kibana` 服务的健康检查(`depends_on: kibana: condition:
service_healthy`)。
2. 循环轮询 `https://localhost:5601`,直到返回 `HTTP/1.1 302 Found`
(Kibana 的重定向至登录页面,意味着 HTTP 服务器本身已实际接受请求,而不仅仅是容器进程在运行)。
3. 将 `saved.objects/siemids.ndjson` `POST` 到 Kibana 的 `/api/saved_objects/_import`
endpoint(`compatibilityMode=true` 允许从稍微不同版本的 Kibana 导出的对象依然能干净导入),并通过 `ELASTIC_PASSWORD` 以 `elastic` 身份进行验证。
4. 退出。由于配置为 `restart: on-failure` 而非 `restart: always`,它只会在步骤 2/3 实际失败时重新运行 —— 正常的成功导入不会在随后的每次 `start.sh` 运行中循环或重新导入。
```
command: >
sh -c '
until curl -s -I --cacert /usr/local/certs/ca/ca.crt https://localhost:5601 | grep -q "HTTP/1.1 302 Found"; do
echo "Waiting for Kibana to be ready...";
sleep 10;
done;
curl -s -X POST "https://localhost:5601/api/saved_objects/_import?compatibilityMode=true" -H "kbn-xsrf: true" --cacert /usr/local/certs/ca/ca.crt --cert /usr/local/certs/elasticsearch/elasticsearch.crt --key /usr/local/certs/elasticsearch/elasticsearch.key -u elastic:${ELASTIC_PASSWORD} --form file=@/usr/local/saved.objects/siemids.ndjson
'
```
- **配置文件位于 `resources/` 目录下**
`[Logs Suricata] Alert Overview` 仪表板包含一个 `Top IoC Feed Matches`
面板(由 `IoC Feed Alerts [Logs Suricata]` 保存的搜索支持),专门隔离匹配精选 IoC 订阅源的命中记录 —— 过滤条件为
`rule.name: SSLBL* or rule.name: "ET CNC Feodo Tracker*" or rule.name: "ETN AGGRESSIVE*"`
—— 按哪个指示器触发以及哪个主机触发它进行细分,与通用的“热门警报签名”表分开,否则它们会被淹没在成千上万的 ET/Open 匹配中。专用的 `siemids-suricata-ioc-feed-match` 检测
规则(参见 [检测规则](#detection-rules))使用相同的过滤器。关于如何
启用这些订阅源,请参见
[设备 B:Suricata 传感器](#device-b-suricata-sensor-eg-a-raspberry-pi-router)。
### 检测规则
`saved.objects/detection-rules.ndjson` 提供了 25 条精选的检测规则,分为
14 条改编自 [Elastic 的免费预置规则目录](https://www.elastic.co/guide/en/security/current/prebuilt-rules.html)
(`elastic-*` 规则 ID)和 11 条专门针对本项目的实际日志
来源和观察到的噪音模式编写的规则(`siemids-*` 规则 ID)—— 每条规则都映射到了其对应的 [MITRE ATT&CK](https://attack.mitre.org/) 战术/技术。
| 类别 | 规则 |
| --- | --- |
| **SSH / 凭据访问** | 暴力破解(内部/外部/成功,包含自定义阈值规则和 Elastic 的 EQL 变体)、直接 root 登录、首次出现的源 IP、异常用户或 SSH 公钥 |
| **权限提升 / `sudo` 滥用** | `sudo` 启动交互式 shell(`sudo bash`/`su`)、`sudo` 触碰 `/etc/passwd`、`/etc/shadow`、`/etc/sudoers` 或账户管理命令 |
| **持久化 / 账户和系统更改** | 创建新的 Linux 用户/组、手动更改 `iptables` 防火墙(排除正常的 Podman/netavark 频繁变动)、可疑的 `rc.local` 错误 |
| **内核完整性** | 加载受污染或树外内核模块、启动可执行栈进程、可疑的 `bpf_probe_write_user` 使用 |
| **命令与控制** | 来自单个客户端的 AdGuard 阻断查询激增(信标指示)、Cobalt Strike 默认团队服务器 TLS 证书、**Suricata IoC 订阅源匹配**(`siemids-suricata-ioc-feed-match` —— 专门针对 Feodo Tracker/SSLBL 指示器命中触发,严重性高,与下方的通用 Suricata 规则分开,因为已确认的恶意指示器匹配应具备不同于启发式签名匹配的优先级) |
| **网络 (Suricata)** | 任何真实的 Suricata 警报签名(经过调整以排除两个已知的解码器噪音签名)、潜在的出站 SSH 扫描(经过调整以排除本项目自身的管理/自动化主机) |
有几项自定义规则明确针对此部署实际产生的
噪音进行了调整 —— 例如,防火墙更改规则排除了日常的 Podman 容器网络
变动,`sudo` 交互式 shell 规则排除了 `start.sh` 自身的 `sudo sh -x
scripts/prune.sh` 调用 —— 这反映了真实的误报率,而不是
理论上的规则集。**这些只是一个起点,并非详尽无遗**:请对照
您自己的日志来源和威胁模型进行审查,重新调整或移除
针对最初部署特定的噪音排除项,并为特定于您
环境的任何内容添加规则。
与仪表板不同,规则**不会**被任何 compose 服务自动导入 —— 检测
引擎是一个独立于 Saved Objects 的 API 命名空间
(`/api/detection_engine/rules/_import`,而不是 `/api/saved_objects/_import`),并且其
底层索引只有在 Security 应用至少打开过(或
像这样的 API 调用触发它)之后才会初始化,因此如果将其接入与 `setup_kibana` 相同的启动依赖链中,会与该初始化过程产生竞争。请在 Kibana 启动后,
自行导入它们一次:
```
curl -sk -u elastic: -X POST \
"https://localhost:5601/api/detection_engine/rules/_import?overwrite=true" \
-H "kbn-xsrf: true" \
--form file=@saved.objects/detection-rules.ndjson
```
成功的导入会报告 `"success":true,"success_count":24,"errors":[]`。规则
在导入时即被启用;请在 **Security → Rules** 中验证,或通过以下方式:
```
curl -sk -u elastic: \
"https://localhost:5601/api/detection_engine/rules/_find?per_page=100" \
-H "kbn-xsrf: true"
```
### ELK 密码与机密
`start.sh` 仅在首次运行时生成 `ELASTIC_PASSWORD`、`KIBANA_PASSWORD` 和 `KIBANA_ENCRYPTION_KEY`,
将密码同时作为 Podman secrets 存储并作为附加行写入
`.env`,而加密密钥则作为 `.env` 中的一行,通过
`XPACK_SECURITY_ENCRYPTIONKEY`/`XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY`/
`XPACK_REPORTING_ENCRYPTIONKEY` 环境变量来消费(Kibana 的 docker entrypoint 会将它们转换为
等效的 `kibana.yml` 设置)。这三者在重启期间必须保持稳定 ——
Elasticsearch 仅在首次引导集群时接受密码,如果
密钥发生更改,Kibana 将无法解密以前加密的已保存对象(例如存储的连接器凭据)—— 因此重新运行 `start.sh` 会重用现有的 secrets,而不是
重新生成它们。使用 `ELASTIC_PASSWORD` 登录 https://localhost:5601。
**正是因为这个原因,`.env` 被 git 忽略** —— 一旦
`start.sh` 运行,它就会保存真实的、有效的机密。切勿使用 `git add -f .env`,也切勿将这三个
值中的任何一个硬编码到被追踪的文件中(该项目的一个早期版本
就是以这种方式将几代密码和 Kibana 加密密钥泄露到了 git 历史记录中)。
```
secrets:
- elastic_password
- kibana_password
command: >
bash -c '
ELASTIC_PASSWORD=$(cat /run/secrets/elastic_password)
KIBANA_PASSWORD=$(cat /run/secrets/kibana_password)
if [ x${ELASTIC_PASSWORD} == x ]; then
echo "Set the ELASTIC_PASSWORD secret";
exit 1;
elif [ x${KIBANA_PASSWORD} == x ]; then
echo "Set the KIBANA_PASSWORD secret";
exit 1;
fi;
```
### Filebeat 日志收集与丰富
`resources/filebeat/filebeat-skynetpi.yml` 是设备 A(ELK 主机)的 Filebeat
配置,由 `podman-compose.yaml` 中的 `filebeat` 服务挂载。由于在此拓扑中设备 A
不是网络传感器,因此该配置特意保持简单:没有 Suricata
模块,没有 AdGuard 输入,没有 geo-enrichment 处理器,也没有 `scripts/interfaces.py`
依赖项 —— 它仅发送设备 A 自身的操作系统日志。
```
nano resources/filebeat/filebeat-skynetpi.yml
```
系统日志从标准路径 `/var/log` 收集,包括 *syslog*、*auth.log* 和 *audit.log* 等文件。
```
filebeat.modules:
- module: auditd
log:
enabled: true
var.paths: ["/var/log/audit/audit.log*"]
- module: system
syslog:
enabled: true
var.paths: ["/var/log/syslog*"]
auth:
enabled: true
var.paths: ["/var/log/auth.log*"]
```
确保 Filebeat 配置(包括文件权限、文件路径、
处理器和字段)已正确设置,以满足您环境的实际要求。
有关更多详细信息,请参阅
[Filebeat 官方文档](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-configuration.html)。
**设备 B 的 Filebeat 配置是不同的,并单独说明** —— 它承载着
Suricata 模块、AdGuard 输入以及为流量流向图提供支持的所有 geo-enrichment 处理器。请参阅下文的
[设备 B:Suricata 传感器](#device-b-suricata-sensor-eg-a-raspberry-pi-router)。
## 准备就绪
`start.sh` 会启动设备 A(`podman-compose`)—— 一旦设置好上述设备 A 的
Filebeat 配置,就在那里运行它。它完全不会触碰设备 B;设备 B 没有
`podman-compose`,将在下一节中单独部署。
**注意**:运行 `start.sh` 脚本不会影响您正在运行的容器,但是它将清理您本地环境中的先前设置,并在您的主机上设置 Elasticsearch 所需的系统参数,同时更改 `resources/` 中配置文件的所有权和权限。这可确保任何先前的配置或数据不会干扰新的设置。
```
sudo ./start.sh
```
**是的,您需要 sudo 来确保 Podman 拥有必要的权限。**
- Podman 需要提升的权限来执行特定任务,例如访问网络接口、绑定 1024 以下的端口,以及由于配置了某些 capabilities(例如 NET_ADMIN),还有挂载需要 root 访问权限的目录和文件。
## 设备 B:Suricata 传感器(例如 Raspberry Pi 路由器)
设备 B(路由器/AP 级别的设备,例如 Raspberry Pi —— 体积太小而无法运行 Elasticsearch)
原生运行 Suricata,并通过专用的轻量级 Filebeat 实例将其 `eve.json` 发送到设备 A。它没有
`podman-compose`,因此由普通的 `podman run --restart=always` 驱动(示例请参见 `scripts/*-podman.sh`),而不是使用 compose。
在开始这里的步骤之前,设备 A 必须已经启动 —— 这些步骤假设其 TLS 证书
已经存在。
1. 从 `resources/suricata/suricata.yaml`(标准示例)或 `resources/suricata/suricata-raspberrysrv.yaml`(一个具体的、完全填充的多接口示例)为传感器主机构建 `suricata.yaml`,将 `af-packet` 接口名称替换为传感器的真实接口(即 AP/局域网和 VPN 出口接口 —— 除非您也想对其进行监控,否则不包括其 WAN 上行链路),并保留 `default-log-dir: /suricata/`。
2. 将其作为原生 systemd 服务(`suricata.service`,由发行版软件包提供)启用/启动 —— 参见 [配置 Suricata](#configure-suricata)。然后运行 `scripts/suricata-update-timer-install.sh`,该脚本会:
- 通过 `suricata-update enable-source` 启用 `et/open` (Emerging Threats Open,约 4 万个签名) 以及四个免费的 IoC 订阅源:`abuse.ch/feodotracker`(活跃的僵尸网络 C2 IP)、`abuse.ch/sslbl-blacklist`/`sslbl-ja3`(恶意 TLS 证书和 JA3 指纹,主要是 C2 流量,采用 CC0 许可)和 `etnetera/aggressive`(一个 IP 黑名单,采用 MIT 许可)—— 加在一起也只有几百到约 1 万条轻量级、单一内容匹配的规则,与 `et/open` 相比微不足道。**启用订阅源是一次性的附加操作** —— 如果没有启用任何订阅源,`suricata-update` *不会*回退到 `et/open`;它只会刷新 Suricata 自带的协议/异常事件规则(如 `dns-events.rules` 等),而这些根本不是威胁签名。跳过此步骤会使传感器在不知不觉中处于没有真正规则集的状态。(`abuse.ch/sslbl-c2` 被有意跳过 —— abuse.ch 在 2025 年弃用了它,现在它没有任何规则了。)
- 立即拉取规则,然后安装每日刷新的 systemd 定时器(`resources/suricata/suricata-update.service`/`.timer`),计划在 `05:00 UTC` 运行(`OnCalendar=*-*-* 05:00:00`,外加最多 30 分钟的随机延迟)。**该定时器可在没有捕获间隙的情况下实时重载 Suricata 的规则** —— `suricata-update` 会通过其 `unix-command` socket 自动检测正在运行的实例,并在成功完成测试后自行触发重载,但在当前部署约 7.8 万条规则的规模下,在 3.7GB 内存的 Raspberry Pi 4B 上,简单的实时重载过去常常会导致更新自身的 `suricata -T` 测试步骤被可靠地 OOM 杀死(相当于两个进程同时进行检测引擎处理的内存需求超过了这台设备本身的承受能力)。此问题已通过两项必要的更改得到修复:(1) 一个额外的 2GB 磁盘支持的交换文件(`/var/swap`,由安装脚本在现有 2GB zram 交换之外激活并持久化)为测试步骤提供了足够的内存余量以使其存活而不是被 OOM 杀死 —— 已通过 dmesg 确认,使用交换文件时没有 OOM 杀死,而没有交换文件时则必定被杀死;(2) 在更新进程上设置 `nice -n 19` + `ionice -c3`,使其在发生交换时向实时捕获线程让渡 CPU/磁盘 I/O —— 如果没有这个,在编译期间,实时捕获明显丢包(根据 Suricata 自身的 `stats.capture.kernel_drops`,大约 9 分钟内分散产生了约 3.87 万个丢包),但使用了该设置后,相同的编译过程仅增加了约 140 个丢包,接近于零,因此相比于直接停止 Suricata,这更令人满意。
- **`abuse.ch/urlhaus` 被有意未启用**,即使采用先停止的方法也是如此 —— 独立测试了两次:一次是 Suricata 仍在运行时(被杀死时占用 2.6GB+ RSS),另一次是先将其停止(被杀死时占用 2.9GB+ RSS,*更多*的余量,但依然不够)。它看起来只是另一个 IoC 订阅源,但实际上包含约 3 万条内容繁重的 HTTP 规则;将其编译进去(MPM/pattern-matcher 构建步骤,而非稳态运行)在目前尝试过的任何配置下所需的内存都超过了这台 Pi 所拥有的容量(已通过两次 dmesg 确认)。只有当传感器的内存明显大于 Pi 4B 时,才应将其开启。
- **内存**:仅在 Pi 4B 上,`et/open` 约 4 万个签名就会让已经在运行 AdGuard/WireGuard/PIA 的 Suricata 从很小的基线增加到约 1.5GB RSS —— 在受限的硬件上启用之前,请先确认有足够的内存余量。当所有四个 IoC 订阅源叠加加上去之后,此部署的编译/测试步骤基本没有留下任何 RAM 余量;上面提到的额外交换文件和 nice/ionice 设置是使同机实时重载成为可能的根本原因,即便如此,在每次更新期间依然存在真实的(尽管现在可以忽略不计的)捕获成本。
3. 首先在**传感器主机上**运行 `scripts/interfaces.py` —— 它会生成设备 B 的 Filebeat geo-enrichment 处理器读取的 `geoip/*.json` 和 `env/*.env` 文件。编辑它以将 `localnet_1`/`vpnet_1`(如果传感器有第二个 VPN 出口,例如 PIA 隧道,则还包括 `piavpn_1`)设置为该主机的实际接口:
```
localnet_1 = "eth0" # modify with your local (internet-facing) interface name
vpnet_1 = "wg0" # modify with your vpn interface name
#localnet_2 = "wlan1" # modify with your local interface name
#vpnet_2 = "wg1" # modify with your vpn interface name
# Second, separate VPN egress (e.g. a PIA tunnel used by a specific
# container/service alongside the main vpnet_1 VPN). Comment out if not
# applicable to your setup.
piavpn_1 = "pia" # modify with your second vpn interface name
```
`localnet_1` 必须是一个**具有直接通往互联网路由**的接口(它用于
公共 IP 地理位置查询)—— 在路由器/AP 设备上,那是 WAN 上行链路,而不是像
`wlan0`/`wlan1` 这样的 AP 接口(这些接口上的客户端流量被强制通过
VPN 隧道传输,没有自己的直接出口)。Filebeat 处理器中
AP 子网的本地 IP 匹配是独立的、硬编码的 IP 前缀逻辑,不受此
变量影响。*我们正计划通过识别活跃的网络接口
来实现此步骤的自动化。*
4. 如果传感器尚未运行 `auditd`/`rsyslog`(例如像 Raspberry Pi OS 这样仅使用 journald 的发行版),请安装并启用两者 —— `filebeat-.yml` 的 `auditd`/`system` 模块需要实际存在 `/var/log/audit/audit.log`、`/var/log/syslog` 和 `/var/log/auth.log`。
5. 将 `certs/ca/ca.crt` 和 `certs/filebeat/{filebeat.crt,filebeat.key}` 从 ELK 主机(由其 `setup_pki` 服务在首次运行 `./start.sh` 后生成)复制到传感器主机上。在首次运行*之前*,将 ELK 主机 `.env` 中的 `ELK_LAN_IP` 设置为其真实的局域网 IP —— 参见 [Podman 容器安全](#podman-container-security) —— 否则传感器的 Filebeat 在通过 IP 连接时,TLS 主机名验证将会失败。
6. 通过 `scripts/filebeat--podman.sh` 脚本部署 `resources/filebeat/filebeat-.yml`(具体示例请参见 `resources/filebeat/filebeat-raspberrysrv.yml` / `scripts/filebeat-raspberrysrv-podman.sh`),将 `ELASTICSEARCH_HOSTS` 指向 ELK 主机的局域网地址,并将 `ELASTICSEARCH_PASSWORD` 指向其 `elastic_password` secret。除了 `suricata` 模块之外,该实例还会发送传感器自身的 `auditd`/`system`(syslog+auth)日志,如果存在,还包括 [AdGuard Home](https://github.com/AdguardTeam/AdGuardHome) 的 JSON 查询日志(标记为其独立的 `adguard.log` 数据集)。
设备 A 自身的 `filebeat` 服务已在上文的
[Filebeat 日志收集与丰富](#filebeat-log-collection-and-enrichment)介绍过
(`filebeat-skynetpi.yml` —— 仅限操作系统日志,不含 Suricata/geo-enrichment)。对于
受内存限制的设备 A(例如同样是 Raspberry Pi 4B),请使用
`podman-compose-skynetpi.yaml` 而不是 `podman-compose.yaml`。
**注意事项**:设备 B 的 geo-enrichment 处理器引用的环境变量(`${localnet_geo_*}` 等)必须作为真实的容器环境变量加载,而不仅仅是作为文件进行 bind-mount —— 部署设备 B 的 Filebeat 时请使用 `podman run --env-file`。单纯的 bind-mount 会导致这些变量无法解析,Filebeat 将拒绝启动。
## 流量流向图
完成上述步骤后,我们现在可以使用为本项目创建的自定义可视化来可视化网络事件,如这张事件可视化地图的屏幕截图所示,它突出了流量流向和源/目标详情:

## OTX 开放威胁交换(开发中)
将您的 [OTX AlienVault](https://otx.alienvault.com/) API_KEY 添加到 `resources/otx-api.py` 中
```
API_KEY = 'YOUR_OTX_API_KEY
```
要查询 OTX API,您可以使用 `curl` 和 `jq` 等工具。
```
curl "http://127.0.0.1:5000/threat_intel?ip=" | jq .
```
将 `` 替换为您要查询的 IP 地址。例如:
```
curl "http://127.0.0.1:5000/threat_intel?ip=8.8.8.8" | jq .
```
## 截图




## 许可证
本代码仓库的原创内容(配置、脚本、文档)均采用
[MIT 许可证](LICENSE) 授权。
它包含了多个第三方开源组件,每个组件都有各自的许可证:
- Suricata:采用 [GPLv2 许可证](https://github.com/OISF/suricata/blob/master/LICENSE) 授权。
- Elasticsearch:采用 [Elastic License 2.0](https://www.elastic.co/licensing/elastic-license) 授权。
- Kibana:采用 [Elastic License 2.0](https://www.elastic.co/licensing/elastic-license) 授权。
- Filebeat:采用 [Elastic License 2.0](https://www.elastic.co/licensing/elastic-license) 授权。
- AdGuard Home:采用 [GPLv3 许可证](https://github.com/AdguardTeam/AdGuardHome/blob/master/LICENSE.txt) 授权。
更多详细信息,请参阅各自项目的 LICENSE 文件。
标签:Elasticsearch, IP 地址批量处理, Metaprompt, Suricata, 入侵检测系统, 子域名变形, 安全数据湖, 插件系统, 现代安全运营, 越狱测试