sudo (superuser do) 是 Linux 系統管理的核心提權機制,比 su 更安全、更可控、更易審計。本文系統剖析 sudo 運作原理、/etc/sudoers 配置語法、常用選項、權限模型、安全強化建議、自動化與除錯技巧,助您建立最小權限、可追蹤的提權體系。
| 特性 | sudo | su |
|---|---|---|
| 密碼 | 當前用戶密碼 | root 密碼 (或目標用戶密碼) |
| 權限粒度 | 命令級、參數級、主機級、用戶組級 | 全權 root shell |
| 審計日誌 | 完整記錄 (誰、何時、什麼命令、成功/失敗) | 僅記錄登入事件 |
| 環境變數 | 可控制保留/重置 (env_reset) | 繼承完整環境 |
| 超時機制 | 預設 5-15 分鐘免密 (timestamp_timeout) | 持續登入直到 exit |
| 最小權限原則 | 原生支援 | 違反 (給予過度權限) |
sudo cmd/etc/sudoers (含 /etc/sudoers.d/*)env_reset/env_keep) → setuid(root) → 執行命令/var/log/auth.log 或 /var/log/secure)編輯必須用 visudo (語法檢查、鎖定、防止同時編輯)
用戶/組 主機=(目標用戶:目標組) 命令列表
# 別名定義 (可選)
User_Alias ADMINS = alice, bob, %wheel
Host_Alias SERVERS = web1, web2, 192.168.1.0/24
Cmnd_Alias WEBCMDS = /usr/bin/systemctl restart nginx, /usr/bin/nginx -t
Runas_Alias WEBUSERS = www-data, nginx
| 需求 | sudoers 行 | 說明 |
|---|---|---|
| 用戶 alice 可在任何主機以任何身份執行任何命令 | alice ALL=(ALL:ALL) ALL | 全權管理員 (謹慎授予) |
| wheel 組成員可執行任何命令 (免密需另加 NOPASSWD) | %wheel ALL=(ALL:ALL) ALL | 標準管理員組 (RHEL/Fedora 預設) |
| 用戶 bob 只能重啟 nginx、查看狀態 | bob ALL=(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx | 命令級限制 |
| 用戶 carol 以 www-data 身份執行 php-fpm 管理 | carol ALL=(www-data) /usr/sbin/php-fpm | Runas 指定目標用戶 |
| 組 developers 免密執行 docker、kubectl | %developers ALL=(ALL) NOPASSWD: /usr/bin/docker, /usr/bin/kubectl | NOPASSWD: 免密 (高風險,嚴格限制命令) |
| 用戶 dave 在 web1、web2 只能查日誌 | dave web1,web2=(ALL) /bin/cat /var/log/nginx/*.log, /usr/bin/tail -f /var/log/nginx/*.log | 主機級限制 |
| 允許帶參數但限制危險參數 | alice ALL=(ALL) /usr/bin/rsync --server --sender * | 參數級控制 (需完整路徑) |
| 禁止特定命令 (黑名單,不推薦) | alice ALL=(ALL) ALL, !/usr/bin/passwd, !/bin/su | 黑名單易繞過,白名單更安全 |
# 記錄輸入/輸出 (需 sudo 1.8.11+,IO 日誌佔磁碟)
Defaults log_input, log_output
Defaults iolog_dir=/var/log/sudo-io
# 環境變數控制
Defaults env_reset # 重置環境 (預設開啟)
Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" # 保留代理變數
Defaults env_keep += "DISPLAY XAUTHORITY" # 保留圖形環境
# 超時設定 (分鐘)
Defaults timestamp_timeout=10 # 10 分鐘免密 (預設 5-15)
# 要求 tty (防止腳本/遠程無終端機濫用)
Defaults requiretty # 關閉可加 !requiretty
# 郵件通知
Defaults mail_always
Defaults mailto="admin@example.com"
# 輸入密碼提示
Defaults passprompt="[sudo] %u@%h 輸入密碼: "
| 選項 | 功能 | 範例 |
|---|---|---|
-u user | 以指定用戶身份執行 (非 root) | sudo -u www-data php artisan migrate |
-g group | 以指定組身份執行 | sudo -g docker docker ps |
-i | 模擬登入 shell (載入目標用戶環境、cd $HOME) | sudo -i (等同 sudo -u root -i) |
-s | 啟動 shell (不載入登入環境,保留當前目錄) | sudo -s |
-E | 保留當前環境變數 (覆蓋 env_reset) | sudo -E python script.py |
-b | 背景執行 | sudo -b nohup long-task.sh |
-n | 非互動 (失敗直接報錯,不提示密碼) | sudo -n true (檢查是否免密) |
-l | 列出當前用戶可執行命令 | sudo -l |
-v | 延長時間戳 (刷新免密窗口) | sudo -v |
-k | 撤銷時間戳 (下次需輸入密碼) | sudo -k |
# 建立獨立規則檔
sudo vi /etc/sudoers.d/nginx-admin
# 內容:
%nginx-admin ALL=(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx
# 權限必須 0440
sudo chmod 440 /etc/sudoers.d/nginx-admin
# visudo 會自動包含 sudoers.d/*
# 檢查語法
visudo -c
NOPASSWD:,並嚴格限制命令範圍。Defaults log_input, log_output,定期審計關鍵操作 (如 passwd、useradd、systemctl stop)。/var/log/auth.log/secure、/var/log/sudo-io/ 轉發至 SIEM (Elastic、Splunk、Loki)。PermitRootLogin no,強制一般用戶 + sudo。sudo passwd -l root (緊急時用單用戶模式/救援模式解鎖)。sudo -l -U user 檢查每用戶實際權限,移除離職/異動人員。sudo_pair 插件、或自製腳本要求第二管理員確認。# 檢查語法
visudo -c
# 查看當前用戶權限
sudo -l
# 查看指定用戶權限 (需 root)
sudo -l -U alice
# 除錯模式 (顯示比對細節)
sudo -D 5 -l
# 查看日誌
grep sudo /var/log/auth.log # Debian/Ubuntu
grep sudo /var/log/secure # RHEL/CentOS
journalctl -u sudo -f # systemd 日誌
# IO 日誌回放 (需 sudo 1.8.11+)
sudoreplay -l # 列出 session
sudoreplay session_id # 回放終端機畫面
# Ansible become
- become: yes
become_method: sudo
become_user: root
become_flags: "-E -H" # 保留環境、設定 HOME
# GitLab CI / GitHub Actions
# 建議用專用部署金鑰 + sudo 規則限制命令
# 而非給 runner 全權 NOPASSWD: ALL
# 腳本中檢查 sudo 權限
if sudo -n true 2>/dev/null; then
echo "有免密權限"
else
echo "需輸入密碼或無權限"
fi
sudo 以「最小權限、完整審計、可控環境」確立了 Linux 提權的黃金標準。善用 visudo、sudoers.d、Defaults 進階選項、IO 日誌、集中審計,即可將「誰能做什麼、何時做、怎麼做」納入可控、可追蹤的治理體系,踏實守護生產環境安全底線。