grounzero/pfsense-redactor

GitHub: grounzero/pfsense-redactor

专门针对 pfSense config.xml 导出文件进行机密信息脱敏与网络标识符匿名化的命令行工具,用于安全地共享配置。

Stars: 11 | Forks: 0

# pfSense XML 配置脱敏工具 [![PyPI version](https://badge.fury.io/py/pfsense-redactor.svg)](https://pypi.org/project/pfsense-redactor/) [![Python Versions](https://img.shields.io/pypi/pyversions/pfsense-redactor.svg)](https://pypi.org/project/pfsense-redactor/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Tests](https://static.pigsec.cn/wp-content/uploads/repos/cas/09/097271ca091990be630ef6043309cc48240faa054413384202036fa2efedb2d2.svg)](https://github.com/grounzero/pfsense-redactor/actions/workflows/tests.yml) [![Downloads](https://pepy.tech/badge/pfsense-redactor)](https://pepy.tech/project/pfsense-redactor) 安全地脱敏 pfSense `config.xml` 导出文件中的敏感字段,让您在分享时不会暴露密码、密钥或网络标识符。 **关键词:** pfSense config.xml 脱敏工具、pfSense 清理器、防火墙配置清理、VPN 配置匿名化、OpenVPN 脱敏、WireGuard 密钥脱敏、IPsec 密钥移除、网络拓扑匿名化工具、Netgate TAC 共享 **pfsense-redactor** 会对 pfSense `config.xml` 导出文件中的机密信息进行脱敏,并可选择对标识符进行匿名化处理——以便您可以安全地将其分享给技术支持、供应商、审计人员、论坛或 AI 工具。 与通用的 XML 脱敏工具不同,pfsense-redactor 深入理解 pfSense 特定的配置结构和 VPN 格式。 ## 为什么选择 pfsense-redactor? - ✅ **pfSense 原生支持** – 深入理解 pfSense XML 结构(IPsec、OpenVPN、WireGuard、软件包) - ✅ **零依赖** – 纯 Python 标准库,可在任何地方运行(Windows、macOS、Linux) - ✅ **经过充分测试** – 在多种操作系统和 Python 版本上进行了全面测试 - ✅ **保留拓扑** – 匿名化而不破坏路由逻辑或防火墙规则 - ✅ **安全至上** – 内置防止路径遍历和符号链接攻击的保护措施 - ✅ **适配 CI/CD** – 适用于自动化合规工作流和 GitOps ## 何时使用 pfsense-redactor? 当您需要在防火墙外部共享 pfSense `config.xml` 文件时(例如与供应商、顾问、论坛或 AI 工具共享),并且希望在不破坏拓扑或路由逻辑的前提下移除机密信息和/或对网络标识符进行匿名化处理,请使用 pfsense-redactor。 ### 快速开始(推荐) #### 1) 保留私有 IP(最适合技术支持 / 故障排查) ``` pfsense-redactor config.xml redacted.xml --keep-private-ips ``` 保持内部寻址可见,同时移除机密信息并对公共标识符进行脱敏。 #### 2) 保留拓扑的匿名化(最适合供应商 / 论坛 / AI) ``` pfsense-redactor config.xml redacted.xml --anonymise ``` 使用一致的占位符替换标识符,这样在降低信息泄露风险的同时,仍能保持清晰的关系。 关于在 pfSense 防火墙本机进行的清理,请参阅下文的 `diag_sanitize.php`;pfsense-redactor 专为脱机使用和匿名化而设计。 有关所有可用选项,请参阅下方的[用法](#usage)部分和[命令行参数参考](#command-line-flags-reference)。 ## 使用场景 根据您的分享对象,这里提供了常见的命令模式。 ### 与 Netgate TAC 技术支持共享 ``` # 在防火墙上(推荐用于 TAC) /usr/local/sbin/diag_sanitize.php /conf/config.xml > /conf/config_sanitised.xml # Off-box:在进一步共享之前进行额外的匿名化 pfsense-redactor config_sanitised.xml support-safe.xml --keep-private-ips --no-redact-domains ``` ### 与 AI 工具共享 如果您安装了第三方软件包,或者不确定机密信息隐藏在哪里,请使用 `--aggressive`。 ``` # 保持拓扑结构的匿名化(使用 --anonymise 时,默认保持 private IP 可见) pfsense-redactor config.xml ai-ready.xml --anonymise --aggressive # 现在可以安全地上传到 AI 工具进行配置分析 ``` ``` # 匿名化所有内容(包括 private IP) pfsense-redactor config.xml ai-ready.xml --anonymise --no-keep-private-ips --aggressive # 现在可以安全地上传到 AI 工具进行配置分析 ``` ### 交付给供应商/MSP ``` # 选项 A:保留 private IP 以用于故障排查上下文 pfsense-redactor config.xml vendor-share.xml --anonymise ``` ``` # 选项 B:匿名化所有内容(包括 private IP)以实现更严格的隐私保护 pfsense-redactor config.xml vendor-share.xml --anonymise --no-keep-private-ips ``` ### 安全审计 ``` # 在共享前预览将被脱敏的内容 pfsense-redactor config.xml --dry-run-verbose ``` ### 自动化合规工作流 ``` # CI/CD 集成以实现自动化脱敏 pfsense-redactor $INPUT_CONFIG $OUTPUT_CONFIG --aggressive --fail-on-warn ``` ## 与 pfSense 内置清理功能的关系 pfSense 包含一个内置的配置清理脚本: ``` /usr/local/sbin/diag_sanitize.php /conf/config.xml > /conf/config_sanitised.xml ``` 这个官方工具**在防火墙本机**运行,主要用于安全地与 Netgate 技术支持共享配置。它会移除高价值机密(密码哈希、预共享密钥、证书等),同时保留原始网络拓扑。 **pfsense-redactor 是互补工具,而非替代品。** | 内置的 `diag_sanitize.php` | pfsense-redactor | | ------------------------------------ | ----------------------------------------------------------------- | | 仅在 pfSense 上运行 | 可在任何地方运行(工作站、CI、自动化环境) | | PHP 编写,pfSense 内部组件 | Python 编写,独立运行,基于 MIT 许证证 | | 固定的清理行为 | 可配置的脱敏与匿名化规则 | | 移除机密信息 | 移除机密信息,**并且**可以对 IP、域名、MAC 地址和 URL 进行匿名化 | | 最适合 Netgate 技术支持 (TAC) | 最适合分享给供应商、顾问、AI 工具和论坛 | pfsense-redactor 的存在是为了涵盖以下使用场景: - 配置文件已经导出, - 您不希望在防火墙上运行额外的工具, - 或者除了基本的机密移除外,您还需要**保护隐私的匿名化**。 这两个工具的目标一致:在共享 pfSense 配置时,防止意外泄露敏感信息。 ## 与替代方案对比
与替代方案对比 | 功能 | pfsense-redactor | 通用 XML 工具 | 手动脱敏 | 内置 diag_sanitize.php | | ----------------------- | ----------------- | ----------------- | ---------------- | -------------------------- | | 感知 pfSense 结构 | ✅ | ❌ | ⚠️ 手动 | ✅ | | 支持脱机运行 | ✅ | ✅ | ✅ | ❌ (仅限 pfSense) | | 网络匿名化 | ✅ | ❌ | ⚠️ 容易出错 | ❌ | | 保持拓扑结构 | ✅ | ❌ | ⚠️ 容易出错 | ✅ | | 可配置模式 | ✅ 多种模式 | ❌ | 不适用 | ❌ 固定模式 | | CIDR 白名单 | ✅ | ❌ | ⚠️ 容易出错 | ❌ | | CI/CD 集成 | ✅ | ⚠️ | ⚠️ 容易出错 | ❌ | | 跨平台支持 | ✅ | ⚠️ | ✅ | ❌ | | 感知 WireGuard/IPsec | ✅ | ❌ | ⚠️ | ✅ | | 零依赖 | ✅ | ⚠️ 视情况而定 | ✅ | ✅ |
## 常见问题 ### pfsense-redactor 默认会脱敏哪些内容? pfsense-redactor 会移除诸如密码、私钥、证书、token 和共享密钥等机密信息。 除非明确要求保留,否则它也会对公共 IP 地址、域名、MAC 地址和 URL 进行脱敏。 ### pfsense-redactor 是进行匿名化还是仅仅移除数据? 两者都支持。脱敏会彻底移除敏感值,而匿名化则会使用一致的占位符替换标识符,从而保持拓扑和关系的清晰。 ### 匿名化会破坏故障排查或拓扑分析吗? 不会。确定性的匿名化确保相同的标识符始终被替换为相同的别名,从而保留逻辑关系和路由流。 ### 我可以安全地将输出结果分享给供应商或 AI 工具吗? 可以。pfsense-redactor 专为对外共享配置而设计,不会暴露机密或可识别的网络信息。 脱敏后的输出仅供分析使用,切勿将其恢复至 pfSense。 ### 它能理解 pfSense 特定的配置结构吗? 能。与通用的 XML 脱敏工具不同,pfsense-redactor 理解 pfSense 的配置布局,包括 VPN、接口、网关以及常见的软件包 XML 结构。 ### 什么时候应该使用 aggressive 模式? 当公开发布配置或第三方软件包可能包含未知的敏感字段时,请使用 `--aggressive`。 aggressive 模式扩大了机密检测和标识符重写的范围。在默认行为的基础上,它还会: - 对任意元素中无法识别的高熵值(base64/hex/PEM 格式)进行脱敏,而不是仅仅将其报告出来 - 直接对自由文本选项块(`custom_options`、`userparams`、`upsd_users`、`advanced` 等)进行整体脱敏 - 对包含凭据格式的 URL **路径**段进行脱敏,例如 Slack/Discord 的 webhook token - 将 IP/域名脱敏应用于所有元素文本,而不仅仅是已知字段 ### 我可以将脱敏后的文件恢复到 pfSense 吗? 不能。脱敏后的输出仅供分析/共享使用,绝不能重新导入 pfSense。 ## 安装说明 ### 通过 PyPI 安装(推荐) ``` pip install pfsense-redactor ``` ### 通过源码安装 ``` git clone https://github.com/grounzero/pfsense-redactor.git cd pfsense-redactor ``` **选项 1:开发模式(推荐用于参与贡献)** ``` pip install -e . ``` **选项 2:使用虚拟环境** ``` python3 -m venv venv source venv/bin/activate pip install -e . ``` 该工具在清理**机密信息和标识符**的同时,会保留**网络架构和路由逻辑**,从而允许进行安全的故障排查和拓扑审查而不会泄露私有数据。 ## 功能 ### 保护真实的机密信息 - 密码和加密密码 - 预共享密钥(IPSec、OpenVPN、WireGuard) - TLS/OpenVPN 静态密钥和证书 - SNMP community 字符串 - LDAP / RADIUS 密钥 - API 密钥和 token - PEM 块(RSA / EC / OpenSSH) ### 保留网络逻辑 - 子网和掩码(255.x.x.x 始终保留) - 路由器拓扑 - VLAN 和 VPN 接口 - 防火墙规则和网关 ### 智能脱敏 | 数据 | 行为 | | ---------------- | ----------------------------------- | | 内部 IP | 使用 `--keep-private-ips` 保留 | | 公共 IP | 掩码或匿名化 | | 电子邮件地址 | 掩码或匿名化 | | URL | 保留结构,对主机名掩码处理 | | MAC 地址 | 掩码并保持格式 | | 证书 | 折叠为 `[REDACTED_CERT_OR_KEY]` | ### 操作模式 | 模式 | 用途 | | ----------------------- | ------------------------------------------------------------------- | | 默认 | 用于安全地共享日志的脱敏模式 | | `--keep-private-ips` | 保留私有 IP(最适合支持/AI) | | `--anonymise` | 用一致的占位符替换标识符(`IP_1`、`domain3.example`) | | `--aggressive` | 清理**所有**字段(插件/自定义 XML) | | `--redact-descriptions` | 同时脱敏描述、主机名和 SSID(可能包含个人姓名) | ## 环境要求 - **Python 3.9+** ## 用法 ### 基本用法 ``` # 输出文件名自动生成为 config-redacted.xml pfsense-redactor config.xml # 或显式指定输出文件名 pfsense-redactor config.xml redacted.xml ``` ### 保留私有 IP(推荐) ``` pfsense-redactor config.xml redacted.xml --keep-private-ips ``` ### 将特定 IP 和域名加入白名单 ``` # 保留特定的 public service(绝不通脱敏) pfsense-redactor config.xml --allowlist-ip 8.8.8.8 --allowlist-domain time.nist.gov # 保留整个 CIDR 范围 pfsense-redactor config.xml --allowlist-ip 203.0.113.0/24 # 使用 allow-list 文件(支持 IP、CIDR 和 domain) pfsense-redactor config.xml --allowlist-file my-allowlist.txt ``` ### 保持拓扑安全的匿名化 ``` pfsense-redactor config.xml redacted.xml --anonymise ``` ### 允许内部 DNS 名称 ``` pfsense-redactor config.xml redacted.xml --no-redact-domains --keep-private-ips ``` ### aggressive 模式 ``` pfsense-redactor config.xml redacted.xml --aggressive ``` ### 试运行 ``` # 仅显示统计信息 pfsense-redactor config.xml --dry-run # 显示统计信息和脱敏样本(已安全掩码) pfsense-redactor config.xml --dry-run-verbose ``` ### 输出到 STDOUT ``` pfsense-redactor config.xml --stdout > redacted.xml ``` ### 原地覆盖(危险) ``` pfsense-redactor config.xml --inplace --force ``` ## 命令行参数参考 ### 版本与帮助 | 参数 | 描述 | | ---------------- | ---------------------------- | | `--version` | 显示程序版本并退出 | | `--check-version`| 检查 PyPI 上的更新 | | `-h, --help` | 显示帮助信息并退出 | ### 输入/输出 | 参数 | 描述 | | ------------------------ | ------------------------------------------------------------------------------------------------------- | | `input` | 输入的 pfSense config.xml 文件(位置参数) | | `output` | 输出的脱敏 config.xml 文件(位置参数,使用 `--stdout`/`--dry-run`/`--inplace` 时可选) | | `--stdout` | 将脱敏后的 XML 输出到 stdout 而非文件 | | `--inplace` | 用脱敏后的输出覆盖输入文件(请谨慎使用) | | `--force` | 如果输出文件已存在则强制覆盖 | | `--allow-absolute-paths` | 允许绝对文件路径(出于安全考虑,默认仅允许相对路径) | ### 脱敏模式 | 参数 | 描述 | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | | `--keep-private-ips` | 保持非全局 IP 地址可见(RFC198/ULA/回环/链路本地)。子网掩码和未指定地址(0.0.0.0, ::)始终保留 | | `--no-keep-private-ips` | 与 `--anonymise` 配合使用时,不保留私有 IP 的可见性(掩码处理所有 IP) | | `--anonymise` | 使用一致的别名(IP_1, domain1.example)来保留网络拓扑。除非指定 `--no-keep-private-ips`,否则隐含 `--keep-private-ips` | | `--aggressive` | 扩大机密检测范围(高熵值、自由文本选项块、URL 路径 token),并对所有元素文本应用 IP/域名脱敏 | | `--no-redact-ips` | 不对 IP 地址进行脱敏 | | `--no-redact-domains` | 不对域名进行脱敏 | | `--redact-url-usernames` | 脱敏 URL 中的用户名(默认:保留用户名,始终脱敏密码) | | `--redact-descriptions` | 脱敏自由文本描述和标识符(`descr`, `detail`, `hostname`, `ssid`)。默认关闭,因为这些信息有助于故障排查 |
白名单 - 白名单允许您保留特定的、不会泄露隐私信息的知名 IP 和域名。 | 参数 | 描述 | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | `--allowlist-ip IP_OR_CIDR` | 从不脱敏的 IP 地址或 CIDR 网络(可重复使用)。适用于文本和 URL | | `--allowlist-domain DOMAIN` | 从不脱敏的域名(可重复使用,不区分大小写,支持后缀匹配)。适用于裸 FQDN 和 URL 主机名 | | `--allowlist-file PATH` | 包含从不脱敏的 IP、CIDR 网络和域名的文件(每行一个) | | `--no-default-allowlist` | 不加载默认的白名单文件(当前目录或 ~/.pfsense-allowlist 中的 .pfsense-allowlist) |
测试与诊断 | 参数 | 描述 | | ------------------- | ----------------------------------------------------------------------- | | `--dry-run` | 仅显示统计信息,不写入输出文件 | | `--dry-run-verbose` | 显示带有脱敏示例的统计信息(安全掩码处理以防止泄露) | | `--fail-on-warn` | 如果根标签不是 'pfsense',则以非零代码退出(在 CI 中很有用) |
### 输出控制 | 参数 | 描述 | | --------------- | ---------------------------------------------------------- | | `-q, --quiet` | 隐藏进度信息(仅显示警告和错误) | | `-v, --verbose` | 显示详细的调试信息 | ## 白名单 白名单允许您保留特定的、不会泄露隐私信息的知名 IP 和域名。 ### 默认白名单文件 该工具会自动从以下位置加载白名单(如果存在): 1. 当前目录下的 `.pfsense-allowlist` 2. 家目录中的 `~/.pfsense-allowlist` 禁用方法:使用 `--no-default-allowlist` ### 白名单文件格式 创建 `.pfsense-allowlist` 或使用 `--allowlist-file`: ``` # 注释以 # 开头 # 每行一个条目(IP、CIDR 或 domain) # 公共 DNS 服务器 8.8.8.8 1.1.1.1 # Cloud provider 范围 203.0.113.0/24 198.51.100.0/24 # NTP 服务器(后缀匹配:保留 time.nist.gov 和 *.time.nist.gov) time.nist.gov pool.ntp.org # 通配符 domain(*.example.org 保留所有子域名) *.pfsense.org ``` 有关完整的模板,请参见 [`allowlist.example`](allowlist.example)。 ### 命令行白名单参数 ``` # 添加特定的 IP 或 CIDR 范围(可重复) --allowlist-ip 8.8.8.8 --allowlist-ip 203.0.113.0/24 # 添加特定的 domain(可重复、不区分大小写、支持后缀匹配) --allowlist-domain time.nist.gov --allowlist-domain pool.ntp.org # 从文件加载(支持 IP、CIDR 和 domain) --allowlist-file /path/to/allowlist.txt # 禁用默认文件加载 --no-default-allowlist ``` **特性:** - **支持 CIDR**:`203.0.113.0/24` 将保留该范围内的所有 IP - **后缀匹配**:`example.org` 将保留 `sub.example.org`、`db.corp.example.org` 等。 - **通配符域名**:`*.example.org` 等同于对 `example.org` 的后缀匹配 - **IDNA/punycode**:自动处理国际化域名(例如,`bücher.example` ↔ `xn--bcher-kva.example`) - **合并来源**:所有命令行参数、文件和默认文件都会被合并处理 **注意:** 白名单中的项目在以下位置绝不会被脱敏: - 文本中的 IP/域名引用 - URL 主机名 - 裸 FQDN ## 示例 ### 输入 ``` 192.168.10.1 -----BEGIN OpenVPN Static key-----ABC123... 198.51.100.10 443 ``` ### 输出(`--keep-private-ips`) ``` 192.168.10.1 [REDACTED] XXX.XXX.XXX.XXX 443 ``` ### 输出(`--anonymise`) ``` IP_1 [REDACTED] IP_2 443 ``` ## 安全说明 脱敏后的输出**仅供分析**,因为: - CDATA 和注释会被 XML 解析器移除 - PEM 块和二进制数据会被折叠 - 某些可选的元数据字段可能会被剔除 请务必妥善保管**原始的安全副本**。 ### 路径安全 该工具内置了防范恶意文件路径操作的保护措施: **默认行为(安全):** - 默认仅允许相对路径 - 阻止目录遍历(`../../../etc/passwd`) - 拒绝包含空字节的路径 - 阻止写入系统目录(`/etc`、`/sys`、`/proc`、`/Windows/System32` 等) - 自动允许安全位置(家目录、当前工作目录、临时目录) **使用 `--allow-absolute-paths` 时:** - 为特定的使用场景启用绝对路径 - 仍然阻止写入敏感的系统目录 - 仍然阻止目录遍历尝试 - 适用于需要显式指定完整路径的情况 **示例:** ``` # 安全:相对路径(默认) pfsense-redactor config.xml output.xml # 已阻止:不带 flag 的绝对路径 pfsense-redactor /etc/config.xml output.xml # 错误:不允许绝对路径(请使用 --allow-absolute-paths) # 已阻止:目录遍历 pfsense-redactor ../../../etc/passwd output.xml # 错误:路径包含目录遍历组件(..) # 已阻止:写入系统目录(即使带有 flag) pfsense-redactor config.xml /etc/output.xml --allow-absolute-paths # 错误:无法写入敏感系统目录 # 允许:使用 flag 指向安全位置的绝对路径 pfsense-redactor ~/config.xml ~/output.xml --allow-absolute-paths # 已阻止:原地编辑系统文件 pfsense-redactor /etc/hosts --inplace --force --allow-absolute-paths # 错误:无法对此文件使用 --inplace ``` **受保护的系统目录:** - Unix/Linux: `/etc`, `/sys`, `/proc`, `/dev`, `/boot`, `/root`, `/bin`, `/sbin`, `/usr/bin`, `/usr/sbin`, `/lib`, `/lib64`, `/var/log`, `/var/run`, `/tmp`, `/run` - Windows: `C:\Windows`, `C:\Windows\System32`, `C:\Program Files`, `C:\ProgramData` - 关键文件:`/etc/passwd`, `/etc/shadow`, `/etc/sudoers` 等。 ## 测试 ### 试运行摘要 ``` # 仅显示统计信息 pfsense-redactor config.xml --dry-run # 显示统计信息和脱敏样本(已安全掩码以避免泄露) pfsense-redactor config.xml --dry-run-verbose ``` **使用 `--dry-run-verbose` 的示例输出:** ``` [+] Redaction summary: - Passwords/keys/secrets: 10 - Certificates: 6 - IP addresses: 26 - Domain names: 47 [+] Samples of changes (limit N=5): IP: 198.51.***.42 → XXX.XXX.XXX.XXX IP: 2001:db8:*:****::1 → XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX URL: https://198.51.***.42/admin → https://XXX.XXX.XXX.XXX/admin FQDN: db.***.example.org → example.com MAC: aa:bb:**:**:ee:ff → XX:XX:XX:XX:XX:XX Secret: p****************d (len=18) → [REDACTED] Cert/Key: PEM blob (len≈2048) → [REDACTED_CERT_OR_KEY] ``` **示例掩码策略**(防止在试运行输出中泄露信息): - **IP**:保留首尾八位组/段,掩码中间部分(例如,`198.51.***.42`) - **URL**:显示完整 URL,但按上述方式掩码主机 - **FQDN**:保留 TLD 和左侧一个标签,掩码其余部分(例如,`db.***.example.org`) - **MAC**:掩码中间的八位组(例如,`aa:bb:**:**:ee:ff`) - **机密信息**:仅显示长度和首尾 2 个字符(例如,`p****************d (len=18)`) - **证书/密钥**:仅显示带有长度的占位符(例如,`PEM blob (len≈2048)`) ### 推荐的测试参数 | 用途 | 命令 | | ---------------------------- | ---------------------------------------- | | 支持与 AI 审查 | `--keep-private-ips --no-redact-domains` | | 无标识符的拓扑图 | `--anonymise` | | 彻底清除所有信息 | `--aggressive` | ## 统计示例 ``` [+] Redaction summary: - Passwords/keys/secrets: 4 - Certificates: 2 - IP addresses: 11 - MAC addresses: 3 - Domain names: 5 - Email addresses: 1 - URLs: 2 ``` ## 参与贡献 欢迎提交 Pull request。特别是关于: - 扩展 pfSense 元素的覆盖范围 - 插件 XML 标签包(WireGuard、pfBlockerNG、HAProxy、Snort、ACME、FRR) - 单元测试配置 ## 许可证 MIT
标签:pfSense, Python, XML处理, 数据隐私, 无后门, 运维工具, 逆向工具, 配置脱敏, 防火墙配置