VPN 登录告警不是入侵告警:盯住会话
异常登录是复核的触发点,不是结论。先把认证记录接到会话上,再接到会话实际触达的资源,才谈入侵。
一条因新国家而触发的 VPN 告警看起来很确凿,通常并不确凿。认证说明某次尝试被接受;会话说明是哪条连接承载了它;资源记录说明那条连接里发生了什么。三者回答的是不同的问题。把它们合并成一条规则,会在周一产出三十张工单,却在周五漏掉真正的案子。
境外地址是问题,不是答案
出差、在异国出口的移动运营商、企业 Web 代理,以及被重新分配的运营商级 NAT 池,都会挪动表面来源,却不挪动攻击者。登录记录反映的是连接从何处进入网络,而不是谁拿着设备。
反向的失败更糟,因为它很安静。被盗密码从用户自己所在的城市使用时,产生的登录在地理检查上与以往每一次登录都吻合。
把地理当成结论,代价可以量化。出差的笔记本不断制造复核,复核者学会不看就关,这种习惯会一直延续,直到真正的案子落进同一条队列。
三类记录回答三个不同的问题
从已部署产品实际发出的记录出发,而不是从产品手册宣称能发出的东西出发。认证决策写明被主张的身份、方法和结果。会话生命周期写明连接、网关和被分配的地址,从开始到停止。
| Record | Question it answers | What it cannot prove |
|---|---|---|
| Authentication decision | Which identity was accepted or rejected, by which method, at what time | That the person operating the device was the account owner |
| Session lifecycle | Which connection, gateway and assigned address were active, and for how long | What the session did with that access |
| Resource event | Which read, write or denied operation a service observed | Which human behind the session triggered it |
| Policy change | Whether an administrator altered the rule that governs the access | Whether the change was reviewed or intended |
空格子是采集缺口,不是无罪判决。如果资源事件从不出现,缺少可疑读取只说明管道没有可报的内容,安静的仪表盘描述的是管道而不是网络。在承诺一条依赖它们的规则之前,先写下部署实际产出哪些记录,并为每条缺失的 feed 点名负责人。
计费细节是会话变得可核查的地方。RFC 2866 所述的 RADIUS 计费携带以会话标识为键的开始、停止和中间更新,因此有开始却没有停止的会话是一条可以点名的缺口,而不是谜团。
按会话关联,而不是按用户名
一个账户合法地同时持有多个会话:笔记本、手机、整夜连着没断的实验室机器。把这个用户名下的所有事件合并,会把三台设备熬成一个故事,然后把这种组合读成失陷。被分配的地址也会被回收,所以会话结束后仍然继续匹配某个地址的关联,会把上个月的设备拖进今天的事件。把会话键保留在地址旁边,并把匹配限制在会话真正覆盖的时间窗内。
在服务看到之前,翻译会去掉原始来源;这时应使用在该边界上仍然存活的身份,例如双向 TLS 主体或单点登录断言。凭空造出地址与人之间的一一映射,是同一类错误,只是多了几步。
没有负责人的告警只是仪表盘
每条规则都需要一个条件、产生它的无害解释、要拉取的证据,以及采取行动的人。反复被拒绝的管理操作、突发失败密码,以及沉默的采集器,是三种不同的事件,对应三种不同的时钟。
通知不是遏制,分发列表也限制不了任何东西。要改变活着的会话,需要有能做到这一点的组件:要么是断开连接的网关,要么是吊销会话的身份提供方。过期的 feed 和缺失的停止记录也应写进规则文本,因为一整天什么都没发送的采集器,从仪表盘看上去和安静的网络一模一样。差别只在管道内部才看得见。
相信安静的一周之前,先检查采集路径
在调整任何一条规则之前,端到端证明这条管道。下面的命令确认认证与计费监听仍在运行、测试凭据因正确的原因被拒绝,以及会话事件仍在到达:
ss -uanp | grep -E ':(1812|1813)\b' radtest alice 'not-the-password' 127.0.0.1 0 testing123 journalctl -u openvpn-server@server --since '-30 min' | grep -c 'Peer Connection Initiated' timedatectl | grep -E 'System clock|synchronized'
测试返回的 Access-Reject 证明请求到达了服务器,且共享密钥匹配,这正是人们跳过的那一步。相反,超时指向密钥、监听器或它前面的过滤器;在修好之前,下游的每一条告警都无法验证。
时钟状态很重要,因为关联窗口默认时间一致。网关差上几分钟,本来干净的会话关联就会显得不可能,复核者于是把窗口放宽,直到关联不再有区分度。改规则之前先检查偏移。
然后用一次无害测试跑一条规则:从一个意料之外的地址生成登录,确认告警触发,确认响应者能拉取会话及其资源事件,并确认工单带有会话标识。能产出连贯故事的规则通过。只产出一堆日志行的规则仍然是仪表盘。把结果记录在规则旁边,让下一次复核从证据开始,而不是从直觉开始。