发送 VPN 日志前先读一遍:逐字段检查
支持日志里有用户名、证书名称、内网地址,有时还有密钥。逐个字段翻看,搜索秘密,然后发送一份已打码的摘录。
你打开一个支持工单,附上客户端生成的诊断导出文件,然后等待。文件里可能完全没有浏览历史,正因如此才让人感觉安全。但它仍然包含你是谁、用了哪台机器、访问过哪些内网地址和时间,偶尔还有客户端在记录配置时复制进去的私钥。发送前把文件过一遍大约需要五分钟,却能避免一次永久泄露。
打开它,读前四十行
从顶部开始,客户端通常把版本、平台和配置堆在这里。头几行会告诉你文件有多啰嗦,这决定了后面还有多少内容需要关心。默认日志和调试日志是两种不同的产物,暴露面也不同。
head -n 40 vpn-support.log
sed -n '1,40p' vpn-support.log | grep -nE 'version|platform|config|option'
读之前先看文件的大小和形态。只有一条重复事件的两兆字节文本文件很容易裁剪。同一文件夹里的二进制抓包则是完全另一回事,需要和索要导出文件的人另做沟通。
在 Windows 上,对应的是各一条 cmdlet,其中第一条值得对任何不是你亲手创建的文件运行:
Get-Content .\vpn-support.txt -TotalCount 40
Get-Item .\vpn-support.txt | Select-Object Length,LastWriteTime
能识别出个人的字段
用户名出现在人们意想不到的地方:认证用的账户、证书主题、主目录下的配置文件路径,以及常常编码了真实姓名的机器名。只对账户字段打码、却把主目录路径原样留下的日志,等于什么都没打码。
| Field | What it identifies | Practical treatment |
|---|---|---|
| Account or username | A person, and often an employer | Replace consistently, keep the mapping |
| Certificate subject and CN | Device or user identity | Keep the structure, replace the value |
| Home directory path | A login name, sometimes a full name | Replace the segment, not the whole path |
| Machine or hostname | A person or a physical location | Replace with a stable pseudonym |
当支持工程师需要沿文件追踪同一次会话时,一致性比完整性更重要。用稳定的标签替换取值,而不是删掉它们,这样同一个用户的每次出现仍然读作同一个用户。把字段整个删掉会切断工程师需要的线索,也不会让文件更安全。
时间戳在汇总意义上也是个人数据。把某个账户一个月的连接时间拿出来,就能勾出工作时段和出行。如果问题不需要完整区间,就把文件裁剪到事件前后的窗口。
能识别出网络的字段
端点地址、内部路由和推送的选项勾勒出一个私有网络的形状。这正是攻击者想要的信息,而它通常比工单所需的详细得多。
要找你实际在用的地址族,而不只是你以为的那一种。双栈客户端可能记录了 IPv6 端点和一组 IPv6 路由,而评审只找了点分四段,没人想到去处理它们。
grep -nEo '([0-9]{1,3}\.){3}[0-9]{1,3}' vpn-support.log | sort -u | head -n 40
grep -nEo '([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}' vpn-support.log | sort -u | head -n 20
去重后的清单才是关键。它会告诉你文件提到了多少个不同地址,通常比滚动时感觉的少得多。它还给你一份打码清单,以及证明你全都覆盖到的方法。十个地址是五分钟的活,一百个则说明这份导出比问题本身更宽。
如果工程师需要,就保留拓扑。替换第二、第三段而保留子网关系,既能回答问题又不公开整个网段。同样的办法对 IPv6 前缀也适用。工程师需要的是故障的形状,而这个形状在一致的替换之后仍然成立。
秘密藏在形态里,而不是标签里
私钥旁边不需要出现“password”这个词。它可能表现为标记行之间的整块内容、一长串 base64,或一段内联的配置转储。令牌会以查询参数的形式出现,凭据则出现在客户端原样记录的 URL 里。
grep -nE 'BEGIN [A-Z ]*PRIVATE KEY|password|passwd|token|secret|psk|auth-user-pass' vpn-support.log
grep -nE 'https?://[^ ]*:[^ ]*@' vpn-support.log
第二种模式是人们常忘的。形如“协议、用户、口令、主机”的 URL 就是一份完整凭据,只要代理或订阅源配置了内联认证,客户端就会把它记下来。
永远不要用发送原始文件来证明你没有改过它。如果对方坚持要未修改的导出,先问清用途,再通过他们经过验证的支持渠道发送,随后删除本地副本。这个要求是正当的,公开粘贴则不是。
生成打码副本并发送摘录
在副本上操作,把原件放在受保护的位置,用可重复的命令而不是手工打码。对着地址模式跑一遍就能抓住大部分:
cp vpn-support.log vpn-support.original.log
sed -E 's/([0-9]{1,3}\.){3}[0-9]{1,3}/ADDR/g; s/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+/USER@DOMAIN/g' \
vpn-support.original.log > vpn-support.redacted.log
grep -cE 'PRIVATE KEY|password|token' vpn-support.redacted.log
最后计数应当为零。如果不是,说明这一遍漏掉了某种形态,发任何东西之前都该先看看那几行。也要用自己的眼睛把打码后的文件读一遍;脚本抓的是模式,不是上下文。
发送仍能体现故障的最小摘录。错误前后十行通常就够了,而且比两兆字节的文件好审得多。然后把标签与真实取值之间的对应关系留在你自己控制的地方,因为后续追问会用到它。
OpenVPN 的日志文档说明了详细级别如何改变记录内容,这对判断问题到底需要文件的多大一部分很有帮助。