kklouzal/Docker_Proxy

GitHub: kklouzal/Docker_Proxy

一款基于 Squid 的容器化代理设备,通过 Web UI 提供策略管理、机群运维、TLS 检查与流量可观测性,替代繁琐的手工命令行配置。

Stars: 0 | Forks: 0

# Docker Proxy [![将 Docker 镜像发布到 GHCR](https://static.pigsec.cn/wp-content/uploads/repos/cas/f8/f88cf485407f8f371c04f641bac329da751af4d71fd1e7c88e90d4f80822e823.svg)](https://github.com/kklouzal/Docker_Proxy/actions/workflows/publish-ghcr.yml) [![Container Registry](https://img.shields.io/badge/GHCR-admin--ui%20%7C%20proxy-blue)](https://github.com/kklouzal/Docker_Proxy/pkgs/container/docker_proxy-admin-ui) [![许可证](https://img.shields.io/badge/license-see%20LICENSE-informational)](LICENSE) Docker Proxy 将 Squid 转变为可通过浏览器操作的代理设备:策略编辑、PAC/WPAD 发布、TLS 检查控制、Web 过滤、广告拦截、ClamAV ICAP 扫描、机群运维、审计历史记录以及可观测性,所有这些都通过一个基于 MySQL 的后台管理 UI 实现,而无需散乱的配置文件和仅限命令行的操作手册。 它专为家庭实验室运维人员、学校、小型办公室、MSP 风格的托管局域网以及需要可审计代理堆栈的高级网络管理员构建,使他们能够在容器中运行这些堆栈,而无需将流量拦截、证书、数据库备份和客户端路由视作虚无缥缈的魔法。它不是 VPN、DNS 沉洞、桌面隐私插件或即插即用的防火墙。 ## 它解决的问题 Squid 功能强大,但其日常运营通常会变成手工编辑配置、临时脚本、脆弱的 PAC 文件、未记录的证书更改和日志挖掘的混合体。Docker Proxy 对运行时和控制平面进行了打包,使运维人员能够: - 在 Web UI 中编辑策略,并在应用之前在选定的 runtime 上验证候选的 Squid 配置; - 从代理容器发布 PAC/WPAD 和代理健康状态端点,同时保持管理 UI 独立; - 将配置、用户、策略修订、遥测数据、拦截日志和操作历史记录保存在 MySQL 8+ 中; - 从划分范围的管理 UI 管理一个或多个代理 runtime,而不会混淆机群操作;以及 - 在同一控制台中查看流量、缓存行为、ICAP 活动、SSL/TLS 诊断、拦截事件、导出数据和修复提示。 ## 管理 UI 预览 下方的截图和动画演示截取自已授权的在线 Docker Proxy 部署环境;未显示任何凭证、密钥、私钥或 token。

Short Docker Proxy Admin UI live workflow showing status, observability, ClamAV, ad blocking, proxy fleet, SSL filtering, and the operations ledger

| 状态和可观测性仪表板 | SSL/缓存策略工作流 | 已注册的代理机群和操作 | | --- | --- | --- | | ![Docker Proxy Admin UI live status and observability dashboard for a selected proxy runtime](https://static.pigsec.cn/wp-content/uploads/repos/cas/0d/0d73bf83e069ea7bfe8018d79b51a716ad21955589c99d481a5a83539a8925db.png) | ![Docker Proxy Admin UI live SSL filtering and cache-bypass policy workflow with runtime apply evidence](https://static.pigsec.cn/wp-content/uploads/repos/cas/55/559e679e6a047621f5cab8097157c79c41fdcf93bc3600148df0fb5ec27b3d95.png) | ![Docker Proxy Admin UI live registered proxy fleet and operations view with mixed proxy health](https://static.pigsec.cn/wp-content/uploads/repos/cas/b6/b661e041105547de2e6ec5b1e137e49068c6f521871239ffee67114206571755.png) | ## 使用预构建镜像的 5 分钟快速入门 此路径使用已发布的 GHCR 镜像以及提交的 `docker-compose.ghcr.yml` 和 `docker-compose.common.yml` 文件。假设您已经安装了 Docker Compose v2 并且有一个可访问的 MySQL 8+ 数据库。对于生产环境,请在启动容器之前创建数据库并配置最小权限的运行时用户;仅在使用被允许创建 schema 的数据库账户进行一次性的初步体验时,才使用 `MYSQL_CREATE_DATABASE=1`。 1. 克隆仓库并创建本地启动环境: git clone https://github.com/kklouzal/Docker_Proxy.git cd Docker_Proxy cat > .env <<'ENV' MYSQL_HOST=mysql.example.com MYSQL_PORT=3306 MYSQL_USER=docker_proxy MYSQL_PASSWORD=replace_with_the_database_password MYSQL_DATABASE=squid_proxy MYSQL_CREATE_DATABASE=0 PROXY_MANAGEMENT_TOKEN=replace_with_a_long_random_shared_token FLASK_SECRET_KEY=replace_with_a_long_random_flask_secret DOCKER_LOG_DRIVER=json-file DOCKER_LOG_MAX_SIZE=10m DOCKER_LOG_MAX_FILE=3 ENV 2. 拉取并启动分离的容器: docker compose -f docker-compose.ghcr.yml pull docker compose -f docker-compose.ghcr.yml up -d docker compose -f docker-compose.ghcr.yml ps 3. 从 Docker 宿主机对公共代理端点进行冒烟测试: curl -fsS http://localhost/health curl -fsS http://localhost/proxy.pac | head 4. 在 `http://localhost:5000` 打开管理 UI,使用首次运行的本地账户登录,并立即更改密码: - 用户名: `admin` - 密码: `admin` 5. 在路由真实客户端之前,请检查生成的代理记录、PAC/WPAD URL、证书颁发机构信任计划、no-bump 策略以及管理平面的暴露情况。不要将管理 UI 直接暴露在互联网上,也不要对不受管理的客户端或不信任代理 CA 的客户端启用 TLS 检查。 Compose 堆栈启动后的默认本地端点: - 管理 UI: `http://localhost:5000` - 显式 HTTP 代理: `http://localhost:3128` - HTTP NAT 拦截监听器: `localhost:3129`(启用并由您的网络路由时生效) - HTTPS NAT 拦截监听器: `localhost:3130`(启用并由您的网络路由时生效) - 代理公共健康状态: `http://localhost/health` - PAC 文件: `http://localhost/proxy.pac` - WPAD: `http://localhost/wpad.dat` ## 特性 - **分离的控制平面和 runtime**:`admin-ui` 负责管理策略和机群状态;`proxy` 运行 Squid、ICAP 助手、PAC/WPAD、本地策略物化以及一个小型管理 API。 - **基于 MySQL 的单一事实来源**:配置修订、代理注册、策略状态、用户、审计事件、遥测数据、拦截日志、PAC 配置文件和操作状态都保存在 MySQL 8+ 中。 - **经过验证的配置工作流**:代理 runtime 在激活之前使用自身的 Squid 二进制文件/包含文件验证候选的 Squid 配置,并保留一条已知良好的回滚路径。 - **机群感知的操作账本**:管理操作会将针对特定代理范围的操作排入队列,用于处理配置、证书、PAC 刷新、广告拦截构件、缓存清理和手动同步。 - **作为一等公民的 PAC/WPAD 运行时服务**:每个代理都会提供公共的 `/health`、`/proxy.pac` 和 `/wpad.dat`,而无需在端口 80 上暴露管理 UI。 - **TLS 检查控制**:CA 生成/上传、SSL-bump 策略、兼容性预设、no-bump/no-cache 规则、client-CIDR 拼接、SSL 错误分析以及一键排除。 - **Web 过滤和威胁情报**:UT1 风格的分类过滤、白名单、用于请求路径查询的代理本地 SQLite 快照,以及可选的 Google Safe Browsing v5 本地哈希前缀检查。 - **ICAP 安全服务**:通过基于 SQLite 的 REQMOD 助手实现 EasyList 风格的广告拦截,以及通过带有远程 `clamd` 的 c-icap RESPMOD 实现 ClamAV 响应扫描。 - **运维可见性**:实时流量、客户端、目标地址、缓存行为、ICAP 活动、SSL/TLS 诊断、拦截事件、导出数据、修复提示以及维护操作。 - **有界的健康检查**:导航健康状态使用轻量级的代理探测,修复视图可以请求完整的 runtime 健康状态,而缓慢的 ICAP/ClamAV 检查则被隔离在明确的超时和短暂的缓存之后。 - **多架构镜像**:GitHub Actions 在通过确定性和在线堆栈测试后,会构建并将 `linux/amd64` 和 `linux/arm64` 镜像发布到 GHCR。 ## 架构 ``` +----------------------------+ | MySQL 8+ | | config, policy, telemetry | | users, audit, operations | +-------------+--------------+ | +--------------+--------------+ | | +--------v--------+ +---------v---------+ | admin-ui | | proxy | | Flask/Gunicorn | | Squid + ICAP | | policy + fleet |<-------->| sync + PAC/WPAD | | port 5000 | mgmt API | ports 80/3128/3129| +-----------------+ +-------------------+ ``` 管理 UI 可以与本地或远程的代理 runtime 一起运行。每个代理都会在 MySQL 中注册其管理 URL 和公共 PAC/代理坐标。管理 UI 会针对选定的代理进行 runtime 检查,并在需要物化策略更改时将持久操作排入队列。 ## 适用操作者 当您想要一个可以从浏览器操作、由可审计的 SQL 控制平面支持、并部署为一个或多个 Docker 化代理 runtime 的托管代理设备时,Docker Proxy 是一个不错的选择。它适用于客户端受管、代理策略明确、且运维人员可以掌控周边基础设施(DNS/WPAD 或 PAC 分发、用于拦截模式的防火墙重定向、证书信任、数据库备份以及管理平面暴露)的网络。 它不是 DNS 沉洞、个人 VPN、桌面隐私插件或即插即用的防火墙。该代理可以执行 Squid 策略、PAC 路由、Web 分类拦截、请求时的广告拦截决策、TLS 检查策略以及 ICAP 防病毒扫描——前提是流量确实经过了它。它不会注册设备、安装路由器规则、绕过应用程序的证书绑定,也不会让 HTTPS 拦截适用于不受管理的用户。 ## 要求 - Docker Engine 和 Docker Compose v2。 - 可访问的 MySQL 8+ 数据库;runtime 和管理状态由 MySQL 提供。 - 启用 ClamAV 响应扫描时,需要远程 `clamd` 服务。 - 在为受管客户端启用 TLS 检查之前,客户端必须信任代理 CA。 ## 管理认证 管理 UI 可以使用本地用户、一个 LDAP 或 Active Directory 提供程序,或者一个基于元数据的 SAML 提供程序。即使启用了外部身份验证,本地用户仍然可用作紧急访问通道。 一次只能启用一个外部提供程序。LDAP、Active Directory 和 SAML 授权目前仅用于管理 UI 登录;它们本身不会启用透明代理身份验证、强制门户身份验证、策略用户归属或拦截页面绕过。 从 `Administration -> LDAP` 或 `Administration -> Active Directory` 配置 LDAP 或 Active Directory: 1. 输入一个或多个 `ldap://` 或 `ldaps://` 服务器 URL 以及绑定 DN / 服务账户。在常规部署中使用 LDAPS 或 StartTLS,以确保绑定和用户凭证不会以明文形式发送。 2. 当目录 TLS 链接到不在系统信任范围内的内部 CA 时,上传或粘贴 PEM CA 包。 3. 保存并测试提供程序。在当前连接设置通过测试之前,无法启用该提供程序。 4. 使用 `Scan directory` 从提交的连接详细信息中填充 Base DN、搜索基准和组选择,然后选择所需的管理组。 5. 测试成功后启用该提供程序。如果目录登录失败或拒绝了用户,本地管理员账户仍可用于紧急访问。 从 `Administration -> SAML` 配置 SAML: 1. 设置 IdP 元数据 URL。对于 AD FS,这通常是 `https://idp.example.com/FederationMetadata/2007-06/FederationMetadata.xml`。 2. 在常规部署中保持启用 `Require HTTPS metadata URL` 和 `Verify TLS certificate`。仅当 AD FS TLS 证书链接到不在系统信任范围内的内部 CA 时,才添加 PEM CA 包。 3. 当 UI 位于反向代理之后时,将 `Public admin base URL` 设置为外部可见的管理 UI 源。生成的服务提供程序元数据位于 `/auth/saml/metadata`,断言消费者服务位于 `/auth/saml/acs`。 4. 将 SP 元数据 URL 作为信赖方信任添加到 AD FS,或者在 SAML 选项卡上输入显示的 SP 实体 ID 和 ACS URL。 5. 将 AD FS 声明映射到已配置的 SAML 声明名称。默认情况下,期望从 `NameID` 获取用户名,从 `groups` 获取组;常见的 AD FS 替代项是 `email`、`upn` 或自定义组声明。 6. 当 SAML 登录必须限制特定组时,将 `Required group value` 设置为确切的管理组声明值。如果为空,任何被 IdP 接受的已验证 SAML 用户都可以登录到管理 UI。 7. 点击 `Refresh metadata`,然后在刷新成功后启用 SAML 并保存。 在提供程序被启用、IdP 元数据成功刷新且元数据缓存仍然有效之前,SAML 登录将被隐藏并拒绝。AD FS 签名证书从缓存的 IdP 元数据中读取;在 AD FS 证书滚动更新后刷新元数据,或者在滚动更新前(如果 AD FS 同时发布了当前和下一个签名证书)进行刷新。缓存过期遵循 IdP 的 `validUntil`/`cacheDuration`(如果存在),否则默认为 24 小时。 该实现要求对断言/消息进行签名,不会在审计记录中记录原始 SAML 响应,并且仅将 RelayState 重定向到本地管理 UI 路径。由于绑定策略、目录 schema、组成员身份规则、声明发布规则、TLS 信任和反向代理公共 URL 因部署而异,线上 LDAP、Active Directory 和 AD FS 的互操作性仍需在目标域中进行验证。 ## 部署选项 ### 源码构建 `docker-compose.yml` 从仓库构建两个容器,并扩展了 `docker-compose.common.yml` 中的共享服务定义。 ``` docker compose up -d --build ``` 源码构建默认使用 Alpine 的 `edge` 镜像标签,以便 Squid 和 runtime 包能够追踪构建时可用的最新 Alpine 包。需固定基础镜像,请传递明确的构建参数: ``` docker compose build --build-arg ALPINE_VERSION=3.23.4 ``` ### 预构建镜像 `docker-compose.ghcr.yml` 运行已发布的分离镜像: - `ghcr.io/kklouzal/docker_proxy-admin-ui:main` - `ghcr.io/kklouzal/docker_proxy-proxy:main` 发布工作流会运行确定性测试,构建两个镜像,运行在线 Compose 测试堆栈,然后发布带有 SBOM 和来源元数据的多架构镜像。 ### 独立控制平面 当代理 runtime 部署在其他位置时,仅运行管理 UI: ``` docker compose up -d --build admin-ui ``` 管理 UI 仍然需要 MySQL。在代理 runtime 注册管理 URL 和公共 PAC/代理元数据之后,特定于代理的操作才可用。在仅包含管理 UI 的主机上,将代理服务排除在活动的 Compose 项目之外,并在更新期间使用 `--remove-orphans`,以免意外重新创建旧的本地代理容器。 管理 UI 的 HTTPS 依然依赖于 `/etc/squid/ssl/certs/ca.crt` 和 `/etc/squid/ssl/certs/ca.key` 处的活动 SSL 检查 CA 材料,以便签署位于 `/etc/squid/ssl/certs/admin-ui.crt` 和 `/etc/squid/ssl/certs/admin-ui.key` 的专用管理 UI 服务器叶证书。打包的 Compose 定义为此目的将 `./squid/ssl/certs` 挂载到管理 UI 中;独立的管理 UI 部署在使用证书页面 HTTPS 切换时,必须保持该挂载可用且可写。 ### 多代理部署 当多个代理 runtime 共享一个 MySQL/admin-ui 控制平面时,每个代理 容器必须具有稳定、唯一的身份和公共坐标: ``` PROXY_INSTANCE_ID=site-a-proxy-1 PROXY_DISPLAY_NAME=Site A Proxy 1 PROXY_PUBLIC_HOST=site-a-proxy-1.example.com PROXY_PUBLIC_PAC_URL=http://site-a-proxy-1.example.com/proxy.pac PROXY_MANAGEMENT_URL=http://site-a-proxy-1.example.com:5000 ``` 仅在管理 UI 主机上设置 `DEFAULT_PROXY_ID` 以选择初始的 UI 选择。不要在多个代理主机上重复使用相同的 `PROXY_INSTANCE_ID`; 注册、心跳、排队操作、PAC 元数据和健康状态 均以该 ID 为键。如果 `PROXY_PUBLIC_PAC_URL` 指向非默认路径(例如 `/wpad.dat` 或反向代理路由),生成的 PAC 元数据将保留该 路径,而不是将其重写为 `/proxy.pac`。 除非您同时降低了 Squid 内存缓存设置,否则请将每个代理容器的共享内存分配保持在 Compose 默认值 `PROXY_SHM_SIZE=512m` 或以上。 默认的 Squid 模板使用共享内存来存储缓存元数据;Docker 裸 `docker run` 默认的 `/dev/shm` 大小对于该生产配置文件来说太小了。 对于一个包含六个代理的机群外加一个管理 UI,请明确规划 MySQL 容量。 捆绑的 MySQL Compose 配置默认设置 `MYSQL_MAX_CONNECTIONS=160` 和 `MYSQL_MAX_ALLOWED_PACKET=256M`;外部 MySQL 部署应设置 等效的连接和数据包余量,以便编译后的广告拦截构件和 更大的策略快照能够干净地持久化。除非您已测量到需要覆盖它,否则请将 `DB_POOL_SIZE` 留空:应用程序从 `WEB_THREADS` 派生出一个较小的每进程空闲池,六个默认代理容器加上一个默认管理 UI 的连接数远在 160 个连接预算之内。 当启用后台服务时,管理 UI 会启动计划的 MySQL 内务处理。在多 worker 的 Gunicorn 部署中,文件锁允许一个进程运行后台 tailer、采样器和内务处理,而其他 worker 正常处理请求。每日运行会清理存储的可观测性行和陈旧的 控制平面历史记录;每周运行还会刷新优化器统计信息。 控制平面清理会保留活动的配置/证书/广告拦截构件 修订,保留最近的 apply/operation/policy 历史记录,使过期的临时策略例外失效,并删除过期的 Safe Browsing 缓存行。仅在部署需要更深的审计深度或更严格的存储边界时,才调整 `MYSQL_CONTROL_PLANE_RETENTION_DAYS`, `MYSQL_HOUSEKEEPING_KEEP_REVISIONS`, `MYSQL_HOUSEKEEPING_KEEP_APPLICATIONS`, `MYSQL_HOUSEKEEPING_KEEP_OPERATIONS`, `MYSQL_HOUSEKEEPING_KEEP_POLICY_ROWS` 和 `MYSQL_HOUSEKEEPING_KEEP_MAINTENANCE_RUNS`。 ## 核心功能 ### 代理策略和 Squid 配置 - 具有结构化控件和原始配置访问权限的、基于模板的 Squid 配置编辑器。 - 可调节的缓存基准,使用 Squid `rock` 存储、限制内存/磁盘缓存设置、保守的刷新语义、明确的超时/网络/DNS 旋钮以及感知 SMP 的 worker 大小调整。 - 存储在 MySQL 中并带有审计追踪的配置修订。 - 代理端验证、应用、重新加载和已知良好回滚。 - 限定于选定代理的缓存清理和手动同步操作。 ### PAC、WPAD 和客户端路由 - 由客户端 IP/CIDR 选择的每代理 PAC 配置文件。 - 除非直接对端在 `PAC_TRUSTED_PROXY_CIDRS` 中列出,否则将忽略转发的客户端 IP 头,防止客户端欺骗 PAC 配置文件选择。 - 针对脆弱应用程序或本地路由的直接域名和直接目标网络规则。 - 由选定代理(而非管理 UI)提供服务的 runtime 渲染的 PAC 文件。 - 兼容 WPAD 的 `/wpad.dat` 和直接 `/proxy.pac` 端点。 - 当渲染状态不可用时的紧急 PAC 回退。 ### TLS 检查和证书 - 自签名 CA 生成和证书下载。 - PKCS#12 和证书/密钥上传验证。 - 带有域名和客户端 CIDR no-bump/no-cache 规则的 SSL-bump 策略管理。 - 专用的 HTTPS NAT 拦截监听器控件,包括用于重定向 TCP/443 流量且应在不解密的情况下进行隧道的可选仅拼接模式。 - 针对常见的 SaaS、身份、更新、协作和设备生态系统的、基于源的兼容性预设,这些系统不太适合进行 TLS 拦截和检查。 - SSL/TLS 错误聚合、导出和排除工作流。 ### Web 过滤 - UT1 风格的分类源摄取和分类选择。 - 精确和白名单通配符支持。 - 具有 proxy-local 查找快照的 MySQL 分类表,用于请求路径决策。 - Squid external ACL 集成和自定义 `ERR_WEBFILTER_BLOCKED` 页面。 - 拦截请求日志记录,包含客户端、目标地址、URL、分类和时间戳。 - 可选的 Google Safe Browsing v5 集成,仅在本地前缀匹配后才使用本地哈希前缀列表和全哈希查询。 ### 广告拦截 - EasyList 风格的订阅下载和编译。 - 位于 `icap://127.0.0.1:${CICAP_PORT:-14000}/adblockreq` 的基于 SQLite 的 REQMOD 服务。 - 针对浏览、CONNECT 隧道设置和常见 API 方法的仅标头广告拦截决策;请求体受到限制并被消耗,仅足以保持 ICAP 事务的健康。 - ABP 风格的网络规则、例外、资源类型选项、第三方检查、域名范围、通配符主机、正则表达式规则和 `$badfilter` 抑制被编译到 proxy-local 查找工件中。 - 域名、主机模式、正则表达式 token、通用字面量、资源类型和域名范围的 SQLite 索引在代理容器中本地暂存,因此请求路径检查不需要扫描每个解析的规则。 - Cosmetic、scriptlet 和 HTML 过滤规则被解析到工件桶中,以供查看和将来使用,但代理 runtime 不会注入浏览器端的 cosmetic 过滤。 - 拦截计数器、最近的事件记录和工件应用追踪。 ### ClamAV 扫描 - 位于 `icap://127.0.0.1:${CICAP_AV_PORT:-14001}/avrespmod` 的 c-icap 请求/上传防病毒服务。 - 使用 `CLAMD_HOST` 和 `CLAMD_PORT` 配置的远程 `clamd` 后端。 - 下载/RESPMOD AV 扫描使用本地 ICAP 助手,当 `CLAMD_HOST` 为 非本地时,该助手使用 TCP INSTREAM 协议将响应 字节流式传输到远程 `clamd`;如果设置了 `CICAP_AV_RESP_PORT`,它将在该端口上监听,否则使用请求/上传 c-icap worker 范围之后的第一个 非重叠端口。 这避免了 proxy-local 临时文件路径的移交。 - 故障开放/故障关闭策略控制,针对上传调整的 c-icap `virus_scan`, 以及针对下载的基于流的 RESPMOD 扫描。 - 每个代理的健康视图,区分 Squid 策略、AV c-icap 监听器健康状态和远程 `clamd` 可达性。 - 通过选定的代理 runtime 执行的 EICAR 和示例 ICAP 验证操作。 ### 可观测性和操作 - 包含已注册代理、实时健康状态和每代理可观测性状态的机群页面。 - 轻量级的导航时代理健康状态,以及用于修复工作流的完整 runtime 健康状态。 - 针对 supervisor 状态、Squid 监听器、ICAP 服务、ClamAV/`clamd`、策略/配置/证书/广告拦截对齐情况以及操作账本的 runtime 健康组件。 - 针对客户端、域名、缓存行为、事务和 ICAP 活动的实时流量页面。 - 将 Squid 和 ICAP 助手日志中的诊断信息提取到基于 MySQL 的汇总中。 - SSL 错误存储、拦截日志、CSV 样式的导出、修复建议和日志维护操作。 - 针对排队中、应用中、已应用、已被取代和失败的代理操作的操作页面,包括在失败的操作具有回滚目标时提供回滚支持。 - 允许用户从自定义拦截页面提交解除拦截/审查请求的策略请求工作流。 ## 配置参考 Compose 文件将常见的生产环境旋钮作为环境变量公开。最重要的设置包括: | 区域 | 变量 | | --- | --- | | 数据库 | `DATABASE_URL`, `MYSQL_HOST`, `MYSQL_PORT`, `MYSQL_USER`, `MYSQL_PASSWORD`, `MYSQL_DATABASE`, `MYSQL_CREATE_DATABASE`, `MYSQL_CONNECT_TIMEOUT`, `MYSQL_READ_TIMEOUT`, `MYSQL_WRITE_TIMEOUT`, `MYSQL_CONNECT_RETRIES`, `MYSQL_CONNECT_RETRY_DELAY_SECONDS`, `MYSQL_RETRY_JITTER_SECONDS`, `MYSQL_LOCK_WAIT_TIMEOUT`, `MYSQL_INNODB_LOCK_WAIT_TIMEOUT`, `MYSQL_SESSION_WAIT_TIMEOUT`, `MYSQL_TRANSACTION_ISOLATION`, `MYSQL_SCHEMA_LOCK_TIMEOUT_SECONDS`, `MYSQL_MAX_CONNECTIONS`, `MYSQL_MAX_ALLOWED_PACKET`, `DB_POOL_SIZE`, `DB_POOL_ACQUIRE_TIMEOUT_SECONDS`, `DB_POOL_MAX_IDLE_SECONDS` | | 容器日志 | `DOCKER_LOG_DRIVER`, `DOCKER_LOG_MAX_SIZE`, `DOCKER_LOG_MAX_FILE` | | 安全 | `FLASK_SECRET_KEY`, `SESSION_COOKIE_SECURE`, `SESSION_TIMEOUT_HOURS`, `PROXY_MANAGEMENT_TOKEN`, `DISABLE_CSRF`(用于受控的测试/开发绕过) | | 运行时健康 | `PROXY_HEALTH_UI_TIMEOUT_SECONDS`, `PROXY_CLAMAV_HEALTH_UI_TIMEOUT_SECONDS`, `PROXY_HEALTH_UI_CACHE_TTL_SECONDS`, `PROXY_OBSERVABILITY_UI_CACHE_TTL_SECONDS`, `PROXY_HEALTH_CACHE_TTL_SECONDS`, `PROXY_CLAMAV_HEALTH_PROBE_TIMEOUT_SECONDS` | | 代理身份 | `DEFAULT_PROXY_ID`, `PROXY_INSTANCE_ID`, `PROXY_DISPLAY_NAME`, `PROXY_MANAGEMENT_URL`, `PROXY_PUBLIC_HOST`, `PROXY_PUBLIC_PAC_URL` | | 公共端口 | `PROXY_PUBLIC_PAC_SCHEME`, `PROXY_PUBLIC_PAC_PORT`, `PROXY_PUBLIC_HTTP_PROXY_PORT`, `PAC_HTTP_HOST`, `PAC_HTTP_PORT`, `FORWARDING_CANARY_HOST`, `FORWARDING_CANARY_PORT`, `FORWARDING_CANARY_PATH`, `PAC_TRUSTED_PROXY_CIDRS`, `SQUID_HTTP_PORT`, `SQUID_INTERCEPT_ENABLED`, `SQUID_INTERCEPT_PORT`, `PROXY_PUBLIC_INTERCEPT_PORT`, `SQUID_HTTPS_INTERCEPT_ENABLED`, `SQUID_HTTPS_INTERCEPT_PORT`, `SQUID_HTTPS_INTERCEPT_SPLICE_ONLY`, `PROXY_PUBLIC_HTTPS_INTERCEPT_PORT` | | Squid 大小设置 | `SQUID_WORKERS`, `SQUID_CACHE_MEM_MB`, `PROXY_SHM_SIZE`, `SQUID_SSLCRTD_CHILDREN`, `SQUID_DYNAMIC_CERT_MEM_CACHE_MB`, `SQUID_MAX_FILEDESCRIPTORS`, `ULIMIT_NOFILE` | | ICAP 和 AV | `CICAP_PORT`, `CICAP_AV_PORT`, `CICAP_AV_RESP_PORT`, `CLAMD_HOST`, `CLAMD_PORT` | | 广告拦截助手 | `ADBLOCK_CACHE_TTL`, `ADBLOCK_CACHE_MAX`, `ADBLOCK_RULE_CACHE_MAX`, `ADBLOCK_ICAP_MAX_REQUEST_BYTES`, `ADBLOCK_ICAP_MAX_BODY_DRAIN_BYTES`, `ADBLOCK_ICAP_REQUEST_TIMEOUT`, `ADBLOCK_ICAP_MAX_KEEPALIVE_REQUESTS` | | Web 过滤助手 | `WEBFILTER_HELPERS`, `WEBFILTER_CACHE_ENTRIES`, `WEBFILTER_CACHE_TTL_SECONDS`, `WEBFILTER_CACHE_NEGATIVE_TTL_SECONDS`, `WEBFILTERAPSHOT_REFRESH_SECONDS`, `WEBFILTER_FAIL`, `SAFE_BROWSING_POLL_SECONDS`, `SAFE_BROWSING_HELPER_CACHE_ENTRIES`, `SAFE_BROWSING_HELPER_PREFIX_HIT_TTL_SECONDS`, `SAFE_BROWSING_HELPER_PREFIX_MISS_TTL_SECONDS`, `SAFE_BROWSING_FAIL` | | 运行时节奏 | `PROXY_HEARTBEAT_INTERVAL_SECONDS`, `PROXY_SYNC_INTERVAL_SECONDS`, `LIVE_STATS_COMMIT_BATCH`, `LIVE_STATS_COMMIT_INTERVAL_SECONDS`, `LIVE_STATS_POLL_INTERVAL_SECONDS`, `LIVE_STATS_DB_WRITE_BACKOFF_INITIAL_SECONDS`, `LIVE_STATS_DB_WRITE_BACKOFF_MAX_SECONDS`, `LIVE_STATS_DB_WRITE_BACKOFF_JITTER_RATIO`, `LIVE_STATS_MAX_PENDING_ROWS`, `DIAGNOSTIC_COMMIT_BATCH`, `DIAGNOSTIC_COMMIT_INTERVAL_SECONDS`, `DIAGNOSTIC_POLL_INTERVAL_SECONDS`, `DIAGNOSTIC_DB_WRITE_BACKOFF_INITIAL_SECONDS`, `DIAGNOSTIC_DB_WRITE_BACKOFF_MAX_SECONDS`, `DIAGNOSTIC_DB_WRITE_BACKOFF_JITTER_RATIO`, `DIAGNOSTIC_PENDING_MAX_ROWS`, `TIMESERIES_STARTUP_JITTER_SECONDS`, `TIMESERIES_ROLLUP_INTERVAL_SECONDS`, `TIMESERIES_SAMPLE_DB_BACKOFF_INITIAL_SECONDS`, `TIMESERIES_SAMPLE_DB_BACKOFF_MAX_SECONDS`, `TIMESERIES_SAMPLE_DB_BACKOFF_JITTER_RATIO`, `TIMESERIES_ROLLUP_DB_BACKOFF_INITIAL_SECONDS`, `TIMESERIES_ROLLUP_DB_BACKOFF_MAX_SECONDS`, `TIMESERIES_ROLLUP_DB_BACKOFF_JITTER_RATIO`, `SSL_ERRORS_COMMIT_BATCH`, `SSL_ERRORS_COMMIT_INTERVAL_SECONDS`, `SSL_ERRORS_POLL_INTERVAL_SECONDS`, `STATS_CACHE_DIR_SIZE_TTL_SECONDS` | | 后台和内务处理 | `DISABLE_BACKGROUND`, `BACKGROUND_LOCK_PATH`, `BACKGROUND_FORCE`, `MYSQL_CONTROL_PLANE_RETENTION_DAYS`, `MYSQL_HOUSEKEEPING_KEEP_REVISIONS`, `MYSQL_HOUSEKEEPING_KEEP_APPLICATIONS`, `MYSQL_HOUSEKEEPING_KEEP_OPERATIONS`, `MYSQL_HOUSEKEEPING_KEEP_POLICY_ROWS`, `MYSQL_HOUSEKEEPING_KEEP_MAINTENANCE_RUNS` | | 管理 UI | `WEB_WORKERS`, `WEB_THREADS`, `WEB_TIMEOUT`, `WEB_GRACEFUL_TIMEOUT`, `WEB_KEEPALIVE`, `ADMIN_UI_HTTPS_ENABLED` | 代理入口点在 supervisor 展开之前会对 `PAC_HTTP_HOST`, `PAC_HTTP_PORT`、仅本地的 `FORWARDING_CANARY_*` 和 `WEB_*` 数字启动器旋钮进行清理,并且容器健康检查会探测有效的 PAC 绑定主机(对于通配符绑定,则回退到 loopback)。转发金丝雀仅在代理容器内部的 loopback 上绑定,并为完整的健康检查提供一个确定性的 Squid/RESPMOD 目标,而无需对公共 PAC 监听器进行自代理。 两个容器在启动时(如果已挂载)也会加载 `/config/app.env`。适用于偏好挂载环境文件而非根目录 `.env` 的主机管理部署。 ### 管理 UI HTTPS 管理 UI 默认在容器端口 5000 上提供纯 HTTP 服务。证书页面包含一个管理 UI HTTPS 切换开关,该开关使用由活动生成或上传的 SSL 检查 CA 包签署的专用管理 UI 服务器叶证书。启用后,gunicorn 将读取 `/etc/squid/ssl/certs/admin-ui.crt` 和 `/etc/squid/ssl/certs/admin-ui.key`;Squid SSL 检查继续使用 `/etc/squid/ssl/certs/ca.crt` 和 `/etc/squid/ssl/certs/ca.key`。该挂载是可写的,以便证书页面可以在重启管理 UI Web 进程之前物化生成的管理 UI 叶证书。 保存首选项不会重写 Compose 文件或更改 `.env`;它将设置存储在控制平面数据库中,并要求 supervisor 仅重启管理 UI Web 进程,以便 gunicorn 使用 HTTP 或 HTTPS 重新执行。在生成或上传的 SSL 检查 CA 包变为活动状态之前,启用请求将被拒绝。在启动时,第一次 UI 保存之后,保存的数据库设置即为事实来源。当数据库不可用或尚未保存 UI 首选项时,`ADMIN_UI_HTTPS_ENABLED` 仍作为引导回退;`ADMIN_UI_SSL_CERTFILE` 和 `ADMIN_UI_SSL_KEYFILE` 是用于自定义启动器的内部回退旋钮,不属于打包的 UI 工作流。 ### 有限日志和可选的捆绑 MySQL Compose 服务默认设置 Docker `json-file` 轮转(`10m`,`3` 个文件),因此管理 UI、代理和可选的捆绑 MySQL 服务不会在 Docker 主机上留下无限的 stdout/stderr 日志。这些 Compose 插值必须从根目录的 `.env` 或 shell 环境中提供;挂载的 `/config/app.env` 文件在容器内加载得太晚,无法影响 Docker 日志记录。 Docker_Proxy 通常针对外部的 MySQL 8+ 服务器。如果与堆栈一起部署 MySQL,请包含可选的 MySQL Compose 文件: ``` docker compose -f docker-compose.yml -f docker-compose.mysql.yml up -d --build ``` 捆绑的 MySQL 服务连接到 Compose 的 `control` 网络,并且默认情况下 不发布到主机。这对于单主机堆栈是故意的。对于物理远程的 代理容器,请使用外部管理的 MySQL 服务,或者在 MySQL 主机上添加显式的主机端口映射,使用 主机/网络防火墙对其进行限制,并使用 `MYSQL_HOST` 和 `MYSQL_PORT` 将每个 管理/代理容器指向该可访问地址。 捆绑的 MySQL 服务挂载了 `config/mysql/conf.d/99-docker-proxy-bounded-logs.cnf`,默认情况下禁用常规和慢查询日志,设置 `log_error_verbosity=2`,设置 `max_connections=160`,设置 `max_allowed_packet=256M`,限制 `innodb_redo_log_capacity=256M`,并在启用 binlog 时在一天后使二进制日志过期。需要详细 SQL 日志记录、不同连接或数据包预算或更长 PITR 保留期的运维人员,应使用稍后挂载的 MySQL 配置文件和显式磁盘监控来覆盖这些设置。 对于外部管理的 MySQL 容器,请在该主机上应用等效的 MySQL 设置和 Docker 日志轮转。如果需要为主机上的每个容器设置主机全局 Docker 守护进程轮转,它仍应属于 `/etc/docker/daemon.json`;此应用程序可以提供 Compose 默认设置,但无法安全地重写主机守护进程策略。 较旧或受磁盘限制的主机可能需要更长时间才能响应管理健康请求。管理 UI 默认设置 1.5 秒的导航健康超时、5 秒的 ClamAV 健康超时和 10 秒的 UI 缓存,而代理 runtime 默认将健康快照缓存 10 秒。正常导航使用 `/api/manage/health` 获取轻量级的 supervisor/listener 快照;修复视图可以请求 `/api/manage/health?full=1` 获取更繁重的策略/配置/证书/广告拦截/操作账本视图。ClamAV 页面使用 `/api/manage/health/clamav`,因此 AV c-icap 和 `clamd` 状态不依赖于完整的 runtime 快照。对于较慢的部署,请调整 `PROXY_HEALTH_UI_TIMEOUT_SECONDS`、`PROXY_CLAMAV_HEALTH_UI_TIMEOUT_SECONDS`、`PROXY_HEALTH_CACHE_TTL_SECONDS` 和 `PROXY_CLAMAV_HEALTH_PROBE_TIMEOUT_SECONDS`。 ## 持久化 权威状态保存在 MySQL 中。代理容器还会在命名卷中持久化本地 runtime 资产: - `proxy_data` -> `/var/lib/squid-flask-proxy`,用于策略工件、PAC 渲染、Web 过滤快照、广告拦截工件和 proxy-local 状态。 - `squid_cache` -> `/var/spool/squid`,用于 Squid 缓存存储。 - `squid_ssl_db` -> `/var/lib/ssl_db`,用于 Squid sslcrtd 状态。 - `./squid/ssl/certs` -> `/etc/squid/ssl/certs`,用于默认 Compose 设置中生成或上传的 CA 材料。 `docker compose down -v` 将删除命名卷。 ## 网络和安全模型 默认 Compose 配置中发布的端口: - `5000/tcp`:管理 UI。 - `80/tcp`:仅用于公共代理健康状态、PAC 和 WPAD。 - `3128/tcp`:显式 HTTP 代理。 - `3129/tcp`:纯 HTTP NAT 拦截监听器,仅在启用了拦截模式并且客户端流量被周边网络重定向时有用。 - `3130/tcp`:HTTPS NAT 拦截监听器,仅在启用了 HTTPS 拦截模式并且客户端 TCP/443 流量被周边网络重定向时有用。 目标端口策略: - 默认情况下允许非标准的 HTTP 和 HTTPS 目标端口。 - 除非运维人员手动添加,否则基准 Squid 模板不会强制执行限制性的 `Safe_ports` 或 `SSL_ports` 拒绝 ACL。 操作指南: - 不要将管理 UI 发布到不受信任的网络。 - 对于共享环境,请将管理 UI 置于管理 VLAN、VPN、反向代理或 SSH 隧道之后。 - 使用强 `PROXY_MANAGEMENT_TOKEN`;管理 UI 和代理管理 API 必须就此 token 达成一致。 - 当您希望由主机管理会话密钥轮转而不是由 MySQL 生成密钥时,请设置 `FLASK_SECRET_KEY`。 - 当 UI 通过反向代理以 HTTPS 提供服务时,请设置 `SESSION_COOKIE_SECURE=1`。 - 将 SSL-bump 视为受管设备的基础设施:客户端必须信任代理 CA,并且具有证书绑定的应用程序应进行拼接。 - HTTP 和 HTTPS NAT 拦截模式需要外部路由器或主机防火墙规则;容器监听拦截端口,但不安装特定于拓扑的重定向规则。 - 拦截仅涵盖 TCP 流。如果代理强制对受管客户端很重要,请在网络边缘阻止或拒绝 UDP/443,以便支持 HTTP/3/QUIC 的应用程序回退到 TCP。 ## 当前限制 Docker Proxy 旨在作为受管网络基础设施运行,而不是作为直接插入的桌面隐私工具或即插即用的防火墙。它不会安装路由器规则、注册客户端信任存储、运行本地 `clamd` 守护进程或自动使 TLS 拦截对不受管理的设备变得安全。 该项目目前需要 MySQL 8+ 作为后端。不支持将 SQLite 和临时本地状态作为 runtime 模式。默认的 Compose 堆栈会发布有用的面向局域网的端口,以进行测试和设备部署,但运维人员仍需对主机防火墙、管理网络暴露、数据库备份、证书分发、出于检查目的的法律/组织同意以及有关保留日志的任何合规性控制负责。 ## 测试和发布门禁 本地确定性测试: ``` .venv\Scripts\python.exe -m pytest -m "not live" -p no:cacheprovider --durations=10 -ra web\tests ``` 在线 Compose 测试堆栈: ``` docker compose -f docker-compose.yml -f docker-compose.live-tests.yml up --build --abort-on-container-exit --exit-code-from live-tests live-tests ``` 清理: ``` docker compose -f docker-compose.yml -f docker-compose.live-tests.yml down -v ``` 确定性测试涵盖存储、路由边界、Squid/配置渲染、证书处理、LDAP/Active Directory 和 SAML 管理身份验证流程、PAC 渲染、Web 过滤和 Safe Browsing 助手、广告拦截解析/查询/物化、ICAP 请求行为、runtime 回滚/自我修复路径、打包契约以及操作数据解析,而无需实时的 Compose 堆栈。 在线测试工具启动 MySQL、管理 UI、两个代理 runtime、流量测试夹具和一个专用的 pytest 运行器。它验证真实的登录、公共/管理健康状态分离、PAC/WPAD 服务、经过身份验证的代理管理 API、同步和配置验证/应用路径、多代理选择和范围界定、证书和策略工作流、广告拦截/Web 过滤强制执行、选定代理的 ClamAV 报告、缓存清理、runtime 中断行为、安全标头/会话/CSRF 契约、可观测性页面、导出和代理请求遥测路径。 GitHub Actions 在 `main` 上运行发布门禁:确定性测试 -> 镜像构建测试 -> 在线测试 -> GHCR 发布。 ## 项目布局 ``` .github/workflows/ CI, live tests, and GHCR publication docker/ Dockerfiles, entrypoints, health checks, supervisord, c-icap config proxy/ Proxy-runtime Flask management API scripts/ Certificate and sslcrtd helpers squid/ Squid template, MIME data, and custom error pages web/app.py Admin UI routes and workflows web/services/ MySQL stores, policy engines, PAC rendering, proxy sync, observability web/templates/ Admin UI pages web/tools/ Squid helper programs and artifact builders web/tests/ Deterministic and live pytest coverage ``` ## 故障排除快速检查 ``` # Container state docker compose ps # Admin UI 和 proxy logs docker compose logs -f admin-ui proxy # Health endpoints curl http://localhost:5000/health curl http://localhost/health # PAC/WPAD curl http://localhost/proxy.pac curl http://localhost/wpad.dat # Explicit proxy smoke test curl --proxy http://localhost:3128 http://example.com/ ``` 常见问题: - **UI 在本地可用但在局域网中不可用**:检查入站 `5000`、`80`、`3128` 以及您发布的任何拦截端口的主机防火墙规则。 - **代理操作不可用**:验证选定的代理已注册并具有可访问的管理 URL。 - **AV 健康状态为红色**:验证 `CLAMD_HOST:CLAMD_PORT`;代理容器需要远程 `clamd` 服务。 - **现代 SaaS 或会议应用程序在 TLS 检查下中断**:拼接供应商域名,使用兼容性预设,并对于需要 DIRECT 回退的客户端首选基于 PAC 的路由。 - **透明 HTTP 拦截循环**:在将客户端 TCP/80 重定向到拦截监听器之前, exempt(免除)代理主机/容器源流量。 - **HTTPS 拦截似乎被某些应用程序绕过**:检查通过 UDP/443 进行的 HTTP/3/QUIC,如果这些客户端必须遵循 Squid 策略,请在路由器/防火墙处强制执行 TCP 回退。 ## 贡献和支持 最有用的贡献是可重现的错误报告、有针对性的修复、文档更正来自真实网络的部署说明,以及在不掩盖操作风险的情况下涵盖代理/runtime 行为的测试。在发送 pull request 之前,请在本地运行最小的相关确定性测试,并解释未涵盖的内容。 该仓库中还没有专门的资助链接。如果以后添加了公共赞助渠道,支持应用于设备完善、文档、安全强化、多架构验证、在线堆栈覆盖率,以及使代理部署运行更安全所需的操作工作。 ## 许可证 参见 [许可证](LICENSE)。
标签:Docker应用, Docker 部署, Squid代理, TLS解密, Web管理界面, 流量过滤, 网络运维, 请求拦截, 逆向工具