Metadata-Version: 2.4
Name: procproxy
Version: 0.1.4.3
Summary: ProcProxy —— 进程级代理：按进程决定哪条连接走哪个上游代理
Author: Longersking
License-Expression: MIT
Project-URL: Homepage, https://github.com/Longersking/procproxy
Project-URL: Repository, https://github.com/Longersking/procproxy
Project-URL: Source, https://github.com/Longersking/procproxy
Project-URL: Issues, https://github.com/Longersking/procproxy/issues
Project-URL: Documentation, https://github.com/Longersking/procproxy/blob/master/docs/README.md
Project-URL: Changelog, https://github.com/Longersking/procproxy/blob/master/CHANGELOG.md
Project-URL: Security, https://github.com/Longersking/procproxy/blob/master/SECURITY.md
Keywords: proxy,transparent-proxy,process,windivert,windows,socks5
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Win32 (MS Windows)
Classifier: Intended Audience :: Developers
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: Proxy Servers
Classifier: Topic :: System :: Networking
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: PyYAML>=6.0
Provides-Extra: windivert
Requires-Dist: pydivert>=3.0; extra == "windivert"
Requires-Dist: psutil>=5.9; extra == "windivert"
Provides-Extra: dev
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"
Requires-Dist: mypy>=1.8; extra == "dev"
Provides-Extra: ui-test
Requires-Dist: uiautomation>=2.0; sys_platform == "win32" and extra == "ui-test"
Requires-Dist: pywin32>=306; sys_platform == "win32" and extra == "ui-test"
Provides-Extra: release
Requires-Dist: build>=1.2; extra == "release"
Requires-Dist: twine>=5; extra == "release"
Dynamic: license-file

# ProcProxy

简体中文 | [English](README.en.md)

[![CI](https://github.com/Longersking/procproxy/actions/workflows/ci.yml/badge.svg)](https://github.com/Longersking/procproxy/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/procproxy.svg)](https://pypi.org/project/procproxy/)
[![Python](https://img.shields.io/pypi/pyversions/procproxy.svg)](https://pypi.org/project/procproxy/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

ProcProxy 按进程决定 TCP 连接走直连、代理还是阻断。它不注入 DLL，不改目标进程内存，也不解密流量。

仅支持 Windows，数据面基于 WinDivert。发行包名 `procproxy`，导入名 `proxycore`，当前版本 `0.1.4.3`。

本工具拦截并转发本机流量。仅在自有或已获授权的设备与网络上使用。

## 功能

按进程、目标地址、端口和域名匹配 TCP，动作有 `direct`、`proxy`、`block`。上游支持 SOCKS5、SOCKS4、HTTP CONNECT 和代理链，入口有 `procproxy` CLI 和 `proxycore` Python API，并可选用内置 mitmproxy 抓包。HTTPS 保持密文；不记录报文内容和凭据，默认不上报遥测。

当前版本 `0.1.x`，公开 API 仍可能调整。Windows 服务、IPC 和 UDP 转发已移除，升级前看 [CHANGELOG.md](CHANGELOG.md)。

## 安装

需要 Python 3.10+。真实抓包还需要管理员权限。

```bash
# 只安装核心依赖，适合联调和规则决策
pip install procproxy

# 真实抓包，额外安装 pydivert 和 psutil
pip install "procproxy[windivert]"
```

从源码安装：

```bash
git clone https://github.com/Longersking/procproxy.git
cd procproxy
pip install -e ".[dev]"
```

也可以不安装，把源码树挂进 `site-packages`：

```bash
python procproxy.py install-path
```


## 快速开始

```bash
procproxy init
procproxy doctor
```

`init` 生成最小模板，默认 `backend: null`，没有上游和规则，不能直接代理进程。`python -m proxycore init` 等价。仓库里的 `python procproxy.py init` 无效，它会把 `init` 当成进程名。

把进程流量交给抓包工具，管理员终端运行：

```bash
procproxy forward --process WeChat.exe --port 8848
```

`--port` 填抓包工具的 MITM 代理监听口，不是 Web 管理口。只影响启动后新建的连接。

先自检、不改流量、不需要管理员：

```bash
procproxy forward --process WeChat.exe --port 8848 --check-only
```

也可以直接用配置文件启动：

```bash
procproxy run --config D:\cfg\chrome.yaml
```

内置 mitmproxy（首次先执行一次 `procproxy capture setup`）：

```bash
procproxy capture setup
procproxy forward --process Weixin.exe --process WeChatAppEx.exe --capture mitmproxy
```

`capture setup` 在 `~/.procproxy/mitm-venv` 创建独立环境，避免和主环境的 `pydivert` 冲突。它只统计捕获到的流数量，不保存报文内容。

也可以直接调用 mitmproxy 原生命令，或管理 CA：

```bash
procproxy capture exec mitmweb -p 8080
procproxy capture cert path
procproxy capture cert install --yes          # 安装到当前用户信任库
procproxy capture cert uninstall --yes
```

安装 CA 会修改系统信任库，只在自有或已获授权的设备上使用。

## 把流量交给抓包工具

ProcProxy 只改道，不解密。HTTPS 明文要看抓包工具的 MITM。

```bash
# 1. 自检，不动流量
procproxy forward --process Weixin.exe --port 8848 --check-only
# 2. 管理员终端运行
procproxy forward --process Weixin.exe --port 8848
# 3. 操作目标程序，观察抓包工具，最后 Ctrl+C
```

一次可以给多个进程，用 `;` 分隔，或重复 `--process`。探测把 HTTP 407 视为代理监听成功；上游要求认证时，后续 CONNECT 会报 `E_UPSTREAM_AUTH`。

完整步骤和排错见 [docs/user/forward-to-capture-tool.md](docs/user/forward-to-capture-tool.md)。

## 常用命令

| 命令 | 作用 |
|---|---|
| `procproxy init` | 生成最小配置 |
| `procproxy doctor` | 环境自检 |
| `procproxy forward --process <exe> --port <port>` | 把进程流量交给抓包工具 |
| `procproxy run --config <yaml>` | 用配置文件启动数据面 |
| `procproxy rules --trace --proc <exe> --dst <ip> --port <port>` | 查看规则判定链路 |
| `procproxy config --json` | 输出当前配置 |
| `procproxy status` | 读 `state.json` |
| `procproxy sessions --follow` | 跟踪会话日志 |
| `procproxy stop` / `procproxy stop --panic` | 写控制文件，通知数据面退出 |
| `procproxy capture setup` / `status` | 安装/查看内置 mitmproxy sidecar |
| `procproxy can-proxy` 等诊断命令 | 检查抓包、路由和上游 |

`status`、`sessions` 和 `rules` 直接读文件。`stop` 和 `--panic` 只写 CLI 运行目录的 `control.json`，由同目录的数据面读取。SDK 后台进程用 `stop_proxy()`，或设置同一个 `PROCPROXY_RUNTIME_DIR`。

`python procproxy.py <进程名>` 是 `forward --process` 的简写。只有这个脚本把首个位置参数当进程名。

`forward --backend null` 不监听，不能验证转发链路；离线验证用 `tests/tools/run_e2e.py`。`forward` 的退出码 5 只表示 `make_backend()` 失败；`runtime.start()` 抛错时可能直接 traceback，退出码为 1。

### 长期运行

本仓库不提供 Windows 服务或 IPC。需要常驻时：

- 管理员终端前台运行 `procproxy run --config <yaml>`，关闭终端即停止。
- 或使用 SDK `start_proxy(background=True)`。父进程退出后子进程继续，注销时可能被系统结束。

## 配置

能直接代理 Chrome 的最小配置：

```yaml
version: 1
service:
  sink: { host: 127.0.0.1, port: 19080 }
  backend: windivert
profile:
  name: chrome-via-socks
  default_action: direct
  dns_mode: remote
upstreams:
  - alias: local-socks
    kind: socks5
    host: 127.0.0.1
    port: 1080
rules:
  - id: chrome
    action: proxy
    upstream: local-socks
    targets: "chrome.exe"
```

规则自上而下匹配，首个命中生效。`action: proxy` 默认跳过私网和回环目标，需要时加 `keep_private_proxied: true`；`block` 和 `default_action: block` 不受限制。

上游地址写 IP 字面量，环路守卫按 `(host, port)` 比较；`chain` 最多 8 个别名。`kind: https` 仍使用明文 HTTP CONNECT，`insecure` 没有代码读取。

字段、默认值和校验规则见 [docs/user/configuration.md](docs/user/configuration.md)，规则语义见 [docs/user/rules-and-profiles.md](docs/user/rules-and-profiles.md)。

## Python SDK

```python
from proxycore.api import get_status, start_proxy, stop_proxy

with start_proxy() as ppx:
    print(ppx.config_source)
    print(ppx.status())

bg = start_proxy("D:/cfg/chrome.yaml", background=True)
print(bg.pid, bg.runtime_dir)     # 默认 ~/.procproxy-app
print(get_status(bg.runtime_dir))
print(stop_proxy(bg.runtime_dir))
```

`config_source` 可能是 `explicit`、`env`、`user`、`packaged` 或 `object`，不会是 `repo`。后台模式用 `state.json` 和 `control.json` 通信。`stop_proxy()` 写控制文件并等待，不强制杀进程。

转发、捕获、诊断、状态和停止都有 API：

```python
from proxycore.api import forward_process, can_proxy, read_sessions

with forward_process(["Weixin.exe", "WeChatAppEx.exe"], capture="mitmproxy") as handle:
    print(handle.capture.listen)
    print(handle.counts().to_dict() if handle.counts() else None)

print(can_proxy()["verdict"])
print(read_sessions(limit=20))
```

完整 API 见 [docs/user/sdk.md](docs/user/sdk.md) 和 [docs/dev/api-map.md](docs/dev/api-map.md)，可执行契约见 [examples/verify_sdk.py](examples/verify_sdk.py)。

## 工作原理

```mermaid
flowchart LR
  A[目标进程] --> B[WinDivert 捕获]
  B --> C[规则决策]
  C -->|PROXY| D[改道到 sink]
  D --> E[上游代理]
  E --> F[目标服务器]
  C -->|DIRECT| F
  C -->|BLOCK| X[丢弃]
```

WinDivert 捕获出向 TCP 包，按客户端源端口反查 PID。`rules.decide()` 返回 `DIRECT`、`BLOCK` 或 `PROXY`。代理连接先记会话，再把目的地址改写到 `127.0.0.1:<sink>`。

sink 用客户端源端口反查原始目标，连接上游并双向转发。反向路径也要改写；只改一半，三次握手完成不了。

`backend` 负责捕获和改道，`rules` 负责决策，`sink/relay` 负责搬字节，`upstream` 负责代理协议。`decide()` 是纯函数，不做 IO。

架构和源码阅读顺序见 [docs/dev/architecture.md](docs/dev/architecture.md)。要改代码，见 [docs/dev/contributor-guide.md](docs/dev/contributor-guide.md)。

## 已知限制

| 限制 | 实际行为 |
|---|---|
| 平台 | 仅 Windows。仓库没有 Linux 抓包后端 |
| 协议 | 只捕获 TCP。UDP 和 QUIC 不支持，本版本没有 UDP 转发实现 |
| 权限 | 真抓包需要管理员。`backend=null` 不抓包、不改道 |
| 域名规则 | `dst_name` 依赖域名来源。WinDivert 只给 IP，这类规则在真机上不会命中 |
| HTTPS | 不解密。要明文请转发给抓包工具 |
| 上游地址 | 写 IP 字面量。写 `localhost` 会让环路守卫失效 |
| 未知 PID | 查表有竞态。默认 `on_unknown_pid: direct`，可以改成 `block` |
| 本机目标 | 目标是本机地址时抓不到。Windows 走回环捷径，包不经过外发路径 |
| `forward --backend null` | 不监听。`forward` 不暴露 `sink_test_target` 和 `upstream` |
| `forward` 退出码 | 5 只覆盖 `make_backend` 失败。capture 环境缺失为 6，capture 启动/端口失败为 7。`runtime.start()` 失败可能 traceback，退出码为 1 |
| 内置 mitmproxy | 需要独立 sidecar 和 Python 3.10–3.12，首次联网安装。只统计流数量，不解密 |
| HTTP 407 | 探测阶段视为代理监听成功。认证失败会在后续 CONNECT 握手时出现 |
| `enable_trace_payload` | 当前是空操作。开启后不会记录报文内容 |
| `kind: https` | 使用明文 HTTP CONNECT。`insecure` 只解析，没有代码读取 |
| 热重载 | `sink.port` 和 `backend` 不能热改，需要重启 |
| 未实现的选项 | `handle_services`、`handle_other_users`、`dns_local_transport: proxy`、`auth: ntlm` 在加载期直接拒绝 |

## 排错

最常见的是 `[WinError 5] 拒绝访问`，表示当前终端不是管理员。WinDivert 驱动和设备句柄需要管理员权限。用管理员终端重新打开，再运行 `procproxy doctor`。

非管理员可以用 `backend=null` 做联调，但它不抓包、不改道。其他症状见 [docs/user/troubleshooting.md](docs/user/troubleshooting.md)。

## 文档与贡献

- [文档索引](docs/README.md)、[架构](docs/dev/architecture.md)、[配置](docs/user/configuration.md)、[规则](docs/user/rules-and-profiles.md)、[SDK](docs/user/sdk.md)、[排错](docs/user/troubleshooting.md)
- [项目图解](docs/dev/diagrams/project-map.md)、[forward](docs/user/forward-to-capture-tool.md)、[内置 mitmproxy](docs/user/capture-mitmproxy.md)
- [模块文档](docs/modules/README.md)、[CLI/API 对照](docs/dev/api-map.md)
- 参与开发见 [CONTRIBUTING.md](CONTRIBUTING.md) 和 [docs/dev/contributor-guide.md](docs/dev/contributor-guide.md)；接手维护先看 [HANDOFF.md](HANDOFF.md)。
- 安全漏洞不要公开提 issue，见 [SECURITY.md](SECURITY.md)；版本变化见 [CHANGELOG.md](CHANGELOG.md)。

## 开发与验证

```bash
pip install -e ".[dev]"
python -m pytest -q tests/
python -m ruff check src tests
python -m mypy src/proxycore
python tests/tools/run_demo.py
python tests/tools/run_e2e.py
python examples/verify_sdk.py
```

部分真机 WinDivert 用例需要管理员。测试数量随仓库变化，以实际输出为准。`run_demo.py` 和 `run_e2e.py` 不需要管理员；`real_machine_check.py` 需要管理员和真实外网。

内置 mitmproxy 和微信 UI 测试：

```bash
python -m proxycore capture setup
python -m pytest -q tests/integration/test_mitm_real.py -m mitmproxy_real
PROCPROXY_WECHAT_E2E=1 python -m pytest -q tests/ui -m wechat_e2e
```

## 许可证与使用边界

本项目以 MIT 许可证发布，全文见 [LICENSE](LICENSE)。第三方组件与许可证见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。

默认不打包 pydivert，只声明依赖；把它打包进 exe 分发时，才需要满足 LGPLv3 的随附全文、源码获取和可替换要求。

本项目是独立的进程级代理实现，与 Proxifier 的权利人无关联，未获授权或背书。本项目不解析 Proxifier 的私有文件格式，不包含绕过授权或 DRM 的功能。

本项目在 AI 编程助手辅助下开发。需求、设计、取舍、测试与发布由人类作者负责。代码按 MIT 许可证提供，不作额外保证。
