weztermtls_clients配置详解:基于 TLS 域的多路复用安全连接
【免费下载链接】weztermA GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust项目地址: https://gitcode.com/GitHub_Trending/we/wezterm
tls_clients是 wezterm 配置中用于定义TLS 多路复用域(TLS multiplexing domain)客户端的核心配置项。通过它,你可以让本地 wezterm GUI 经由 TLS 加密的 TCP 连接,接入运行在远程主机上的 wezterm mux server,从而获得与本地一致的分屏、标签页、剪贴板与滚动回看体验,且整个通道默认由 TLS 保护。读完本文,你将掌握tls_clients的全部字段语义、两种证书获取方式(SSH 引导与手动分发)、与服务端tls_servers的完整对接方法,并能通过源码理解连接建立与自动重连的底层流程。
什么是 TLS 域(TLS Domain)
wezterm 的多路复用功能围绕multiplexing domains展开。一个 domain 代表一组独立的窗口与标签页集合;wezterm 启动时默认创建一个local domain管理本机 UI,同时允许你额外配置并接入其他 domain,例如通过 Unix socket 连接的 Unix Domain、通过 SSH 通道连接的 SSH Domain,以及本文讨论的TLS Domain——经由 TLS 加密 TCP 连接接入的远程多路复用域,详见 multiplexing 总览。
从 multiplexing.md 可知:自版本20200202-180558-2489abf9起,wezterm 支持先通过一次 SSH 连接在远端启动 wezterm multiplexer 并安全地获取密钥,完成bootstrap;之后客户端与服务器之间的通信全部走 TLS 保护的 TCP 连接,不再依赖 SSH 通道。
与 Unix Domain 相比,TLS Domain 的核心差异在于跨主机且加密:Unix Domain 依赖本机(或同机互通的 AF_UNIX)socket,而 TLS Domain 面向局域网乃至广域网环境,服务端在指定host:port上监听,客户端据此发起加密连接。
tls_clients与TlsDomainClient
tls_clients接受一个 TlsDomainClient 对象列表。该配置项在 config/src/config.rs 中被声明为:
/// The set of tls domains that we can connect to as a client #[dynamic(default)] pub tls_clients: Vec<TlsDomainClient>,而TlsDomainClient结构体的完整字段定义位于 config/src/tls.rs。注意,配置加载时会调用check_domain(&d.name, "tls domain")(见 config/src/config.rs),因此每个 TLS 客户端的name必须满足 domain 名称校验规则,且在配置文件中所有类型的 domain 之间保持唯一。
最小可用的客户端配置
参考 multiplexing.md,一个最简配置如下:
config.tls_clients = { { -- 本 domain 的别名;后续用 `wezterm connect server.name` 连接 name = 'server.name', -- 远端主机的 host:port remote_address = 'server.hostname:8080', -- 取值可以是 "user@host:port",与 `wezterm ssh` 子命令接受的语法一致 bootstrap_via_ssh = 'server.hostname', }, }这里bootstrap_via_ssh是**通过 SSH 引导(bootstrap)**的关键开关:连接时 wezterm 会先通过 SSH 在远端启动 mux server,并获取一份用于 TLS 通信的客户端证书,随后自动切换到 TLS 通道。配置完成后,在客户端执行:
$ wezterm connect server.name即可连接:连接窗口会展示进度,并可能提示你进行 SSH 认证。一旦通过 bootstrap 拿到证书,如果连接中途被中断,wezterm 会自动用该证书重新连接并恢复远程终端会话。
全部字段速查(来自 TlsDomainClient.md)
以下是TlsDomainClient的完整字段说明(源码对应 config/src/tls.rs):
config.tls_clients = { { -- 本 domain 名称,须在所有类型 domain 中唯一 name = 'server.name', -- 若设置,则通过 ssh 连接、启动服务端并获取证书。 -- 取值为 "user@host:port",与 "wezterm ssh" 接受的语法一致。 bootstrap_via_ssh = 'server.hostname', -- 远端服务器的 host:port 对 remote_address = 'server.hostname:8080', -- x509 PEM 编码的私钥文件路径。 -- 使用 bootstrap_via_ssh 时请省略。 -- pem_private_key = "/some/path/key.pem", -- x509 PEM 编码的证书文件路径。 -- 使用 bootstrap_via_ssh 时请省略。 -- pem_cert = "/some/path/cert.pem", -- x509 PEM 编码的 CA 链文件路径。 -- 使用 bootstrap_via_ssh 时请省略。 -- pem_ca = "/some/path/ca.pem", -- 额外加载的 CA 证书路径集合。 -- 每个条目可以是目录或 PEM 编码的 CA 文件;若为目录, -- 其内容会被当作 CA 证书加载进信任库。 -- 使用 bootstrap_via_ssh 时请省略。 -- pem_root_certs = { "/some/path/ca1.pem", "/some/path/ca2.pem" }, -- 是否校验服务端证书与 remote_address 中主机名一致。默认 true。 -- 该选项仅为排障提供,不应在受控环境之外使用, -- 因为它会削弱 TLS 通道的安全性。 -- accept_invalid_hostnames = false, -- 期望与服务端证书 Common Name 字段匹配的主机名字符串。 -- 默认取 remote_address 的主机名部分,通常无需覆盖。 -- expected_cn = "other.name", -- 若为 true,wezterm 启动时自动连接该 domain。 -- connect_automatically = false, -- 指定替代的读超时 -- read_timeout = 60, -- 指定替代的写超时 -- write_timeout = 60, -- 远端主机上 wezterm 二进制文件的路径 -- remote_wezterm_path = "/home/myname/bin/wezterm" }, }补充几个从源码确认的细节:
name字段带有#[dynamic(validate = "validate_domain_name")]校验(config/src/tls.rs),配置不合法会在加载期直接报错;read_timeout与write_timeout的默认值均为 60 秒(default_read_timeout/default_write_timeout,见 config/src/config.rs);remote_wezterm_path用于指定远端 wezterm 二进制的位置;当远端不在标准安装路径时很有用,bootstrap 阶段执行远程命令时会使用它(见下文源码分析)。
手动分发证书(不使用 SSH 引导)
如果远端 mux server 不希望暴露 SSH 端口,或者你想完全控制证书体系,可以不设置bootstrap_via_ssh,改为由你自行分发 PEM 私钥、证书与 CA 链。此时客户端显式指定:
config.tls_clients = { { name = 'server.name', remote_address = 'server.hostname:8080', pem_private_key = '/path/to/client-key.pem', pem_cert = '/path/to/client-cert.pem', pem_ca = '/path/to/ca.pem', -- pem_root_certs = { '/path/to/extra-ca.pem' }, -- 可选追加信任库 }, }这种方式下,TLS 握手完全由 openssl 依据你提供的 PEM 文件完成,不涉及远程命令执行。注意 TlsDomainClient.md 明确提示:使用bootstrap_via_ssh时应省略这三类 PEM 字段,二选一即可。
客户端连接的底层流程
客户端的 TLS 连接实现在 wezterm-client/src/client.rs 的tls_connect方法中,其执行顺序清楚地印证了文档描述:
- 优先复用已有凭证:如果配置了
bootstrap_via_ssh且本地已缓存凭据,先尝试直接用 TLS 连接远端(try_connect)。只有当连接被拒绝(ConnectionRefused,即服务端尚未启动)时,才回退到 SSH bootstrap;其他 IO 错误则直接向上抛出,因为此时重试 SSH 引导大概率也会失败。 - SSH bootstrap:当本地还没有 TLS 凭据(
self.tls_creds.is_none())时,通过wezterm_ssh::Config读取默认 SSH 配置文件(add_default_config_files),用bootstrap_via_ssh中的host[:port]与username构造连接;成功后执行远程命令:wezterm cli tlscreds该命令对应 wezterm/src/cli/tls_creds.rs,会从 mux server 请求一份凭据响应
GetTlsCredsResponse(内含 CA 证书与服务端签发的客户端证书),并将其写入本地磁盘缓存路径,供 openssl 加载。远程二进制路径由remote_wezterm_path决定(Self::wezterm_bin_path(...))。 - 建立 TLS 流:bootstrap 完成后,再次调用
try_connect,用remote_address解析出的主机名与端口建立AsyncSslStream(SslConnector::builder(SslMethod::tls()),见 wezterm-client/src/client.rs),替换连接流后完成接入。
从 wezterm/src/cli/tls_creds.rs 的注释可知:这些凭据在 mux server 进程存活期间有效,且持有凭据的人可以直接通过网络连接 mux server 并启动 shell,无需额外认证——务必像对待密钥一样妥善保管。
ClientDomainConfig枚举在 wezterm-client/src/domain.rs 中区分Unix、Tls、Ssh三种客户端域,new_tls则负责从配置构造一个带自动重连能力的 TLS 客户端域(wezterm-client/src/client.rs)。
与服务端tls_servers的对接
tls_clients是客户端视角的配置,与之对应的是服务端配置项tls_servers。服务端配置同样在 config/src/config.rs 中声明:
/// When running in server mode, defines configuration for /// each of the endpoints that we'll listen for connections #[dynamic(default)] pub tls_servers: Vec<TlsDomainServer>,服务端定义(结构体见 config/src/tls.rs,文档见 TlsDomainServer.md):
config.tls_servers = { { -- 服务端监听客户端连接的 address:port bind_address = 'server.hostname:8080', -- x509 PEM 编码的私钥文件路径。 -- 若客户端使用 bootstrap_via_ssh,可省略。 -- pem_private_key = "/path/to/key.pem", -- x509 PEM 编码的证书文件路径。 -- 若客户端使用 bootstrap_via_ssh,可省略。 -- pem_cert = "/path/to/cert.pem", -- x509 PEM 编码的 CA 链文件路径。 -- 若客户端使用 bootstrap_via_ssh,可省略。 -- pem_ca = "/path/to/chain.pem", -- 额外加载的 CA 证书路径集合(目录或 PEM 文件)。 -- 若客户端使用 bootstrap_via_ssh,可省略。 -- pem_root_certs = { "/some/path/ca1.pem", "/some/path/ca2.pem" }, }, }两种对接模式对比
| 模式 | 客户端字段 | 服务端字段 | 适用场景 |
|---|---|---|---|
| SSH 引导 | bootstrap_via_ssh(必填),PEM 字段省略 | 服务端 PEM 字段可省略 | 首次接入自动分发证书、无需手动运维 PKI,最省事 |
| 手动 PKI | pem_private_key/pem_cert/pem_ca | pem_private_key/pem_cert/pem_ca(pem_ca为 CA 链) | 不想开放 SSH 端口、需要自建 CA 信任体系的受控网络 |
在 SSH 引导模式下,客户端通过远程执行wezterm cli tlscreds从服务端取得凭据,因此服务端必须运行一个兼容版本的 wezterm(mux server 即wezterm-mux-server,其入口在 wezterm-mux-server/src/main.rs,负责加载配置并启动监听器spawn_listener),这与 multiplexing.md 对 SSH Domain 提出的要求一致。
延迟优化与运维进阶
预测式本地回显(Predictive Local Echo)
自版本20220319-142410-0fcdea07起,TLS 客户端支持配置local_echo_threshold_ms:当实测的客户端与服务器往返延迟超过该阈值(毫秒)时,客户端会尝试预测服务器对按键事件的响应并在本地直接回显,从而对用户隐藏网络延迟。该选项仅在multiplexing = "WezTerm"模式下生效。默认阈值为 100ms(default_local_echo_threshold_ms,见 config/src/config.rs)。示例:
config.tls_clients = { { name = 'server.name', bootstrap_via_ssh = 'server.hostname', remote_address = 'server.hostname:8080', local_echo_threshold_ms = 10, }, }延迟指示器(Lag Indicator)
自版本20221119-145034-49b9839f起,延迟指示器默认关闭。官方推荐在状态栏中展示延迟信息,示例见 pane/get_metadata.md(利用since_last_response_ms);若你更偏好旧式的内容区浮层,可以设置:
config.tls_clients = { { name = 'server.name', bootstrap_via_ssh = 'server.hostname', remote_address = 'server.hostname:8080', overlay_lag_indicator = true, }, }但 TlsDomainClient.md 明确提示作者未来可能移除overlay_lag_indicator这一功能,建议新配置直接采用状态栏方案。
与 SSH 域、Unix 域的取舍
结合 multiplexing.md 可作如下选择:
- 同机或 WSL 互通:优先 Unix Domain,零加密开销,支持
proxy_command、local_echo_threshold_ms等; - 通过 SSH 通道接入远端:使用 SSH Domain(
config.ssh_domains),远端同样需安装兼容版本 wezterm; - 跨网络、希望获得独立于 SSH 的长连接通道:使用
tls_clients+tls_servers的 TLS Domain 组合,TLS 加密保护数据,bootstrap 过程完成一次性的证书分发。
无论选择哪种 domain,连接命令都是统一的wezterm connect <domain-name>,或通过wezterm cli spawn --domain-name <domain-name>在现有 GUI 实例的新标签页中接入。启动时自动连接某个 TLS domain 可设置connect_automatically = true;不过对于其他 domain 类型,multiplexing.md 推荐用default_gui_startup_args = { 'connect', '<domain>' }替代旧式的connect_automatically,它工作更可靠。
安全注意事项
- 凭据即通行证:bootstrap 获取的 TLS 凭据在整个 mux server 进程生命周期内有效,任何持有者都能直连服务器启动 shell(wezterm/src/cli/tls_creds.rs)。请勿将其写入公开渠道或提交到版本库。
- 主机名校验:
accept_invalid_hostnames默认false(见 config/src/tls.rs),保持默认即会校验服务端证书与remote_address主机名一致;expected_cn用于在特殊场景(如 IP 直连、证书 CN 与主机名不一致)下指定期望的 Common Name。这两项仅在排障或受控环境下才考虑修改。 - 端口选择:示例中使用
8080,实际生产环境建议改用未被占用的高位端口,并配合防火墙限制来源 IP,避免 mux server 暴露给不可信网络。
【免费下载链接】weztermA GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust项目地址: https://gitcode.com/GitHub_Trending/we/wezterm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考