# 在 Windows PowerShell 端建立 SSH 公鑰認證,免密碼登入 Ubuntu Server - 伺服器:Ubuntu Server(固定 IP,例如 `192.168.X.XXX`) - 用戶端:Windows 10/11(以 PowerShell 操作) - 目標:使用公鑰認證(public key authentication)免密碼登入,並關閉密碼登入 ## 前置條件 - Windows 需已安裝 OpenSSH Client(預設已內建,可在 PowerShell 執行 ssh -V 確認) - Ubuntu 可連上 22/TCP(若有 UFW/防火牆,先允許:sudo ufw allow OpenSSH) ## 流程總覽 ```mermaid sequenceDiagram actor Win as Windows PowerShell participant U as Ubuntu Server Win->>U: 1) 使用密碼 ssh 你的userName@192.168.X.XXX 初次登入 U-->>Win: 要求密碼並允許登入 Win->>U: 2) 安裝 openssh-server(若未安裝) U-->>Win: sshd 服務啟動 Win->>Win: 4) 產生本機 SSH 金鑰 (ed25519) Win->>U: 5) 傳送公鑰到 ~/.ssh/authorized_keys Win->>U: 7) 設定 sshd 僅允許金鑰、禁止 root 密碼 U-->>Win: 重新載入 sshd 設定 Win->>U: 6/8) 測試:金鑰可登入;密碼登入已被拒絕 ``` ## 詳細步驟 1) 先用密碼連線到 Ubuntu Server 在 PowerShell: ```powershell ssh 你的userName@192.168.X.XXX ``` 首次會提示是否信任指紋,輸入 yes,並輸入使用者密碼登入。 2) 安裝 OpenSSH Server(若已安裝可略過) 在 Ubuntu 端: ```bash sudo apt update sudo apt install -y openssh-server sudo systemctl enable --now ssh sudo systemctl status ssh --no-pager ``` 3) 備份 sshd_config 在 Ubuntu 端: ```bash sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F_%H%M%S) ``` 4) 在 Windows PowerShell 產生 SSH 金鑰 在 PowerShell: ```powershell ssh-keygen -t ed25519 -a 100 -C "你的名稱@你的電腦" # 產生: # C:\Users\<你>\.ssh\id_ed25519 (私鑰 private key,請妥善保護) # C:\Users\<你>\.ssh\id_ed25519.pub (公鑰 public key,會放到伺服器) ``` 說明: - 註解(Comment)僅用於識別,例如 "alice@my-laptop" 或你的電子郵件。 5) 將公鑰傳到 Ubuntu 的 authorized_keys **方法 A:使用 scp(建議)** ```powershell $PUB="$env:USERPROFILE\.ssh\id_ed25519.pub" scp $PUB 你的userName@192.168.X.XXX:~/id_ed25519.pub.tmp ssh 你的userName@192.168.X.XXX "umask 077; mkdir -p ~/.ssh && chmod 700 ~/.ssh; touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys; cat ~/id_ed25519.pub.tmp >> ~/.ssh/authorized_keys; rm ~/id_ed25519.pub.tmp" ``` **方法 B:使用管線(處理 CRLF 問題)** ```powershell $PUB="$env:USERPROFILE\.ssh\id_ed25519.pub" type $PUB | ssh 你的userName@192.168.X.XXX "umask 077; mkdir -p ~/.ssh && touch ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys && tr -d '\r' >> ~/.ssh/authorized_keys" ``` 6) 測試「只用公鑰」能否登入 請先保持你目前的 SSH 連線不要關閉,再開新視窗測試: ```powershell ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no 你的userName@192.168.X.XXX ``` 若成功即代表金鑰配置無誤。 7) 設定安全的 SSH 連線(建議使用方法 1) **方法 1:建立優先權設定檔(推薦)** ```bash sudo tee /etc/ssh/sshd_config.d/99-custom.conf << EOF PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no PermitRootLogin prohibit-password UsePAM yes AuthenticationMethods publickey EOF ``` **方法 2:編輯主設定檔** ```bash sudo vim /etc/ssh/sshd_config ``` 確認或加入以下設定: ``` PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no PermitRootLogin prohibit-password UsePAM yes AuthenticationMethods publickey ``` 套用前先檢查語法並重新載入: ```bash sudo sshd -t sudo systemctl reload ssh ``` ## 驗證設定 **檢查 SSH 伺服器的實際運行設定:** ```bash sudo sshd -T | grep -Ei "(passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|authenticationmethods)" ``` **期望輸出應該是:** ``` pubkeyauthentication yes passwordauthentication no kbdinteractiveauthentication no authenticationmethods publickey ``` **若系統有 Match 區塊,使用更精確的檢查:** ```bash sudo sshd -T -C user=你的userName,host=$(hostname),addr=192.168.X.XXX | grep -Ei "(passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|authenticationmethods)" ``` 8) 驗證密碼登入已被禁用 - 金鑰登入仍應成功: ```powershell ssh 你的userName@192.168.X.XXX ``` - 強制用密碼嘗試,應被拒絕: ```powershell ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no 你的userName@192.168.X.XXX ``` 看到 Permission denied 即為正確。 完成後,就可以在 Windows PowerShell 以 SSH 公鑰認證安全、免密碼地登入 Ubuntu Server,並且伺服器端已禁止密碼登入,降低被暴力破解的風險。 ## 安全建議 1. **測試後再斷線**:在確認 SSH 金鑰登入正常運作之前,請保持至少一個 SSH 連線會話開啟。 2. **備份設定檔**: ```bash sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup ``` 3. **監控登入日誌**: ```bash sudo tail -f /var/log/auth.log ``` 4. **考慮使用額外的安全措施**: - 更改 SSH 預設埠號 - 設定防火牆規則 - 使用 fail2ban 防止暴力破解 - 限制允許登入的使用者: ```bash # 在 sshd 設定中加入 AllowUsers 你的userName # 或使用群組控制 AllowGroups sshusers ``` ## 常見問題:Cloud-init 設定覆蓋 ### 問題描述 在 Ubuntu Server 22.04 中,即使在 `/etc/ssh/sshd_config` 中設定了 `PasswordAuthentication no`,使用 `sudo sshd -T` 檢查時可能仍然顯示 `passwordauthentication yes`,導致密碼登入依然被允許。 ### 根本原因 現代 Ubuntu Server 預設包含 **Cloud-init** 系統,它會透過 `/etc/ssh/sshd_config.d/` 目錄中的設定檔覆蓋主要的 SSH 設定。 **SSH 設定檔的載入機制:** 1. OpenSSH 從上到下解析 `/etc/ssh/sshd_config` 2. 當遇到 `Include /etc/ssh/sshd_config.d/*.conf` 指令時,會在該位置展開所有 `.conf` 檔案(按字母順序) 3. 後出現的設定會覆蓋先前的設定 4. Ubuntu 22.04 預設在主設定檔開頭附近就有 Include 指令 ### 為什麼全新安裝的 Linux 會有 Cloud-init? 現代 Linux 發行版(特別是 Ubuntu Server)預設包含 cloud-init,原因如下: 1. **雲端優先設計**:Ubuntu Server 針對雲端部署優化,即使在本地安裝也包含雲端工具 2. **統一映像檔**:使用相同的 ISO 映像檔部署到不同環境(本地、AWS、Azure、GCP 等) 3. **自動化需求**:即使在本地環境,也可能需要自動化配置功能 #### Cloud-init 的主要功能 ``` 初始開機時自動執行: ├── 網路設定 (IP、DNS、路由) ├── 使用者帳號建立與 SSH 金鑰配置 ├── 套件安裝與更新 ├── 檔案系統掛載與調整 ├── SSH 服務設定 (包括認證方式) ├── 主機名稱設定 └── 執行自訂腳本 ``` ### 診斷步驟 **檢查是否存在 Include 設定和額外的設定檔:** ```bash # 檢查主設定檔中的 Include 指令 grep -n "Include" /etc/ssh/sshd_config # 列出額外的設定檔 ls -la /etc/ssh/sshd_config.d/ # 檢查 cloud-init 設定檔內容 cat /etc/ssh/sshd_config.d/50-cloud-init.conf ``` 典型的 `50-cloud-init.conf` 內容可能包含: ``` PasswordAuthentication yes ``` ### 解決方案 **方法 1:建立優先權更高的設定檔(推薦)** sshd_config.d 的設定套用順序是按照字母順序排列的,後面的設定會覆蓋前面的設定: ```bash sudo tee /etc/ssh/sshd_config.d/99-custom.conf << EOF PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no PermitRootLogin prohibit-password AuthenticationMethods publickey EOF sudo sshd -t && sudo systemctl reload ssh ``` **方法 2:停用 Cloud-init SSH 設定檔** 如果是地端架設的 Ubuntu Server 且確定不需要 Cloud-init 的 SSH 管理: ```bash sudo mv /etc/ssh/sshd_config.d/50-cloud-init.conf /etc/ssh/sshd_config.d/50-cloud-init.conf.disabled sudo sshd -t && sudo systemctl reload ssh ``` ### 驗證修正結果 ```bash # 確認設定已正確套用 sudo sshd -T | grep -Ei "(passwordauthentication|authenticationmethods|pubkeyauthentication)" # 測試設定檔語法 sudo sshd -t # 測試密碼登入(應被立即拒絕,不會提示輸入密碼) ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no username@localhost ``` ### 關於 PermitRootLogin 設定說明 - `PermitRootLogin no`:完全禁止 root 登入(包括金鑰登入) - `PermitRootLogin prohibit-password`:禁止 root 密碼登入,但允許金鑰登入 - `PermitRootLogin yes`:允許 root 以任何方式登入(不建議) ### 補述:關於 Cloud-init Cloud-init 是一個雲端環境初始化系統,用於在虛擬機器或容器啟動時自動執行配置。即使在本地安裝的 Ubuntu Server 也會包含此套件。 如果您的環境確定不需要 Cloud-init 功能,可以選擇: **完全移除 Cloud-init:** ```bash sudo apt remove --purge cloud-init sudo rm -rf /etc/cloud/ /var/lib/cloud/ ``` **或禁用 Cloud-init 的 SSH 模組:** ```bash sudo vim /etc/cloud/cloud.cfg # 在 cloud_config_modules 區段中註解掉: # - ssh ``` **注意**:移除 Cloud-init 會影響雲端化引導流程與部分自動化工具,建議在本機/裸機長期使用且確定無需雲端初始化時再執行。
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.