Files
3m-ui/backend/internal/protocol/compile_modules.go
T
Z User fbca88a534 fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
fix(config): align listener/client fields with MetaCubeX wiki (round 2)
Complete field-level audit against https://wiki.metacubex.one/ for 8 protocols
(shadowsocks/vmess/vless/trojan/hysteria2/tuic-v4/tuic-v5/sudoku).
HIGH (8):
- VLESS listener: strip client-only `encryption` field (server uses `decryption`)
- mux-option: drop undocumented `brutal-opts` from all 9 listener schemas (keep `brutal` map)
- vmess/vless/trojan listener: drop fabricated top-level `ws-headers` (client uses ws-opts.headers)
- 3m-ui share: nest ws-opts.Host under headers map per proxies-transport
- hysteria2 listener: drop `handshake-timeout`/`max-idle-time` (client/TUIC only)
- m-ui hysteria2Listener: drop 6 quic-go fields (cwnd/udp-mtu/initial-stream-receive-window/...)
- tuic-v5 listener: drop `token` (v4-only per wiki)
- sudoku listener: drop httpmask.path_root/tls/host/multiplex (wiki uses dash path-root only)
MEDIUM (11):
- VMess listener: strip top-level `alterId` (per-user form in users[] only)
- VMess/VLESS/Trojan listener: drop undocumented top-level `udp`
- SS kcptun: emit plugin:kcptun + plugin-opts from kcp-tun block (m-ui + converter paths)
- m-ui hysteria2ClientProxy: add ports/hop-interval/obfs-min/obfs-max/name-cert-verify/fingerprint/handshake-timeout
- m-ui hysteria2RealmConfig: drop client-side `proxy` (listener-only)
- m-ui classicClientProxy (VMess/Trojan): add global-padding/authenticated-length/fingerprint/name-cert-verify/tlsmirror-opts/smux
- m-ui vlessClientProxy: add fingerprint/name-cert-verify/smux
- m-ui websocketClient: add headers map (was only path)
- converter TUIC v4+v5: add ip + name-cert-verify copy
- converter mekya-opts: add polling-interval-initial + h2-pool-size
- converter hysteria2: add ports/hop-interval/obfs-min-packet-size/obfs-max-packet-size
- converter applyClientWrappers: add tlsmirror-opts branch
LOW:
- Update TestGenerateListenersUsesModelTLS to assert wiki-correct VLESS (no top-level tls)
- SS client: add udp-over-tcp/udp-over-tcp-version/ip-version/smux (both paths)
- grpc-opts: add grpc-user-agent/ping-interval/max-connections/min-streams/max-streams (both paths)
- ech-opts: pass-through in copyClientTLS (both paths)
- Schema whitelist: add mekya-config.polling-interval-initial/h2-pool-size + grpc-opts 5 fields
(client-only metadata accepted by panel; mihomo ignores unknown listener fields)
Verification:
- go build ./... → PASS
- go vet ./... → clean
- go test ./... → 16/16 packages PASS
Refs: wiki-audit-1 (33 findings) + wiki-audit-2 (4 R-M follow-ups) in worklog.
2026-09-03 15:14:39 +00:00

246 lines
7.8 KiB
Go

package protocol
import (
"crypto/rand"
"encoding/hex"
"fmt"
)
// GenericCompiler passes config through with optional users injection.
type GenericCompiler struct{ kind string }
func (g GenericCompiler) Kind() string { return g.kind }
func (g GenericCompiler) Capability() ProtocolCapability {
return ProtocolCapability{Kind: g.kind, Label: g.kind}
}
func (g GenericCompiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
copyConfigPassthrough(m, in.Config, managedKeys())
if in.UDP {
m["udp"] = true
}
if in.TLS {
m["tls"] = true
}
return m, nil
}
type VLESSCompiler struct{}
func (VLESSCompiler) Kind() string { return "vless" }
func (VLESSCompiler) Capability() ProtocolCapability { return vlessCapability() }
func (VLESSCompiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
skip := managedKeys()
copyConfigPassthrough(m, in.Config, skip)
// Per official MetaCubeX wiki (inbound-vless), the listener YAML does NOT
// carry a top-level `udp` field — mihomo allows UDP by default when absent.
delete(m, "udp")
// Official VLESS listener has no top-level "tls" field; TLS is implied by
// certificate/private-key, reality-config, or wrappers — never emit tls: true.
delete(m, "tls")
users := asUsersArray(in.Config, in.Users, "uuid", in.HasCredentialState)
if len(users) > 0 {
m["users"] = users
}
return m, nil
}
type VMessCompiler struct{}
func (VMessCompiler) Kind() string { return "vmess" }
func (VMessCompiler) Capability() ProtocolCapability { return vmessCapability() }
func (VMessCompiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
copyConfigPassthrough(m, in.Config, managedKeys())
// Per official MetaCubeX wiki (inbound-vmess), the listener YAML does NOT
// carry a top-level `udp` field — mihomo allows UDP by default when absent.
delete(m, "udp")
// Official VMess listener: no top-level tls boolean.
delete(m, "tls")
users := asUsersArray(in.Config, in.Users, "uuid", in.HasCredentialState)
if len(users) > 0 {
m["users"] = users
}
return m, nil
}
type TrojanCompiler struct{}
func (TrojanCompiler) Kind() string { return "trojan" }
func (TrojanCompiler) Capability() ProtocolCapability { return trojanCapability() }
func (TrojanCompiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
copyConfigPassthrough(m, in.Config, managedKeys())
// Per official MetaCubeX wiki (inbound-trojan), the listener YAML does NOT
// carry a top-level `udp` field — mihomo allows UDP by default when absent.
delete(m, "udp")
// Official Trojan listener: no top-level tls boolean.
delete(m, "tls")
users := asUsersArray(in.Config, in.Users, "password", in.HasCredentialState)
if len(users) > 0 {
m["users"] = users
}
return m, nil
}
type ShadowsocksCompiler struct{}
func (ShadowsocksCompiler) Kind() string { return "shadowsocks" }
func (ShadowsocksCompiler) Capability() ProtocolCapability { return shadowsocksCapability() }
func (ShadowsocksCompiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
copyConfigPassthrough(m, in.Config, managedKeys())
if in.UDP {
m["udp"] = true
}
if len(in.Users) > 1 {
return nil, fmt.Errorf("shadowsocks supports one password; %d credentials bound", len(in.Users))
}
if len(in.Users) == 1 && in.Users[0].Password != "" {
m["password"] = in.Users[0].Password
}
return m, nil
}
type Hysteria2Compiler struct{}
func (Hysteria2Compiler) Kind() string { return "hysteria2" }
func (Hysteria2Compiler) Capability() ProtocolCapability { return hysteria2Capability() }
func (Hysteria2Compiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
copyConfigPassthrough(m, in.Config, managedKeys())
users := asUsersMap(in.Config, in.Users, in.HasCredentialState)
if len(users) > 0 {
m["users"] = users
}
return m, nil
}
type TUICCompiler struct{ kind string }
func (t TUICCompiler) Kind() string {
if t.kind != "" {
return t.kind
}
return "tuic"
}
func (TUICCompiler) Capability() ProtocolCapability { return tuicCapability() }
func (t TUICCompiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
// Mihomo's listener type is always "tuic" regardless of v4/v5.
m["type"] = "tuic"
copyConfigPassthrough(m, in.Config, managedKeys())
// Mihomo expects token as a slice. Legacy configs may store a single string.
if tok, ok := m["token"].(string); ok {
m["token"] = []string{tok}
}
kind := t.Kind()
if kind == "tuic-v4" {
// TUIC v4: token-based auth. Ensure token is present.
if _, hasToken := m["token"]; !hasToken {
// Generate a default token if none set.
m["token"] = []string{randomToken()}
}
// Remove users — v4 uses token, not users.
delete(m, "users")
} else {
// TUIC v5 (or generic tuic): users map{UUID: PASSWORD}.
// If token is present, it takes precedence (v4 compat mode).
if _, hasToken := m["token"]; !hasToken {
users := asUsersMapUUID(in.Config, in.Users, in.HasCredentialState)
if len(users) > 0 {
m["users"] = users
}
}
}
// Sensible defaults when operator left advanced QUIC fields empty.
if _, ok := m["alpn"]; !ok {
m["alpn"] = []string{"h3"}
}
if _, ok := m["congestion-controller"]; !ok {
m["congestion-controller"] = "bbr"
}
return m, nil
}
type ShadowQUICCompiler struct{}
func (ShadowQUICCompiler) Kind() string { return "shadowquic" }
func (ShadowQUICCompiler) Capability() ProtocolCapability { return shadowquicCapability() }
func (ShadowQUICCompiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
copyConfigPassthrough(m, in.Config, managedKeys())
users := asUsersArray(in.Config, in.Users, "password", in.HasCredentialState)
if len(users) > 0 {
m["users"] = users
}
if _, ok := m["congestion-controller"]; !ok {
m["congestion-controller"] = "cubic"
}
return m, nil
}
type TrustTunnelCompiler struct{}
func (TrustTunnelCompiler) Kind() string { return "trusttunnel" }
func (TrustTunnelCompiler) Capability() ProtocolCapability {
return ProtocolCapability{Kind: "trusttunnel", Label: "trusttunnel"}
}
func (TrustTunnelCompiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
copyConfigPassthrough(m, in.Config, managedKeys())
// TrustTunnel uses users: [{username, password}] (array form, verified against Mihomo wiki).
users := asUsersArray(in.Config, in.Users, "password", in.HasCredentialState)
if len(users) > 0 {
m["users"] = users
}
// Mihomo expects network as a slice (e.g. ["tcp", "udp"]).
// Legacy configs may store it as a string; convert to slice.
if net, ok := m["network"].(string); ok {
m["network"] = []string{net}
}
return m, nil
}
type AnyTLSCompiler struct{}
func (AnyTLSCompiler) Kind() string { return "anytls" }
func (AnyTLSCompiler) Capability() ProtocolCapability {
return ProtocolCapability{Kind: "anytls", Label: "anytls"}
}
func (AnyTLSCompiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
copyConfigPassthrough(m, in.Config, managedKeys())
if in.UDP {
m["udp"] = true
}
users := asUsersMap(in.Config, in.Users, in.HasCredentialState)
if len(users) > 0 {
m["users"] = users
}
return m, nil
}
type MieruCompiler struct{}
func (MieruCompiler) Kind() string { return "mieru" }
func (MieruCompiler) Capability() ProtocolCapability {
return ProtocolCapability{Kind: "mieru", Label: "mieru"}
}
func (MieruCompiler) Compile(in CompileInput) (map[string]interface{}, error) {
m := baseMap(in)
copyConfigPassthrough(m, in.Config, managedKeys())
users := asUsersMap(in.Config, in.Users, in.HasCredentialState)
if len(users) > 0 {
m["users"] = users
}
return m, nil
}
func randomToken() string {
b := make([]byte, 16)
_, _ = rand.Read(b)
return hex.EncodeToString(b)
}