procproxy 0.1.0__tar.gz → 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {procproxy-0.1.0/src/procproxy.egg-info → procproxy-0.1.1}/PKG-INFO +19 -3
- {procproxy-0.1.0 → procproxy-0.1.1}/README.md +18 -2
- {procproxy-0.1.0 → procproxy-0.1.1}/pyproject.toml +4 -1
- {procproxy-0.1.0 → procproxy-0.1.1/src/procproxy.egg-info}/PKG-INFO +19 -3
- {procproxy-0.1.0 → procproxy-0.1.1}/src/procproxy.egg-info/SOURCES.txt +1 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/__init__.py +1 -1
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/__main__.py +7 -7
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/canproxy.py +5 -2
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/checkroute.py +7 -2
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/cli.py +119 -5
- procproxy-0.1.1/src/proxycore/data/default.yaml +15 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/LICENSE +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/setup.cfg +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/procproxy.egg-info/dependency_links.txt +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/procproxy.egg-info/entry_points.txt +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/procproxy.egg-info/requires.txt +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/procproxy.egg-info/top_level.txt +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/api.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/__init__.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/base.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/null.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/windivert/__init__.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/windivert/filter.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/windivert/pidmap.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/windivert/pkt.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/config.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/dns/__init__.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/dns/cache.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/dns/modes.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/dns/udp.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/forward.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/ipc.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/log.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/pathsetup.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/probe.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/proc.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/rules.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/runtime.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/service/__init__.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/service/__main__.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/tunnel/__init__.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/tunnel/relay.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/tunnel/sessions.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/tunnel/sink.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/types.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/__init__.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/base.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/chain.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/http_connect.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/socks4.py +0 -0
- {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/socks5.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: procproxy
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: ProcProxy —— 进程级代理:按进程决定哪条连接走哪个上游代理
|
|
5
5
|
Author: Longersking
|
|
6
6
|
License-Expression: MIT
|
|
@@ -68,8 +68,24 @@ python procproxy.py doctor | rules | sessions | ... # 子命令(等价于 pyt
|
|
|
68
68
|
|
|
69
69
|
需要 **Python 3.10+**。
|
|
70
70
|
|
|
71
|
+
### 从 PyPI 安装(推荐)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install procproxy
|
|
75
|
+
procproxy init # 生成 ~/.procproxy/config.yaml
|
|
76
|
+
procproxy doctor # 环境自检
|
|
77
|
+
procproxy forward WeChat.exe --port 8848 # 真实转发(需管理员)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
安装后直接运行 `procproxy` 会显示首次使用指引,不依赖任何样例文件。
|
|
81
|
+
|
|
82
|
+
非管理员:WinDivert 抓包必须管理员;可以用 `--backend null` 做转发链路联调,
|
|
83
|
+
或在服务已启动、且配置了 `service.ipc_allow_group` 时读取状态。
|
|
84
|
+
|
|
85
|
+
### 源码开发安装
|
|
86
|
+
|
|
71
87
|
```bash
|
|
72
|
-
pip install -e .
|
|
88
|
+
pip install -e ".[dev]"
|
|
73
89
|
# 或者不装(零依赖方式,往 site-packages 写一个 .pth,让 python -m proxycore 全局可用)
|
|
74
90
|
python procproxy.py install-path
|
|
75
91
|
```
|
|
@@ -77,7 +93,7 @@ python procproxy.py install-path
|
|
|
77
93
|
数据面依赖(要用真抓包就必需):
|
|
78
94
|
|
|
79
95
|
```bash
|
|
80
|
-
pip install
|
|
96
|
+
pip install "procproxy[windivert]"
|
|
81
97
|
```
|
|
82
98
|
|
|
83
99
|
> `pydivert` 自带**已签名**的 `WinDivert64.sys` —— 所以**不需要**开测试签名、不需要自己签驱动。
|
|
@@ -29,8 +29,24 @@ python procproxy.py doctor | rules | sessions | ... # 子命令(等价于 pyt
|
|
|
29
29
|
|
|
30
30
|
需要 **Python 3.10+**。
|
|
31
31
|
|
|
32
|
+
### 从 PyPI 安装(推荐)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install procproxy
|
|
36
|
+
procproxy init # 生成 ~/.procproxy/config.yaml
|
|
37
|
+
procproxy doctor # 环境自检
|
|
38
|
+
procproxy forward WeChat.exe --port 8848 # 真实转发(需管理员)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
安装后直接运行 `procproxy` 会显示首次使用指引,不依赖任何样例文件。
|
|
42
|
+
|
|
43
|
+
非管理员:WinDivert 抓包必须管理员;可以用 `--backend null` 做转发链路联调,
|
|
44
|
+
或在服务已启动、且配置了 `service.ipc_allow_group` 时读取状态。
|
|
45
|
+
|
|
46
|
+
### 源码开发安装
|
|
47
|
+
|
|
32
48
|
```bash
|
|
33
|
-
pip install -e .
|
|
49
|
+
pip install -e ".[dev]"
|
|
34
50
|
# 或者不装(零依赖方式,往 site-packages 写一个 .pth,让 python -m proxycore 全局可用)
|
|
35
51
|
python procproxy.py install-path
|
|
36
52
|
```
|
|
@@ -38,7 +54,7 @@ python procproxy.py install-path
|
|
|
38
54
|
数据面依赖(要用真抓包就必需):
|
|
39
55
|
|
|
40
56
|
```bash
|
|
41
|
-
pip install
|
|
57
|
+
pip install "procproxy[windivert]"
|
|
42
58
|
```
|
|
43
59
|
|
|
44
60
|
> `pydivert` 自带**已签名**的 `WinDivert64.sys` —— 所以**不需要**开测试签名、不需要自己签驱动。
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "procproxy"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "ProcProxy —— 进程级代理:按进程决定哪条连接走哪个上游代理"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -51,6 +51,9 @@ package-dir = { "" = "src" }
|
|
|
51
51
|
[tool.setuptools.packages.find]
|
|
52
52
|
where = ["src"]
|
|
53
53
|
|
|
54
|
+
[tool.setuptools.package-data]
|
|
55
|
+
"proxycore" = ["data/*.yaml"]
|
|
56
|
+
|
|
54
57
|
# ---------------------------------------------------------------- pytest ----
|
|
55
58
|
[tool.pytest.ini_options]
|
|
56
59
|
minversion = "7.4"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: procproxy
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: ProcProxy —— 进程级代理:按进程决定哪条连接走哪个上游代理
|
|
5
5
|
Author: Longersking
|
|
6
6
|
License-Expression: MIT
|
|
@@ -68,8 +68,24 @@ python procproxy.py doctor | rules | sessions | ... # 子命令(等价于 pyt
|
|
|
68
68
|
|
|
69
69
|
需要 **Python 3.10+**。
|
|
70
70
|
|
|
71
|
+
### 从 PyPI 安装(推荐)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install procproxy
|
|
75
|
+
procproxy init # 生成 ~/.procproxy/config.yaml
|
|
76
|
+
procproxy doctor # 环境自检
|
|
77
|
+
procproxy forward WeChat.exe --port 8848 # 真实转发(需管理员)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
安装后直接运行 `procproxy` 会显示首次使用指引,不依赖任何样例文件。
|
|
81
|
+
|
|
82
|
+
非管理员:WinDivert 抓包必须管理员;可以用 `--backend null` 做转发链路联调,
|
|
83
|
+
或在服务已启动、且配置了 `service.ipc_allow_group` 时读取状态。
|
|
84
|
+
|
|
85
|
+
### 源码开发安装
|
|
86
|
+
|
|
71
87
|
```bash
|
|
72
|
-
pip install -e .
|
|
88
|
+
pip install -e ".[dev]"
|
|
73
89
|
# 或者不装(零依赖方式,往 site-packages 写一个 .pth,让 python -m proxycore 全局可用)
|
|
74
90
|
python procproxy.py install-path
|
|
75
91
|
```
|
|
@@ -77,7 +93,7 @@ python procproxy.py install-path
|
|
|
77
93
|
数据面依赖(要用真抓包就必需):
|
|
78
94
|
|
|
79
95
|
```bash
|
|
80
|
-
pip install
|
|
96
|
+
pip install "procproxy[windivert]"
|
|
81
97
|
```
|
|
82
98
|
|
|
83
99
|
> `pydivert` 自带**已签名**的 `WinDivert64.sys` —— 所以**不需要**开测试签名、不需要自己签驱动。
|
|
@@ -30,6 +30,7 @@ src/proxycore/backend/windivert/__init__.py
|
|
|
30
30
|
src/proxycore/backend/windivert/filter.py
|
|
31
31
|
src/proxycore/backend/windivert/pidmap.py
|
|
32
32
|
src/proxycore/backend/windivert/pkt.py
|
|
33
|
+
src/proxycore/data/default.yaml
|
|
33
34
|
src/proxycore/dns/__init__.py
|
|
34
35
|
src/proxycore/dns/cache.py
|
|
35
36
|
src/proxycore/dns/modes.py
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
目标是让"用 Python 启动"最省事:
|
|
4
4
|
|
|
5
|
-
python -m proxycore #
|
|
5
|
+
python -m proxycore # 首次使用指引
|
|
6
|
+
python -m proxycore init # 生成配置
|
|
6
7
|
python -m proxycore --config 你的.yaml # 起服务(等价于 run)
|
|
7
8
|
python -m proxycore --config 你的.yaml --backend null # 联调
|
|
8
9
|
python -m proxycore rules --config 你的.yaml # 子命令原样转给 CLI
|
|
9
10
|
python -m proxycore --help / --version
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
`python -m proxycore forward` 就会被误补成 `run forward`)。
|
|
12
|
+
没写参数时打印首次使用指引(不启动服务);顶层给 `--config` 等 run 选项时
|
|
13
|
+
自动补 `run`;写了子命令就原样透传。子命令清单取自 `cli` 的单一来源,
|
|
14
|
+
不在这里再抄一遍。
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
@@ -32,7 +32,7 @@ RUN_OPTIONS = (
|
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
#: 自带 argparse 的原生子命令。
|
|
35
|
-
NATIVE_SUBCOMMANDS = ("rules", "config", "status", "sessions", "run", "doctor", "stop")
|
|
35
|
+
NATIVE_SUBCOMMANDS = ("rules", "config", "status", "sessions", "run", "doctor", "init", "stop")
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def known_subcommands() -> tuple[str, ...]:
|
|
@@ -45,7 +45,7 @@ def known_subcommands() -> tuple[str, ...]:
|
|
|
45
45
|
def normalize_args(argv: list[str]) -> list[str]:
|
|
46
46
|
"""把顶层选项补成 `run <选项>`;其它情况原样返回。"""
|
|
47
47
|
if not argv:
|
|
48
|
-
return [
|
|
48
|
+
return [] # 交给 cli.main 打印首次使用指引
|
|
49
49
|
# 显式子命令、或 -h/--help/--version:原样交给 CLI
|
|
50
50
|
if argv[0] in known_subcommands() or argv[0] in ("-h", "--help", "--version"):
|
|
51
51
|
return argv
|
|
@@ -109,10 +109,13 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
109
109
|
|
|
110
110
|
config: Config | None = None
|
|
111
111
|
config_error = ""
|
|
112
|
+
from .cli import default_config_path
|
|
113
|
+
|
|
114
|
+
path = default_config_path(args.config) or resolve_config_path(args.config)
|
|
112
115
|
try:
|
|
113
|
-
config = Config.load(
|
|
116
|
+
config = Config.load(path)
|
|
114
117
|
except (ConfigError, OSError) as exc:
|
|
115
|
-
config_error =
|
|
118
|
+
config_error = f"{exc}(首次使用请运行 procproxy init)"
|
|
116
119
|
|
|
117
120
|
backend = args.backend or (config.service.backend if config else "windivert")
|
|
118
121
|
sink_host = config.service.sink.host if config else "127.0.0.1"
|
|
@@ -28,6 +28,7 @@ from collections import Counter
|
|
|
28
28
|
from pathlib import Path
|
|
29
29
|
|
|
30
30
|
from proxycore.backend.windivert.pidmap import PortPidTable, is_supported
|
|
31
|
+
from proxycore.cli import default_config_path
|
|
31
32
|
from proxycore.config import Config, ConfigError
|
|
32
33
|
from proxycore.proc import get_proc_info, iter_pids
|
|
33
34
|
from proxycore.rules import GuardSet, decide
|
|
@@ -176,13 +177,17 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
176
177
|
return 2
|
|
177
178
|
proc_name = args.proc or target
|
|
178
179
|
|
|
180
|
+
path = default_config_path(args.config)
|
|
181
|
+
if path is None:
|
|
182
|
+
print(f"配置文件不存在: {args.config};首次使用请运行 procproxy init", file=sys.stderr)
|
|
183
|
+
return 2
|
|
179
184
|
try:
|
|
180
|
-
config = Config.load(
|
|
185
|
+
config = Config.load(path)
|
|
181
186
|
except ConfigError as exc:
|
|
182
187
|
print(f"配置无效:{exc}", file=sys.stderr)
|
|
183
188
|
return 2
|
|
184
189
|
|
|
185
|
-
print(f"# check_route target={target} expect={args.expect} config={args.config}")
|
|
190
|
+
print(f"# check_route target={target} expect={args.expect} config={config.path or args.config}")
|
|
186
191
|
print(f"# 规则复算:{proc_name} -> {args.dst}:{args.port}/{args.proto}")
|
|
187
192
|
|
|
188
193
|
actual_action, replay_note = replay_rule(config, proc_name, args.dst, args.port, args.proto)
|
|
@@ -16,6 +16,8 @@ import time
|
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
from typing import Any
|
|
18
18
|
|
|
19
|
+
import yaml
|
|
20
|
+
|
|
19
21
|
from proxycore import __version__
|
|
20
22
|
from proxycore.config import Config, ConfigError, ConfigManager, port_in_use
|
|
21
23
|
from proxycore.log import LEVELS, build_logger, enable_trace_payload, get_logger, redact
|
|
@@ -24,6 +26,7 @@ from proxycore.types import ConnRequest, Endpoint, ProcInfo, Proto
|
|
|
24
26
|
|
|
25
27
|
DEFAULT_CONFIG = "samples/profiles/dev.yaml"
|
|
26
28
|
RUNTIME_DIR_ENV = "PROCPROXY_RUNTIME_DIR"
|
|
29
|
+
USER_CONFIG_ENV = "PROCPROXY_CONFIG"
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
# ============================================================ 运行时目录 ====
|
|
@@ -38,6 +41,12 @@ def runtime_dir() -> Path:
|
|
|
38
41
|
return Path.home() / ".procproxy"
|
|
39
42
|
|
|
40
43
|
|
|
44
|
+
def user_config_path() -> Path:
|
|
45
|
+
"""用户配置的默认路径(非管理员可写;可用 `PROCPROXY_CONFIG` 覆盖)。"""
|
|
46
|
+
override = os.environ.get(USER_CONFIG_ENV)
|
|
47
|
+
return Path(override) if override else Path.home() / ".procproxy" / "config.yaml"
|
|
48
|
+
|
|
49
|
+
|
|
41
50
|
def state_path() -> Path:
|
|
42
51
|
return runtime_dir() / "state.json"
|
|
43
52
|
|
|
@@ -113,15 +122,48 @@ def resolve_config_path(raw: str) -> Path:
|
|
|
113
122
|
return path
|
|
114
123
|
|
|
115
124
|
|
|
125
|
+
def packaged_default_config() -> Path | None:
|
|
126
|
+
"""安装包内置的最小默认配置(PyPI 安装后也能首次运行)。"""
|
|
127
|
+
try:
|
|
128
|
+
from importlib.resources import files
|
|
129
|
+
|
|
130
|
+
path = Path(str(files("proxycore").joinpath("data/default.yaml")))
|
|
131
|
+
except (ImportError, ModuleNotFoundError, TypeError, ValueError):
|
|
132
|
+
return None
|
|
133
|
+
return path if path.is_file() else None
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def default_config_path(raw: str) -> Path | None:
|
|
137
|
+
"""用户指定的配置 → 仓库样例 → 安装包内置默认配置。"""
|
|
138
|
+
path = resolve_config_path(raw)
|
|
139
|
+
if path.exists():
|
|
140
|
+
return path
|
|
141
|
+
if raw == DEFAULT_CONFIG:
|
|
142
|
+
return packaged_default_config()
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
|
|
116
146
|
def _load_config(args: argparse.Namespace) -> Config:
|
|
117
147
|
raw = getattr(args, "config", DEFAULT_CONFIG) or DEFAULT_CONFIG
|
|
118
148
|
path = resolve_config_path(raw)
|
|
149
|
+
using_packaged = False
|
|
150
|
+
if not path.exists() and raw == DEFAULT_CONFIG:
|
|
151
|
+
packaged = packaged_default_config()
|
|
152
|
+
if packaged is not None:
|
|
153
|
+
path = packaged
|
|
154
|
+
using_packaged = True
|
|
119
155
|
if not path.exists():
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
156
|
+
raise SystemExit(
|
|
157
|
+
f"配置文件不存在: {path}\n"
|
|
158
|
+
"首次使用请运行: procproxy init\n"
|
|
159
|
+
"或指定配置: procproxy doctor --config <你的.yaml>"
|
|
160
|
+
)
|
|
161
|
+
if using_packaged:
|
|
162
|
+
print(
|
|
163
|
+
"[i] 未找到用户配置,使用内置默认配置(backend=null,不抓包)。"
|
|
164
|
+
"运行 `procproxy init` 生成可编辑配置。",
|
|
165
|
+
file=sys.stderr,
|
|
166
|
+
)
|
|
125
167
|
try:
|
|
126
168
|
return Config.load(path, check_sink=bool(getattr(args, "check_sink", False)))
|
|
127
169
|
except ConfigError as exc:
|
|
@@ -219,6 +261,51 @@ def cmd_config(args: argparse.Namespace) -> int:
|
|
|
219
261
|
return 0
|
|
220
262
|
|
|
221
263
|
|
|
264
|
+
def cmd_init(args: argparse.Namespace) -> int:
|
|
265
|
+
"""生成一份可编辑的启动配置(PyPI 安装后首次使用)。"""
|
|
266
|
+
target = Path(args.path) if args.path else user_config_path()
|
|
267
|
+
if target.exists() and not args.force:
|
|
268
|
+
print(f"配置文件已存在: {target}(加 --force 覆盖)", file=sys.stderr)
|
|
269
|
+
return 2
|
|
270
|
+
if not 1024 <= args.sink_port <= 65535:
|
|
271
|
+
print("--sink-port 必须在 1024-65535", file=sys.stderr)
|
|
272
|
+
return 2
|
|
273
|
+
packaged = packaged_default_config()
|
|
274
|
+
if packaged is None:
|
|
275
|
+
print("安装包缺少内置默认配置,请重新安装 procproxy", file=sys.stderr)
|
|
276
|
+
return 2
|
|
277
|
+
|
|
278
|
+
doc = yaml.safe_load(packaged.read_text(encoding="utf-8")) or {}
|
|
279
|
+
service = doc.setdefault("service", {})
|
|
280
|
+
service["backend"] = args.backend
|
|
281
|
+
sink = service.setdefault("sink", {})
|
|
282
|
+
sink.setdefault("host", "127.0.0.1")
|
|
283
|
+
sink["port"] = args.sink_port
|
|
284
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
285
|
+
header = "# ProcProxy 配置(由 `procproxy init` 生成)\n"
|
|
286
|
+
target.write_text(
|
|
287
|
+
header + yaml.safe_dump(doc, allow_unicode=True, sort_keys=False),
|
|
288
|
+
encoding="utf-8",
|
|
289
|
+
)
|
|
290
|
+
try:
|
|
291
|
+
Config.load(target)
|
|
292
|
+
except ConfigError as exc:
|
|
293
|
+
with contextlib.suppress(OSError):
|
|
294
|
+
target.unlink()
|
|
295
|
+
print(f"生成的配置未通过校验:{exc.code} — {exc.message}", file=sys.stderr)
|
|
296
|
+
return 2
|
|
297
|
+
|
|
298
|
+
print(f"已生成配置: {target}")
|
|
299
|
+
print("下一步:")
|
|
300
|
+
print(f" procproxy doctor --config \"{target}\"")
|
|
301
|
+
print(f" procproxy run --config \"{target}\"")
|
|
302
|
+
if args.backend == "windivert":
|
|
303
|
+
print(" 提示: backend=windivert 需要管理员权限;非管理员请加 --backend null 只做联调。")
|
|
304
|
+
else:
|
|
305
|
+
print(" 提示: backend=null 不抓包;真实抓包请用 `procproxy forward ...` 或 --backend windivert。")
|
|
306
|
+
return 0
|
|
307
|
+
|
|
308
|
+
|
|
222
309
|
def cmd_status(args: argparse.Namespace) -> int:
|
|
223
310
|
state = _read_json(state_path())
|
|
224
311
|
config: Config | None = None
|
|
@@ -473,6 +560,24 @@ def cmd_stop(args: argparse.Namespace) -> int:
|
|
|
473
560
|
return 0
|
|
474
561
|
|
|
475
562
|
|
|
563
|
+
def _quickstart() -> int:
|
|
564
|
+
"""无参数时的首次使用指引(不依赖配置文件)。"""
|
|
565
|
+
print(f"ProcProxy {__version__}")
|
|
566
|
+
print()
|
|
567
|
+
print("首次使用:")
|
|
568
|
+
print(" procproxy init 生成配置")
|
|
569
|
+
print(" procproxy doctor 环境自检")
|
|
570
|
+
print(" procproxy forward WeChat.exe --port 8848 把进程流量转发给抓包工具")
|
|
571
|
+
print()
|
|
572
|
+
print("其他:")
|
|
573
|
+
print(" procproxy run --config <path> 前台运行数据面")
|
|
574
|
+
print(" procproxy rules --config <path> 查看规则")
|
|
575
|
+
print(" procproxy --help 全部命令")
|
|
576
|
+
print()
|
|
577
|
+
print("非管理员: --backend null 只联调不抓包;真实抓包需要管理员。")
|
|
578
|
+
return 0
|
|
579
|
+
|
|
580
|
+
|
|
476
581
|
# ============================================================ 参数解析 ====
|
|
477
582
|
|
|
478
583
|
# ====================================================== 外包子命令(透传)====
|
|
@@ -568,6 +673,13 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
568
673
|
p_doctor.add_argument("--backend", choices=["null", "windivert"], default="")
|
|
569
674
|
p_doctor.set_defaults(func=cmd_doctor)
|
|
570
675
|
|
|
676
|
+
p_init = sub.add_parser("init", help="生成一份可编辑的启动配置")
|
|
677
|
+
p_init.add_argument("--path", default="", help="输出路径(默认 ~/.procproxy/config.yaml)")
|
|
678
|
+
p_init.add_argument("--backend", choices=["null", "windivert"], default="null")
|
|
679
|
+
p_init.add_argument("--sink-port", type=int, default=19080)
|
|
680
|
+
p_init.add_argument("--force", action="store_true", help="覆盖已存在的配置")
|
|
681
|
+
p_init.set_defaults(func=cmd_init)
|
|
682
|
+
|
|
571
683
|
p_stop = sub.add_parser("stop", help="停止服务(--panic 为紧急全量放行)")
|
|
572
684
|
add_common(p_stop)
|
|
573
685
|
p_stop.add_argument("--panic", action="store_true", help="紧急停止:尽快停掉数据面并退出")
|
|
@@ -579,6 +691,8 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
579
691
|
def main(argv: list[str] | None = None) -> int:
|
|
580
692
|
_force_utf8_console()
|
|
581
693
|
argv = list(sys.argv[1:] if argv is None else argv)
|
|
694
|
+
if not argv:
|
|
695
|
+
return _quickstart()
|
|
582
696
|
handled = _dispatch_passthrough(argv)
|
|
583
697
|
if handled is not None:
|
|
584
698
|
return handled
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# ProcProxy 内置默认配置
|
|
2
|
+
# backend=null:不抓包、不改道,只用于首次自检/联调。
|
|
3
|
+
# 真实使用请运行 `procproxy init` 或 `procproxy forward <进程名> --port <端口>`。
|
|
4
|
+
version: 1
|
|
5
|
+
service:
|
|
6
|
+
sink: { host: 127.0.0.1, port: 19080 }
|
|
7
|
+
backend: null
|
|
8
|
+
on_unknown_pid: direct
|
|
9
|
+
on_decide_error: block
|
|
10
|
+
profile:
|
|
11
|
+
name: default
|
|
12
|
+
default_action: direct
|
|
13
|
+
dns_mode: remote
|
|
14
|
+
upstreams: []
|
|
15
|
+
rules: []
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|