封面圖片:我如何用一支腳本自動化 Ubuntu 伺服器強化

Tesleem Amuda

保護並自動化雲端伺服器

第一次啟動雲端伺服器時,我以為最困難的部分已經結束。其實不然。那台伺服器完全暴露在網路上:root 登入啟用、22 號連接埠公開給網路上所有掃描器、沒有防火牆,也沒有憑證。

幾小時後我查看 /var/log/auth.log,發現數百次登入失敗嘗試。那一刻我才理解為什麼 SSH 強化絕非可有可無。

為什麼 SSH 強化如此重要

SSH 是伺服器的大門。預設情況下,這扇門大開:22 號連接埠、允許密碼驗證、root 登入許可。自動化機器人每小時掃描數百萬個 IP 位址,專找這種漏洞。

強化 SSH 代表在其他任何東西接觸伺服器前先堵住缺口:

  • 停用 root 登入:PermitRootLogin no
  • 停用密碼驗證,只允許金鑰:PasswordAuthentication no
  • 將 SSH 移出 22 號連接埠——我改用連接埠 2247
  • 限制僅特定使用者登入:AllowUsers deploy
  • 閒置 10 分鐘後斷線:

    • ClientAliveInterval 300
    • ClientAliveCountMax 2

這五項變更即可消除絕大多數自動化攻擊。你不會隱形,但也不再是容易下手的目標。

UFW 的功能

UFW——Uncomplicated Firewall——是 Ubuntu 對 iptables 的親民介面。你不需要撰寫低階規則,只需表達意圖:

ufw default deny incoming
ufw default allow outgoing

ufw allow 2247/tcp   # SSH 使用自訂連接埠
ufw allow 80/tcp     # HTTP
ufw allow 443/tcp    # HTTPS

ufw --force enable

Enter fullscreen mode Exit fullscreen mode

未明確允許的流量一律封鎖。這就是最小權限原則應用在網路層,與良好的 Kubernetes NetworkPolicies、IAM 角色和 RBAC 遵循相同原則。

從這裡開始學習。

Let's Encrypt 的運作方式

Let's Encrypt 是瀏覽器信任的免費自動化憑證頒發機構。流程簡單:

  1. 將網域名稱指向伺服器 IP 位址。
  2. Certbot 透過 HTTP 提供挑戰檔案,證明你擁有該網域。
  3. Let's Encrypt 核發有效期 90 天的憑證。
  4. Certbot 自動修改 Nginx 設定,提供 HTTPS 並自動將 HTTP 重新導向。
  5. 排程任務在憑證到期前自動續期——無需手動操作。

結果就是免費且自動維護的 HTTPS 網站。

下列指令可在不更動現有憑證的情況下,確認續期流程是否正常運作:

certbot renew --dry-run

Enter fullscreen mode Exit fullscreen mode

冪等性的意義——以及為什麼重要

冪等(Idempotent) 指的是同一個操作執行兩次,結果與執行一次相同。

聽起來很學術,其實不然。

實際上,這表示:

  • deploy 使用者已存在,則跳過而非回傳錯誤。
  • 若憑證已存在,則跳過而非申請重複憑證。
  • 若套件已安裝,apt-get 會優雅處理。

沒有冪等性,設定腳本在部分失敗後重新執行,可能會導致你被鎖在自己的伺服器外面。有了它,你可以在任何中斷後安心重新執行腳本。

這個習慣也會延續到 Ansible、Terraform,以及你日後在專業層級使用的所有自動化工具。

腳本

完整腳本請見:

github.com/tesddev/server-bootstrap

在全新的 Ubuntu 22.04 伺服器上,一條指令即可完成所有設定:

sudo bash setup.sh

Enter fullscreen mode Exit fullscreen mode

腳本依序執行:

  1. 更新系統並安裝必要套件。
  2. 建立非 root 的 deploy 使用者並複製 SSH 金鑰。
  3. 強化 SSH:變更連接埠、停用 root 登入與密碼驗證、設定閒置逾時。
  4. 使用明確允許清單設定 UFW。
  5. 安裝 Nginx 並提供自訂頁面。
  6. 使用 Certbot 取得 Let's Encrypt 憑證。

最終成果

  • SSH 限制為非標準連接埠的金鑰驗證
  • 防火牆僅允許必要流量
  • 位於 https://tes-devops.duckdns.org 的即時網站,具備有效且自動續期的憑證
  • 一支可隨時在新伺服器上執行的腳本

真正的教訓

手動設定伺服器無法規模化,更重要的是無法可靠地重現。同樣步驟由兩個人、在不同日子執行,會產生兩台細微不同的伺服器。

腳本則沒有這個問題。

撰寫小型、冪等的自動化腳本是 DevOps 中最值得傳承的習慣之一。之後的一切——Ansible Playbook、Terraform 模組、Kubernetes manifest——都是同一個概念在更大規模的應用。

➡️ 在 GitHub 查看 server-bootstrap 儲存庫