monch1962/l3-firewall

GitHub: monch1962/l3-firewall

一个纯 Go 实现的三层防火墙 sidecar,结合 NFQUEUE 和 OPA/Rego 策略即代码,对 IP 数据包进行实时安全检测与过滤。

Stars: 0 | Forks: 0

# l3-firewall 一个**三层防火墙 sidecar**,它使用 OPA/Rego 策略即代码来拦截、检查和过滤 IP 数据包。完全使用 Go 构建,零 cgo 依赖。 ``` ┌───────────┐ NFQUEUE ┌──────────────┐ rules ┌─────────┐ Client ─▶ nftables │ queue │ l3-firewall │◀───────▶│ OPA │ │ QUEUE │───────────▶│ sidecar │ eval │ Embedded │ │ rule │ verdict │ (userspace) │ │(in-proc) │ └───────────┘ └──────────────┘ └─────────┘ ``` ## 攻击覆盖范围 l3-firewall 的 OPA Rego 策略涵盖 **17 个攻击类别**,包含 **296 个 Go 测试**和 **76 个 Rego 测试**,以及跨越 15 个内部包和 12 个独立演示的 **28 个演示测试**。 请参阅 [`opa-demos/`](opa-demos/) 目录,获取涵盖每项功能的可运行、独立策略演示。 ### OPA 策略覆盖范围(17 个类别) | # | 攻击向量 | 检测方式 | 状态 | |---|---|---|---| | 1 | **IP 欺骗** — 源 IP 不在允许的子网中 | `allowed_subnets` 检查 (CIDR) | ✅ | | 2 | **端口扫描** — 快速连接多个目标端口 | `recent_ports` 阈值 | ✅ | | 3 | **SYN Flood** — 仅含 SYN 的数据包速率超过阈值 | `syn_rate_per_second` | ✅ | | 4 | **协议异常** — 无效的 TCP 标志 (SYN+RST, FIN+RST, SYN+FIN) | 标志组合检查 | ✅ | | 5 | **入口/出口过滤** — 目标 IP 不在允许的子网中 | `allowed_subnets` 检查 (CIDR) | ✅ | | 6 | **端口控制** — 阻断特定 TCP/UDP 端口(支持范围) | `blocked_ports` 列表 + `port_in_ranges()` | ✅ | | 7 | **ICMP 控制** — 阻断 ICMP 类型/代码,对 flood 进行速率限制 | `blocked_icmp_types/codes` + 速率 | ✅ | | 8 | **连接状态违规** — 向不存在的 flow 发送 RST | TCP FSM 状态跟踪 | ✅ | | 9 | **协议阻断** — 根据 IP 协议阻断流量 | `blocked_protocols` 列表 | ✅ | | 10 | **流量速率限制** — 每个源 IP 的 packets/sec 预算 | `max_packets_per_second` | ✅ | | 11 | **分片攻击** — 非零偏移量的 IP 分片 | `fragment.offset > 0` 检查 | ✅ | | 12 | **源端口过滤** — 阻断来自特定源端口的流量 | `port_in_ranges(src_port, blocked_ports)` | ✅ | | 13 | **新连接速率** — 来自单一源头的 flow 过多 | `new_conns_per_sec` 阈值 | ✅ | | 14 | **单端口速率限制** — 发往特定目标端口的流量过大 | `src_port_pps` 阈值 | ✅ | | 15 | **连接数限制** — 来自单一源 IP 的并发 flow 过多 | 每个源的 flow 计数器 + `MaxFlowsPerSrcIP` | ✅ | | 16 | **基于时间的访问** — 按小时和星期几进行阻断/允许 | `time_based_rules` 配合 `utc_hour`/`utc_day` | ✅ | | 17 | **GeoIP 阻断** — 根据源/目的国家进行阻断/允许 | MaxMind .mmdb + `blocked_src_countries` / `allowed_src_countries` | ✅ | ### 红队验证的传输层防护(19 项攻击模拟测试) | # | 攻击向量 | 防护措施 | 状态 | |---|---|---|---| | R1 | **阻断统计 map 无限制** — 唯一的拒绝原因耗尽内存 | 上限设为 256 条目 | ✅ | | R2 | **速率限制器 map 无限制** — 唯一的 IP 耗尽内存 | 上限 10 万条目,驱逐最早的 | ✅ | | R3 | **引擎 panic 崩溃** — 未捕获的 panic 杀死进程 | 在 packetHandler + evaluatePacket 中使用 `recover()` | ✅ | | R4 | **端口速率限制器无限制** — IP:port 组合耗尽内存 | 与 R2 相同的 MaxEntries 上限 | ✅ | | R5 | **OPA 超时硬编码** — 无法针对工作负载进行调整 | `EmbedConfig.Timeout` (0 = 默认 500ms) | ✅ | | R6 | **并发阻断统计竞争** — map 写入时发生竞争 | 受 `sync.RWMutex` 保护 | ✅ | | R7 | **阻断统计原因 flood** — 大量唯一原因 | 达到 256 条目上限后阻止新条目写入 | ✅ | | R8 | **速率限制器突发间隙** — 60秒清理窗口导致 OOM | MaxEntries 驱逐机制处理突发流量 | ✅ | | R9 | **每源 flow 计数无限制** — 大量源 IP 耗尽 `srcFlowCount` map | 每 IP 计数器自然受 `MaxEntries` (65536) 限制 | ✅ | | R10 | **状态文件内存耗尽** — 大型/恶意 JSON 状态文件 | LoadState 中的 `io.LimitReader` (10MB 上限) | ✅ | | R11 | **Nil 阻断统计 panic** — 重载 nil `BlockStats` map 时写入发生 panic | 在 LoadState 中自动初始化 map | ✅ | | R12 | **威胁情报主体大小** — 恶意情报服务器发送大量响应 | 针对 FetchFromURL resp.Body 使用 `io.LimitReader` (50MB 上限) | ✅ | | R13 | **onUpdate 回调 panic** — 策略回调中的 panic 杀死 goroutine | 所有回调调用周围的 `safeOnUpdate()` panic 恢复包装器 | ✅ | | R14 | **Unicode MAC 绕过** — Unicode 空白字符(NBSP、细空格等)绕过 MAC 规范化 | `strings.Fields()` 在 `normalizeMAC` 中剥离所有 Unicode 空白字符类别 | ✅ | | R15 | **零间隔 ticker panic** — `StartRefresher(0)` 因 `time.NewTicker(0)` panic 而崩溃 | 最小间隔保护 (100ms) 钳制低于最小值的请求 | ✅ | | R16 | **pcap WriteBlock panic 故障开放** — `WriteBlock` 中的 panic 导致 `packetHandler` 返回 0 (NF_ACCEPT) 而非 1 (NF_DROP) | `packetHandler` 中的命名返回在 panic 恢复时设置 `ret=1` | ✅ | | R17 | **pcap WriteBlock 错误静默丢弃** — Pcap 捕获失败对运维人员不可见 | 错误通过 `slog.Warn` 记录 | ✅ | | R18 | **saveState 错误静默丢弃** — 状态持久化失败对运维人员不可见 | 错误通过 `slog.Warn` 记录 | ✅ | | R19 | **IPv4 映射的 IPv6 黑名单绕过** — `::ffff:10.0.0.1` 在威胁情报中不匹配 `10.0.0.1` | `Add` 和 `Contains` 中均使用 `To4()` 进行规范化 | ✅ | ### 已验证测试覆盖率(339 个 Go+Rego 测试) | 包 | 测试数 | 覆盖范围 | |---------|-------|----------------| | `internal/packet` | 11 | TCP (SYN/SYN-ACK-RST-FIN)、UDP、ICMP echo、short/nil、大小、IPv6、分片检测(非零偏移、首分片、非分片)、MAC 地址提取 | | `internal/opa` | 13 | 结果 JSON、输入构建 (TCP/UDP/ICMP/端口/分片/速率/时间/GeoIP)、数据存储 CRUD、嵌入式 eval 阻断/允许、runtime 参数、错误策略、nil store | | `internal/conntrack` | 25 | 每个协议的超时时间、TCP/UDP/ICMP 过期、统计信息(命中/创建/过期/驱逐)、新连接速率、TCP FSM (SYN→ESTABLISHED→FIN→RST→CLOSED)、并发访问、每源 flow 限制(限制下阻断、多源、删除后、过期后、统计、TCP 状态、默认无限制) | | `internal/geoip` | 6 | NewReader nil 路径、错误路径、nil reader 查询、无效 IP、nil DB、真实文件(跳过) | | `internal/threatintel` | 30 | NewBlocklist、添加/包含/移除、CIDR、重复、并发、URL 获取、HTTP 错误、刷新、nil 安全、OPA 数据、主体大小限制、刷新增长、快速刷新、URL 编码的 IP、空黑名单移除、零间隔保护、双重关闭预防、慢速服务器、并发 CIDR/包含、IPv6 包含、带 CIDR 的 DataForOPA、IPv4 映射的 IPv6 规范化、IP 边缘情况、超长字符串、nil stopCh | | `internal/ratelimit` | 15 | 基本配额、突发、每 IP 独立性、字节速率、陈旧清理、活跃 key 保留、并发、速率查询、每目标端口 AllowPort、GetPortPPS、端口独立性、未知端口 | | `internal/audit` | 7 | NewLogger 默认路径、阻断事件、允许事件、并发安全、轮转、关闭、无效路径 | | `internal/capture` | 15 | NewWriter nil 目录、目录创建、写入块、轮转、nil 安全、关闭、目录遍历、高文件数量、并发关闭/写入、大数据包、无最大数据包大小、清理大量文件、关闭后写入、并发写入 | | `internal/engine` | 17 | 允许、阻断、TCP 状态跟踪、conntrack 更新、仅审计、故障关闭、速率限制、ICMP、最近阻断、阻断元数据、运行状态、统计信息、连接限制阻断、不同源 OK、pcap panic 故障开放、pcap 错误静默丢弃、saveState 错误静默丢弃、引擎+threatintel 边缘情况、状态持久化集成、引擎+threatintel 阻断、panic 恢复 | | `internal/alert` | 9 | 类型字符串、默认值、webhook payload、冷却抑制、多类型、异步非阻塞、nil 安全、并发 | | `internal/l2filter` | 21 | MAC 允许/阻断、规范化、nil 过滤器、ARP 学习/不匹配/一致、DHCP、空 MAC、非十六进制字符、广播/多播、长度极端值、并发规范化、大型 MAC 列表、Unicode 空白字符绕过、MAC 同形异义词、DHCP 空 IP、ARP 长 IP、并发 CheckARP | | `internal/admin` | 11 | 健康、统计、阻断、阻断统计、规则 GET/UPDATE、无效 JSON、错误方法、认证、策略版本 | | `internal/persist` | 13 | 保存/加载、缺失文件、空路径、损坏文件、nil 安全、超大文件、路径遍历、稀疏文件、nil 阻断统计、tmp 墓碑文件、超大 BlockStats、并发保存 | | `internal/syncer` | 13 | 空 endpoint、错误 endpoint、nil start、nil close、回调、context 取消、nil onUpdate、关闭后启动、nil client watch、多次 Start 泄漏、无策略大小限制、safeOnUpdate panic 恢复、列表中的空 endpoint | | OPA 策略 (Rego) | 76 | 默认允许、CIDR 匹配 (6)、IP 欺骗 (3)、端口扫描 (2)、SYN flood (2)、协议异常 (4)、入口/出口 (2)、端口控制 (7)、ICMP 控制 (3)、状态违规 (2)、协议阻断 (2)、流量速率 (3)、分片攻击 (3)、端口范围 (6)、源端口过滤 (2)、新连接速率 (2)、单端口速率 (2)、组合 (1)、基于时间的规则 (13)、GeoIP 规则 (11) | ## 架构 ``` Packets → [nftables NFQUEUE] → engine.evaluatePacket() ├── packet.ParsePacket(raw bytes) ├── conntrack.LookupOrCreate(5-tuple) ├── ratelimit.Allow(srcIP, packetSize) ├── opa.BuildInput(packet + rate + conn state + time) ├── opaEval.Evaluate(input) ├── NF_ACCEPT or NF_DROP + stats └── audit.Log() → JSON file (block/allow events) Admin API (:8082) ├── /admin/health → {"status":"ok","version":"0.1.0","uptime":"...","engine_running":bool} ├── /admin/stats → {"packets_processed":N,"packets_allowed":N,"packets_blocked":N, │ "conntrack_entries":N,"conntrack_expired":N,"conntrack_evicted":N} ├── /admin/blocks → [{timestamp,src_ip,dst_ip,protocol,src_port,dst_port,reason,...}] ├── /admin/block-stats → {"blocked SSH": 42, "SYN flood": 7, ...} ├── /admin/policy/reload → Trigger policy hot-reload (POST) ├── /admin/policy/versions → Policy reload history └── State + pcap files on disk Metrics (:9090 or admin port) └── /metrics → Prometheus format ``` ### 关键设计决策 | 决策 | 选择 | 理由 | |----------|--------|-----------| | **拦截** | 通过 `florianl/go-nfqueue` 的 NFQUEUE | 纯 Go、内核级过滤、在 `CAP_NET_ADMIN` 下兼容容器 | | **数据包解析** | `google/gopacket` | 成熟稳定、全面的协议支持 | | **策略引擎** | OPA 嵌入式(进程内) | ~10µs 评估、可通过 `opa test` 测试策略、与 gql-firewall 相同的模式 | | **安全模型** | Deny-override | 流量默认放行,匹配拒绝规则时被阻断 | | **速率限制** | 基于 EWMA 的 PPS/BPS | 平滑的速率估算,避免骤降 | | **连接跟踪** | 5 元组 flow 表 | 针对连接状态违规的有状态检测 | ## 快速入门 ### 前置条件 - Go 1.25+ - OPA 1.0+(用于策略测试:`opa test opa-policies/`) - 带有 nftables 的 Linux(用于 NFQUEUE runtime) - 容器:`--cap-add=NET_ADMIN` ### 构建与测试 ``` # 构建 make build # 运行所有 Go 和 Rego 测试 make test # 仅运行 Go 测试 make test-go # 仅运行 Rego 测试 make test-opa # Lint 和 vet make lint make vet ``` ### 运行(开发环境 — 无 NFQUEUE) ``` # 仅启动 admin API 进行测试(engine 会记录 NFQUEUE 错误) ./l3-firewall --admin-listen :8082 ``` ### 运行(容器) ``` docker build -t l3-firewall:latest . docker run --cap-add=NET_ADMIN --rm -p 8082:8082 l3-firewall:latest ``` 入口点(`deploy/entrypoint.sh`)配置 nftables 将转发和输入流量发送到 QUEUE,然后启动防火墙二进制文件。 ## 配置 ### CLI 标志 | 标志 | 默认值 | 描述 | |------|---------|-------------| | `--admin-listen` | `:8082` | Admin API 监听地址 | | `--admin-token` | `""` | 用于 Admin API 认证的 Bearer token | | `--queue` | `0` | 用于转发流量的 NFQUEUE 编号 | | `--queue-input` | `1` | 用于输入流量的 NFQUEUE 编号 | | `--opa-embed` | `./opa-policies/l3.rego` | Rego 策略文件的路径(配置嵌入在此处) | | `--opa-fail-closed` | `false` | 当 OPA 不可达时进行阻断 | | `--opa-audit-only` | `false` | 在不强制执行的情况下记录潜在的阻断行为 | | `--log-format` | `text` | 日志格式:text 或 json | | `--metrics-listen` | `""` | 独立的 metrics 地址(空 = 在 admin 端口上提供) | | `--rate-limit-pps` | `0` | 每 IP 数据包速率限制(0 = 不限制) | | `--rate-limit-bps` | `0` | 每 IP 字节速率限制(0 = 不限制) | | `--conntrack-max` | `65536` | 最大跟踪连接数 | | `--conntrack-idle` | `5m` | TCP 连接空闲超时 | | `--conntrack-udp-timeout` | `30s` | UDP 连接空闲超时 | | `--conntrack-icmp-timeout` | `5s` | ICMP 连接空闲超时 | | `--conntrack-max-flows-per-src` | `0` | 每个源 IP 的最大并发 flow 数(0 = 不限制) | | `--audit-log` | `""` | 结构化 JSON 审计日志的路径(空 = 不进行审计日志记录) | | `--alert-webhook-url` | `""` | 用于防火墙告警的 webhook URL(例如 Slack, Discord, PagerDuty) | | `--geoip-db` | `""` | 用于国家/地区查找的 MaxMind GeoLite2/GeoIP2 .mmdb 数据库路径 | | `--threat-intel-url` | `""` | 指向 IP 信誉黑名单的 URL(逗号分隔,自动刷新) | | `--pcap-dir` | `""` | 用于被阻断数据包 pcap 捕获的目录 | | `--state-file` | `""` | 用于在重启过程中持久化防火墙状态的路径 | | `--etcd-endpoints` | `""` | 用于分布式策略同步的 etcd endpoint(逗号分隔) | | `--etcd-key` | `/l3-firewall/policy` | 监视策略更新的 etcd key | ### 策略配置(嵌入在 `opa-policies/l3.rego` 中) 配置以 Rego 常量的形式直接嵌入在 OPA/Rego 策略文件中。 要更改配置:编辑 `.rego` 文件 —— 热重载器会在 5 秒内获取更改。 | 常量 | 类型 | 默认值 | 描述 | |----------|------|---------|-------------| | `allowed_subnets` | array | `["0.0.0.0/0"]` | 允许的源/目的子网 | | `allowed_ports` | array | `[]` | 仅允许这些端口(空 = 允许所有) | | `blocked_ports` | array | `[22,23,3389,5900,5901]` | 被阻断的 TCP/UDP 端口 | | `blocked_protocols` | array | `[]` | 被阻断的 IP 协议 | | `blocked_icmp_types` | array | `[8]` | 被阻断的 ICMP 类型 | | `blocked_icmp_codes` | array | `[]` | 被阻断的 ICMP 代码 | | `syn_rate_per_second` | number | `100` | SYN flood 阈值 | | `icmp_rate_per_second` | number | `10` | ICMP flood 阈值 | | `max_packets_per_second` | number | `10000` | 每 IP 数据包速率限制 | | `enable_ip_spoofing_check` | bool | `true` | 启用 IP 欺骗检测 | | `enable_port_scan_detection` | bool | `true` | 启用端口扫描检测 | | `enable_syn_flood_protection` | bool | `true` | 启用 SYN flood 保护 | | `enable_stateful_inspection` | bool | `true` | 启用连接状态跟踪 | | `enable_ingress_egress_filtering` | bool | `true` | 启用入口/出口过滤 | | `connection_table_size` | number | `65536` | 最大跟踪连接数 | | `connection_idle_timeout_sec` | number | `300` | TCP 连接空闲超时(秒) | | `connection_udp_timeout_sec` | number | `30` | UDP 连接空闲超时(秒) | | `connection_icmp_timeout_sec` | number | `5` | ICMP 连接空闲超时(秒) | | `port_scan_threshold` | number | `20` | 触发扫描检测的唯一端口数 | | `port_scan_window_sec` | number | `10` | 端口扫描检测窗口 | | `max_new_connections_per_second` | number | `1000` | 每 IP 新建连接速率限制 | | `max_port_pps` | number | `500` | 每个目标端口的 PPS 限制 | | `time_based_rules` | array | `[]` | 计划访问规则:`{ports, days(0-6), start_hour, end_hour, effect("deny"|"allow")}` | | `blocked_src_countries` | set | `{"KP"}` | 阻断的源国家代码 (ISO 3166-1 alpha-2) | | `allowed_src_countries` | set | `{}` | 仅允许这些源国家代码(空 = 允许所有) | | `allowed_dst_countries` | set | `{}` | 仅允许这些目的国家代码(空 = 允许所有) | ## 安全特性 | 特性 | 机制 | 防范内容 | |---------|-----------|------------------| | Admin API 认证 | `--admin-token` | 未经授权的规则更改 | | OPA 故障关闭 | `--opa-fail-closed` | 通过 OPA DoS 绕过 | | 仅审计模式 | `--opa-audit-only` | 在强制执行前安全地收集数据 | | Deny-override 模型 | 默认 `allow := true` | 安全的分阶段推出 | | 速率限制器 map 上限 | MaxEntries 驱逐(最早优先) | 因唯一 IP 导致的内存耗尽 | | 阻断统计原因上限 | 最多 256 种唯一的拒绝原因 | 因原因 flood 导致的内存耗尽 | | 引擎 panic 恢复 | packetHandler + evaluatePacket 中的 defer/recover | 意外 panic 导致的进程崩溃 | | 可配置的 OPA 超时 | EmbedConfig.Timeout (0=默认 500ms) | 针对特定工作负载调整超时 | | TCP FSM 跟踪 | 9 状态机 (SYN→ESTABLISHED→FIN→CLOSED) | 连接状态违规、逃避性握手 | | 分片检测 | 解析 IPv4 FragOffset + MoreFragments | 基于分片的规避(重叠、微小分片) | | CIDR 子网匹配 | `net.cidr_contains` | 真正的子网过滤(非字符串匹配) | | 端口范围 | `port_in_ranges()` 辅助函数 | 基于范围的规则(例如 `"8000-9000"`) | | 每个协议的超时 | TCP=300s, UDP=30s, ICMP=5s | 每种协议的最佳内存使用量 | | 丢弃日志记录 | 结构化 slog + 环形缓冲区 | 对被阻断流量的取证分析 | | 最近阻断 API | `/admin/blocks` | 对阻断情况的实时可见性 | | Conntrack 统计信息 | `/admin/stats` | 监控连接表健康状态 | | 引擎健康状态 | `/admin/health` endpoint | Liveness 和 readiness 探针 | | Body 大小限制 | `http.MaxBytesReader` | Admin API OOM | | 服务器超时 | `ReadHeaderTimeout`、`IdleTimeout` | 慢速攻击 / 连接耗尽 | | 优雅关闭 | 信号处理 + context 取消 | 部署时丢弃连接 | | 每 IP 速率跟踪 | 基于 EWMA 的 PPS/BPS | 内存高效的速率估算 | | 连接限制 | 受 `MaxFlowsPerSrcIP` 限制的每源 flow 计数器 | 通过过多并发连接进行的 DoS | | 基于时间的调度 | Rego 策略中带有 UTC 小时/天的 `time_based_rules` | 阻止在批准时间之外的访问 | | 审计日志记录 | `--audit-log` 写入结构化 JSON | SIEM 集成、合规审计追踪 | | Webhook 告警 | `--alert-webhook-url` 在事件发生时触发 JSON POST | 实时事件通知 | | GeoIP 过滤 | `--geoip-db` + Rego `blocked_src_countries` / `allowed_src_countries` | 基于国家/地区的访问控制 | | 威胁情报源 | `--threat-intel-url` 获取 IP 黑名单 | 阻断已知的恶意 IP | | MAC 过滤 | `--mac-allow` / `--mac-block` + L2 过滤器 | MAC 欺骗、未经授权的设备 | | Unicode MAC 规范化 | `strings.Fields()` 剥离所有 Unicode 空白字符 | 通过 NBSP、细空格等绕过 MAC 过滤 | | ARP/DHCP 检测 | IP→MAC 绑定表、更改检测 | ARP 欺骗、DHCP 投毒 | | 数据包捕获 | `--pcap-dir` 将被阻断的数据包写入 pcap | 取证分析 | | 状态持久化 | `--state-file` 将阻断统计信息保存为 JSON | 重启后保留计数器 | | 状态持久化大小限制 | LoadState 中的 `io.LimitReader` (10MB) | 通过恶意状态文件造成的内存耗尽 | | 策略版本控制 | `/admin/policy/versions` endpoint | 规则更改的审计追踪 | | 分布式同步 | `--etcd-endpoints` 监视 etcd 以获取策略更新 | 多实例规则的一致性 | | etcd watcher panic 恢复 | 围绕所有回调调用的 `safeOnUpdate()` 包装器 | syncer 中 onUpdate panic 导致的 Goroutine 死亡 | | 威胁情报源主体限制 | 针对 FetchFromURL resp.Body 的 `io.LimitReader` (50MB) | 通过恶意情报源服务器造成的内存耗尽 | | Nil 阻断统计防护 | 在 LoadState 中自动初始化 `BlockStats` map | 状态重载时的 nil map panic | ## 项目结构 ``` l3-firewall/ ├── cmd/server/main.go # Entry point, flag parsing, wiring ├── internal/ │ ├── packet/parser.go # L3/L4 header parsing (gopacket) │ ├── engine/engine.go # NFQUEUE reader, eval pipeline │ ├── opa/ # OPA embedded evaluator │ │ ├── embed.go # In-process Rego evaluation │ │ ├── input.go # Input document builder │ │ ├── result.go # Result type │ │ ├── store.go # Thread-safe params store │ │ └── evaluator.go # Evaluator interface │ ├── conntrack/table.go # 5-tuple connection tracking │ ├── ratelimit/ratelimit.go # Per-IP EWMA rate limiter │ ├── alert/alert.go # Webhook alerting with cooldown │ ├── audit/audit.go # Structured JSON audit logging │ ├── geoip/geoip.go # MaxMind GeoIP country lookup │ ├── l2filter/l2filter.go # MAC filtering & ARP/DHCP inspection │ ├── threatintel/threatintel.go # IP reputation blocklist fetcher │ ├── capture/capture.go # Pcap packet capture on block │ ├── persist/persist.go # State persistence across restarts │ ├── syncer/syncer.go # Distributed policy sync via etcd │ ├── metrics/metrics.go # Prometheus metrics │ └── admin/api.go # REST admin API ├── opa-policies/ │ ├── l3.rego # 10 attack rule categories │ └── l3_test.rego # Rego policy tests ├── config/params.json # Default parameters ├── deploy/entrypoint.sh # Container nftables setup ├── Makefile # Build, test, lint, docker ├── Dockerfile # Multi-stage container build └── .github/workflows/ci.yml # CI pipeline ``` ## OPA 策略测试 所有防火墙规则在部署前均可进行测试: ``` # 测试所有 Rego 策略 opa test opa-policies/ -v # 带覆盖率测试 opa test opa-policies/ --coverage # 单独测试 opa test opa-policies/ -r test_default_allow ``` Rego 策略测试示例(`opa-policies/l3_test.rego`): ``` package l3_firewall mock_params := {"enable_ip_spoofing_check": false} test_default_allow if { allow with data.params as mock_params } test_ip_in_subnets_exact if { ip_in_subnets("10.0.0.1", {"10.0.0.1"}) } ``` ## 性能 - **数据包解析**:每个数据包约 1µs(gopacket,缓存的层类型) - **OPA 评估**:每个数据包约 10µs(进程内,预编译的查询) - **连接查找**:使用 RWMutex 的 O(1) 哈希 map - **速率限制**:O(1) EWMA 更新 ## 对比 | 特性 | l3-firewall | nftables | iptables | |---------|-------------|----------|----------| | 策略语言 | Rego(可测试) | nft 语法 | iptables 语法 | | 有状态检测 | ✅ 5 元组跟踪 | ✅ conntrack | ✅ conntrack | | 端口扫描检测 | OPA 可配置 | ❌ | ❌ | | 动态规则更新 | ✅ REST API | nft 命令 | iptables 命令 | | 仅审计模式 | ✅ | ❌ | ❌ | | 策略测试 | ✅ `opa test` | ❌ | ❌ | | 每 IP 速率限制 | ✅ 基于 EWMA | ✅ limit 匹配 | ✅ limit 匹配 | | 协议异常检测 | ✅ OPA 规则 | ❌ | ❌ | | 容器支持 | ✅ `--cap-add=NET_ADMIN` | ✅ | ✅ |
标签:EVTX分析, Go语言, NFQUEUE, OPA/Rego, 云原生Sidecar, 入侵防御, 插件系统, 日志审计, 程序破解, 结构化提示词, 网络安全, 网络防火墙, 自动化扫描, 自定义请求头, 配置错误, 隐私保护