katana
katana 是一个兼容 XrayR 的代理节点 agent,构建在 Etemenanki 内核之上。它支持 XrayR 所支持的面板 API 中的两种:UniProxy 和 SSPanel 的 mod_mu。它的 [node.api] 和 [node.controller] 中的键是 XrayR ApiConfig 和 ControllerConfig 的 snake_case 子集(host 对应 ApiHost,node_id 对应 NodeID,update_periodic 对应 UpdatePeriodic,依此类推)。你只需把它指向一个面板(Xboard、V2board 或 SSPanel),并给出节点 ID。katana 会向面板询问节点的配置以及哪些用户可以使用它,然后提供该节点的服务,让每个用户都遵守各自的限速和面板的审计规则,并把每个用户的流量上报给面板。
本页是一张总览图。它展示 katana 的各个组成部分,列出支持的面板和协议,划清哪些由面板决定、哪些由你的配置文件决定,并说明 katana 有意不提供的功能。在写第一个 [[node]] 之前请先读本页;katana 部分的其余页面会逐一详细介绍各个部分。
katana 的工作方式
Section titled “katana 的工作方式”一个 katana 进程可以服务一个或多个节点。配置文件中的每个 [[node]] 都有自己的节点管理器,它维护自己与面板的连接、自己的监听器和自己的路由表。所有节点共享同一个出站池和同一个 DNS 解析器。
flowchart TB
Panel["面板:UniProxy 或 mod_mu"]
Client["客户端"]
Dest["目标地址"]
subgraph K["katana"]
NM["节点管理器"]
L["监听器:TCP、TLS、WebSocket、gRPC 或 QUIC"]
Core["协议核心"]
Adm["用户准入"]
R["路由器"]
A["审计规则"]
M["计量器:限速与字节计数"]
Pool["出站池"]
end
Panel -- "节点信息、用户、审计规则" --> NM
NM -- "流量、审计命中(SSPanel)" --> Panel
NM -. "构建监听器、替换用户表" .-> L
Client --> L --> Core --> Adm --> R --> A --> M --> Pool --> Dest
M -. "每用户字节数" .-> NM
两个循环并行运行。
- 控制循环。 每隔
update_periodic秒(默认60),节点管理器从面板拉取节点设置和用户列表,应用其中的变化,刷新审计规则,并上报自上次上报以来统计的流量。 - 数据路径。 客户端连接到节点的监听器。监听器剥离传输层(TLS、WebSocket、gRPC,或 Hysteria 2 使用的 QUIC),把字节交给协议核心,协议核心根据面板提供的用户表认证用户。之后客户端打开的每个流,无论是一个 TCP 请求、一个 mux 子流还是一个 UDP 关联,都要依次经过以下阶段。UDP 包逐个进行路由和审计。
- 准入检查该用户是否仍在节点当前的用户列表中。已被面板移除的用户会被拒绝,其已打开的连接也会被结束。
- 路由器根据节点的
[node.route]规则选择一个出站。被路由到block的流会被拒绝。 - 审计规则在流的目标主机(域名或 IP,不含端口)匹配其中任意一条时拒绝该流,并记录这次命中。
- 计量器包裹出站连接。它统计用户的上传和下载字节数,并按用户的限速控制速率。同一用户在该节点上的所有流共享一个限速。
- 出站连接到目标地址:直连,或经由
[[outbound]]中配置的上游代理或 WireGuard 隧道。
katana 在应答客户端的 TCP 请求之前先拨号目标地址:VMess 和 VLESS 只有在目标连接建立后才发送响应头。如果拨号失败,或者路由器或审计规则拒绝了该流,这个请求就会直接结束;在 mux 连接中,只有对应的子流结束。Trojan 和 Shadowsocks 不发送应答,因此对它们来说,被拒绝的请求会关闭整个连接。
配置文件中的一个节点
Section titled “配置文件中的一个节点”下面是 Xboard 面板上一个节点的完整配置。注意其中没有的内容:没有端口,没有协议设置,也没有用户。这些全部由面板提供。
# 为 Xboard 面板提供服务的一个节点。端口、传输层、TLS 开关和# 用户都来自面板;本文件只说明如何连接面板。[[node]]panel_type = "NewV2board" # Xboard 和 V2board(UniProxy API)
[node.api]host = "https://panel.example.com"node_id = 1key = "replace-with-the-panel-key"node_type = "V2ray" # 面板上的节点是 VMess 节点
[node.controller]listen_ip = "0.0.0.0"update_periodic = 60 # 轮询面板和上报的间隔秒数
[node.controller.cert] # 仅在面板开启 TLS 时使用mode = "file"cert_file = "/etc/katana/fullchain.pem"key_file = "/etc/katana/privkey.pem"
[node.route]default = "direct"katana --test -c /etc/katana/config.toml 会检查该文件并输出 Configuration OK。它会构建出站、每个节点的面板客户端和路由表,并检查 Hysteria 2 节点的本地 [node.hysteria] 设置,但不会绑定任何端口,也不会连接面板。面板将下发的内容要到节点启动时才会检查。配置文件页面介绍了每一个键。
panel_type 选择面板 API。katana 比较时不区分大小写,因此 NewV2board、newv2board 和 NEWV2BOARD 是等价的。
| 面板 | panel_type |
katana 调用的 API | katana 接受的节点类型 |
|---|---|---|---|
| Xboard、V2board | NewV2board 或 V2board |
UniProxy:GET /api/v1/server/UniProxy/config、GET …/user、POST …/push |
V2ray(VMess 或 VLESS)、Trojan、Shadowsocks、Hysteria 2 |
| SSPanel | SSpanel |
mod_mu:/mod_mu/nodes/{node_id}/info、/mod_mu/users、/mod_mu/users/traffic、/mod_mu/func/detect_rules、/mod_mu/users/detectlog |
V2ray(VMess 或 VLESS)、Trojan、Hysteria 2 |
V2board是NewV2board的别名;两者都使用 UniProxy 客户端。- 其他任何值都会让
--test失败并报configuration error: unknown panel_type "xboard"(显示的值会转为小写)。启动时 katana 会记录同样的错误,跳过该节点并启动其他节点;只有在没有任何节点能启动时才会退出。 - 两种客户端都会在
If-None-Match中带上面板上次返回的ETag。当面板返回304 Not Modified时,katana 保留已有的节点设置、用户列表或规则。 - SSPanel 的 Shadowsocks 节点会在节点启动时被拒绝(
sspanel: Shadowsocks node type is not supported)。SSPanel 上的 Hysteria 2 节点必须来自面板的custom_config(旧式server字符串无法描述 Hysteria 2 节点),或者通过[node.hysteria].port在本地描述。
各面板的专页列出了 katana 读取的每个字段:Xboard 和 V2board以及 SSPanel。
[node.api].node_type 告诉 katana 面板描述的是哪种节点。比较时不区分大小写。其他任何值都会让 --test 失败并报 unknown node_type "…",启动时该节点也会因同样的错误被跳过。
node_type |
提供的协议 | 传输层 | TLS | UDP |
|---|---|---|---|---|
V2ray(也可写 vmess、vless) |
使用 AEAD 头的 VMess,或不带 flow 的 VLESS | TCP、WebSocket、gRPC | 可选,由面板决定 | 在连接内承载,包括 mux.cool 和 XUDP |
Trojan |
Trojan;每个用户的密码就是其 UUID | UniProxy:TCP。SSPanel:custom_config 可指定 TCP、WebSocket 或 gRPC,旧式 server 字符串可指定 TCP 或 gRPC |
始终启用 | 在连接内承载 |
Shadowsocks |
AEAD(SIP004)或 Shadowsocks 2022 多用户(SIP022),由面板的加密方式决定 | TCP | 无 | 不提供:katana 不会为 Shadowsocks 绑定 UDP socket |
Hysteria2(也可写 hysteria、hy2) |
基于 QUIC 的 Hysteria 2 | UDP 上的 QUIC | 始终启用,位于 QUIC 内 | 当 [node.hysteria].udp = true 时提供 |
- 当
[node.api].enable_vless = true,或 SSPanel 的custom_config中有enable_vless = "1"时,V2ray 节点提供 VLESS 而不是 VMess。 - VMess、VLESS 和 Trojan 节点接受客户端的 mux.cool;Shadowsocks 节点不接受。每个 mux 子流都单独进行路由、审计和计量,它们共同占用该用户的同一个限速。
- 来自面板的传输层名称不区分大小写:
tcp或raw、ws或websocket、grpc或gun。空值表示 TCP。 - TLS 节点或 Hysteria 2 节点需要
[node.controller.cert].mode = "file",并提供 PEM 格式的证书和私钥文件。
协议页面介绍了每种协议的设置和客户端要求,Hysteria 2 页面介绍了本地的 [node.hysteria] 表。
哪些由面板决定,哪些由你决定
Section titled “哪些由面板决定,哪些由你决定”katana 把节点的设置分成两部分。凡是客户端必须与服务端一致的内容,以及按用户变化的内容,都归面板管理。凡是与这台机器和这位运维者相关的内容,都归你的配置文件管理。
| 设置 | 来源 | 说明 |
|---|---|---|
| 监听端口 | 面板 | UniProxy 的 server_port;SSPanel custom_config 中的 offset_port_node,或旧式 server 字符串。在本地描述的 Hysteria 2 节点使用 [node.hysteria].port |
| 传输层 | 面板 | V2ray 节点和 SSPanel Trojan 节点的 network:TCP、WebSocket 或 gRPC。UniProxy Trojan 节点始终为 TCP |
WebSocket 路径和 Host、gRPC 服务名 |
面板 | VMess 使用 UniProxy 的 networkSettings,VLESS 使用 network_settings;SSPanel 的 path、host 和 servicename |
| TLS 开关 | 面板 | V2ray 节点:UniProxy 的 tls = 1,SSPanel 的 security = "tls" 或 "xtls",或旧式 server 字符串中的 tls。Trojan 和 Hysteria 2 始终使用 TLS |
| Shadowsocks 加密方式和服务端密钥 | 面板 | UniProxy 的 cipher 和 server_key |
| 用户 | 面板 | 允许使用该节点的每个用户的 ID 和 UUID |
| 每用户限速 | 面板 | 每个用户的 speed_limit(UniProxy)或 node_speedlimit(SSPanel),单位 Mbps |
| 节点限速 | 面板 | 仅 SSPanel:节点的 node_speedlimit |
| 审计规则 | 面板,外加一个本地文件 | UniProxy:节点 routes 中 action = "block" 的条目。SSPanel:/mod_mu/func/detect_rules |
| Hysteria 2 混淆 | 面板 | obfs 和 obfs-password,除非你用 [node.hysteria].port 在本地描述该节点 |
| 面板连接 | 本地 | panel_type,以及 [node.api] 中的 host、node_id、key、node_type 和 timeout(默认 5 秒) |
| VMess 或 VLESS | 本地 | [node.api].enable_vless;SSPanel 也可以通过 custom_config 开启 VLESS |
| 证书 | 本地 | [node.controller.cert]。不读取面板的 tls_settings 和证书设置 |
| 监听地址 | 本地 | [node.controller].listen_ip,默认 "0.0.0.0" |
| 轮询和上报间隔 | 本地 | [node.controller].update_periodic,默认 60 秒。不读取面板的推送和拉取间隔 |
| 出站 | 本地 | [[outbound]],由所有节点共享 |
| 路由 | 本地 | [node.route],每个节点一张表 |
| DNS | 本地 | [dns],由所有节点共享 |
| 限速覆盖 | 本地 | [node.api].speed_limit,单位 Mbps。大于 0 时,它会替换每个用户在面板上的限速,在 SSPanel 上还会替换节点限速 |
| 本地审计规则 | 本地 | [node.api].rule_list_path,每行一个正则表达式;空行和以 # 开头的行会被跳过。katana 与面板规则一起读取该文件,因此 disable_get_rule = true 也会关闭本地规则 |
| 嗅探、规则拉取、流量上传 | 本地 | [node.controller] 中的 disable_sniffing、disable_get_rule、disable_upload_traffic |
| Hysteria 2 监听器 | 本地 | [node.hysteria]:credential、udp、udp_idle_timeout 和 masquerade;对于在本地描述的节点,还有 port、obfs 和 obfs_password |
当用户同时有节点限速和用户限速时,取两者中较小的非零值。限速单位是兆比特每秒;katana 把 1 Mbps 换算为每秒 125 000 字节。限速页面解释了限速是如何执行的。
节点的生命周期
Section titled “节点的生命周期”-
启动。 节点管理器拉取节点设置和用户列表,构建并绑定监听器。用户列表为空的节点在出现用户之前不绑定任何端口。启动的任何一步失败,katana 都会重试,详见列表后的说明。监听器启动后,katana 会记录:
2026-09-24T20:22:05.118204Z INFO katana::manager::node: node 1: listening on 0.0.0.0:443 -
轮询。 节点启动完成后经过一个完整的
update_periodic周期,以及此后的每个周期,节点管理器都会执行一轮:拉取节点设置,拉取用户,应用变化,刷新审计规则,上报流量,上报审计命中。拉取失败时,保留上一次可用的设置和用户。节点设置中的端口为0时,保留上一次的节点设置,但这一轮拉到的用户照常生效。流量上报失败时,计数会保留到下一轮。配置文件的修改被接受后,如果它影响该节点的面板客户端或监听器,节点会立即执行一轮,而不等待定时器。 -
变更。 变更的代价取决于改了什么:
-
增删用户或修改限速:katana 原地替换用户表。保留下来的用户的连接不受影响,新的限速作用于变更之后打开的流;被移除用户的连接会被结束。如果用户列表变为空,katana 会关闭监听器。
-
新的端口、传输层、路径、TLS 设置、加密方式或混淆:katana 重建监听器,这会断开该节点上的所有连接。
-
修改 katana 自己的配置文件:katana 无需重启即可应用。
- 新的监听地址、证书、
enable_vless、disable_sniffing、[node.hysteria]设置、路由规则或出站会重建监听器。 [node.api]中的其他修改,例如speed_limit、rule_list_path或timeout,通过新的面板客户端在线生效,新客户端会立即重新拉取节点设置和用户。只有当拉取结果改变了会重建监听器的面板设置(例如端口或传输层)时,才会断开连接。- 新的
panel_type、host、node_id或key指向面板上的另一个节点,因此 katana 会停止该节点并重新启动它。在 Xboard 和 V2board 上,如果修改node_type改变了 katana 请求的类型(只改大小写不算),或者在V2ray、Vmess节点上修改enable_vless,也会如此,因为 UniProxy 除了按 ID,还按请求的类型查找节点。 - 如果修改后的文件中出站或任一节点无法构建(例如
node_type未知),katana 会拒绝整次重载,所有节点都按原样继续运行。如果某个节点的修改导致其路由规则无法构建,则只拒绝该节点的修改,该节点保留正在运行的设置。 - 只修改
[dns]不会生效。
热重载页面列出了每种修改的效果。
- 新的监听地址、证书、
-
-
停止。 收到
SIGINT或SIGTERM时,每个节点关闭自己的监听器,最后上报一次剩余的流量和审计命中,然后退出。
katana 不做的事
Section titled “katana 不做的事”对于下表中节点可能请求的功能,katana 会拒绝该节点,而不是悄悄降级处理:节点启动或重建失败,错误信息中会指明该功能。表格之后的警告列出了 katana 既不提供也不拒绝的面板设置。
| 功能 | katana 的处理方式 |
|---|---|
ACME 证书(cert.mode = "dns"、"http" 或 "tls") |
拒绝该节点:node requests kernel-unsupported feature: ACME cert mode "dns"。Hysteria 2 节点则报 hysteria2 node requires cert.mode = "file"。请自行申请和续期证书,并使用 mode = "file"。 |
| REALITY | 拒绝面板设置要求 REALITY 的节点(UniProxy V2ray 的 tls = 2,SSPanel custom_config 中的 enable_reality):node requests kernel-unsupported feature: REALITY。 |
| XTLS flow | 拒绝 flow 非空的节点,无论 flow 来自面板,还是在使用旧式 SSPanel server 字符串时来自 [node.api].vless_flow:node requests kernel-unsupported feature: VLESS XTLS flow。 |
httpupgrade、splithttp 和 xhttp 传输层 |
拒绝该节点,例如 node requests kernel-unsupported feature: httpupgrade transport。其他未知传输层也以同样方式拒绝。 |
cert.reject_unknown_sni = true |
拒绝该节点:node requests kernel-unsupported feature: cert.reject_unknown_sni。 |
| 在线用户和在线 IP | 不上报。katana 从不调用 UniProxy 的 alive 或 alivelist,也不调用 SSPanel 的 /mod_mu/users/aliveip,因此面板上看不到该节点的在线用户。 |
| 设备数限制 | 不执行。[node.api].device_limit 会被接受但忽略,也不读取面板上的每用户设备数限制。 |
| 出站源地址 | 不生效。[node.controller].send_ip 会被接受但忽略;出站连接使用主机路由表选出的地址。 |
| 节点状态 | 不上报。katana 从不发送 UniProxy 的 status 或 SSPanel 的节点状态,因此面板上看不到 CPU、内存或磁盘数据。Xboard 仍会在每次拉取用户列表时记录节点的签到。 |
| 向 UniProxy 面板上报审计命中 | UniProxy API 没有对应的接口。katana 仍会拒绝这些流。只有 SSPanel 会收到命中记录,而且仅限其自身的 detect_rules;本地 rule_list_path 规则的命中从不上报。 |
| Hysteria 2 Brutal 拥塞控制 | 未实现。面板的 up_mbps 和 down_mbps 会被忽略;每用户限速由计量器负责。 |
| Shadowsocks 插件 | 不支持。UniProxy 的 obfs 值不是空、plain 或 none 时,节点会失败并报 newV2board: shadowsocks obfs "…" is not supported。 |
katana 文档导览
Section titled “katana 文档导览”| 页面 | 适合在你想要…时阅读 |
|---|---|
| 快速开始 | 对接面板,启动第一个节点 |
| 配置文件 | 查找任意键及其类型和默认值 |
| Xboard 和 V2board | 为 UniProxy 配置面板一侧,并了解 katana 读取哪些字段 |
| SSPanel | 配置 custom_config 或旧式 server 字符串 |
| 节点 | 在一个进程中运行多个节点,选择端口和监听地址 |
| 协议 | 提供 VMess、VLESS、Trojan 或 Shadowsocks 服务,并配置 TLS 证书 |
| Hysteria 2 | 提供 Hysteria 2 节点服务,节点来自面板或在本地描述 |
| 出站 | 让流量经由上游代理或 WireGuard 隧道发出 |
| 路由 | 用域名、CIDR、端口、GeoIP 和 GeoSite 编写 [node.route] 规则 |
| 限速 | 了解每用户和每节点限速以及限速覆盖 |
| 审计规则 | 用面板规则或本地规则屏蔽目标地址 |
| 流量上报 | 了解流量何时、以何种方式上报到面板 |
| 热重载 | 修改正在运行的 katana 的配置 |
| 部署 | 把 katana 安装为系统服务 |
| 从 XrayR 迁移 | 转换 XrayR 配置 |
| 故障排查 | 解读错误信息,或排查无法启动的节点 |