设备可以输出日志,收集器位于互联网的另一端,而所有人首先问的都是:该建哪条隧道。这个提问的出发点就错了。决定传输方式的是设备能产生的格式、收集器会接受的认证,以及链路中断时“已送达”应当意味着什么。把这三个答案写下来,传输方式通常就会自己浮现。

从设备能输出的内容开始

实践中只有三种形态。通过 UDP 或 TCP 发送单条 syslog 事件;产品内置的认证 HTTPS 上传;或者写入磁盘、必须搬运的完整文件。只能发送 UDP syslog 的防火墙,不会因为你加了隧道就变成 TLS 发送方;它仍会发送未经确认的数据报,只是如今套在了加密信封里。

所以先盘点发送方:协议、TLS 支持以及使用哪个 TLS 库、能否验证收集器的证书、能否出示客户端证书、发送缓冲区能否经受重启。设备做不到的事,必须由路径上的其他环节完成,而那个环节就成为你设计的一部分。

TLS syslog:两端都说它时的最短路径

如果设备支持通过 TLS 发送 syslog,而收集器负责终止,那就用它并到此为止。应用协议自我保护,收集器认证发送方,也不会多出一段可用性要由你负责的跳转。陷阱在于“TLS syslog”涵盖的实现范围很广,而 当前的安全 syslog 指南 已经超越了旧教程里的加密套件清单,这就是原本可用的转发器在库升级后失效的原因。

在 rsyslog 中,仅凭传输模块的名字就能看出你处在哪个时代:lmnsd_gtls 封装 GnuTLS,而 lmnsd_ossl 封装 OpenSSL,当前 8.x 软件包提供的正是后者。带证书校验的转发动作大致如下,具体参数名值得对照你安装的版本核实:

action(type="omfwd" target="collector.example" port="6514" protocol="tcp"
       StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/name"
       StreamDriver.CAFile="/etc/pki/ca.pem"
       queue.type="LinkedList" queue.filename="fwdq" queue.maxDiskSpace="1g"
       queue.saveOnShutdown="on" action.resumeRetryCount="-1")

在调试发送方之前,先验证端点。openssl s_client -connect collector.example:6514 -servername collector.example -CAfile /etc/pki/ca.pem -verify_return_error 要么以有效证书链完成握手,要么准确告诉你哪一项检查失败。要从设备上测试,而不是从你的笔记本电脑,因为设备自己的信任库才是关键。

SFTP:适合文件,不适合流

基于文件的交付适合只写轮转日志、不做别的事的设备。基于 SSH 的传输提供主机密钥、按账户的密钥以及可审计的文件系统,对一个完全不会 TLS 的设备来说,这是合理的信任叙事。它对事件流并不合适:“每小时写一个文件”意味着一次故障就会让你丢掉当前小时的尾部。

保持主机校验开启。为了避开提示而把它关掉的批处理调用,会摧毁传输方式仅有的认证:

sftp -b /etc/logship/batch -o BatchMode=yes -o StrictHostKeyChecking=yes      -o IdentitiesOnly=yes -i /etc/logship/id_ed25519 [email protected]

在配置阶段把主机密钥固定到账户的 known_hosts 中,把账户限制在目标目录,并优先使用带 chroot 的 internal-sftp 子系统。还要规划重传策略:如果文件在部分失败后被重发,收集器必须能区分重复文件与新文件,通常依据文件名加校验和,而不是到达时间。

当本地网关或隧道才是诚实的答案

有些设备只会说一种没人愿意暴露的格式。这种情况下,由设备自身网络中的授权收集器接收原始格式,再通过 TLS 转发出去。这是合法的设计,但要准确说明它买到了什么:从网关开始的加密,并不会回溯保护设备与网关之间的那一段,所以那一跳仍然需要自己的信任边界和访问控制。

路由式的站点或设备隧道是最重的选项,当 收集器必须保留私有地址 且要承载多项服务而不只是日志时,它才是正确选择。它带来地址规划、访问规则、返回路径以及隧道端点的生命周期。它也不会改善内部协议:IPsec 隧道里的 UDP syslog 仍然是没有交付确认的数据报服务。

无论选哪种,都要让收集器的授权比传输方式更窄。隧道身份属于某个端点,它并不能说明某条消息里的特定主机名字段是哪个下游设备产生的。

发运之前写下交付约定

加密、认证和留存回答的是不同问题,而队列不是留存策略。在第一份日志离开设备之前,先确定确认在这个收集器上究竟意味着什么:在线上收到、被接受处理,还是持久写入存储。这是三种不同的保证,只有最后一种能挺过收集器重启。

然后用书面形式回答运维问题。未发送的事件在哪里等待,那块缓冲区能否挺过断电?写满时会发生什么,谁会被告知?重试如何受限,重复如何识别?既然转发跳可能改写主机名,哪个字段能证明发送方的身份?

把设计控制在一段话就能解释的规模:能承载所需事件的最小受支持传输方式,加上对它所不提供保证的明确说明。如果答案需要两跳,就在 runbook 里写明,并为每一跳指定负责人。

相关文章