踢掉一个 OpenVPN 客户端:杀掉、拒绝还是吊销证书?
OpenVPN 的三个操作都能移除客户端,但各自终止的东西不同:正在运行的会话、一次登录尝试,或重新连接的权利。按身份来选择。
你的笔记里有一个 common name 和一个地址,还有三条看起来都在移除客户端的命令。只有一条能做到你要的效果,而选择取决于你是要结束当前正在运行的会话、拒绝下一次登录,还是彻底收回连接的权利。动手之前先读清你真正掌握的身份,因为 OpenVPN 的连接池之后会把同一个隧道地址分配给另一个会话。
你实际掌握的是哪种身份
版本 3 的状态文件是常见的起点。CLIENT_LIST 段包含 common name、真实地址、字节计数和连接时间;ROUTING TABLE 段把虚拟地址映射到 common name,并带有最后引用时间戳。common name 才是稳定的身份。虚拟地址只是一种分配,NAT 后面的真实地址可能在不同会话之间变化,而服务器上什么都没有改变。
管理接口通过 status 命令给出类似视图,并为每个会话增加一个客户端 ID。client-kill 期待的正是这个 ID,而不是隧道地址。如果你需要知道连接时哪个 common name 拿到了哪个地址,client-connect 脚本的环境里两者都有,还带有可信的外部地址,但该脚本以 OpenVPN 用户身份运行,并且需要可写的日志路径。
| What you hold | Where it came from | What it can act on |
|---|---|---|
| Common name | CLIENT_LIST, or the auth hook | kill, and credential revocation |
| Client ID | status on the management socket | client-kill, that one session |
| Tunnel address | ROUTING TABLE, client-connect environment | Nothing durable, the address is recycled |
立刻杀死、登录时拒绝、永久吊销
管理接口里的两条移除命令都是会话级操作。kill 接受 common name 或真实地址加端口;client-kill 接受客户端 ID 并立即结束那个实例。两者都不是封禁:被踢掉但证书和密码仍然有效的客户端几秒内就会重连,这在回收测试对端时没问题,在笔记本被盗时则毫无用处。
client-deny 是另一种性质的判断。它通常由认证钩子或 client-connect 钩子发出,并带原因拒绝会话,所以它适合拒绝登录的策略,而不适合中断连接的策略。文档还警告说,在 TLS 重新协商期间发出的拒绝会让重新协商的密钥失效,而现有会话可能一直运行到过渡窗口关闭。如果要求是客户端必须立刻消失,文档给出的答案是 client-kill。
持久移除位于这一切之下。吊销证书并确保 crl-verify 指向服务器真正重新加载的列表,禁用 ccd 目录中该客户端专属的配置文件,或者在认证钩子查询的后端里禁用账户。吊销也不是瞬时的:在默认的 reneg-sec 设置下,已建立的会话可以一直运行到重新协商,所以会话操作和凭据操作是互补的,而不是二选一。
管理套接字空闲吗?
管理接口一次只服务一个客户端。如果 GUI 或监控守护进程已经占住连接,你的脚本无法在旁边接入,而且视客户端而定,你可能把现有连接挤掉而不是干净地失败。它的密码在该套接字上明文传输,所以只应放在本地地址或 unix 套接字上,绝不能放在公网接口上。
拿不到套接字时你仍有选择,而且都更慢。先释放 GUI 的会话(如果你能控制它),或者接受凭据层的路线并等待下一次重新协商。不该做的是为了甩掉一个客户端而重启服务,因为那会同时结束其他所有会话,并毁掉这个会话的状态文件证据。
我在生产服务器上执行的顺序
接入、读取当前状态、对刚读到的 ID 动手,然后再读一遍。从文档里抄来的值是杀错人的最常见原因。
status # note the client ID and common name
client-kill 3 # end that session now
kill Test-Client # alternative: by common name
status # confirm the session is gone上面的名字和数字是占位符,ID 在其他客户端断开后会被复用。在把任何事记为完成之前,确认那一行已经消失,并检查已连接客户端的数量是变化了一个而不是好几个。
确认它没有再回来
记录 common name、隧道地址、外部地址和移除的分钟。如果同一个 common name 一分钟后又出现,说明会话操作起了作用而凭据层没有,这与命令从未生效是完全不同的修复。
然后从客户端侧测试。被吊销的证书应该在下一次握手中失败;如果它还能连上,说明 CRL 根本没有被读取,而这正是值得上报的发现。按你需要结束的东西选择操作,用第二次 status 确认,并在答案必须比会话更持久时修好凭据层。