sonahangelo/acf_project

GitHub: sonahangelo/acf_project

一个结合签名规则和机器学习的自适应认知防火墙引擎,提供实时网络异常检测、iptables 拦截和可视化仪表盘。

Stars: 1 | Forks: 0

## 安全优先的部署清单 在暴露 dashboard 或启用实时拦截之前: 1. 设置真实的 dashboard 密码。除非您明确选择在本地实验室中使用,否则 ACF 现在会拒绝依赖演示密码的 dashboard 请求。 ``` export ACF_DASHBOARD_PASSWORD='replace-with-a-long-random-password' # 仅限本地课堂/demo: # export ACF_ALLOW_DEFAULT_PASSWORD=true ``` 2. 在审查您自己网络中的告警之前,请保持 `dry_run: true`。仅当您准备好让 ACF 调用 `iptables` 时,才设置 `dry_run: false`。 3. 将 `models/anomaly_model.pkl` 视为受信任的代码,因为 joblib 在内部使用 Python pickle。对于生产环境,请在 `config.yml` 中使用 `model_sha256` 锁定已训练的模型。 ``` sha256sum models/anomaly_model.pkl ``` 4. 将本地源 IP 威胁情报指示器添加到 `data/threat_intel.txt`,每行一个 IP 地址或 CIDR 网络。使用 `#` 保留注释。 ``` 203.0.113.10 198.51.100.0/24 ``` 5. 对于 Docker 部署,在运行 `docker compose up` 之前,请在环境中提供 `ACF_DASHBOARD_PASSWORD`。如果缺少此项,compose 文件将有意以失败关闭。 ## 设置:避免使用 sudo 进行抓包 数据包捕获需要原始套接字访问权限。我们没有将其授予系统级的 Python 解释器(这会允许*任何*脚本使用原始 套接字),而是专门为 ACF 使用了一个专用的 Python 副本: ``` cp /usr/bin/python3.11 acf-env/bin/python3-acf sudo setcap cap_net_raw,cap_net_admin=eip acf-env/bin/python3-acf ``` 然后使用 `acf-env/bin/python3-acf` 而不是 `python3` 运行 ACF 命令,用于捕获/学习/检测模式: ``` acf-env/bin/python3-acf main.py --mode learn --count 5000 acf-env/bin/python3-acf main.py --mode detect ``` 其他命令(训练、状态、blocklist、反馈、dashboard)不 需要原始套接字访问权限,可以继续使用常规的 `python3`。 注意:`python3-acf` 是一个真实的副本,而不是符号链接,并且不会在虚拟环境 重新创建后保留下来——如果您重建虚拟环境,请重新执行 `cp` + `setcap` 步骤。 保存并退出。 **第 2 步 — 将 `python3-acf` 添加到 `.gitignore`**(它是一个二进制副本,不应该被提交): ``` echo "acf-env/bin/python3-acf" >> .gitignore ``` **第 3 步 — 提交:** ``` git add . git commit -m "Narrow setcap grant: use a dedicated python3-acf binary instead of the system-wide interpreter, confining raw-socket capability to just ACF" ``` 粘贴确认信息——这将关闭 #4 并完成您原始列表中的所有内容。 注意:如果 Python 虚拟环境或系统 Python 版本 发生更改(例如在 `apt upgrade` 或重新创建虚拟环境之后),则必须重新应用此操作,因为 capabilities 存储在特定的二进制文件上,不会自动延续。 实时执行(`dry_run: false`)仍然需要 `sudo` 才能进行实际的 `iptables` 调用——这仅消除了在捕获、 训练和试运行检测期间对 sudo 的需求。 ## 真实网络测试(局域网设备访问) 要针对来自真正外部设备(手机、另一台 PC)的流量而不是仅限 WSL 内部流量测试 ACF: 1. 查找您的 Windows 主机的局域网 IP:`ipconfig` (PowerShell) -> IPv4 地址 2. 通过 Windows 将 dashboard 端口转发到 WSL(提升权限的 PowerShell): netsh interface portproxy add v4tov4 listenport=5050 listenaddress=0.0.0.0 connectport=5050 connectaddress= New-NetFirewallRule -DisplayName "ACF Dashboard" -Direction Inbound -LocalPort 5050 -Protocol TCP -Action Allow 3. 将 Flask 绑定到 `0.0.0.0`(在 app.py 中已经是默认设置) 4. 运行 `main.py --mode detect` 和 `app.py` 来捕获流量 5. 从另一台设备通过 `http://:5050` 访问 注意:WSL IP 在重启时会发生变化,因此 portproxy 规则每次 都需要更新。完成测试后移除这两个规则(参见上面的命令,使用 `delete`/`Remove-NetFirewallRule`)以避免不必要地保持端口开放。 曾尝试将镜像网络模式(`.wslconfig` 中的 `networkingMode=mirrored`)作为 替代方案,但在当前设置中失败并出现错误 0x8007054f (可能是 Hyper-V/VPN/防火墙冲突)——因此改为使用上述 portproxy 方法,并成功验证了真实外部设备流量 到达 ACF 的捕获管道。 ## 作为后台服务运行 (systemd) ACF 可以通过 systemd 持续运行,而无需手动终端会话: ``` sudo systemctl start acf-detect.service # detection engine sudo systemctl start acf-dashboard.service # web dashboard sudo systemctl enable acf-detect.service # auto-start on WSL boot sudo systemctl enable acf-dashboard.service ``` 检查状态:`./acf_service_status.sh` 查看日志:`sudo journalctl -u acf-detect.service -f`(添加 `-f` 以实时跟踪) 停止:`sudo systemctl stop acf-detect.service` / `acf-dashboard.service` 两个服务在崩溃时都会自动重启(延迟 5 秒)。服务文件位于 `/etc/systemd/system/acf-detect.service` 和 `acf-dashboard.service`。 注意:WSL 本身必须处于运行状态这些服务才能激活——它们在 WSL 启动时启动,不一定在 Windows 引导时启动,除非 WSL 被单独配置为自动启动。 ## ARP 欺骗检测 ACF 还会监控 ARP 流量以发现 IP 到 MAC 绑定冲突——这是 ARP 欺骗的经典特征(攻击者冒充另一台 设备,通常是网关,以进行中间人拦截)。 重要提示:这仅用于检测/告警,而不是预防。ARP 欺骗 是一种二层攻击;通过 iptables(三层)拦截违规 IP 并 不能阻止它,因为攻击者仍然存在于您的本地网络 网段上。真正的缓解措施需要交换机级别的保护(动态 ARP 检查)或为您的网关等关键主机设置静态 ARP 条目。 需要捕获 ARP 流量:config.yml 中的 `bpf_filter` 必须包含 `arp`(默认值:`"arp or ip"`)。 ## DNS 隧道检测 监控 DNS 查询中经典的隧道特征:将数据编码为 一个基础域名下的许多唯一、随机的子域名 (例如 `a8f3k2x9.tunnel.evil.com`、`b91d7xq2.tunnel.evil.com` 等)。 两个独立的信号,任何一个都会触发告警: 1. 来自一个源的一个基础域名下有许多不同的子域名, 且查询速度很快(默认:10 秒内 15 次以上) 2. 单个高熵、长子域名标签(默认:20 个字符以上, 熵 >= 3.5 比特/字符)——看起来像 base32/64 编码的数据 可通过 config.yml 中的 dns_window_seconds、dns_min_distinct_subdomains、 dns_entropy_threshold、dns_min_label_length 进行调整。 实时验证:在一个虚假基础域名下使用随机子域名精心构造了 20 个 DNS 查询, 恰好在配置的阈值(第 15 个不同的子域名)处触发。 ## 隐秘扫描检测 (NULL/FIN/XMAS) 捕获 nmap 的隐秘扫描技术(-sN、-sF、-sX),这些技术故意 避免正常的 SYN,专门为了规避基于 SYN 的扫描/泛洪检测器: - NULL 扫描:完全没有设置任何标志的 TCP 数据包 - FIN 扫描:仅设置了 FIN 标志(没有 ACK——正常的连接关闭 是 FIN+ACK,这不会被标记) - XMAS 扫描:FIN+PSH+URG 全部一起设置 这些标志组合在合法流量中基本上不会出现,因此 这是一种无状态、即时的检查(不需要跟踪窗口)—— 直接添加到 check_hybrid_rules() 中,而不是像 ARP/DNS 需要 的单独跟踪器模块。 使用针对非白名单回环地址的真实 nmap -sN/-sF/-sX 扫描进行了实时验证;通过捕获的流量(正确的标志值: ''、'F'、'FPU')和记录了正确原因的告警进行了确认。 ## ICMP 泛洪(Ping 泛洪)检测 跟踪每个源 IP 的 ICMP 回显请求速率(默认:5 秒内 50 次以上 触发告警),重用了与 SYN 泛洪跟踪 相同的滑动窗口技术。 关于实时验证的诚实说明:经过测试时(向非白名单目标发送 60 个精心构造的 ICMP 数据包),告警 正确地触发了,但实际上是被基础 ML 异常模型捕获的,而不是 icmp_flood 规则具体 捕获的——因为训练数据通常包含接近于零的 ICMP 流量,所以 即使是单个 ICMP 数据包在模型看来也已经在统计学上 异常了,远早于达到规则的体积阈值。该规则 本身通过单元测试(隔离的、确定性的)确认为正确, 并作为后盾:如果训练数据稍后包含一些正常的 ICMP 流量(例如,您偶尔 ping 某些东西),ML 模型的 敏感度将恢复正常,而基于规则的阈值将成为 防御真实泛洪的主要手段。 ## 暴力破解登录检测 监控对已知身份验证端口的重复连接尝试 (SSH 22、Telnet 23、FTP 21、RDP 3389、MySQL 3306、PostgreSQL 5432、 MSSQL 1433、VNC 5900),使用比通用 repeated_port_probe 规则更低/更快的阈值(默认:5 次尝试),因为真实的 暴力破解工具会非常快速地访问这些端口。 在通用端口探测规则之前进行检查,因此对已知身份验证 端口的匹配会获得更具体的“brute_force”标签,而不是通用的 那个标签,即使两个阈值在技术上都可以被跨越。 可通过 config.yml 中的 brute_force_ports(列表)和 brute_force_threshold 进行配置。 实时验证:使用 hping3 模拟 SSH 暴力破解(10 个快速 SYN 数据包到端口 22),恰好在配置的 阈值(第 5 次尝试)处触发,并且在告警中确定了特定端口。 ## 无效的 TCP 标志组合 检测在真实网络堆栈中永远不会出现的逻辑上自相矛盾的 TCP 标志组合——仅来自用于 防火墙/IDS 规避或 OS 指纹识别的数据包构造工具: - SYN+FIN:一个声称同时打开和关闭连接的数据包 - SYN+RST:一个声称同时打开和中止连接的数据包 与 check_hybrid_rules() 中现有的 NULL/FIN/XMAS 隐秘扫描检测一起 检查——采用相同的无状态、即时检查模式。 实时验证:通过 Scapy 针对非白名单 回环目标精心构造 SYN+FIN 数据包,正确触发并识别出具体原因。 SYN+RST 使用相同的逻辑(通过单元测试确认);实时确认 由于 blocklist 去重正确地抑制了在同一 进程生命周期内对已被拦截的测试源 IP 的重复告警而变得复杂——这是一个已知的、正确的行为,而不是检测漏洞。 ## 基于 TTL 的 IP 欺骗检测 真实主机发送的数据包具有一致的 TTL,源自固定的 OS 起始值(Linux/Mac 为 64,Windows 为 128,某些网络设备为 255)减去 稳定网络路径上的跳数。如果相同的源 IP 突然显示出 截然不同的 TTL,那就是 IP 欺骗的强烈信号—— 攻击者的实际路径/OS 与真实主机的 不匹配。 镜像了 arp_monitor.py 的设计:每个 IP 的基准 TTL 在首次出现时固定,标记超出 ttl_anomaly_threshold 的偏差(默认值:20)。 局限性:合法的路由更改偶尔会使 TTL 移动 几跳(罕见的误报);基准不会随时间推移而适应。 实时验证:精心构造了两个具有相同欺骗源 IP 但 TTL 分别为 64 和 128 的 ICMP 数据包——正确触发,并在 告警原因中包含了确切的基准 和差异值。 注意:此会话还暴露了一类真实的反复出现的 bug——在 db.py 中向 TRAFFIC_COLUMNS 添加一 列不会追溯性地更改已经创建的 SQLite 表(CREATE TABLE IF NOT EXISTS 在现有表上是空操作)。通过重新创建数据库修复;添加了一个永久测试 (test_traffic_columns_match_actual_db_schema),用于检查新创建的 表的真实 schema 与 TRAFFIC_COLUMNS 是否一致。这捕获了 Python 列表与新表不匹配的情况,但不能捕获“已部署的数据库已过时”—— 当 TRAFFIC_COLUMNS 发生变化时,必须重新创建数据库(如果数据 很重要,请先通过 retention.py 进行备份/ 归档)。 ## Smurf 攻击检测 检测针对广播地址(255.255.255.255 或 x.x.x.255 样式的子网广播)的 ICMP 回显请求。在真实的 smurf 攻击中,这是 使用欺骗源(受害者的 IP)发送到网络的广播 地址,导致该网络上的每台主机都向受害者回复—— 从而放大流量。合法主机基本上永远不会 ping 广播 地址,因此这是一种可靠的无状态信号(与隐秘扫描和无效标志检查的模式相同——不需要跟踪器)。 实时验证:通过 Scapy 精心构造了发往 255.255.255.255 的 回显, 正确触发,并在告警原因中识别出了目标地址。 注意:发往广播的数据包通过默认接口 (eth0) 路由, 而不是 loopback,无论 ACF 的配置接口设置如何——这在最初的实时测试中绊倒了(当 interface="lo" 时发送的数据包 从未被捕获,因为它们根本没有接触到 loopback 接口)。 在调试期间通过 tcpdump -i any 确认。对于任何 未来与广播相关的测试,值得记住这一点。 ## Slowloris 检测 检测“许多缓慢涓涓细流般的连接”特征:与泛洪(许多数据包快速发送)不同,Slowloris 打开许多到同一目标端口的连接,并以最少的数据保持它们打开,在不看起来像体积攻击的情况下耗尽 服务器的连接池。 FlowTracker 计算每个(源、目标、端口)有多少当前 活动的流同时具有长持续时间(默认:30 秒以上)和非常低 的字节速率(默认:<=100 字节/秒)。slowloris_min_connections(默认: 10)设置了触发告警的此类缓慢流的数量。 关于实时验证的诚实说明:底层的 slow_flow_count 计算 已完全验证——通过单元测试以及对 check_hybrid_rules() 使用真实特征值(低 port_repeat_count, 高 slow_flow_count)的直接隔离调用进行了确认,这正确地以正确的原因触发了。 然而,实时端到端模拟(精心构造 SYN+ACK 对来模拟保持打开的连接)也碰巧触发了 repeated_port_probe 规则,该规则在 check_hybrid_rules 中较早被检查 并首先返回。这是 SYN 重复模拟 方法的属性,而不是 Slowloris 检测中的缺陷——真正的 Slowloris 攻击 每个连接只发送一个 SYN(没有重复),所以它根本不会触发 repeated_port_probe,而 slowloris 将是实践中捕获 它的规则。直截了当地记录下来,而不是声称产生了特定测试场景实际上并未产生的实时端到端 告警。 测试期间还发现:通过 bash heredoc 管道传输给 sudo 来发送定时脚本可能会悄无声息地破坏 time.sleep() 的时序(所有数据包 最终聚集在一起而不是散开)——可能是 stdin/pipe 交互所致。将脚本保存到文件并直接运行它 (sudo /path/to/script.py)可靠地解决了这个问题。 ## 流氓 DHCP 服务器检测 跟踪哪些 IP 已被观察到发送 DHCP 服务器响应 (OFFER 或 ACK 消息)。大多数家庭/小型网络恰好只有一台 合法的 DHCP 服务器(路由器)。如果第二个、不同的 IP 突然 开始作为 DHCP 服务器响应,那就会被标记为可能的流氓 DHCP 服务器——一种常见的中间人技术,因为恶意 服务器可以将假网关或 DNS 服务器分发给任何加入网络的新设备。 镜像了 arp_monitor.py 的设计:看到的第一台服务器建立 基准(不被标记),之后的任何不同的服务器都会被标记。 局限性:合法的 DHCP 故障转移/冗余设置(设计上有多个真实 服务器)会在第二个合法服务器上导致一次性误报。 关于实时验证的诚实说明:在此环境中,WSL 的虚拟网络完全阻止了出站 UDP 广播流量(通过 tcpdump -i any 确认,显示 ANY 广播 UDP 的数据包为零,不仅仅是 DHCP 端口特定或欺骗源数据包——也使用不相关的端口/有效载荷进行了 测试)。这是一个真实的环境限制, 而不是检测缺陷。ICMP 广播(用于 smurf 攻击测试) 在同一环境中运行良好,因此该限制似乎是特定于 UDP 广播的。 检测逻辑本身确实得到了验证:直接调用 check_rogue_dhcp() 处理了 真实的、正确构造的 Scapy DHCP 数据包对象(仅绕过了 WSL 阻止的网络传输步骤),确认了 正确的解析、基准建立以及带有确切预期原因文本的流氓服务器标记。这执行了与实时捕获使用的相同的代码路径——只是不需要数据包穿过 WSL 的 网络堆栈,而这在此设置中对于广播 UDP 是不可能的。
标签:Apex, iptables, 威胁情报, 开发者工具, 异常检测, 机器学习, 红队行动, 网络安全, 请求拦截, 逆向工具, 防火墙, 隐私保护