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.
Files changed (51) hide show
  1. {procproxy-0.1.0/src/procproxy.egg-info → procproxy-0.1.1}/PKG-INFO +19 -3
  2. {procproxy-0.1.0 → procproxy-0.1.1}/README.md +18 -2
  3. {procproxy-0.1.0 → procproxy-0.1.1}/pyproject.toml +4 -1
  4. {procproxy-0.1.0 → procproxy-0.1.1/src/procproxy.egg-info}/PKG-INFO +19 -3
  5. {procproxy-0.1.0 → procproxy-0.1.1}/src/procproxy.egg-info/SOURCES.txt +1 -0
  6. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/__init__.py +1 -1
  7. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/__main__.py +7 -7
  8. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/canproxy.py +5 -2
  9. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/checkroute.py +7 -2
  10. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/cli.py +119 -5
  11. procproxy-0.1.1/src/proxycore/data/default.yaml +15 -0
  12. {procproxy-0.1.0 → procproxy-0.1.1}/LICENSE +0 -0
  13. {procproxy-0.1.0 → procproxy-0.1.1}/setup.cfg +0 -0
  14. {procproxy-0.1.0 → procproxy-0.1.1}/src/procproxy.egg-info/dependency_links.txt +0 -0
  15. {procproxy-0.1.0 → procproxy-0.1.1}/src/procproxy.egg-info/entry_points.txt +0 -0
  16. {procproxy-0.1.0 → procproxy-0.1.1}/src/procproxy.egg-info/requires.txt +0 -0
  17. {procproxy-0.1.0 → procproxy-0.1.1}/src/procproxy.egg-info/top_level.txt +0 -0
  18. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/api.py +0 -0
  19. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/__init__.py +0 -0
  20. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/base.py +0 -0
  21. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/null.py +0 -0
  22. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/windivert/__init__.py +0 -0
  23. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/windivert/filter.py +0 -0
  24. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/windivert/pidmap.py +0 -0
  25. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/backend/windivert/pkt.py +0 -0
  26. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/config.py +0 -0
  27. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/dns/__init__.py +0 -0
  28. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/dns/cache.py +0 -0
  29. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/dns/modes.py +0 -0
  30. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/dns/udp.py +0 -0
  31. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/forward.py +0 -0
  32. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/ipc.py +0 -0
  33. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/log.py +0 -0
  34. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/pathsetup.py +0 -0
  35. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/probe.py +0 -0
  36. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/proc.py +0 -0
  37. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/rules.py +0 -0
  38. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/runtime.py +0 -0
  39. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/service/__init__.py +0 -0
  40. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/service/__main__.py +0 -0
  41. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/tunnel/__init__.py +0 -0
  42. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/tunnel/relay.py +0 -0
  43. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/tunnel/sessions.py +0 -0
  44. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/tunnel/sink.py +0 -0
  45. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/types.py +0 -0
  46. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/__init__.py +0 -0
  47. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/base.py +0 -0
  48. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/chain.py +0 -0
  49. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/http_connect.py +0 -0
  50. {procproxy-0.1.0 → procproxy-0.1.1}/src/proxycore/upstream/socks4.py +0 -0
  51. {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.0
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 pydivert psutil
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 pydivert psutil
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.0"
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.0
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 pydivert psutil
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,6 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "0.1.0"
5
+ __version__ = "0.1.1"
6
6
 
7
7
  __all__ = ["__version__"]
@@ -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
- 也就是说:没写子命令时默认补 `run`(只对 run 支持的参数生效),
12
- 写了子命令就原样透传。子命令清单取自 `cli` 的单一来源,不在这里再抄一遍
13
- (两边各抄一份的话,新增 `forward` / `can-proxy` 之后这里会漏,
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 ["run", "--config", "samples/profiles/dev.yaml"]
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(resolve_config_path(args.config))
116
+ config = Config.load(path)
114
117
  except (ConfigError, OSError) as exc:
115
- config_error = str(exc)
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(args.config)
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
- hint = ""
121
- root = repo_root()
122
- if root is not None:
123
- hint = f"\n提示:仓库根是 {root},可用 --config {root / 'samples' / 'profiles' / 'dev.yaml'}"
124
- raise SystemExit(f"配置文件不存在: {path}{hint}")
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