??大家好,我是 展菲,目前在上市企業從事人工智能項目研發管理工作,平時熱衷于分享各種編程領域的軟硬技能知識以及前沿技術,包括iOS、前端、Harmony OS、Java、Python等方向。在移動端開發、鴻蒙開發、物聯網、嵌入式、云原生、開源等領域有深厚造詣。
圖書作者:《ESP32-C3 物聯網工程開發實戰》
圖書作者:《SwiftUI 入門,進階與實戰》
超級個體:COC上海社區主理人
特約講師:大學講師,谷歌亞馬遜分享嘉賓
科技博主:華為HDE/HDG
我的博客內容涵蓋廣泛,主要分享技術教程、Bug解決方案、開發工具使用、前沿科技資訊、產品評測與使用體驗。我特別關注云服務產品評測、AI 產品對比、開發板性能測試以及技術報告,同時也會提供產品優缺點分析、橫向對比,并分享技術沙龍與行業大會的參會體驗。我的目標是為讀者提供有深度、有實用價值的技術洞察與分析。
展菲:您的前沿技術領航員
👋 大家好,我是展菲!
📱 全網搜索“展菲”,即可縱覽我在各大平臺的知識足跡。
📣 公眾號“Swift社區”,每周定時推送干貨滿滿的技術長文,從新興框架的剖析到運維實戰的復盤,助您技術進階之路暢通無阻。
💬 微信端添加好友“fzhanfei”,與我直接交流,不管是項目瓶頸的求助,還是行業趨勢的探討,隨時暢所欲言。
📅 最新動態:2025 年 3 月 17 日
快來加入技術社區,一起挖掘技術的無限潛能,攜手邁向數字化新征程!
文章目錄
- 摘要
- 引言
- 常見方法分析
- 1. 修改 `.bashrc` 或 `~/.bash_profile`
- 2. sshd 的 `ForceCommand`
- 3. auditd
- 更靠譜的方案
- 方案一:利用 `sshd` 自帶的日志功能
- 方案二:用 `command` 包裝器捕獲日志
- Demo 示例
- paramiko 腳本
- sshd 配置
- 查看日志
- QA 環節
- 總結
摘要
很多同學在容器里開了 ssh 服務,平時沒什么問題。但當你需要審計的時候,就會發現坑:
- 交互式終端下的命令(比如你手動 ssh 登錄然后敲
ls
)是能記錄的; - 可一旦換成 Python 腳本(例如用
paramiko
執行ssh.exec_command("ls")
),這些命令就沒法出現在history
或auditd
日志里。
那么問題來了:如何在 docker 容器中記錄所有 ssh 用戶執行的命令,包括非交互式的?
本文會逐步分析這個問題的成因,并給出幾種可運行的解決方法。
引言
為什么交互式和非交互式會有區別?
- 交互式 shell:登錄后進入 bash/zsh,會執行
.bashrc
、.bash_profile
等配置文件,所以很多審計手段(比如PROMPT_COMMAND
寫日志)能生效。 - 非交互式 shell:paramiko 這類工具在執行時,并不會啟動一個完整的交互式 shell,而是直接讓 sshd 幫它執行命令。這時候
.bashrc
就不會跑,自然也就沒日志了。
所以很多常見的方法(改 .bashrc
、加 history
、啟用 auditd
)對 paramiko 這種場景是無效的。
常見方法分析
1. 修改 .bashrc
或 ~/.bash_profile
思路:在用戶 shell 的初始化文件里加個鉤子,把每條命令寫到日志里。
問題:非交互式執行根本不會加載這些文件,命令直接被丟掉。
2. sshd 的 ForceCommand
思路:在 /etc/ssh/sshd_config
里寫上 ForceCommand /path/to/logger.sh
,所有命令都通過這個腳本轉一遍。
問題:這會破壞交互體驗,而且你必須自己解析和轉發命令,比較繁瑣。
3. auditd
思路:通過 Linux 內核審計所有系統調用,理論上能捕獲 execve 之類的事件。
問題:在 docker 容器里 auditd 支持有限,很多內核鉤子被屏蔽,不一定能裝。
結論:上面這些辦法在本地服務器行得通,但在容器里或者 paramiko 這種場景下不理想。
更靠譜的方案
有兩個比較實用的方案:
方案一:利用 sshd
自帶的日志功能
sshd 的配置里有個參數叫 LogLevel
。默認是 INFO
,只會記錄登錄/退出。如果改成 VERBOSE
,就能記錄所有用戶通過 ssh 執行的命令。
配置方法:
編輯 /etc/ssh/sshd_config
,添加:
LogLevel VERBOSE
然后重啟 sshd:
service ssh restart
之后,你會在 /var/log/auth.log
(Debian/Ubuntu)或 /var/log/secure
(CentOS)里看到類似這樣的記錄:
sshd[123]: User root executed command: ls -l
sshd[123]: User root executed command: cat /etc/passwd
這種方式優點是簡單,不用額外寫腳本,非交互式命令也能被捕獲。
方案二:用 command
包裝器捕獲日志
如果你想要更細粒度的控制,比如把日志寫到自定義文件,可以用 ForceCommand
配合一個包裝器腳本:
# /usr/local/bin/ssh-logger.sh
#!/bin/bash
echo "$(date) - user: $USER - command: $SSH_ORIGINAL_COMMAND" >> /var/log/ssh_commands.log# 執行原始命令
exec $SSH_ORIGINAL_COMMAND
然后在 /etc/ssh/sshd_config
里加:
ForceCommand /usr/local/bin/ssh-logger.sh
重啟 sshd 后,無論是 paramiko 還是交互式 ssh,都會先經過這個腳本,把命令寫入日志。
缺點是會影響交互式 shell(比如你直接登錄想要跑 bash,會變成只跑 ssh-logger.sh
)。如果你只在容器里跑腳本任務,這沒啥問題;但如果要保留交互功能,就得在腳本里做條件判斷。
Demo 示例
這里我們模擬一下 paramiko 執行命令,然后在容器里看到日志。
paramiko 腳本
import paramikoclient = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("127.0.0.1", username="root", password="123456")stdin, stdout, stderr = client.exec_command("ls /etc")
print(stdout.read().decode())client.close()
sshd 配置
把 /etc/ssh/sshd_config
里的 LogLevel
調高:
LogLevel VERBOSE
查看日志
運行上面的 Python 腳本后,在容器里執行:
tail -f /var/log/auth.log
你會看到:
sshd[1024]: User root executed command: ls /etc
這樣一來,paramiko 非交互式執行的命令也能被記錄了。
QA 環節
Q: 我在容器里沒找到 /var/log/auth.log
怎么辦?
A: 可能是你的容器沒啟用 syslog,可以直接讓 sshd 把日志寫到 stdout,或者安裝 rsyslog
。
Q: auditd 在容器里能不能用?
A: 大部分情況下不行,因為 auditd 需要內核支持,容器里隔離了很多能力。但在宿主機上用 auditd 是沒問題的。
Q: 如果我只想要 paramiko 的日志,不要交互式的怎么辦?
A: 可以用 Match
塊在 sshd_config
里做條件匹配,比如根據 IP 或用戶區分。
總結
- 交互式和非交互式 ssh 的行為差別在于 shell 初始化,這就是
.bashrc
等方法失效的原因。 - 最簡單可行的方案是:sshd 配置
LogLevel VERBOSE
,非交互式命令也能被完整記錄。 - 如果需要自定義日志格式,可以用
ForceCommand
+ 腳本包裝的方式。
所以,要在 docker 容器里審計所有 ssh 用戶的操作,推薦直接從 sshd
的日志功能下手,既穩定又省事。