目 录CONTENT

文章目录

nfd-proxy代理节点技术深度剖析

qaiu
2026-01-01 / 0 评论 / 0 点赞 / 4 阅读 / 974 字
温馨提示:
C4droid交流群: 1026766509(验证问题自行百度)
Pydroid交流群: 1026766509
netdisk-fast-download开源交流群:1017480890
有什么疑问可以评论区留言
提问之前建议阅读下提问的智慧
尽量不要屏蔽广告😘 条件允许的话 可以请作者喝杯咖啡不胜感激

NFD Proxy — 分布式代理节点系统

将用户设备注册为代理节点,通过 WebSocket 控制面实现 geo 感知分发的 SOCKS5 / HTTP 代理网络。


架构


用户 / Vert.x 后端

  │  HTTP CONNECT :8888  (Proxy-Authorization: Basic)

  │  SOCKS5       :1080  (用户名/密码子协商)

  ▼

proxy_server.py          GeoIP 解析 → 同城→同省→默认→任意

  │  WebSocket :9000/ws/node

  ▼

dnode_client.py          用户设备(真实出口 IP)

  ▼

目标服务器


组件

| 文件 | 说明 |

|------|------|

| proxy_server.py | 服务端:SOCKS5 + HTTP CONNECT 代理,WS 节点注册,Admin API,控制面板 |

| dnode_client.py | 节点客户端:全平台,单依赖 websockets,Android Chaquopy 支持 |

| run.py | 通用启动器:自动安装依赖,venv 管理,支持远程拉取执行 |

| dashboard.html | 实时监控大屏:节点地图、KPI、事件流 |

| admin.html | 管理面板:节点列表、踢除、URL 参数自动登录 |

| api-docs.html | API 文档 |

| start.sh | 服务端启动脚本,支持完整参数透传 |


快速启动

服务端


# 基础启动

PROXY_USER=admin PROXY_PASS=secret ADMIN_TOKEN=tok python3 proxy_server.py

# 或使用启动脚本

./start.sh -u admin -p secret -t tok --debug

| 端口 | 协议 | 说明 |

|------|------|------|

| 1080 | SOCKS5 | 代理入口 |

| 8888 | HTTP CONNECT | 代理入口 |

| 9000 | HTTP / WS | 控制面板、API、节点注册 |

节点客户端


# 直接运行

python dnode_client.py wss://dnode.qaiu.top/ws/node

# 通过启动器(自动安装依赖)

python run.py wss://dnode.qaiu.top/ws/node

# 从远程拉取执行(Pydroid 等嵌入式环境)

python run.py --url https://qaiu.top/src/py/dnode_client.py


环境变量

| 变量 | 默认 | 说明 |

|------|------|------|

| PROXY_USER | 空 | 代理用户名,逗号分隔多账号,空则不鉴权 |

| PROXY_PASS | 空 | 代理密码,与 PROXY_USER 一一对应 |

| ADMIN_TOKEN | 空 | Admin API 令牌,空则 Admin 全部拒绝 |

| SOCKS5_PORT | 1080 | SOCKS5 端口 |

| HTTP_PORT | 8888 | HTTP CONNECT 端口 |

| CONTROL_PORT | 9000 | 控制面板端口 |

| LOG_LEVEL | INFO | 日志级别,DEBUG 开启流量详情 |

| SHOW_TARGET | true | 事件流是否显示目标地址 |


代理认证 & 真实 IP

支持在凭证中携带真实 IP,用于 geo 节点选择(优先级:凭证 IP > XFF 头 > TCP peer):


# 格式 A  标准

curl -x http://admin:secret@host:8888 https://ipinfo.io

# 格式 B  携带真实 IP(适用于 Vert.x ProxyOptions 无法加自定义头的场景)

curl -x http://'admin:1.2.3.4':secret@host:8888 https://ipinfo.io


// Vert.x ProxyOptions

new ProxyOptions()

    .setType(ProxyType.HTTP)

    .setHost("dnode.qaiu.top").setPort(8888)

    .setUsername("admin:" + userRealIp)   // "admin:1.2.3.4"

    .setPassword("secret");


Admin API

所有 Admin 接口需要 Authorization: Bearer <ADMIN_TOKEN>?token=<ADMIN_TOKEN>

| 方法 | 路径 | 说明 |

|------|------|------|

| GET | /api/stats | 全局统计 + 最近 100 条事件(无需鉴权) |

| GET | /api/admin/nodes | 列出所有在线节点详情 |

| POST | /api/admin/node/{conn_id}/kick | 踢除单个节点,支持前 8 位前缀 |

| POST | /api/admin/nodes/kick-all | 踢除全部节点 |


节点分发策略


Tier 0  同城   (city 匹配)

Tier 1  同省   (province 匹配)

Tier 2  默认节点 (X-Default-Node: true)

Tier 3  任意节点 (兜底)

同 Tier 内取负载最低节点。节点存活由 WS 断开事件驱动,无时间窗口过滤。


Android 集成


// Chaquopy — 启动

thread {

    Python.getInstance()

        .getModule("dnode_client")

        .callAttr("main_for_android",

            "wss://dnode.qaiu.top/ws/node",

            filesDir.absolutePath,  // 配置目录

            "",                     // node_id,空则自动生成

            "",                     // secret

            false,                  // is_default

            false)                  // debug

}

// 停止(任意线程安全调用)

Python.getInstance()

    .getModule("dnode_client")

    .callAttr("stop_from_android")

停止机制stop_from_android() 通过 loop.call_soon_threadsafe 主动关闭 WS 连接,打断 async for 循环,event loop 立即退出,不依赖 flag 轮询。


依赖

服务端 (proxy_server.py)


aiohttp >= 3.9

节点客户端 (dnode_client.py)


websockets >= 10.0

其余均为标准库(asyncio / ssl / struct / json)。


0

评论区