故障排查
本页从你看到的现象出发:节点始终起不来、客户端连不上、面板上看不到流量。每一节列出 katana 针对该问题写出的日志行、产生原因和解决办法。日志行按 katana v3.0.1 的原文引用。其他版本的部分措辞不同,某些行为也有差异,所以请先用 katana --version 确认你的版本。
深入排查具体问题之前,请先阅读提高日志详细程度:大多数单个连接的失败只在 debug 级别记录,而该级别默认是关闭的。
| 现象 | 章节 |
|---|---|
| katana 启动后立即退出 | katana 启动即退出 |
| katana 在运行,但某个节点的端口没有打开 | 节点始终没有启动 |
| 保存了配置文件,但什么都没变 | 修改配置没有生效 |
| 端口已打开,但客户端连接失败 | 客户端无法连接 |
| 用户的速度比套餐快或慢 | 速度与预期不符 |
| 面板上没有流量,或流量数值不对 | 面板中看不到流量 |
| 审计规则本应拦截的目标仍能访问 | 审计规则没有拦截 |
| 只有经 WireGuard 路由的目标超时 | WireGuard 出站无法传输流量 |
出现 node_info: GET … 或 report traffic: … 之类的日志行 |
面板请求错误 |
… inbound handshake failures in the last 1s … |
握手失败告警 |
继续往下读之前,下面三项检查就能回答大多数问题:
-
检查配置文件。
katana --test -c /etc/katana/config.toml会输出Configuration OK或configuration error: …。它会解析文件、构建出站、检查每个节点的panel_type、node_type和路由,并检查 Hysteria 2 节点的设置。它不会联系面板,也不会绑定端口,所以Configuration OK并不说明面板或监听器没有问题。 -
检查监听器。 已启动的节点会占用自己的端口。基于 TCP 的节点监听 TCP,Hysteria 2 节点监听 UDP:
终端窗口 ss -ltnp | grep katana # VMess, VLESS, Trojan, Shadowsocksss -lunp | grep katana # Hysteria 2不在此列表中的节点要么还没有启动、正在重试,要么没有用户。它的日志行会说明是哪一种。
-
阅读日志。 katana 写入标准输出。在 systemd 下即为 journal,例如
journalctl -u katana -f。
如何阅读日志行
Section titled “如何阅读日志行”每一行都包含 UTC 时间戳、级别、target 和消息:
2026-09-24T08:15:02.481233Z ERROR katana::manager::node: node 1: node_info failed: GET /api/v1/server/UniProxy/config; retrying in 4starget 是写出该行的模块;提高日志详细程度就是用它来只为 katana 的某一部分打开详细日志。本页的示例省略时间戳,通常也省略 target。
不同的日志行用不同的方式指代节点:
| 形式 | 示例 | 用于 |
|---|---|---|
node <node_id> |
node 1: listening on 0.0.0.0:443 |
启动及其重试、轮询、上报、重建,以及节点拒绝的配置修改(node 1: config edit refused, …) |
node <Type>_<listen_ip>_<port> |
node V2ray_0.0.0.0_443: 37 inbound handshake failures … |
握手告警和预认证限制 |
SSPanel 上为 <panel_type>@<host>#<node_id>,NewV2board 和 V2board 上为 <panel_type>@<host>#<node_id>/<node type> |
reload: added node newv2board@https://panel.example.com#1/v2ray |
配置重载,包括被拒绝的重载(reload: node …: …; keeping current config) |
在重载形式中,<panel_type> 为小写,<node type> 是 katana 向面板请求的类型:即你配置的 node_type 的小写形式;如果 V2ray、VMess 或 VLESS 节点设置了 enable_vless = true,则为 vless。
面板请求错误和重载日志行从不包含面板密钥或查询字符串。但配置解析错误会引用解析失败的那一行文件内容,所以分享日志之前请先读一遍。
提高日志详细程度
Section titled “提高日志详细程度”katana 的日志过滤器使用 tracing 的过滤器语法:先是默认级别,然后是可选的、以逗号分隔的 target=level 对。一个 target 匹配其自身及其下的所有模块,因此 katana::manager=debug 也覆盖 katana::manager::node。
可以在两个地方设置过滤器:
启动时,如果 RUST_LOG 环境变量是有效的过滤器,katana 就使用它,否则使用 [log].level。这种方式适合一次性的前台运行:
RUST_LOG=info,katana::serve=debug katana -c /etc/katana/config.toml对于 systemd 服务,把变量写进 drop-in 文件,然后重启服务。重启会断开所有连接。
[Service]Environment=RUST_LOG=info,katana::serve=debug修改后的 [log].level 会在热重载时生效,不会断开连接。保存文件后查找 reload: log level → …:
[log]level = "info,katana::serve=debug"此后文件的设置优先于 RUST_LOG。排查完毕后删除该配置项,级别会恢复为 info。无效的值会记录 invalid log level "<value>": …,并保留当前的过滤器。
以下是值得了解的 target:
| Target | 记录的内容 |
|---|---|
katana::runtime |
启动错误、配置重载、文件监视器、关闭 |
katana::manager::node |
节点启动、轮询、面板请求错误、监听器重建、流量和审计上报 |
katana::manager::proxy |
握手失败告警(warn)、因预认证限制而丢弃的流(debug)、用户刷新失败(error) |
katana::manager |
因 UUID 无效而被跳过的用户(warn) |
katana::serve |
每个握手失败或以错误结束的连接各一行 debug、accept 错误、活动连接数限制,以及 Hysteria 2 监听器失败(error) |
katana::api |
审计规则问题:规则文件无法读取,或正则表达式无法编译(warn) |
katana::connector |
无法打开出站的 UDP 关联(debug) |
katana::outbound |
因域名没有可用地址而丢弃的 direct UDP 数据报(debug) |
etemenanki_protocols |
代理内核:协议核心(core)、传输层、Hysteria 2 监听器(etemenanki_protocols::hysteria)和 WireGuard 隧道(etemenanki_protocols::wireguard) |
boringtun |
WireGuard 握手、keepalive 和会话变化 |
katana 启动即退出
Section titled “katana 启动即退出”katana 完全无法运行时会以状态码 1 退出。最后一行说明原因:
| 日志行 | 原因 | 解决办法 |
|---|---|---|
failed to load config: … |
文件不存在、不是 UTF-8、不是有效的 TOML,或包含未知配置项 | 运行 katana --test,它会输出同样的错误以及行号和列号。配置文件列出了所有配置项。 |
failed to build outbounds: … |
某个 [[outbound]] 条目或 [dns] 无法构建 |
见出站。 |
config defines no [[node]] entries |
文件中没有 [[node]] 表 |
添加一个。单括号的 [node] 不算。 |
node 1: unknown panel_type "…" |
panel_type 不是 SSpanel、NewV2board 或 V2board(不区分大小写)。Xboard 对应 NewV2board。 |
修正该值。 |
node 1: unknown node_type "…" |
node_type 不是已知的值 |
使用 V2ray、Trojan、Shadowsocks 或 Hysteria2。 |
node 1: build router: … |
节点的 [node.route] 无法编译 |
见路由。 |
no nodes could be started |
所有节点都因上面三种原因之一被跳过 | 逐一修正;--test 会报告第一个。 |
因上述三种 node 1: … 原因之一被跳过的节点不会影响其他节点。只有一个节点都不剩时 katana 才会退出。
重载时,同样的错误不会跳过节点,而是拒绝整次保存。如果保存的文件中某个 [[node]] 表的 panel_type 或 node_type 未知,或者新增的节点路由无法编译,katana 会记录类似 reload: node newv2board@https://panel.example.com#1/v3ray: unknown node_type "v3ray"; keeping current config 的日志行,不应用这次保存中的任何内容,所有节点都保持原样继续运行。因此,启动时被跳过且仍然有误的节点会让之后的每次保存都被拒绝,即使这次保存只修改了文件的其他部分,直到你修正或删除它的 [[node]] 表;见热重载。已在运行的节点的新路由由该节点自己检查;见修改配置没有生效。
节点始终没有启动
Section titled “节点始终没有启动”节点会一直尝试,直到启动成功。每次尝试都会向面板请求节点设置、请求用户列表,然后绑定监听器。设置了 [node.hysteria].port 的 Hysteria 2 节点从文件中读取设置,只向面板请求用户。node 1: listening on 0.0.0.0:443 表示这三步都成功了。
flowchart TB
S["尝试启动"] --> I{"面板返回节点设置?"}
I -- 否 --> R["ERROR,然后等待"]
I -- 是 --> P{"端口不为 0?"}
P -- 否 --> R
P -- 是 --> U{"面板返回用户列表?"}
U -- 否 --> R
U -- 是 --> E{"有用户?"}
E -- 否 --> W["不绑定端口;下一次轮询重试"]
E -- 是 --> B{"监听器构建并绑定成功?"}
B -- 否 --> R
B -- 是 --> L["listening on ip:port"]
R -- "等待结束,或保存了该节点的配置" --> S
某一步失败时,节点会记录一行 ERROR,写明失败的步骤和等待时间,例如 node 1: user_list failed: GET /api/v1/server/UniProxy/user; retrying in 2s,等待结束后再次尝试。第一次等待 1 秒,之后每失败一次翻倍,最多 60 秒或 update_periodic,取较小者。每次尝试都会重新向面板请求所有内容,所以在面板中的修复会在下一次尝试时被看到。
这些日志行都来自 katana::manager::node,级别为 ERROR。每一行都以 node <node_id>: 开头,以 ; retrying in <N>s 结尾,表中省略了结尾部分。节点会在等待结束后再次尝试,所以修复原因后留意下一行日志即可。
| 日志行 | 原因 | 解决办法 |
|---|---|---|
node_info failed: GET /api/v1/server/UniProxy/config |
对 Xboard 或 V2board 面板的请求失败。该行不说明原因:可能是 host 错误或无法访问、请求超时,也可能是面板拒绝了密钥、node_id 或节点类型。 |
手动发送请求,查看面板的响应。检查节点类型。 |
node_info failed: GET /mod_mu/nodes/1/info |
同上,面板为 SSPanel。 | 同上。 |
node_info failed: /mod_mu/nodes/1/info: panel returned ret=0 |
SSPanel 有响应但拒绝了请求,通常是 key 或 node_id 错误。 |
检查 SSPanel 中的 muKey 和节点 ID。 |
node_info failed: parse UniProxy config response 或 node_info failed: parse /mod_mu/nodes/1/info |
面板返回的不是节点配置,常见的是 host 错误时得到的 HTML 页面,或面板前面的 Web 防火墙、机器人验证页面。 |
手动发送请求并查看响应体。host 是面板的基础 URL,包括 https://。 |
node_info failed: newV2board: server port must be > 0 |
该节点在 Xboard 或 V2board 中没有端口。 | 在面板中设置端口。 |
panel returned port 0 |
SSPanel 描述的节点端口为 0。 |
在 custom_config 中设置 offset_port_node,或在旧式 server 字符串中设置端口。 |
node_info failed: invalid offset_port_node "" |
SSPanel 节点的 custom_config 中没有 offset_port_node。 |
将其设为 katana 应监听的端口。 |
node_info failed: sspanel: Shadowsocks node type is not supported |
在 SSPanel 上使用了 node_type = "Shadowsocks"。 |
通过 Xboard 或 V2board 面板提供 Shadowsocks。 |
node_info failed: custom_config is empty, disable custom config |
SSPanel 节点没有 custom_config。 |
见 SSPanel。 |
node_info failed: newV2board: shadowsocks obfs "…" is not supported |
面板为 Shadowsocks 节点发送的 obfs 值不是 plain 或 none。Xboard 则把插件放在 plugin 中发送,katana 不读取该字段:节点会在没有插件的情况下启动,使用插件的客户端会失败。 |
从节点中移除插件。 |
user_list failed: … |
用户请求失败。节点需要用户列表才能启动,因此不绑定任何端口并重试。结尾部分与 node_info failed 相同。 |
按 node_info failed 的方法检查面板。在 Xboard 上,user_list failed: parse UniProxy user response 通常表示某个用户没有限速;见没有用户的节点。 |
panel returned no node info 或 panel returned no user list |
面板或其前面的某个组件返回了 304 Not Modified,尽管 katana 请求时没有带标签。 |
手动发送请求,检查是谁在响应。 |
initial start failed: TLS node requires cert.mode = "file" |
节点使用 TLS(面板开启了 TLS,或者是始终使用 TLS 的 Trojan 节点),但 [node.controller.cert] 中没有 mode = "file"。 |
设置 mode = "file"、cert_file 和 key_file。 |
initial start failed: TLS node requires cert.cert_file and cert.key_file |
设置了 mode = "file",但缺少路径。 |
设置两个路径。 |
initial start failed: No such file or directory (os error 2) |
cert_file 或 key_file 不存在。该行不说明是哪一个。 |
检查两个路径。使用绝对路径:相对路径会相对于 katana 的工作目录打开。 |
initial start failed: Permission denied (os error 13) |
katana 无权绑定 1024 以下的端口,或无权读取私钥文件。 | 授予 CAP_NET_BIND_SERVICE 或以 root 运行,并检查私钥文件的属主和权限。 |
initial start failed: Address already in use (os error 98) |
其他程序或同一文件中的另一个节点占用了该端口。 | 释放端口,或在面板中更改端口。 |
initial start failed: Cannot assign requested address (os error 99) |
listen_ip 不是本机的地址。 |
使用本机拥有的地址,或 0.0.0.0。 |
initial start failed: node requests kernel-unsupported feature: … |
面板要求了 katana 不支持的功能:REALITY、VLESS XTLS flow、httpupgrade transport、splithttp transport、transport "…"、shadowsocks cipher "…",或者你自己的文件中的 ACME cert mode "…" 或 cert.reject_unknown_sni。 |
在面板中修改节点,或修改文件中的配置项。协议列出了 katana 支持的内容。 |
Hysteria 2 节点上的 initial start failed: … |
[node.hysteria] 设置(unknown hysteria credential kind …、udp_idle_timeout must be between 2 and 600 seconds)、证书(hysteria2 node requires cert.mode = "file")或混淆(unknown obfs …、obfs_password must be at least 4 bytes for salamander、obfs_password is set but obfs is not; …)有问题。Xboard 在关闭混淆时仍会发送混淆密码,从而产生最后一种错误。 |
运行 katana --test,它会检查本地设置。它无法检查来自面板的混淆设置:请在面板中开启混淆,或清空混淆密码。见 Hysteria 2 节点。 |
没有用户的节点
Section titled “没有用户的节点”用户列表为空的节点启动后没有监听器,也不写任何相关日志行。它不绑定任何端口,因为没有需要服务的人;它会在第一次返回用户的轮询时绑定,即 update_periodic 秒之后(默认 60)。检查面板发送的内容:
- Xboard 只列出属于节点某个权限组、未被封禁、未过期且未超出流量配额的用户。没有权限组的节点得不到任何用户。
- Xboard,
user_list failed: parse UniProxy user response; retrying in <N>s。 对于套餐没有限速的用户,Xboard 会发送"speed_limit": null,katana 会因此拒绝整个列表。节点会不断重试且不绑定任何端口,直到面板发送的列表中不再有这样的用户,然后自行启动。请为每个套餐和每个用户设置限速;0表示不限速。限速对此有说明。
手动发送请求
Section titled “手动发送请求”katana 的面板错误日志行从不包含 URL,因为 URL 中带有密钥。要查看面板的响应,请用 curl 发送同样的请求。把密钥读入变量可以避免它进入 shell 历史:
read -rs KEY # paste the panel key, then press Entercurl -sS -i "https://panel.example.com/api/v1/server/UniProxy/config?node_id=1&node_type=v2ray&token=$KEY"使用 katana 发送的 node_type:即你配置的 node_type 的小写形式;如果 V2ray、VMess 或 VLESS 节点设置了 enable_vless = true,则为 vless。正常的节点返回 200 和包含 server_port 的 JSON。密钥错误时 Xboard 返回 Invalid token,类型未知时返回 Invalid node type specified,该 ID 下没有此类型的节点时返回 Server does not exist。请求用户列表时,把 config 换成 user。
read -rs KEY # paste the muKey, then press Entercurl -sS -i "https://panel.example.com/mod_mu/nodes/1/info?key=$KEY&muKey=$KEY"正常的节点返回 200 和 "ret":1。请求用户列表时,请求 /mod_mu/users?key=$KEY&muKey=$KEY&node_id=1。
请在节点所在的主机上运行,这样 DNS、路由和防火墙都与 katana 一致。连接错误、证书错误、HTTP 错误状态码和非 JSON 的响应体分别对应不同的解决办法,面板的错误消息通常会指出问题所在。
修复原因之后
Section titled “修复原因之后”无需重启 katana。节点会在下一次尝试时发现修复,最多 60 秒之后;如果 update_periodic 更短,则最多一个 update_periodic 间隔。如果修复在该节点的 [[node]] 表中,保存文件会结束等待,并立即以新设置开始下一次尝试。保存前先用 katana --test 检查文件。
已启动的节点停止服务
Section titled “已启动的节点停止服务”曾经启动过的节点能从大多数问题中自行恢复:
| 日志行 | 发生了什么 | 接下来会怎样 |
|---|---|---|
node 1: rebuild failed: … |
面板或文件变化后,监听器重建时构建或绑定失败。消息是上面 initial start failed 的原因之一。 |
节点没有监听器。每次轮询都会重试,所以修复原因后的第一次轮询就会恢复。 |
| 无,端口关闭 | 面板中该节点的用户列表变为空。 | 节点会在第一次返回用户的轮询时重新绑定。 |
node 1: refreshed port is 0, keeping the last one |
面板在某次轮询中报告端口为 0。 |
节点保留当前的监听器和端口,但仍会应用这次轮询得到的用户列表。 |
hysteria listener failed: … |
Hysteria 2 节点的 QUIC 监听器停止了。 | 轮询不会重建它。请重启 katana,或保存一次会重建该节点监听器的修改,例如修改 [node.hysteria]。 |
修改配置没有生效
Section titled “修改配置没有生效”保存配置文件后约 500 ms,katana 会重新加载它,几乎所有修改都会立即生效。对 [node.api] 的修改(例如 speed_limit、timeout 或 rule_list_path)会为节点创建新的面板客户端,它会立即重新读取节点和用户;只有当修改改变了节点的协议或传输层时才会断开连接。enable_vless 以及 Xboard 和 V2board 上的 node_type 修改也可能断开连接;见下表前两行。例外是少数只在 katana 构建相应对象时读取的文件,以及无法构建的保存,katana 会拒绝后者。katana 应用的保存会为每个发生变化的部分写一行 reload:,被拒绝的保存则会写一行包含 keeping current 或 refused 的日志。
| 你修改了 | 发生了什么 | 怎么办 |
|---|---|---|
Xboard 或 V2board 上的 api.node_type 或 api.enable_vless,使 katana 向面板请求另一种类型,且节点重启了 |
面板按 ID 和 katana 请求的类型查找节点,所以新类型对应的是面板中的另一个节点。katana 停止旧节点(并做最后一次流量上报),为新类型启动一个节点:先是 reload: removing node …#1/v2ray,然后是 reload: added node …#1/vless。该节点上的所有连接都会断开,新节点的流量计数从零开始。 |
预期行为。请在节点空闲时修改。 |
disable_sniffing、[node.hysteria] 中的某个配置项,或 SSPanel 上的 api.enable_vless(在 Xboard 或 V2board 上则是不改变 katana 所请求类型的 api.enable_vless),且节点的连接断开了 |
这些修改通过重建节点的监听器立即生效,这会结束该监听器上的所有连接。 | 预期行为。请在节点空闲时做这些修改。 |
controller.send_ip、api.device_limit |
katana 接受这些配置项,但不使用它们。 | 无需应用。 |
只改了 [dns] |
解析器只会随出站一起重建,而且 katana 不记录 reload: 日志行。 |
重启 katana,或随下一次 [[outbound]] 修改一起应用。 |
| 续期了证书,路径不变 | katana 在构建监听器时读取证书文件。 | 每次续期后重启 katana。 |
替换了 geoip 或 geosite 文件,路径不变 |
katana 在编译节点路由时读取它们。 | 重启 katana,或保存一次对 [node.route] 或 [[outbound]] 的修改。 |
[node.route],且日志显示 node 1: config edit refused, keeping the running one: … |
节点的新路由无法编译。节点不应用其 [[node]] 表中的任何修改,保留原有的规则、监听器和连接。重载仍会记录 reload: reconfigured node …,这次保存的其余部分(例如其他节点和日志级别)照常生效。 |
修正规则后重新保存。保存前先运行 katana --test。 |
[[outbound]],且日志显示 node 1: route rebuild failed, keeping current: … |
节点的路由引用了新出站池中已不存在的出站。节点继续使用之前的路由表(仍指向旧的出站),并重建监听器。 | 恢复该出站,或修改节点的路由使之匹配,然后重新保存。 |
[[outbound]],且日志显示 reload: bad outbounds, keeping current config: … |
新出站无法构建,因此 katana 没有应用这次保存中的任何内容。 | 修正出站后重新保存。 |
任意修改,且日志显示 reload: node …: …; keeping current config |
新文件中某个 [[node]] 表无法构建:panel_type 或 node_type 未知,或本次保存新增的节点路由无法编译(build router: …)。katana 没有应用这次保存中的任何内容。 |
修正日志行指出的节点后重新保存。katana --test 会报告同样的错误。 |
任意修改,且日志显示 config reload failed, keeping current: … |
文件无法解析。 | 修正文件后重新保存。 |
| 任意修改,且没有出现任何日志行 | 文件监视器没有启动(启动时记录了 config watcher disabled (no live reload): …),或者配置路径是指向其他目录的符号链接,katana 察觉不到那里的变化。 |
每次修改后重启 katana。 |
| 尚未启动的节点中的任意修改 | 不会丢失任何东西:该节点仍在运行和重试。它会接受修改,并立即以新设置开始下一次尝试。 | 查看该节点的下一行日志:listening on …,或带有剩余原因的 retrying in <N>s。 |
每个配置项在重载时的效果、哪些修改会断开连接的完整表格见热重载。
客户端无法连接
Section titled “客户端无法连接”单个连接失败时,katana 在默认的 info 级别下不写任何内容。如果节点的端口已打开(见先看哪里),请按顺序检查连接经过的各个阶段:
| 阶段 | 可能的失败 | 查看 |
|---|---|---|
| 到达端口 | 防火墙、云安全组、Hysteria 2 的 UDP 被阻断、IPv6 客户端遇上 listen_ip = "0.0.0.0" |
端口是否可达 |
| TLS | 证书缺失或错误,证书不覆盖客户端使用的服务器名称 | 证书 |
| 传输层 | WebSocket 路径或 Host、gRPC 服务名 |
当前 Xboard 上基于 WebSocket 或 gRPC 的 VLESS |
| 协议 | 客户端协议与 katana 提供的不同、未知用户、时钟偏差 | node_type 与面板的协议,VMess 与时钟 |
| 目标 | 路由到 block、审计规则、出站失败 |
审计规则没有拦截,WireGuard 出站无法传输流量 |
要查看每次握手失败的原因,按提高日志详细程度所述打开 katana::serve=debug。日志行如下:
DEBUG katana::serve: inbound handshake failed: proxy core: vmess: unknown user or invalid auth idDEBUG katana::serve: inbound handshake failed: proxy core: invalid vless request user idDEBUG katana::serve: inbound handshake failed: proxy core: trojan: invalid userDEBUG katana::serve: inbound handshake failed: timed out after 10sDEBUG katana::serve: inbound handshake failed: closed before the handshake completedDEBUG katana::serve: inbound transport ended: …inbound transport ended 涵盖代理协议之下的失败,例如没有完成的 TLS 握手或 WebSocket 升级。10 秒后仍处于协议握手阶段的客户端会以 timed out after 10s 断开。这些日志行不包含节点或用户。
端口是否可达
Section titled “端口是否可达”- 防火墙。 在主机防火墙和所有云安全组中,为 VMess、VLESS、Trojan 和 Shadowsocks 节点开放 TCP 端口,为 Hysteria 2 节点开放 UDP 端口。UDP 被阻断时 Hysteria 2 会静默失败:客户端超时,katana 不记录任何内容。例如
ufw allow 443/udp或firewall-cmd --add-port=443/udp --permanent。 - 地址族。 默认的
listen_ip = "0.0.0.0"只接受 IPv4。在 Linux 上若要同时接受 IPv6 客户端,请设置listen_ip = "::";除非主机设置了net.ipv6.bindv6only = 1,它同样接受 IPv4。 - 文件描述符。
accept error, backing off 100ms: Too many open files (os error 24)表示 katana 达到了打开文件数上限,新客户端会等待或失败。请提高上限,例如在 systemd unit 中设置LimitNOFILE=。
katana 的所有证书都来自 [node.controller.cert]。它忽略面板发送的 TLS 设置和证书,所以上传到面板的证书永远不会被使用。
- 文件不存在时节点无法启动:它会以
initial start failed: No such file or directory (os error 2)不断重试,直到文件出现。见启动日志行。 - 客户端会用它发送的服务器名称去核对证书的 Subject Alternative Names。只在 Common Name 中写了主机名,或覆盖的是其他名称的证书,会在客户端报证书错误,而 katana 只能看到一次失败的 TLS 握手。
- 自签名证书只有在客户端固定该证书或跳过验证时才能使用。
- katana 会一直使用构建监听器时读取的证书。续期后请重启 katana,否则客户端会看到旧证书过期。
node_type 与面板的协议
Section titled “node_type 与面板的协议”无论面板认为节点是什么,katana 提供哪种协议都由 node_type 决定。两者不一致时,要么面板拒绝请求,要么 katana 提供了客户端不支持的协议。
使用 Xboard 或 V2board 时,katana 每次请求都会带上 node_type,面板按 ID 和类型共同查找节点:
| 面板中的节点 | node_type |
enable_vless |
katana 发送 |
|---|---|---|---|
| VMess | V2ray 或 VMess |
false |
v2ray 或 vmess |
| VLESS | V2ray |
true |
vless |
| Trojan | Trojan |
false |
trojan |
| Shadowsocks | Shadowsocks |
false |
shadowsocks |
| Hysteria 2 | Hysteria2 或 Hysteria |
false |
hysteria2 或 hysteria |
常见错误:
- 设置了
node_type = "vless"却没有enable_vless = true。 katana 向面板请求 VLESS 节点、收到后却在上面提供 VMess。所有客户端都会以vmess: unknown user or invalid auth id失败。设置enable_vless = true并保存。节点仍对应原来的面板节点,因为 katana 本来就在请求vless,它会立即重建监听器以提供 VLESS。 node_type = "hy2"。 katana 接受这个名称,但会原样发送给面板,而 Xboard 不认识它,因此所有面板请求都以Invalid node type specified失败。请使用Hysteria2。- 该 ID 下没有这种类型的节点。 面板找不到节点,请求以
node_info failed: GET /api/v1/server/UniProxy/config失败。手动发送请求会看到 Xboard 返回的Server does not exist。 - 基于 WebSocket 或 gRPC 的 Trojan。 对于来自 Xboard 或 V2board 的 Trojan 节点,katana 忽略面板的
network,始终以 TCP + TLS 提供 Trojan。请把 Trojan 客户端配置为 TCP。
使用 SSPanel 时,面板只按 ID 查找节点,katana 则按你配置的 node_type 解读它。类型不匹配时节点能启动,但客户端握手会失败。请让 node_type 与 SSPanel 中的节点类型一致。
VMess 与时钟
Section titled “VMess 与时钟”VMess 认证包含时间戳,katana 只接受与自身时钟前后相差 120 秒以内的时间戳。超出这个范围,每个连接都会以 vmess: unknown user or invalid auth id 失败,与未知用户的日志行相同。使用 2022-blake3-… 加密方式的 Shadowsocks 节点更严格:请求头的时间戳必须在 30 秒以内,超出范围的客户端会以 shadowsocks-2022: bad timestamp 失败。请检查服务器和客户端的时间都准确:
timedatectl status # "System clock synchronized: yes"如果同一节点上只有一个客户端失败而其他客户端正常,请检查该设备的时钟和时区设置。VLESS、Trojan、Hysteria 2 和较早的 Shadowsocks 加密方式不以这种方式依赖时钟。
当前 Xboard 上基于 WebSocket 或 gRPC 的 VLESS
Section titled “当前 Xboard 上基于 WebSocket 或 gRPC 的 VLESS”katana 从面板响应的 network_settings 键读取 VLESS 节点的传输层设置。当前的 Xboard 版本对所有节点类型都以 networkSettings 发送这些设置,因此 katana 看不到路径、Host 或服务名:
- VLESS WebSocket 节点监听路径
/并接受任意Host,因此配置了其他路径的客户端会收到 HTTP404; - VLESS gRPC 节点期望空的服务名,因此配置了服务名的客户端会失败。
要确认这一点,请手动发送配置请求,看响应中是否只有 networkSettings 而没有 network_settings。绕过办法有:在面板中把 WebSocket 路径设为 /,改用 TCP + TLS 提供 VLESS,或把 WebSocket 或 gRPC 节点改为 VMess 提供。VMess 节点读取 networkSettings,不受影响。
Hysteria 2 客户端
Section titled “Hysteria 2 客户端”除了 UDP 防火墙之外:
- 凭据。 默认情况下,客户端的密码是用户的 UUID。设置
[node.hysteria].credential = "user_pass"后,在 Xboard 和 V2board 上为<uuid>@v2board.user:<uuid>,在 SSPanel 上为<user id>:<uuid>。发送了错误格式的客户端会得到authentication error, HTTP status code: 404,或你设置的 masquerade 状态码。 - 混淆。 客户端的
salamander密码必须与节点的一致:即面板的obfs-password,本地描述的节点则为[node.hysteria].obfs_password。不一致时的表现与 UDP 被阻断完全相同,只是超时而没有认证错误,因为 katana 无法读取这些数据包。 - 证书。 Hysteria 2 客户端像任何 TLS 客户端一样验证证书;见证书。
RUST_LOG=info,etemenanki_protocols::hysteria=debug 会显示监听器一侧的情况,例如 hysteria2: a handshake failed: …。Hysteria 2 节点介绍了相关设置。
- 新用户暂时无法连接。 katana 在下一次轮询时才得知用户变化,最多在变化后
update_periodic秒(默认 60)。 - 某个用户始终不被接受。 在
V2ray节点上,UUID 不是有效 UUID 的用户会被排除,并在WARN级别记录skipping user 7: uuid is not a valid UUID。请在面板中修正 UUID。 - 某个时间点之后添加的用户都无法连接。 查看每次轮询时是否有
user_list: …警告:katana 会继续使用它最后一次成功读取的用户列表。在 Xboard 上,user_list: parse UniProxy user response通常是某个用户或套餐没有限速;见没有用户的节点。 - 已删除的用户仍能使用。 删除在下一次轮询时生效,届时也会断开该用户已打开的连接。
速度与预期不符
Section titled “速度与预期不符”用户的速率取节点限速和用户自身限速中较小的一个,值为 0 的忽略不计。只有 SSPanel 有节点限速;在 Xboard 和 V2board 上,用户的限速就是其速率。katana 为节点上的每个用户使用一个令牌桶来执行限速。限速解释了其机制。
| 现象 | 原因 | 怎么办 |
|---|---|---|
| 节点上所有用户的速度都一样,与套餐无关 | [node.api].speed_limit 大于 0。它会替换每个用户的限速,包括套餐本身不限速的用户。它不是上限。 |
设为 0 并保存。节点上的用户会立即使用各自的限速,作用于此后打开的流,现有连接保持不变。 |
| 速率比预期低或高 8 倍 | 所有限速的单位都是兆比特每秒(十进制)。speed_limit = 100 即每秒 12,500,000 字节,客户端显示约为 12.5 MB/s。 |
换算:字节每秒乘以 8,再除以 1,000,000。 |
| 修改的限速只对部分流量生效 | 在面板中修改的限速在下一次轮询时生效,在文件中保存的 speed_limit 则立即生效,Hysteria 2 节点也一样。两种情况下修改都原地生效、不断开连接,并且只作用于之后打开的流。已打开的流以旧速率继续直到结束。 |
等待客户端打开新连接。 |
| 同时下载和上传的用户,每个方向只有约一半的速率 | 两个方向以及该用户在节点上的所有连接共享一个令牌桶。 | 预期行为。按合计流量规划套餐。 |
| SSPanel 用户比套餐慢 | SSPanel 中节点自身的限速更低,取较小者。 | 提高或清除节点限速。 |
| Hysteria 2 客户端声明的带宽没有作用 | katana 的每用户限速只来自面板和配置文件。 | 在面板中设置限速。 |
| 没有设置限速,但所有人都很慢 | 瓶颈在别处:主机、线路或出站。 | 绕过 katana 测试;隧道问题见 WireGuard 出站无法传输流量。 |
面板中看不到流量
Section titled “面板中看不到流量”katana 在每次轮询时上报流量,即每 update_periodic 秒一次。没有传输任何字节的用户不会被上报;所有用户都没有流量时,katana 根本不发送请求。
| 现象 | 原因 | 怎么办 |
|---|---|---|
| 完全没有流量,也没有警告 | [node.controller].disable_upload_traffic = true |
设为 false,修改在下一次上报时生效。流量上报解释了在此期间计数会怎样。 |
| 刚启动,还没有流量 | 第一次上报在节点成功启动后一个完整的 update_periodic 间隔才发出。 |
等待一个间隔。 |
node 1: report traffic: POST UniProxy push |
向 Xboard 或 V2board 上报失败。 | 见面板请求错误。katana 会保留计数,并计入下一次上报。 |
node 1: report traffic: POST /mod_mu/users/traffic,或 … panel returned ret=0 |
向 SSPanel 上报失败或被拒绝。 | 同上。 |
| 节点没有监听器 | 节点还没有启动、正在重试,因此没有可上报的内容。 | 见节点始终没有启动。 |
| Xboard 显示节点在线,但没有推送 | 一段时间内没有用户传输任何字节,所以 katana 没有推送。 | 空闲节点上属于预期行为。 |
| 面板显示的流量少于客户端或网卡统计 | katana 只计费有效载荷:TLS、WebSocket、gRPC 和代理协议的开销不计入。 | 预期行为。 |
| 面板显示的流量多于 katana 实际传输的 | Xboard 乘以了节点倍率;或者某次上报在面板已接受后在 katana 一侧超时,katana 又发送了一次。 | 检查节点倍率。见流量上报;如果面板响应慢,请调大 api.timeout。 |
面板访问日志中的 304 Not Modified 响应是正常的。katana 请求节点配置、用户列表以及 SSPanel 上的审计规则时,会带上上一次响应的标签。304 表示没有变化,katana 保留已有内容,不记录任何日志。流量上报是 POST 请求,永远不会得到 304。
审计规则没有拦截
Section titled “审计规则没有拦截”katana 在拨号之前,用审计规则检查客户端请求中的主机。目标审计完整解释了匹配方式。规则没有触发的常见原因:
- 客户端通过 IP 地址连接。 规则只看到代理请求中的地址,从不看从 TLS 服务器名称或 HTTP
Host嗅探到的域名。客户端自行解析了域名时,域名规则不会匹配。要拦截某个站点的 TCP 流量而不论客户端如何指定地址,请在路由中添加一条把它发往block的domain_suffix规则;开启嗅探时,路由能看到嗅探到的域名。 - 大小写和锚点。 匹配区分大小写:请在模式开头加上
(?i)。^blocked\.example\.com$不匹配www.blocked.example.com。 - 规则被关闭。 启动时设置了
disable_get_rule = true,katana 不加载任何审计规则,本地文件也不例外。通过重载将其设为true会停止刷新,但保留已加载的规则;再设回false会在下一次轮询时加载规则。 - 规则尚未加载,或加载失败。 规则在节点启动后立即加载,并在每次轮询时刷新。查找
WARN级别的invalid local rule …、invalid block rule …、invalid panel rule …或cannot read rule_list_path …;在 SSPanel 上还要查找node_rule: …警告。 - 路由已经拦截了它。 被路由发往
block的流在审计规则运行之前就被拒绝,因此不会记录审计命中。 - 流在之前就已打开。 规则只作用于新的流。已打开的 TCP 连接不会被重新检查。
- 在 SSPanel 上修改了本地规则文件。 SSPanel 以
304响应规则请求时,katana 也不会重新读取本地文件。修改要等面板的规则发生变化、保存的[node.api]修改为节点创建了新的面板客户端,或 katana 重启后才生效。
被拒绝的流在客户端看来与路由到 block 相同,katana 也不为它写日志行。在 SSPanel 上,面板规则的命中会在下一次轮询时进入检测日志。本地规则的命中,以及 Xboard 或 V2board 上的所有命中,都不会上报到任何地方。
WireGuard 出站无法传输流量
Section titled “WireGuard 出站无法传输流量”如果路由到 wireguard 出站的目标超时而其他一切正常,问题就在该出站。经隧道超时的连接,katana 自身不写任何日志行。在默认级别下,你可能会看到以下警告:
| 警告 | 含义 |
|---|---|
HANDSHAKE(REKEY_TIMEOUT)(target boringtun) |
对端不响应握手。持续约 90 秒后,会出现 ERROR 级别的 CONNECTION_EXPIRED(REKEY_ATTEMPT_TIME)。 |
wireguard: tunnel start failed: … |
隧道根本无法启动,例如其 endpoint 无法解析。 |
wireguard: tunnel driver stopping, send failed: … 或 … receive failed: … |
隧道的 UDP socket 出错,隧道停止。 |
wireguard: tunnel driver stopped, rebuilding |
下一个连接发现隧道已停止,katana 启动一个新隧道。 |
握手成功的隧道在 info 级别不记录任何内容,无论流量是否通过。请按以下步骤排查:
-
在 katana 之外测试上游。 在一个临时的 etemenanki-app 中运行同样的隧道,配一个回环地址上的 SOCKS 入站,并通过它访问一个 IP 回显服务。出站给出了步骤和现成的配置。这不会影响正在运行的 katana。
-
第一次请求失败时重试一次。 新隧道的第一个连接要等待 WireGuard 握手,而且某些服务上用新签发密钥建立的第一个连接会失败。判定密钥失效之前先重试一次:第一次请求超时、第二次成功,说明配置没有问题。
-
不要只看握手。 握手成功只说明对端认识你的公钥,不说明服务仍会为它转发流量:有些服务会为已不再接受的密钥完成握手,然后丢弃所有数据包。只有返回上游出口地址的请求才能证明密钥有效。如果握手成功但没有流量通过,请先从服务商那里获取新的密钥或配置。
-
阅读隧道自身的日志。 在 katana 或临时的 etemenanki-app 中打开 WireGuard 相关的 target:
终端窗口 RUST_LOG=info,boringtun=debug,etemenanki_protocols::wireguard=debug反复出现
Sending handshake_initiation而没有Received handshake_response,说明对端没有响应:检查server、port、public_key、pre_shared_key和reserved,并确认允许出站 UDP。出现Received handshake_response和New session之后仍然超时,说明隧道已建立但对端不转发。WireGuard 完整解释了这些日志行。 -
如果小请求正常而大请求卡住,请调低
mtu,例如调到1280。
面板请求错误
Section titled “面板请求错误”面板错误日志行只写出失败的请求,不写原因:
WARN katana::manager::node: node 1: node_info: GET /api/v1/server/UniProxy/configkatana 只写出错误最外层的描述:方法和路径。它省略面板的主机名、带有密钥的查询字符串,以及底层原因,例如连接被拒绝、超时或 HTTP 状态码。因此同一行日志可能对应 host 错误、面板无法访问、请求慢于 api.timeout,以及任何 4xx 或 5xx 响应。请手动发送请求确认是哪一种。
node <node_id>: 之后的内容 |
请求 |
|---|---|
node_info failed: …; retrying in <N>s(节点启动过程中,ERROR)或 node_info: …(轮询时,WARN) |
节点设置 |
user_list failed: …; retrying in <N>s(节点启动过程中,ERROR)或 user_list: …(轮询时,WARN) |
用户列表 |
report traffic: … |
流量上报 |
node_rule: … |
SSPanel 审计规则 |
report illegal: … |
SSPanel 检测日志 |
冒号之后的部分说明请求进行到了哪一步:
| 结尾 | 含义 |
|---|---|
GET /api/v1/server/UniProxy/config、GET /mod_mu/users、POST UniProxy push、POST /mod_mu/users/traffic |
没有可用的响应:网络或 TLS 错误、超时,或 HTTP 错误状态码。 |
GET /mod_mu/users body 等以 body 结尾的形式 |
katana 读取响应时响应中断了。 |
parse UniProxy config response、parse UniProxy user response、parse /mod_mu/users、parse sspanel user list 等 |
面板有响应,但不是 katana 期望的 JSON:常见的是 HTML 错误页面、panel_type 设成了另一种面板,或在 Xboard 上有用户没有限速。 |
/mod_mu/users: panel returned ret=0 等 |
SSPanel 有响应,但拒绝了请求。 |
各种失败的后果:
- 节点启动过程中,节点设置或用户请求失败会让节点等待后重试:见节点始终没有启动。
- 轮询时,katana 保留最后一次收到的设置和用户。不会拆除任何东西,下一次轮询会重试。
- 流量上报失败时,计数保留到下一次上报,不会丢失。
- 检测日志上报失败时,该日志被丢弃。
api.timeout 是每个请求的时限,单位为秒;0 或不设置表示 5 秒。经常较慢的面板需要更大的值。保存的修改立即生效:katana 原地重建节点的面板客户端,并保留节点的连接。
握手失败告警
Section titled “握手失败告警”WARN katana::manager::proxy: node V2ray_0.0.0.0_443: 37 inbound handshake failures in the last 1s (possible handshake scan/DoS or misconfigured clients)每个基于 TCP 的节点都会统计在客户端完成认证之前失败的连接,并每秒检查一次计数。某一秒超过 10 次时,katana 写出这条警告。计入的有:
- 在第一个流之前失败的传输层握手:TLS、WebSocket 升级、gRPC 的 HTTP/2 preface;
- 失败的协议握手:未知用户、格式错误的请求、提前关闭或 10 秒内未完成握手的客户端;
- 因节点达到活动连接数或预认证限制而被拒绝的连接。
这条警告只是告警:katana 不会因此拦截任何东西。Hysteria 2 节点不统计失败次数,也从不写出这条警告。
它通常意味着:
| 模式 | 可能的原因 | 怎么办 |
|---|---|---|
| 在面板中修改节点的传输层、TLS 或协议后立即出现一阵 | 客户端仍在使用旧设置。 | 无需处理,或让用户刷新订阅。 |
| 全天持续出现,来自大量地址 | 互联网扫描器在探测端口。 | 通常无害。如果在意这些噪音,可在主机防火墙中对新连接做速率限制。 |
| 所有客户端都失败,告警持续不断,没有人能连接 | 影响所有人的不匹配:node_type、enable_vless、证书或时钟。 |
见客户端无法连接。 |
计数非常高,debug 日志显示 pre-auth limit reached 或 live connection limit reached |
节点触及了连接护栏。 | 见连接护栏。 |
要查看失败的原因,打开 katana::serve=debug 一分钟,阅读 inbound handshake failed 和 inbound transport ended 日志行,方法见客户端无法连接。