#3818·v2ray-core

feat: 请求支持socks/http端口复用

Author: weaving118Created Sep 9, 2026Updated Sep 9, 2026

背景

本地入站目前 SOCKS 和 HTTP 各占一个端口(例如 1080 + 8080)。浏览器走 HTTP CONNECT,CLI / 部分应用走 SOCKS5,部署时要开两个 listener、记两套地址,系统代理也只能填其中一个。

这两个协议首包就能分开,没有必要各占一个端口。

期望行为

同一个 listen 地址 + 端口同时接受:

  • SOCKS4 / SOCKS4a / SOCKS5
  • HTTP CONNECT(以及普通 HTTP 代理请求,如 GET http://host/

客户端无需改配置:socks5://127.0.0.1:7890http://127.0.0.1:7890 指向同一端口即可。

独立的 socks / http inbound 继续保留,复用作为新增能力。

协议识别

TCP accept 后 peek 第一个字节再分流,peek 过的字节必须回灌给后续 handshake,不能丢掉:

首字节 协议
0x04 SOCKS4 / SOCKS4a
0x05 SOCKS5
其它(常见 C/G/P/H 等 ASCII) HTTP

既不是 SOCKS 也解析不成 HTTP 的连接直接关闭,不要卡住 listener。

UDP Associate 仍走 SOCKS5;HTTP 入站不提供 UDP。

鉴权

SOCKS 和 HTTP 共用同一套账号。SOCKS5 username/password 开了之后,HTTP 用相同的 Basic Auth(Proxy-Authorization)。一边通过、另一边匿名可进,等于鉴权失效。

已有实现

Xray

SOCKS inbound 默认兼容 HTTP,不再需要单独的 mixed 开关(旧字段 mixed 已废弃)。

首字节不是 0x04/0x05 时,把连接连同已读字节转给内置 HTTP handler。鉴权账号两边共用。

{
  "listen": "127.0.0.1",
  "port": 1080,
  "protocol": "socks",
  "settings": {
    "auth": "password",
    "udp": true,
    "accounts": [
      { "user": "alice", "pass": "secret" }
    ]
  }
}

文档:Socks inbound(明确写了兼容 HTTP)。
实现:XTLS/Xray-core#3682proxy/socks/server.go 首字节分流。

验证:

curl -x socks5h://127.0.0.1:1080 https://example.com -o /dev/null
curl -x http://127.0.0.1:1080 https://example.com -o /dev/null

sing-box

独立 inbound 类型 mixed:先 peek 1 字节,0x04/0x05 走 SOCKS,其余走 HTTP。

{
  "type": "mixed",
  "tag": "mixed-in",
  "listen": "127.0.0.1",
  "listen_port": 7890,
  "users": [
    { "username": "alice", "password": "secret" }
  ]
}

文档:Inbound / Mixed
实现:protocol/mixed/inbound.go

Clash / mihomo 的 mixed-port 是同一类能力,行为可对照,实现以 Xray / sing-box 为准即可。

建议落地

配置上二选一即可:

  1. Xray 路线:现有 SOCKS inbound 默认附带 HTTP 识别(改动小,用户不用换 inbound 类型)。
  2. sing-box 路线:新增 mixed inbound,SOCKS / HTTP 纯协议入口保持不变。

倾向 1:现有只开了 SOCKS 的用户直接受益,浏览器和 curl -x http:// 不用再加端口。

实现要点:

  • peek 后把首字节塞回 reader(buffered reader / UnreadByte
  • 鉴权账号两边同一套
  • SOCKS5 UDP 不受 HTTP 分流影响
  • 非法首包尽快断开
  • 文档和示例改成一个端口;changelog 写明旧的双端口配置仍然有效

验收

  • 同一端口:curl -x socks5h://127.0.0.1:<port>curl -x http://127.0.0.1:<port> 都能通
  • 配置了用户密码时,两种协议都要带同一组凭据,缺凭据都拒绝
  • SOCKS5 UDP Associate 仍可用(若当前已支持 UDP)
  • 只开 SOCKS 或只开 HTTP 的旧配置行为不变