跳转到内容

协议与传输层

每个 katana 节点运行一个监听器,它使用什么协议由两方面决定。[node.api] 中的 node_type 选定协议族;其余部分由面板对 katana 节点信息请求的应答补全:端口、传输层、是否启用 TLS,以及 Shadowsocks 加密方式等协议细节。katana 根据这份应答构建监听器;如果应答要求的功能 katana 没有实现,就拒绝构建。

当你在面板中配置节点,想知道 katana 会遵循哪些设置时,或者节点无法启动、日志显示 node requests kernel-unsupported feature 时,请阅读本页。面板 API 本身见各面板页面(Xboard 与 V2board、SSPanel)。

node_type 协议 传输层 TLS UDP 中继 多路复用 面板
V2ray VMess,仅 AEAD(alter_id 为 0) TCP、WebSocket、gRPC 可选 支持 mux.cool 和 XUDP UniProxy、SSPanel
V2ray 且 enable_vless = true VLESS,不支持 flow TCP、WebSocket、gRPC 可选 支持 mux.cool 和 XUDP UniProxy、SSPanel
Trojan Trojan,密码为用户的 UUID UniProxy:TCP。SSPanel:TCP、WebSocket、gRPC 始终启用 支持 mux.cool 和 XUDP UniProxy、SSPanel
Shadowsocks AEAD(SIP004)或 2022 多用户(SIP022) TCP 从不启用 不支持 不支持 仅 UniProxy
Hysteria2 Hysteria 2 基于 UDP 的 QUIC 始终启用,在 QUIC 内部 [node.hysteria].udp = true 时支持 不适用 UniProxy、SSPanel(custom_config)或本地设置

“UniProxy”指 Xboard 和 V2board 提供的 newV2board API(panel_type = "NewV2board",或其别名 "V2board")。Hysteria 2 有单独的页面 Hysteria 2 节点;本页其余部分讨论四种基于流的协议。

katana 在绑定端口之前先检查所有可能失败的环节,因此被拒绝的节点不会启动到一半:

flowchart TB
  P["面板节点信息"] --> N["按节点类型解析"]
  N -->|"Shadowsocks obfs、SSPanel Shadowsocks"| E1["node_info failed"]
  N --> T["构建传输层:TCP、WebSocket、gRPC、TLS"]
  T -->|"REALITY、ACME、缺少证书、未知传输层"| E2["initial start failed"]
  T --> R["构建协议用户表"]
  R -->|"XTLS flow、未知加密方式"| E2
  R --> B["绑定 TCP 端口并提供服务"]

证书在构建传输层这一步读取,因此缺少证书的 TLS 节点在检查协议设置之前就会被拒绝。

node_type 在 katana 的配置文件中设置,而不是在面板中。取值不区分大小写:

写法 节点类型 说明
V2ray、vmess、vless V2ray 提供 VMess;enable_vless = true 时提供 VLESS。
Trojan Trojan
Shadowsocks Shadowsocks 仅限 UniProxy 面板。
Hysteria2、hysteria、hy2 Hysteria 2 见 Hysteria 2 节点。katana 会把 hy2 原样发给 UniProxy 面板,而 Xboard 不接受这个类型,所以在 Xboard 上请写 Hysteria2。

其他任何值(包括空值)都会被拒绝。katana --test 输出:

configuration error: unknown node_type "Socks"

启动时 katana 会记录 node 1: unknown node_type "Socks" 并跳过该节点,其他节点照常启动。

如果热重载的文件中含有这样的节点,整次重载都会被拒绝:katana 不会应用新文件中的任何内容,所有节点保持原样运行。日志会用面板、主机、ID 标明该节点,在 UniProxy 面板上还会带上所请求的类型:

reload: node newv2board@https://panel.example.com#1/socks: unknown node_type "Socks"; keeping current config

启动时被跳过的节点只要还留在文件中,情况也一样:在修正该节点的 node_type 之前,对文件的任何修改都不会生效。

UniProxy 面板上的一个 VLESS 节点如下:

config.toml
[[node]]
panel_type = "NewV2board"
[node.api]
host = "https://panel.example.com"
node_id = 1
key = "replace-with-the-panel-key"
node_type = "V2ray"
enable_vless = true
[node.controller.cert]
mode = "file"
cert_file = "/etc/katana/fullchain.pem"
key_file = "/etc/katana/privkey.pem"

在 UniProxy 面板上,节点类型还会出现在每个请求中:对于 enable_vless = true 的 V2ray 节点,katana 发送 node_type=vless,否则发送小写的 node_type。Xboard 通过节点 ID 和这个类型来查找节点,因此同一个 node_id 以 vless 和以 v2ray 请求时,指向的是面板中两个不同的节点。因此,改变 katana 所请求类型的修改(例如为 V2ray 节点打开 enable_vless)会在热重载时重启该节点,流量计数从零开始;见节点身份与热重载。

面板的 network 值决定传输层。katana 在匹配前会先将其转为小写:

面板 network 传输层 行为
空、tcp、raw TCP 协议直接运行在 TCP 连接上,或运行在其上的 TLS 之上。
ws、websocket WebSocket 只在配置的路径上接受升级请求。空路径即 /;不以 / 开头的路径会自动补上;?ed= 查询参数会被去掉,因为它用于配置 early data,而 katana 通过 Sec-WebSocket-Protocol 接收 early data(最多 16 KiB,超出时以 HTTP 413 应答)。面板给出 host 时,请求的 Host 头必须与之匹配(不区分大小写,忽略端口)。路径或 host 不符时以 HTTP 404 应答。
grpc、gun gRPC 在 /<serviceName>/Tun 上提供 gun 隧道,在 /<serviceName>/TunMulti 上提供 multi-hunk 隧道,service name 严格按面板给出的值使用。其他路径上的 stream 会被重置。每个 HTTP/2 stream 是一条被代理的连接,因此一条 TCP 连接可以承载多条。
httpupgrade 拒绝 node requests kernel-unsupported feature: httpupgrade transport
splithttp、xhttp 拒绝 node requests kernel-unsupported feature: splithttp transport
其他任何值 拒绝 node requests kernel-unsupported feature: transport "quic",其中给出实际的值

只有 V2ray 节点和 SSPanel 的 Trojan 节点读取 network。UniProxy 的 Trojan 节点始终使用 TCP,Shadowsocks 节点也始终使用 TCP。

节点是否使用 TLS 取决于其类型;对于 V2ray,还取决于面板:

节点类型 TLS
V2ray 由面板决定是否启用:UniProxy 的 tls = 1,SSPanel 的 security = "tls" 或 "xtls",或 SSPanel 旧式字符串中的 tls。
Trojan 始终启用,无论面板如何设置。
Shadowsocks 从不启用。
Hysteria 2 始终启用;TLS 握手是 QUIC 的一部分。

证书从不来自面板。katana 从 [node.controller.cert] 读取证书,面板的 tls_settings、server_name 等字段都不会被使用:

键类型必填默认值说明
modestring (enum)视情况"none""none"(不用证书)或 "file"(读取 cert_file 和 key_file),区分大小写。所有使用 TLS 的节点都必须用 "file";否则流式节点报 TLS node requires cert.mode = "file",Hysteria 2 节点报 hysteria2 node requires cert.mode = "file"。ACME 模式 "dns"、"http"、"tls" 在任何流式节点上都会被拒绝,不论它是否用 TLS:node requests kernel-unsupported feature: ACME cert mode "dns";在 Hysteria 2 节点上,它们和其他不是 "file" 的值一样报错。在流式节点上,其他值的效果与 "none" 相同。
cert_filepath视情况""PEM 格式的证书链:服务器证书在前,中间证书在后(即 fullchain.pem)。mode = "file" 时必填;它或 key_file 为空时,使用 TLS 的节点或 Hysteria 2 节点报 TLS node requires cert.cert_file and cert.key_file。每次构建监听器时读取,文件变化本身不会触发读取。文件不存在时只报操作系统的错误,例如 No such file or directory (os error 2),错误里不含路径。
key_filepath视情况""与 cert_file 配对的 PEM 私钥。mode = "file" 时必填。读取时机与 cert_file 相同;私钥与证书不匹配时,监听器构建失败。
reject_unknown_snibool否false没有实现,所以写 true 会被拒绝,而不是悄悄忽略:节点报 node requests kernel-unsupported feature: cert.reject_unknown_sni。请保持 false。

TLS 服务端的细节:

  • 版本: TLS 1.2 和 1.3,更早的版本会被拒绝。
  • 证书: cert_file 中的第一张证书作为服务端证书,其余证书作为证书链发送。
  • ALPN: gRPC 节点选择 h2,这正是 HTTP/2 客户端所提供的。TCP 和 WebSocket 节点不配置 ALPN,因此会接受客户端的 ALPN 列表,但不选定任何协议。
  • SNI: 不检查。任何 server name 都会得到同一张证书。如上表所述,reject_unknown_sni = true 会被拒绝。

只有下列字段会影响流式节点的监听器(Hysteria 2 的字段见 Hysteria 2 节点页面)。面板应答中的其他字段一律忽略,包括 Xboard 的 tls_settings、multiplex、decryption、plugin 和 plugin_opts,因此只存在于这些字段中的设置对 katana 节点没有任何作用。

字段 节点类型 用途
server_port 全部 监听端口。为 0 或缺失时报错 newV2board: server port must be > 0。
network V2ray 传输层,取值见上表。
networkSettings V2ray,VMess path(WebSocket)、headers.Host(WebSocket host 检查)、serviceName(gRPC)、header(TCP,忽略)。
network_settings V2ray,VLESS 字段相同;enable_vless = true 时读取它,而不是 networkSettings。
tls V2ray 0 或缺失:不启用 TLS。1:TLS。2:REALITY,拒绝。
flow V2ray 必须为空。任何值都会作为 XTLS flow 被拒绝。
cipher Shadowsocks 加密方式,取值见下方 Shadowsocks 表格。
server_key Shadowsocks 2022 加密方式的服务端 PSK,base64 编码。
obfs Shadowsocks 空、plain 或 none(必须完全一致,小写)。其他值都会被拒绝。

Trojan 节点在这里只读取 server_port,并以 TCP 加 TLS 提供服务。

未设置 enable_vless 的 V2ray 节点提供 VMess。

  • 仅支持 AEAD 头部。 未实现与大于 0 的 alterId 配套的旧式 MD5 头部。katana 为每个用户设置的 alter ID 都是 0,并忽略 SSPanel 旧式字符串中的值,因此客户端必须使用 alterId: 0。
  • 数据加密: aes-128-gcm 或 chacha20-poly1305。设为 auto 的客户端会从中选择其一。不接受 none 和 zero,连接会在握手阶段被关闭。
  • 时钟: VMess 头部带有时间戳,katana 只接受与自身时钟相差 120 秒以内的时间戳。请保持服务器时钟同步。
  • 用户: 账户 ID 即用户的 UUID。UUID 无法解析的用户会被跳过,并记录 skipping user 7: uuid is not a valid UUID,其他用户照常提供服务。
  • 命令: TCP、UDP 和 mux(见多路复用)。

Etemenanki 的 VMess 页面更详细地介绍了协议实现。

设置了 enable_vless = true,或在 SSPanel 的 custom_config 中设置了 enable_vless = "1" 的 V2ray 节点提供 VLESS。

  • 不支持 flow。 未实现 xtls-rprx-vision 等 XTLS flow。面板的 flow(SSPanel 发送旧式字符串时则为 [node.api].vless_flow)会使整个节点被拒绝,报错 node requests kernel-unsupported feature: VLESS XTLS flow。如果客户端仍然发送 flow,会握手失败。
  • 加密: 客户端必须使用 encryption: "none"。
  • 用户: ID 即用户的 UUID。与 VMess 相同,UUID 无法解析的用户会被跳过。
  • 命令: TCP、UDP 和 mux。

协议实现见 VLESS。

  • 密码: 面板中用户的 UUID,与面板列出的完全一致。这是 XrayR 的约定,也是 Xboard 下发给 Trojan 客户端的密码。
  • TLS: 始终启用,因此 Trojan 节点需要配置 mode = "file" 的 [node.controller.cert]。
  • 传输层: UniProxy 面板上为 TCP;SSPanel 上为 TCP、WebSocket 或 gRPC。
  • UDP: 通过 Trojan 的 UDP associate 命令提供。
  • Mux: 客户端通过连接 v1.mux.cool 来表示使用 mux.cool,katana 会把这条连接当作 mux 载体。

协议实现见 Trojan。

Shadowsocks 节点仅在 UniProxy 面板上可用,并且只支持 TCP:katana 不会为它绑定 UDP socket,因此客户端的 UDP 中继无法通过 katana 的 Shadowsocks 节点工作。

面板的 cipher 决定使用哪一代 Shadowsocks:

cipher 类别 用户密钥
aes-128-gcm、aes-256-gcm AEAD(SIP004) 用户的 UUID,作为密码
chacha20-ietf-poly1305(也可写作 chacha20-poly1305) AEAD(SIP004) 用户的 UUID,作为密码
xchacha20-ietf-poly1305(也可写作 xchacha20-poly1305) AEAD(SIP004) 用户的 UUID,作为密码
2022-blake3-aes-128-gcm 2022 多用户(SIP022) UUID 的前 16 个字符
2022-blake3-aes-256-gcm 2022 多用户(SIP022) UUID 的前 32 个字符
2022-blake3-chacha20-poly1305 拒绝 2022 规范只为 AES 加密方式定义了多用户
其他任何值 拒绝 node requests kernel-unsupported feature: shadowsocks cipher "rc4-md5"

AEAD 名称匹配时不区分大小写,并接受 aead_aes_128_gcm、aead_aes_256_gcm 和 aead_chacha20_poly1305 作为别名。2022 名称必须与上表完全一致,且为小写。

2022 节点始终以多用户模式运行,所有用户共用一个端口。每条客户端连接都带有一个身份头,告诉 katana 它属于哪个用户。这里涉及两个密钥:

  • 服务端密钥即面板的 server_key,是 base64 编码的 PSK,2022-blake3-aes-128-gcm 为 16 字节,2022-blake3-aes-256-gcm 为 32 字节。更长的密钥会被折叠到该长度;更短的会报错 shadowsocks-2022: PSK too short (0 < 32),无效的 base64 会报 decode PSK: 错误。
  • 用户密钥是用户 UUID 字符串的前 16 或 32 个字符,按原始字节使用。

Xboard 构建客户端密码时使用的是同样的派生方式:base64(UUID 的前 N 个字符),再用冒号与服务端密钥拼接。以 2022-blake3-aes-128-gcm 节点上的 UUID 11111111-2222-3333-4444-555555555555 为例:

user key bytes: 11111111-2222-33
client password: <server_key>:MTExMTExMTEtMjIyMi0zMw==

这些都不需要在 katana 中配置,只要与面板保持一致即可,而 katana 与 Xboard 是一致的。

katana 接受的 obfs 值为空、plain 和 none。其他任何值都会在 katana 读取节点信息时被拒绝,早于任何构建步骤:

node 1: node_info failed: newV2board: shadowsocks obfs "http" is not supported

katana 不读取 plugin 或 plugin_opts。面板中配置的 SIP003 插件不会生效,使用该插件的客户端无法连接。

协议实现见 Shadowsocks。

VMess、VLESS 和 Trojan 节点接受来自 Xray 兼容客户端的 mux.cool 连接。无需任何设置来开启:katana 会在每条连接上识别 mux 命令(VMess 和 VLESS)或 v1.mux.cool 目标地址(Trojan)。

  • mux 载体中的每条子连接都是一个独立的流:它会像单独的连接一样,针对已认证的用户进行路由、审计、速率限制和计量。
  • 支持 UDP 子连接,包括每个数据包各自携带地址的 XUDP。
  • 一个载体同时最多容纳 256 条子连接。客户端再打开一条时,只有这一条子连接被拒绝,载体及其其他子连接继续工作。
  • 只实现了 mux.cool。sing-box 多路复用(Xboard 的 multiplex 设置)既不读取,也不支持。

katana 采用 fail closed(出错即拒绝):当面板要求它无法提供的功能时,节点不会启动,而不是在缺少客户端所期望功能的情况下启动。下表列出所有拒绝情形以及 katana 记录的消息:

功能 来源 错误
REALITY UniProxy tls = 2,SSPanel enable_reality = true node requests kernel-unsupported feature: REALITY
XTLS flow 面板 flow;SSPanel 旧式字符串对应 [node.api].vless_flow node requests kernel-unsupported feature: VLESS XTLS flow
HTTPUpgrade network = "httpupgrade" node requests kernel-unsupported feature: httpupgrade transport
SplitHTTP、XHTTP network = "splithttp" 或 "xhttp" node requests kernel-unsupported feature: splithttp transport
其他传输层 quic、kcp、h2 等 network 值 node requests kernel-unsupported feature: transport "quic"
PROXY protocol 要求接受它的节点;在 katana 3.0.1 中没有面板字段会设置它 node requests kernel-unsupported feature: PROXY protocol accept
ACME 证书 [node.controller.cert].mode 为 dns、http 或 tls node requests kernel-unsupported feature: ACME cert mode "dns"
SNI 强制检查 [node.controller.cert].reject_unknown_sni = true node requests kernel-unsupported feature: cert.reject_unknown_sni
未知的 Shadowsocks 加密方式 面板 cipher node requests kernel-unsupported feature: shadowsocks cipher "rc4-md5"
2022 ChaCha20 多用户 cipher = "2022-blake3-chacha20-poly1305" shadowsocks-2022: multi-user requires an aes-gcm method,没有密钥时为 PSK too short
Shadowsocks obfs 面板 obfs 不是 plain 或 none newV2board: shadowsocks obfs "http" is not supported
SSPanel 上的 Shadowsocks node_type = "Shadowsocks" 且 panel_type = "SSPanel" sspanel: Shadowsocks node type is not supported
无文件证书的 TLS TLS 节点的 mode 不是 "file",包括默认值 "none" TLS node requires cert.mode = "file"
无路径的 TLS mode = "file" 但 cert_file 或 key_file 为空 TLS node requires cert.cert_file and cert.key_file

这些设置大多来自面板,所以 katana --test 看不到它们:它检查配置文件,构建出站、面板客户端和路由器,并验证 [node.hysteria],但不会联系面板。一个 REALITY 节点的配置能通过 --test,却会在启动时失败。

错误会连同节点 ID 出现在日志中。构建监听器时发现的拒绝如下:

ERROR katana::manager::node: node 1: initial start failed: node requests kernel-unsupported feature: REALITY; retrying in 1s

解析面板应答时发现的拒绝(例如 Shadowsocks 的 obfs)在启动时记录为 node 1: node_info failed: 加上错误消息,以及同样的 ; retrying in 提示。如果是在之后的轮询中出现,katana 会记录一条警告(node 1: node_info:),并继续使用已有的设置提供服务。同一文件中的其他节点不受影响。

尚未启动成功的节点会持续重试。第一次尝试失败后 katana 等待 1 秒,此后每失败一次等待时间翻倍,最长 60 秒;如果 update_periodic 更短,则以 update_periodic 为上限。每次尝试都会重新从面板读取节点信息和用户列表,因此在面板中修正节点后,它会在下一次尝试时启动,无需重启 katana。在配置文件中保存对该节点 [[node]] 表的修改,会立即触发下一次尝试。

如果运行中节点的设置在面板中被改成了会被拒绝的内容,该节点会失去监听器,并记录 node 1: rebuild failed: 加上原因。它会在每次轮询时重试,因此面板修正后节点就会恢复。其他启动错误见故障排查。

katana 的集成测试用真实的 katana 二进制对接一个模拟面板,并使用独立的客户端实现进行连接。每个测试都会经节点发送一段数据并校验回显的字节。Xray 测试还会检查面板是否收到了该用户的流量上报。

客户端 协议 传输层 TLS Mux
Xray-core VMess TCP、WebSocket、gRPC 否 仅 TCP
Xray-core VMess TCP 是 否
Xray-core VLESS WebSocket 是 是
Xray-core VLESS gRPC 是 否
Xray-core Trojan TCP 是 是
Hysteria 2 官方客户端 Hysteria 2 QUIC 是 不适用

Xray 客户端使用 VMess security auto 和 VLESS encryption none,并通过固定证书哈希来验证 katana 的证书。Xray mux 测试的并发数为 8。Hysteria 2 客户端仅凭用户的 UUID 认证,跳过证书验证,并在一条连接上打开两个 stream;它的节点从 [node.hysteria] 而不是面板获取端口。

katana 中没有任何测试用外部客户端驱动 Shadowsocks 节点。