block-proxy 0.1.14 → 0.1.16
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.
- package/.claude/settings.local.json +88 -34
- package/.claude/skills/icon_generate/skill.md +45 -0
- package/CLAUDE.md +3 -3
- package/README.md +28 -187
- package/client/app.py +29 -9
- package/client/build.sh +6 -0
- package/client/config.py +1 -0
- package/client/config_window.py +36 -26
- package/client/icons/app.icns +0 -0
- package/client/icons/christmas-sock_light.png +0 -0
- package/client/icons/christmas-sock_light_bar.png +0 -0
- package/client/icons/christmas-sock_light_bar_off.png +0 -0
- package/client/icons/socks_on_G.png +0 -0
- package/client/icons/socks_on_G_bar.png +0 -0
- package/client/icons/socks_on_M.png +0 -0
- package/client/icons/socks_on_M_bar.png +0 -0
- package/client/proxy_core.py +305 -21
- package/client/tests/test_proxy_core_udp.py +466 -0
- package/config.json +3 -1
- package/package.json +1 -1
- package/socks5/server.js +74 -167
- package/wiki.md +287 -0
- package/client/icons/backup/app_example.png +0 -0
- package/client/icons/backup/christmas-sock_dark.png +0 -0
- package/client/icons/backup/christmas-sock_light.png +0 -0
- package/client/icons/backup/socks_on_G.png +0 -0
- package/client/icons/backup/socks_on_M.png +0 -0
- package/client/icons/christmas-sock_dark.png +0 -0
|
@@ -1,43 +1,97 @@
|
|
|
1
1
|
{
|
|
2
2
|
"permissions": {
|
|
3
3
|
"allow": [
|
|
4
|
-
"Bash(git commit:*)",
|
|
5
4
|
"Bash(git add:*)",
|
|
6
|
-
"Bash(
|
|
7
|
-
"Bash(
|
|
8
|
-
"Bash(
|
|
9
|
-
"Bash(
|
|
10
|
-
"Bash(
|
|
11
|
-
"Bash(
|
|
12
|
-
"Bash(oha *)",
|
|
13
|
-
"Bash(ping *)",
|
|
14
|
-
"Bash(brew install *)",
|
|
15
|
-
"Bash(npm run *)",
|
|
16
|
-
"Bash(pnpm i *)",
|
|
17
|
-
"Bash(break)",
|
|
18
|
-
"Bash(pkill -f \"node ./proxy/start.js\")",
|
|
19
|
-
"Bash(pkill -f \"node ./socks5/start.js\")",
|
|
20
|
-
"Bash(pkill -f \"node proxy/start.js\")",
|
|
21
|
-
"Bash(pkill -f \"node socks5/start.js\")",
|
|
22
|
-
"Bash(gh release *)",
|
|
23
|
-
"Read(//Library/Frameworks/Python.framework/Versions/**)",
|
|
24
|
-
"Bash(/Library/Frameworks/Python.framework/Versions/3.13/bin/python3 -m nuitka --version)",
|
|
25
|
-
"Bash(ps *)",
|
|
26
|
-
"Bash(pkill -f nuitka)",
|
|
27
|
-
"Bash(sips *)",
|
|
5
|
+
"Bash(git commit:*)",
|
|
6
|
+
"Bash(npm test:*)",
|
|
7
|
+
"Bash(pnpm add:*)",
|
|
8
|
+
"Bash(npm install:*)",
|
|
9
|
+
"Bash(find:*)",
|
|
10
|
+
"Bash(.venv/bin/pip install *)",
|
|
28
11
|
"Bash(git *)",
|
|
29
|
-
"
|
|
12
|
+
"Read(//Library/Frameworks/Python.framework/Versions/3.13/bin/**)",
|
|
13
|
+
"Bash(/Users/bachi/jaylli/block-proxy/client/.venv/bin/python -m pytest --version)",
|
|
14
|
+
"Bash(.venv/bin/python -m pytest tests/test_config.py -v)",
|
|
15
|
+
"Bash(.venv/bin/python --version)",
|
|
16
|
+
"Bash(chmod +x *)",
|
|
17
|
+
"Bash(bash *)",
|
|
18
|
+
"Bash(xxd)",
|
|
19
|
+
"Bash(md5 *)",
|
|
20
|
+
"Bash(python *)",
|
|
21
|
+
"Bash(mkdir -p \"/Users/bachi/Library/Application Support/SocksProxy\")",
|
|
22
|
+
"Bash(cp \"/Users/bachi/Library/Application Support/BlockProxyClient/config.json\" \"/Users/bachi/Library/Application Support/SocksProxy/config.json\")",
|
|
23
|
+
"Bash(rm -rf \"/Users/bachi/Library/Application Support/BlockProxyClient\")",
|
|
24
|
+
"Bash(shasum -a 256 /Users/bachi/jaylli/block-proxy/client/dist/SocksClient.app/Contents/MacOS/SocksClient)",
|
|
25
|
+
"Bash(xargs file)",
|
|
26
|
+
"Bash(shasum -a 256 /Users/bachi/Library/Python/3.13/lib/python/site-packages/py2app/apptemplate/prebuilt/main-universal2)",
|
|
27
|
+
"Bash(pip3 list *)",
|
|
28
|
+
"Bash(pip3 install *)",
|
|
29
|
+
"Bash(pip install *)",
|
|
30
|
+
"Bash(rm -rf build dist)",
|
|
31
|
+
"Bash(/Users/bachi/Library/Python/3.13/bin/pyinstaller --windowed --name SocksClient --icon icons/app_example.png --add-data \"icons:icons\" --osx-bundle-identifier com.jaylli.socksclient main.py)",
|
|
32
|
+
"Bash(sips -z 256 256 icons/app_example.png --out icons/app.iconset/icon_256x256.png)",
|
|
33
|
+
"Bash(sips -z 128 128 icons/app_example.png --out icons/app.iconset/icon_128x128.png)",
|
|
34
|
+
"Bash(sips -z 16 16 icons/app_example.png --out icons/app.iconset/icon_16x16.png)",
|
|
35
|
+
"Bash(iconutil -c icns icons/app.iconset -o icons/app.icns)",
|
|
36
|
+
"Bash(/Users/bachi/Library/Python/3.13/bin/pyinstaller --windowed --name SocksClient --icon icons/app.icns --add-data \"icons:icons\" --osx-bundle-identifier com.jaylli.socksclient main.py)",
|
|
37
|
+
"Bash(plutil *)",
|
|
38
|
+
"Bash(/Users/bachi/jaylli/block-proxy/client/dist/SocksClient.app/Contents/MacOS/SocksClient *)",
|
|
39
|
+
"Bash(pkill -f SocksClient)",
|
|
40
|
+
"Bash(./SocksClient -c ' *)",
|
|
41
|
+
"Bash(cat)",
|
|
42
|
+
"Bash(/Library/Frameworks/Python.framework/Versions/3.13/bin/python3 /tmp/test_socksclient.py)",
|
|
43
|
+
"Bash(cp /Users/bachi/jaylli/block-proxy/client/dist/SocksClient.app/Contents/MacOS/SocksClient /tmp/SocksClient_backup)",
|
|
44
|
+
"Read(//tmp/**)",
|
|
45
|
+
"Bash(networksetup *)",
|
|
46
|
+
"Bash(sw_vers *)",
|
|
47
|
+
"Bash(echo \"exit: $?\")",
|
|
48
|
+
"Bash(pytest *)",
|
|
49
|
+
"Bash(.venv/bin/python -m pytest tests/ -q)",
|
|
30
50
|
"Bash(npm view *)",
|
|
31
|
-
"Bash(
|
|
32
|
-
"Bash(
|
|
33
|
-
"Bash(
|
|
34
|
-
"Bash(
|
|
35
|
-
"
|
|
36
|
-
"Bash(
|
|
37
|
-
"Bash(
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"Bash(
|
|
51
|
+
"Bash(gh release *)",
|
|
52
|
+
"Bash(zip -r -q SocksClient-macos-arm64.zip SocksClient.app)",
|
|
53
|
+
"Bash(sips -g pixelWidth -g pixelHeight socks_on_G_bar.png socks_on_M_bar.png christmas-sock_light_bar.png)",
|
|
54
|
+
"Bash(sips *)",
|
|
55
|
+
"WebSearch",
|
|
56
|
+
"Bash(iconutil -c iconset --output /tmp/check_iconset client/dist/SocksClient.app/Contents/Resources/app.icns)",
|
|
57
|
+
"Bash(iconutil -c iconset -o /tmp/check_iconset.iconset client/dist/SocksClient.app/Contents/Resources/app.icns)",
|
|
58
|
+
"WebFetch(domain:stackoverflow.com)",
|
|
59
|
+
"WebFetch(domain:forums.developer.apple.com)",
|
|
60
|
+
"Bash(echo \"Network OK: $?\")",
|
|
61
|
+
"Read(//System/Applications/Calculator.app/Contents/Resources/**)",
|
|
62
|
+
"Bash(codesign -dv client/dist/SocksClient.app)",
|
|
63
|
+
"Read(//System/Library/**)",
|
|
64
|
+
"Bash(defaults read *)",
|
|
65
|
+
"Read(//Applications/Visual Studio Code.app/Contents/Resources/**)",
|
|
66
|
+
"Read(//Applications/iTerm.app/Contents/Resources/**)",
|
|
67
|
+
"Bash(xcode-select -p)",
|
|
68
|
+
"Read(//Library/Developer/**)",
|
|
69
|
+
"Bash(xcrun --version)",
|
|
70
|
+
"Read(//Applications/**)",
|
|
71
|
+
"Bash(mdfind \"kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'\")",
|
|
72
|
+
"Bash(brew list *)",
|
|
73
|
+
"Bash(assetutil --info \"/Applications/iTerm.app/Contents/Resources/Assets.car\")",
|
|
74
|
+
"Bash(brew search *)",
|
|
75
|
+
"Bash(brew info *)",
|
|
76
|
+
"Bash(pip3 search *)",
|
|
77
|
+
"Bash(xcode-select --install)",
|
|
78
|
+
"Bash(swift --version)",
|
|
79
|
+
"Bash(/tmp/set_icon client/icons/app_icon.png client/dist/SocksClient.app)",
|
|
80
|
+
"Bash(xattr -l client/dist/SocksClient.app)",
|
|
81
|
+
"Bash(xattr client/dist/SocksClient.app)",
|
|
82
|
+
"Bash(GetFileInfo client/dist/SocksClient.app)",
|
|
83
|
+
"Bash(mdfind \"kMDItemFSName == 'Icon Composer*'\")",
|
|
84
|
+
"Bash(/usr/bin/actool --version)",
|
|
85
|
+
"Bash(/usr/bin/actool --help)",
|
|
86
|
+
"Bash(brew install *)",
|
|
87
|
+
"Bash(fileicon set *)",
|
|
88
|
+
"Bash(echo \"Exit: $?\")",
|
|
89
|
+
"Bash(fileicon test *)",
|
|
90
|
+
"Bash(.venv/bin/pytest tests/ -v)",
|
|
91
|
+
"Bash(.venv/bin/pytest *)",
|
|
92
|
+
"Bash(.venv/bin/python3 *)",
|
|
93
|
+
"Bash(/usr/local/bin/python3 *)",
|
|
94
|
+
"Bash(.venv/bin/python -m pytest tests/ -v)"
|
|
41
95
|
]
|
|
42
96
|
}
|
|
43
97
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Skill: Icon Generate
|
|
2
|
+
|
|
3
|
+
从源图标生成状态栏 bar 图标。将白色区域镂空为透明,缩放并添加 padding 后输出 44x44 @ 144 DPI 的状态栏图标。
|
|
4
|
+
|
|
5
|
+
## Instructions
|
|
6
|
+
|
|
7
|
+
1. **镂空白色区域**:
|
|
8
|
+
- 读取 `client/icons/socks_on_M.png` 和 `client/icons/socks_on_G.png`
|
|
9
|
+
- 将白色像素(R>240, G>240, B>240)的 alpha 设为 0(透明)
|
|
10
|
+
- 保存回原文件
|
|
11
|
+
|
|
12
|
+
2. **生成 bar 图标**:
|
|
13
|
+
- 将镂空后的图片缩放至 38x38(内容区)
|
|
14
|
+
- 放置在 44x44 透明画布中央(四周各 3px padding)
|
|
15
|
+
- 设置 DPI 为 144x144
|
|
16
|
+
- 输出为 `client/icons/socks_on_M_bar.png` 和 `client/icons/socks_on_G_bar.png`
|
|
17
|
+
|
|
18
|
+
3. **执行脚本**:
|
|
19
|
+
```bash
|
|
20
|
+
python3 << 'PYEOF'
|
|
21
|
+
from PIL import Image
|
|
22
|
+
|
|
23
|
+
for name in ["socks_on_M", "socks_on_G"]:
|
|
24
|
+
img = Image.open(f"client/icons/{name}.png").convert("RGBA")
|
|
25
|
+
pixels = img.load()
|
|
26
|
+
w, h = img.size
|
|
27
|
+
for y in range(h):
|
|
28
|
+
for x in range(w):
|
|
29
|
+
r, g, b, a = pixels[x, y]
|
|
30
|
+
if r > 240 and g > 240 and b > 240:
|
|
31
|
+
pixels[x, y] = (r, g, b, 0)
|
|
32
|
+
img.save(f"client/icons/{name}.png")
|
|
33
|
+
print(f"{name}.png: 白色已镂空")
|
|
34
|
+
|
|
35
|
+
canvas = Image.new("RGBA", (44, 44), (0, 0, 0, 0))
|
|
36
|
+
resized = img.resize((38, 38), Image.LANCZOS)
|
|
37
|
+
canvas.paste(resized, (3, 3), resized)
|
|
38
|
+
canvas.save(f"client/icons/{name}_bar.png", dpi=(144, 144))
|
|
39
|
+
print(f"{name}_bar.png: 44x44 @ 144 DPI")
|
|
40
|
+
PYEOF
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
4. **报告结果**:
|
|
44
|
+
- 确认源文件白色已镂空
|
|
45
|
+
- 确认 bar 图标尺寸(44x44)和分辨率(144 DPI)
|
package/CLAUDE.md
CHANGED
|
@@ -50,7 +50,7 @@ Block-Proxy is a MITM-based proxy filtering tool designed for parental control a
|
|
|
50
50
|
|
|
51
51
|
6. **CLI** (`/bin/start.js`) – 全局命令入口,失败自动重启(max 10000 次),退出时清理全局配置
|
|
52
52
|
|
|
53
|
-
7. **AnyProxy Fork** (`node_modules/@bachi/anyproxy/`) – 核心 MITM 代理引擎,fork 自 AnyProxy 的私有 npm 包(v0.1.
|
|
53
|
+
7. **AnyProxy Fork** (`node_modules/@bachi/anyproxy/`) – 核心 MITM 代理引擎,fork 自 AnyProxy 的私有 npm 包(v0.1.6)。关键源码:`proxy.js`(入口)、`lib/requestHandler.js`(HTTP/HTTPS 请求处理与转发)、`lib/httpsServerMgr.js`(HTTPS MITM 服务管理、动态证书生成)、`lib/certMgr.js`(根证书与域名证书管理)。所有底层连接处理、TLS 拦截、请求转发的实现分析都应从此包查找
|
|
54
54
|
|
|
55
55
|
8. **TLS Certificates** (`/cert/`) – `rootCA.key` + `rootCA.crt`,Docker 构建时复制到容器的 `~/.anyproxy/certificates/`,客户端需安装此证书才能 HTTPS MITM
|
|
56
56
|
|
|
@@ -127,7 +127,7 @@ SOCKS5 先做 TLS 握手和认证,然后通过 CONNECT 命令建立隧道,
|
|
|
127
127
|
### Dependencies
|
|
128
128
|
**Note:** `@bachi/anyproxy` 与较新 Node.js 版本不完全兼容,因此连同大多数运行时依赖一起放在 `devDependencies` 中(查看 package.json 了解完整列表)
|
|
129
129
|
|
|
130
|
-
**核心依赖 `@bachi/anyproxy`(v0.1.
|
|
130
|
+
**核心依赖 `@bachi/anyproxy`(v0.1.6):** fork 自开源 AnyProxy 的私有 npm 包,是整个代理系统的底层引擎。分析连接处理、TLS 拦截、请求转发等底层逻辑时,应直接阅读 `node_modules/@bachi/anyproxy/` 的源码(而非项目根目录下的其他备份)。关键文件:
|
|
131
131
|
- `proxy.js` — 包入口,创建代理服务器实例
|
|
132
132
|
- `lib/requestHandler.js` — HTTP/HTTPS 请求处理与转发核心
|
|
133
133
|
- `lib/httpsServerMgr.js` — HTTPS MITM 服务管理、动态伪造证书
|
|
@@ -171,6 +171,6 @@ main.py (入口, 文件锁单实例) → app.py (rumps 状态栏 App)
|
|
|
171
171
|
|
|
172
172
|
# Project Rules & Skills
|
|
173
173
|
|
|
174
|
-
- **Local Skills**: 实时遵循 `.claude/skills/*/skill.md` 中的指令。可用技能: `commit`, `pcap-analyse`
|
|
174
|
+
- **Local Skills**: 实时遵循 `.claude/skills/*/skill.md` 中的指令。可用技能: `commit`, `build-client`, `release-client`, `icon_generate`, `pcap-analyse`
|
|
175
175
|
- **CLI入口**: 全局命令 `block-proxy` 注册在 `bin/start.js`,通过 `npm i -g` 安装后可直接调用
|
|
176
176
|
- **config.json** 是运行时配置文件(非源码),由 `proxy/fs.js` 管理读写和备份,不在 git 中追踪变更
|
package/README.md
CHANGED
|
@@ -1,213 +1,54 @@
|
|
|
1
|
-
|
|
2
1
|
<img width="287" alt="image" src="https://github.com/user-attachments/assets/2bb069d8-508a-41b9-9fee-94a1e31cc0cb" />
|
|
3
2
|
|
|
4
|
-
---------------------------
|
|
5
|
-
|
|
6
3
|
<a href="https://nodei.co/npm/block-proxy/"><img src="https://nodei.co/npm/block-proxy.svg?style=mini"></a>
|
|
7
4
|
|
|
8
|
-
>
|
|
9
|
-
|
|
10
|
-
Socks5/http 代理工具,支持 MITM 和二次开发
|
|
11
|
-
|
|
12
|
-
用在家庭网关,限制小朋友上网用。特性:
|
|
5
|
+
> Socks5/HTTP 代理工具,支持 MITM 和二次开发。用于家庭网关限制小朋友上网。
|
|
13
6
|
|
|
14
7
|
- HTTP 代理 + Socks5 over TLS 代理
|
|
15
|
-
- 域名拦截、
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
### 1)服务端使用方法
|
|
8
|
+
- 域名拦截、URL 正则匹配、MAC 地址定向拦截
|
|
9
|
+
- 按时间段和星期拦截,内置广告过滤
|
|
10
|
+
- [macOS 客户端](https://github.com/jayli/block-proxy/releases) 一键连接
|
|
20
11
|
|
|
21
|
-
|
|
12
|
+
## 快速开始
|
|
22
13
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
```
|
|
14
|
+
```bash
|
|
26
15
|
npm install -g block-proxy
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
启动:
|
|
30
|
-
|
|
31
|
-
```
|
|
32
16
|
block-proxy
|
|
33
17
|
```
|
|
34
18
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
```
|
|
38
|
-
block-proxy -c rule.js
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
配置文件参照 [rule.js](example/rule.js),可留空
|
|
42
|
-
|
|
43
|
-
#### ② 方式二,Docker 部署(推荐)
|
|
44
|
-
|
|
45
|
-
1. 拉取镜像(自动匹配架构):
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
docker pull crpi-x1zji86f6jpcd7t1.cn-hangzhou.personal.cr.aliyuncs.com/lijing00333/block-proxy:latest
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
2. 启动:
|
|
19
|
+
或使用 Docker(推荐):
|
|
52
20
|
|
|
53
|
-
```
|
|
21
|
+
```bash
|
|
54
22
|
docker run --init -d --restart=unless-stopped \
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
--log-opt max-file=3 \
|
|
60
|
-
--cpus="5" \
|
|
61
|
-
--memory 400m \
|
|
62
|
-
-v "$(pwd)/":/app/config \
|
|
63
|
-
--name block-proxy crpi-x1zji86f6jpcd7t1.cn-hangzhou.personal.cr.aliyuncs.com/lijing00333/block-proxy:latest
|
|
23
|
+
-e TZ=Asia/Shanghai --network=host \
|
|
24
|
+
-v "$(pwd)/":/app/config \
|
|
25
|
+
--name block-proxy \
|
|
26
|
+
crpi-x1zji86f6jpcd7t1.cn-hangzhou.personal.cr.aliyuncs.com/lijing00333/block-proxy:latest
|
|
64
27
|
```
|
|
65
28
|
|
|
66
|
-
|
|
29
|
+
首次启动后访问 `http://代理IP:8003` 进入后台配置面板。
|
|
67
30
|
|
|
68
|
-
|
|
31
|
+
## 端口说明
|
|
69
32
|
|
|
70
|
-
|
|
33
|
+
| 端口 | 说明 | 可否关闭 |
|
|
34
|
+
|:----:|:----|:------:|
|
|
35
|
+
| 8001 | HTTP 代理端口 | 不可 |
|
|
36
|
+
| 8002 | Socks5 over TLS 代理端口 | 可 |
|
|
37
|
+
| 8003 | 后台配置面板 | 可 |
|
|
71
38
|
|
|
72
|
-
|
|
39
|
+
## 开发
|
|
73
40
|
|
|
41
|
+
```bash
|
|
42
|
+
pnpm i
|
|
43
|
+
npm run dev # 开发模式(含 React HMR,端口 3000)
|
|
44
|
+
npm run start # 生产启动
|
|
45
|
+
npm run proxy # 仅启动代理,不开后台面板
|
|
74
46
|
```
|
|
75
|
-
docker run --init -d --restart=unless-stopped --user=root \
|
|
76
|
-
-v "$(pwd)/":/app/config \
|
|
77
|
-
-e TZ=Asia/Shanghai -p 8001:8001 -p 8002:8002 \
|
|
78
|
-
--name block-proxy crpi-x1zji86f6jpcd7t1.cn-hangzhou.personal.cr.aliyuncs.com/lijing00333/block-proxy:latest
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### 2)服务侧端口配置
|
|
82
|
-
|
|
83
|
-
1. 服务端配置:配置面板 <http://server-ip:8003>,关闭、启用配置面板:<http://server-ip:8001>
|
|
84
|
-
2. 客户端配置:http 代理直接在 iphone wifi 详情里手动配置,socks5 代理只支持 socks5 over TLS,用小火箭配置。配置信息参照[配置面板](http://localhost:8003)
|
|
85
|
-
|
|
86
|
-
### 3)服务侧代码的开发和调试
|
|
87
|
-
|
|
88
|
-
代码 clone 下来后执行`pnpm i`,执行 `npm run dev` 运行本地服务。默认开启 5 个端口:
|
|
89
|
-
|
|
90
|
-
|端口 |说明 |可否关闭|
|
|
91
|
-
|:----:|:------:|:------:|
|
|
92
|
-
|3000 |调试端口(仅开发调试配置面板用)| 生产环境不启用|
|
|
93
|
-
|8001 |HTTP 代理端口 | 不可禁用 |
|
|
94
|
-
|8002 |Socks5(Over TLS)代理端口 | 可禁用 |
|
|
95
|
-
|8003 |后台配置页端口 | 可禁用 |
|
|
96
|
-
|8004 |~~已废弃~~ | 原后台配置页,已迁移至 8003 |
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
### 4)Block-Proxy 的 Docker 构建说明
|
|
100
|
-
|
|
101
|
-
准备工作,构建 docker 包,先启动本地 Docker:
|
|
102
|
-
|
|
103
|
-
- 开发调试:`npm run dev`,开发调试用3000端口
|
|
104
|
-
- 生产启动:`npm run start`,生产环境使用
|
|
105
|
-
- 只启动代理:`npm run proxy`,不启动配置后台,只启动代理
|
|
106
|
-
- 后台构建:`npm run build`
|
|
107
|
-
- 本地构建 amd64:`npm run docker:build`
|
|
108
|
-
- 本地构建 arm64:`npm run docker:build:arm`
|
|
109
|
-
- 推送 amd64 + arm64 双架构到 ACR:`npm run docker:push`
|
|
110
|
-
- 仅推送 amd64:`npm run docker:push:amd64`
|
|
111
|
-
- 仅推送 arm64:`npm run docker:push:arm64`
|
|
112
|
-
|
|
113
|
-
> 首次使用 `docker:push` 前需要先 ACR 登录:
|
|
114
|
-
> ```
|
|
115
|
-
> docker login --username=hi50078584@aliyun.com crpi-x1zji86f6jpcd7t1.cn-hangzhou.personal.cr.aliyuncs.com
|
|
116
|
-
> ```
|
|
117
|
-
> 要是打包 docker 空间不够就执行 `docker system prune -a --volumes`
|
|
118
|
-
|
|
119
|
-
拷贝 tar 到 openwrt 后启动容器:参照上文 Docker部署。
|
|
120
|
-
|
|
121
|
-
### 5)客户端配置说明
|
|
122
|
-
|
|
123
|
-
#### ① 代理端口
|
|
124
|
-
|
|
125
|
-
- 8001:HTTP 代理
|
|
126
|
-
- 8002:socks5 over TLS
|
|
127
|
-
|
|
128
|
-
⚠️ Socks5 代理不支持对 Mac 地址的定向拦截,Mac 地址的拦截只对局域网内的 HTTP 代理绑定生效。建议局域网绑定 http 代理,公网绑定 Socks5 代理。
|
|
129
|
-
|
|
130
|
-
⚠️ 使用小火箭的 Socks5 over TLS 代理,TLS 选项里勾选“允许不安全”
|
|
131
|
-
|
|
132
|
-
#### ② 后台配置
|
|
133
|
-
|
|
134
|
-
访问路径:`http://proxy-ip:8003`
|
|
135
|
-
|
|
136
|
-
路由表间隔两小时刷新一次。如果新加入网的设备没生效,刷新一下路由表。添加限制条件后,点击重启代理按钮。
|
|
137
|
-
|
|
138
|
-
<img src="https://github.com/user-attachments/assets/16f47d3f-1ef9-47a2-8640-c7e04ec64e1a" width=300 />
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
#### ③ 设备配置
|
|
142
|
-
|
|
143
|
-
1. 证书设置:进入后台配置,扫码安装证书,在手机设置中安装该证书,同时配置完全信任:设置→通用→关于本机→证书信任设置→打开对AnyProxy的完全信任
|
|
144
|
-
2. 代理设置:iPhone/iPad 为例:设置 → 无线局域网 → 点击当前网络 → HTTP代理/配置代理,设置服务器和端口。
|
|
145
|
-
|
|
146
|
-
如果要通过 mac 地址拦截小朋友上网,小朋友的设备里把 Mac 固定下来:
|
|
147
|
-
|
|
148
|
-
<img width="350" alt="image" src="https://github.com/user-attachments/assets/f9bfab89-7194-4a72-b1ae-5cca27911bc9" />
|
|
149
|
-
|
|
150
|
-
#### ④ 禁掉设备直连
|
|
151
|
-
|
|
152
|
-
防止小朋友修改网Wifi连接,只允许设备通过代理访问,把直连上网权限关掉。网关里配置防火墙规则:
|
|
153
|
-
|
|
154
|
-
```
|
|
155
|
-
iptables -I FORWARD -m mac --mac-source D2:9E:8D:1B:F1:4E -j REJECT
|
|
156
|
-
ip6tables -I forwarding_rule -m mac --mac-source D2:9E:8D:1B:F1:4E -j REJECT
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
然后重启防火墙
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
### 6)关于 MITM
|
|
163
|
-
|
|
164
|
-
#### 应用条件:
|
|
165
|
-
|
|
166
|
-
1. MITM 基于 AnyProxy 的规则实现,客户端设备必须要安装 AnyProxy 的证书。
|
|
167
|
-
2. 服务需要根据 ip 反查 mac 地址,需要代理服务工作在对子网有扫描权限的节点,最好是部署在 openwrt 网关,可以`arp -a`看下是否可以扫描完全。
|
|
168
|
-
3. 服务会自动更新路由表,每 2 个小时更新一次,对于新入网的设备,最好在后台手动刷新并重启代理,以免拦截规则不能立即生效。
|
|
169
|
-
4. 所有规则都在 HTTP 代理中生效,Socks5 on tls 是指向 AnyProxy 的反向代理,内网 Mac 地址的拦截只对直接绑定 HTTP 代理的情况生效。
|
|
170
|
-
|
|
171
|
-
#### Youtube 去广告
|
|
172
|
-
|
|
173
|
-
一共六条拦截规则,这几条 reject 规则直接配置在后台里:
|
|
174
|
-
|
|
175
|
-
- *youtube.com*:`^https?:\/\/(www|s)\.youtube\.com\/(pagead|ptracking)`
|
|
176
|
-
- *youtube.com*:`^https?:\/\/s\.youtube\.com\/api\/stats\/qoe\?adcontext`
|
|
177
|
-
- *youtube.com*:`^https?:\/\/(www|s)\.youtube\.com\/api\/stats\/ads`
|
|
178
|
-
- *googlevideo.com*:`^https?:\/\/[\w-]+\.googlevideo\.com\/(?!(dclk_video_ads|videoplayback\?)).+&oad`
|
|
179
|
-
|
|
180
|
-
另外两条规则在这里:<https://github.com/jayli/block-proxy/blob/main/proxy/mitm/rule.js>(手工添加上面四条规则就够了)
|
|
181
|
-
|
|
182
|
-
#### 有道词典会员
|
|
183
|
-
|
|
184
|
-
done!
|
|
185
|
-
|
|
186
|
-
#### 代理性能
|
|
187
|
-
|
|
188
|
-
**并发测试**:
|
|
189
|
-
|
|
190
|
-
|直连测试 |代理测试 |
|
|
191
|
-
|:---------:|:----------------:|
|
|
192
|
-
|<img height="500" alt="image" src="https://github.com/user-attachments/assets/8268bc5c-956f-4b67-89c1-cdd5725114b3" /> | <img height="500" alt="image" src="https://github.com/user-attachments/assets/abf4bfa1-c8b8-4907-ba0e-bcc76e8899fa" />|
|
|
193
|
-
|
|
194
|
-
**网速测试**:
|
|
195
|
-
|
|
196
|
-
<img width="544" alt="image" src="https://github.com/user-attachments/assets/67c61e34-67ae-4345-97ca-d266cd35ddf4" />
|
|
197
|
-
|
|
198
|
-
> ⚠️ 提示:如果把 block-proxy 部署在 openwrt 网关上,代理地址和网关地址一致,iOS Safari 有一个默认安全限制,不支持带认证的代理和网关 IP 一致,两个解决办法:
|
|
199
|
-
>
|
|
200
|
-
>1. 不要填代理认证用户名和密码
|
|
201
|
-
>2. 给 openwrt lan 口再绑定一个 IP,ios 设备在局域网内绑定这个 IP
|
|
202
|
-
>
|
|
203
|
-
><img width="300" alt="image" src="https://github.com/user-attachments/assets/0f46d6b4-00b1-44aa-9be7-fa23a09bb199" />
|
|
204
|
-
|
|
205
|
-
### 7)客户端软件
|
|
206
47
|
|
|
207
|
-
|
|
48
|
+
## 更多文档
|
|
208
49
|
|
|
209
|
-
|
|
50
|
+
详见 [wiki.md](wiki.md)
|
|
210
51
|
|
|
211
|
-
|
|
52
|
+
## License
|
|
212
53
|
|
|
213
54
|
MIT
|
package/client/app.py
CHANGED
|
@@ -4,6 +4,7 @@ import subprocess
|
|
|
4
4
|
import threading
|
|
5
5
|
import platform
|
|
6
6
|
import rumps
|
|
7
|
+
from AppKit import NSImage, NSSize
|
|
7
8
|
from PyObjCTools import AppHelper
|
|
8
9
|
from Foundation import NSObject
|
|
9
10
|
from config import Config
|
|
@@ -36,6 +37,7 @@ class SocksClient(rumps.App):
|
|
|
36
37
|
self.proxy = ProxyCore()
|
|
37
38
|
self.sys_proxy = SystemProxy()
|
|
38
39
|
self.connected = False
|
|
40
|
+
self._config_proc = None
|
|
39
41
|
|
|
40
42
|
self._measuring = False
|
|
41
43
|
self._build_menu()
|
|
@@ -55,7 +57,7 @@ class SocksClient(rumps.App):
|
|
|
55
57
|
|
|
56
58
|
def _build_menu(self):
|
|
57
59
|
self.toggle_item = rumps.MenuItem("启动代理", callback=self.toggle_proxy)
|
|
58
|
-
self.config_item = rumps.MenuItem("Socks 节点配置...", callback=self.open_config)
|
|
60
|
+
self.config_item = rumps.MenuItem("Socks/HTTP 节点配置...", callback=self.open_config)
|
|
59
61
|
|
|
60
62
|
self.global_item = rumps.MenuItem("全局代理(设置系统代理)", callback=self.set_global_mode)
|
|
61
63
|
self.manual_item = rumps.MenuItem("手动模式(关闭系统代理)", callback=self.set_manual_mode)
|
|
@@ -93,10 +95,19 @@ class SocksClient(rumps.App):
|
|
|
93
95
|
if self.connected:
|
|
94
96
|
icon_name = "socks_on_G_bar.png" if self.config.data["mode"] == "global" else "socks_on_M_bar.png"
|
|
95
97
|
else:
|
|
96
|
-
icon_name = "christmas-
|
|
98
|
+
icon_name = "christmas-sock_light_bar_off.png"
|
|
97
99
|
icon_path = os.path.join(self._icon_dir(), icon_name)
|
|
98
100
|
if os.path.exists(icon_path):
|
|
99
|
-
|
|
101
|
+
image = NSImage.alloc().initByReferencingFile_(icon_path)
|
|
102
|
+
image.setSize_(NSSize(22, 22))
|
|
103
|
+
if self._template is not None:
|
|
104
|
+
image.setTemplate_(self._template)
|
|
105
|
+
self._icon = icon_path
|
|
106
|
+
self._icon_nsimage = image
|
|
107
|
+
try:
|
|
108
|
+
self._nsapp.setStatusBarIcon()
|
|
109
|
+
except AttributeError:
|
|
110
|
+
pass
|
|
100
111
|
self.title = None
|
|
101
112
|
|
|
102
113
|
def _is_compiled(self):
|
|
@@ -135,11 +146,17 @@ class SocksClient(rumps.App):
|
|
|
135
146
|
"SocksClient", "启动失败", str(e),
|
|
136
147
|
)
|
|
137
148
|
return
|
|
149
|
+
if (self.proxy.socks_port != self.config.data["local"]["socks_port"]
|
|
150
|
+
or self.proxy.http_port != self.config.data["local"]["http_port"]):
|
|
151
|
+
self.config.data["local"]["socks_port"] = self.proxy.socks_port
|
|
152
|
+
self.config.data["local"]["http_port"] = self.proxy.http_port
|
|
153
|
+
self.config.save()
|
|
154
|
+
|
|
138
155
|
if self.config.data["mode"] == "global":
|
|
139
156
|
try:
|
|
140
157
|
self.sys_proxy.enable(
|
|
141
|
-
socks_port=self.
|
|
142
|
-
http_port=self.
|
|
158
|
+
socks_port=self.proxy.socks_port,
|
|
159
|
+
http_port=self.proxy.http_port,
|
|
143
160
|
)
|
|
144
161
|
except Exception as e:
|
|
145
162
|
rumps.notification(
|
|
@@ -179,10 +196,11 @@ class SocksClient(rumps.App):
|
|
|
179
196
|
self.config.save()
|
|
180
197
|
script_path = os.path.join(self._bundle_resource_dir(), "config_window.py")
|
|
181
198
|
python_path = self._find_python() if self._is_compiled() else sys.executable
|
|
182
|
-
|
|
199
|
+
self._config_proc = subprocess.Popen([python_path, script_path, self.config.config_path])
|
|
183
200
|
|
|
184
201
|
def _reload_after_window():
|
|
185
|
-
|
|
202
|
+
self._config_proc.wait()
|
|
203
|
+
self._config_proc = None
|
|
186
204
|
old_data = self.config.data.copy()
|
|
187
205
|
self.config.load()
|
|
188
206
|
if self.connected and self.config.data != old_data:
|
|
@@ -198,8 +216,8 @@ class SocksClient(rumps.App):
|
|
|
198
216
|
self._update_icon()
|
|
199
217
|
if self.connected:
|
|
200
218
|
self.sys_proxy.enable(
|
|
201
|
-
socks_port=self.
|
|
202
|
-
http_port=self.
|
|
219
|
+
socks_port=self.proxy.socks_port,
|
|
220
|
+
http_port=self.proxy.http_port,
|
|
203
221
|
)
|
|
204
222
|
|
|
205
223
|
def set_manual_mode(self, sender):
|
|
@@ -257,6 +275,8 @@ class SocksClient(rumps.App):
|
|
|
257
275
|
)
|
|
258
276
|
|
|
259
277
|
def quit_app(self, sender):
|
|
278
|
+
if self._config_proc and self._config_proc.poll() is None:
|
|
279
|
+
self._config_proc.terminate()
|
|
260
280
|
if self.connected:
|
|
261
281
|
self.sys_proxy.disable()
|
|
262
282
|
threading.Thread(target=self.proxy.stop, daemon=True).start()
|
package/client/build.sh
CHANGED
|
@@ -43,6 +43,8 @@ sips -z 128 128 "$SCRIPT_DIR/icons/app_icon.png" --out "$ICONSET/icon_128x128.pn
|
|
|
43
43
|
sips -z 256 256 "$SCRIPT_DIR/icons/app_icon.png" --out "$ICONSET/icon_128x128@2x.png" &>/dev/null
|
|
44
44
|
sips -z 256 256 "$SCRIPT_DIR/icons/app_icon.png" --out "$ICONSET/icon_256x256.png" &>/dev/null
|
|
45
45
|
sips -z 512 512 "$SCRIPT_DIR/icons/app_icon.png" --out "$ICONSET/icon_256x256@2x.png" &>/dev/null
|
|
46
|
+
sips -z 512 512 "$SCRIPT_DIR/icons/app_icon.png" --out "$ICONSET/icon_512x512.png" &>/dev/null
|
|
47
|
+
sips -z 1024 1024 "$SCRIPT_DIR/icons/app_icon.png" --out "$ICONSET/icon_512x512@2x.png" &>/dev/null
|
|
46
48
|
iconutil -c icns "$ICONSET" -o "$SCRIPT_DIR/icons/app.icns"
|
|
47
49
|
rm -rf "$(dirname "$ICONSET")"
|
|
48
50
|
|
|
@@ -71,6 +73,10 @@ plutil -replace CFBundleExecutable -string "$APP_NAME" "$APP_DIR/Contents/Info.p
|
|
|
71
73
|
plutil -replace CFBundleIdentifier -string "$BUNDLE_ID" "$APP_DIR/Contents/Info.plist"
|
|
72
74
|
plutil -replace CFBundleVersion -string "$VERSION" "$APP_DIR/Contents/Info.plist"
|
|
73
75
|
plutil -replace CFBundleShortVersionString -string "$VERSION" "$APP_DIR/Contents/Info.plist"
|
|
76
|
+
plutil -replace NSSupportsAutomaticIconComposition -bool false "$APP_DIR/Contents/Info.plist"
|
|
77
|
+
|
|
78
|
+
echo "==> Setting custom icon (bypass Liquid Glass)..."
|
|
79
|
+
fileicon set "$APP_DIR" "$SCRIPT_DIR/icons/app_icon.png"
|
|
74
80
|
|
|
75
81
|
echo "==> Cleaning Nuitka build artifacts..."
|
|
76
82
|
rm -rf "$DIST_DIR/main.build" "$DIST_DIR/main.dist"
|