Pika Monitor SSH 登录监控原理

引言

对于服务器管理员来说,监控 SSH 登录行为是安全运维的基础需求。传统方案通常依赖定期解析 /var/log/auth.log/var/log/secure 等日志文件,但这种方式存在明显的局限性:需要不断轮询文件、日志格式因发行版而异、无法实时响应异常登录。

Pika Monitor 采用了一种更优雅的方案:基于 Linux PAM(Pluggable Authentication Modules)机制,实现了毫秒级的 SSH 登录实时监控。当有用户登录时,系统能立即感知并触发告警,无需任何轮询操作。

核心原理

PAM 是什么

PAM 是 Linux 系统的插件式认证框架,几乎所有需要身份验证的程序(包括 SSH)都会调用 PAM。PAM 将认证过程分为四个阶段:

  • auth:身份验证(检查密码、密钥等)
  • account:账户检查(账户是否过期、是否被锁定等)
  • password:密码管理
  • session:会话管理(登录成功后的环境配置)

PAM 提供了 pam_exec.so 模块,允许在认证流程的任何阶段执行外部程序。这是我们实现监控的关键切入点。

监控流程

整个监控流程可以用一条简洁的链路表示:

SSH 登录 → PAM 认证 → pam_exec.so → pika-ssh-login-hook → Unix Socket → pika-agent → 告警/记录

具体步骤如下:

  1. 用户通过 SSH 登录服务器
  2. SSH 服务器调用 PAM 进行身份认证
  3. 认证成功后,PAM 进入 session 阶段(会话打开)
  4. 此时 pam_exec.so 模块被触发,执行 pika-ssh-login-hook 程序
  5. pika-ssh-login-hook 从 PAM 提供的环境变量中读取登录信息(用户名、客户端 IP、端口、终端类型等)
  6. 将这些信息封装成 JSON 格式,通过 Unix Domain Socket 发送给 pika-agent
  7. pika-agent 收到事件后,立即进行处理(记录日志、发送告警等)

整个过程在毫秒级别完成,对用户登录体验没有任何影响。

设计关键点

为什么使用 optional 标志

在 PAM 配置中,我们使用 session optional pam_exec.so 的方式注册 hook。optional 表示即使这个模块执行失败,也不会影响用户正常登录。这是一个重要的安全设计:监控功能不应该成为系统可用性的瓶颈。

为什么选择 Unix Socket

进程间通信有很多方式(文件、管道、共享内存等),我们选择 Unix Domain Socket 的原因是:

  • 高性能:本地通信,无需网络协议栈开销
  • 无需轮询:事件驱动,实时推送
  • 简单可靠:单向通信,无需复杂的同步机制
  • 权限控制:可以通过文件权限限制访问

我们使用 unixgram 类型(类似 UDP),因为 hook 进程生命周期很短,无需维护长连接。

自动化安装

Pika 提供了自动化的安装流程,用户只需执行一条命令即可完成配置。安装过程包括以下步骤:

配置步骤

  1. 检查并启用 SSH 的 PAM 支持:在 /etc/ssh/sshd_config 中确保 UsePAM yes 已启用
  2. 修改 PAM 配置:在 /etc/pam.d/sshd 文件末尾添加 hook 配置行
  3. 安装可执行文件:将 pika-agent 放到 /usr/local/bin/ 目录(优先使用软链接)
  4. 重启 sshd 服务:使配置生效(自动检测 systemd 或 SysV init)

设计亮点

幂等性:安装程序会先检查配置是否已存在,避免重复安装导致配置文件混乱。

安全回滚:在修改任何配置文件前,都会先创建 .bak 备份。如果安装过程中出现错误,会自动恢复原始配置,确保系统不会因为安装失败而无法登录。

兼容性:自动识别系统使用的服务管理工具(systemctl 或 service),并尝试多种可能的服务名称(sshd 或 ssh),适配不同的 Linux 发行版。

权限控制:Socket 文件的权限设置为 0600,确保只有 root 用户可以访问,防止敏感登录信息泄露。

技术细节

环境变量提取

pam_exec.so 执行外部程序时,会将认证信息通过环境变量传递:

  • PAM_USER:登录的用户名
  • PAM_RHOST:客户端的 IP 地址
  • PAM_TTY:使用的终端类型(如 pts/0)
  • SSH_CONNECTION:完整的连接四元组,格式为 “客户端IP 客户端端口 服务器IP 服务器端口”

pika-ssh-login-hook 从这些环境变量中提取信息,并处理各种边界情况(如变量为空时使用默认值)。

进程间通信机制

监控服务在启动时会创建 Unix Socket 并持续监听。当 hook 进程发送事件时:

  1. Hook 进程连接到 Socket(/run/pika/ssh_login.sock
  2. 将事件序列化为 JSON 并发送
  3. 立即关闭连接并退出(整个过程 < 10ms)

监控服务收到数据后:

  1. 从 Socket 读取数据(使用 4096 字节缓冲区)
  2. 反序列化 JSON
  3. 补全缺失字段(如时间戳、状态)
  4. 将事件发送到事件队列(缓冲 100 个事件)

错误处理策略

发送端(Hook):如果 Socket 连接失败或发送失败,静默失败,不影响用户登录流程。

接收端(Monitor):如果 JSON 解析失败,记录错误日志并跳过该事件。如果事件队列已满,丢弃新事件而非阻塞(避免影响后续登录)。

这种设计确保了监控功能的失败不会成为系统可用性的单点故障。

总结

Pika Monitor 的 SSH 登录监控方案充分利用了 Linux PAM 机制,实现了以下优势:

  • 实时性:毫秒级事件通知,无需轮询日志文件
  • 可靠性:基于系统原生的 PAM 框架,无需额外守护进程
  • 低开销:Hook 进程快速退出,对系统性能影响极小
  • 安全性:使用 optional 标志,配置失败不影响正常登录

这套方案特别适合需要实时感知 SSH 登录的场景,如安全审计、异常登录告警、堡垒机监控等。通过在认证流程中插入轻量级的 hook,我们在不牺牲性能和可靠性的前提下,获得了对系统访问行为的完整掌控。

完整的代码实现可以参考:https://github.com/dushixiang/pika