08-1. SSH 安全遠端登入完整指南
深入理解 SSH 協定、公私鑰認證與端口轉發
目錄
🔒 SSH 安全遠端登入完整指南
⏱️ 閱讀時間: 15 分鐘 🎯 難度: ⭐⭐ (中等)
🎯 本篇重點
理解 SSH 協定的原理、連線建立流程、公私鑰認證機制、Port Forwarding 應用,以及與 Telnet 的差異。
🤔 什麼是 SSH?
SSH (Secure Shell) = 安全的遠端登入協定
一句話解釋: SSH 是一種加密的網路協定,讓你可以安全地遠端登入到另一台電腦,就像坐在那台電腦前面操作一樣。
比喻:遠端遙控器
Telnet = 透明的遙控器
- 所有按鈕動作都被看光光
- 任何人都能攔截並知道你按了什麼
SSH = 加密的遙控器
- 按鈕訊號經過加密
- 即使被攔截也看不懂
- 確認遙控器是真的(認證)🚨 為什麼需要 SSH?Telnet 的問題
Telnet(不安全)
Telnet 的致命缺陷:明文傳輸!
場景:你用 Telnet 登入伺服器
你輸入:
username: admin
password: myPassword123
網路傳輸:
→ admin (明文)
→ myPassword123 (明文)
駭客用 Wireshark 抓包:
「太好了!帳號密碼都拿到了!」
結果:
❌ 帳號被盜
❌ 伺服器被入侵
❌ 資料被竊取Telnet 的三大問題:
1️⃣ 明文傳輸
所有資料(包括密碼)都是明文
任何人都能攔截
範例:
Wireshark 抓包顯示:
Telnet Data: password: admin123
↑ 密碼直接暴露!2️⃣ 無法驗證伺服器身份
你無法確認連線的伺服器是真的
中間人攻擊:
你以為連到 → 真實伺服器
實際連到 → 駭客的假伺服器
駭客記錄你的帳號密碼
再轉發給真實伺服器
你完全不知道!3️⃣ 無完整性保護
資料可以被竄改
範例:
你輸入:rm /tmp/test.txt
駭客修改:rm -rf / ← 刪除整個系統!SSH(安全)
SSH 如何解決這些問題:
場景:你用 SSH 登入伺服器
1. 加密傳輸
你輸入:admin, myPassword123
網路傳輸:sD9fj#$kL@mNpQ2vX... (加密後的亂碼)
駭客抓包:完全看不懂! ✅
2. 伺服器身份驗證
Server 提供:Public Key Fingerprint
Client 檢查:是否match已知的伺服器
如果不match → 警告!可能是假的! ✅
3. 完整性保護
每個封包都有 HMAC(雜湊訊息驗證碼)
如果被竄改 → 立即發現並拒絕! ✅對比表:
| 特性 | Telnet | SSH |
|---|---|---|
| 傳輸加密 | ❌ 明文 | ✅ 加密 |
| 密碼安全 | ❌ 明文 | ✅ 加密 |
| 伺服器驗證 | ❌ 無 | ✅ 有 |
| 完整性保護 | ❌ 無 | ✅ 有 |
| 預設 Port | 23 | 22 |
| 使用場景 | ❌ 已淘汰 | ✅ 現代標準 |
| 安全性 | ⚠️ 非常危險 | ✅ 安全 |
結論:
- Telnet:已經過時,絕對不要使用
- SSH:現代標準,必須使用
🏗️ SSH 協定架構
SSH 在網路模型中的位置
OSI 7 層模型
┌──────────────────────────────┬─────────────────┐
│ 7. Application Layer (應用層) │ SSH, SFTP, SCP │ ← SSH 在這裡
├──────────────────────────────┼─────────────────┤
│ 6. Presentation Layer (表示層)│ 加密、壓縮 │
├──────────────────────────────┼─────────────────┤
│ 5. Session Layer (會話層) │ 建立、維護會話 │
├──────────────────────────────┼─────────────────┤
│ 4. Transport Layer (傳輸層) │ TCP (Port 22) │
├──────────────────────────────┼─────────────────┤
│ 3. Network Layer (網路層) │ IP │
├──────────────────────────────┼─────────────────┤
│ 2. Data Link Layer (資料鏈結層)│ Ethernet │
├──────────────────────────────┼─────────────────┤
│ 1. Physical Layer (實體層) │ 網路線、光纖 │
└──────────────────────────────┴─────────────────┘SSH 位於第 7 層(應用層)
- SSH 是應用層協定
- 提供遠端登入、檔案傳輸等服務
- 使用者直接透過 SSH client 與 server 互動
TCP/IP 4 層模型
┌─────────────────────────────┬─────────────────┐
│ 4. Application Layer (應用層) │ SSH, SFTP, SCP │ ← SSH 在這裡
├─────────────────────────────┼─────────────────┤
│ 3. Transport Layer (傳輸層) │ TCP (Port 22) │
├─────────────────────────────┼─────────────────┤
│ 2. Internet Layer (網際網路層)│ IP │
├─────────────────────────────┼─────────────────┤
│ 1. Network Access (網路存取層)│ Ethernet │
└─────────────────────────────┴─────────────────┘SSH 位於第 4 層(應用層)
- 在 TCP/IP 模型中,SSH 同樣是應用層協定
- 使用 TCP 作為傳輸層協定(Port 22)
- TCP 提供可靠的連線導向傳輸
對比表:
| 模型 | SSH 所在層級 | 層級編號 | 底層協定 |
|---|---|---|---|
| OSI 7 層 | Application Layer | Layer 7 | TCP (Layer 4) |
| TCP/IP 4 層 | Application Layer | Layer 4 | TCP (Layer 3) |
重點:
- SSH 是應用層協定(兩種模型都是)
- 使用 TCP 作為傳輸層(Port 22)
- TCP 提供可靠傳輸,SSH 提供加密與認證
SSH 協定層次
SSH Protocol 分為 3 層:
┌─────────────────────────────────────┐
│ SSH Connection Protocol (連線層) │ ← Port Forwarding, SCP, SFTP
│ - Channel 管理 │
│ - Port Forwarding │
│ - 終端機、Shell │
├─────────────────────────────────────┤
│ SSH Authentication Protocol (認證層)│ ← 密碼、公私鑰認證
│ - Password Authentication │
│ - Public Key Authentication │
│ - Host-based Authentication │
├─────────────────────────────────────┤
│ SSH Transport Protocol (傳輸層) │ ← 加密、金鑰交換
│ - 加密演算法協商 │
│ - 金鑰交換 (Diffie-Hellman) │
│ - 伺服器認證 │
├─────────────────────────────────────┤
│ TCP (Port 22) │
└─────────────────────────────────────┘📡 SSH 連線建立流程
完整流程(5 個階段)
Client Server
│ │
├──────── 1. TCP 連線 ─────────>│
│ (三次握手) │
│ │
├──── 2. Version Exchange ─────>│
│ "SSH-2.0-OpenSSH_8.0" │
│<──────────────────────────────┤
│ "SSH-2.0-OpenSSH_7.9" │
│ │
├──── 3. Key Exchange ─────────>│
│ (協商加密演算法) │
│ (Diffie-Hellman 金鑰交換) │
│<──────────────────────────────┤
│ (Session Key 建立) │
│ │
├──── 4. Authentication ───────>│
│ (密碼 or 公私鑰) │
│<──────────────────────────────┤
│ (OK or Fail) │
│ │
├──── 5. Session Established ──>│
│ (開始執行命令) │
│<──────────────────────────────┤
│ (命令輸出) │
│ │
└────── 6. Disconnect ──────────┘階段 1:TCP 連線建立
Client → Server (Port 22)
1. SYN
2. SYN-ACK
3. ACK
→ TCP 連線建立完成階段 2:Version Exchange(版本交換)
Client 先發送:
SSH-2.0-OpenSSH_8.9 Ubuntu-3ubuntu0.1\r\n
格式:
SSH-<protocol_version>-<software_version> <comments>
範例:
SSH-2.0-OpenSSH_8.9 Ubuntu-3ubuntu0.1
└──┬─┘ └────────┬─────────┘ └───────┬────────┘
協定版本 軟體版本 註解Server 回應:
SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u2\r\n版本檢查:
如果 Client 是 SSH-1.x:
Server:「SSH-1 不安全,拒絕連線!」
如果雙方都是 SSH-2.x:
「OK,繼續!」階段 3:Key Exchange(金鑰交換)⭐
目的:建立 Session Key(會話金鑰)
問題:
Client 和 Server 如何安全地協商出一個共同的金鑰?
→ 使用 Diffie-Hellman 金鑰交換
Diffie-Hellman 簡化原理:
1. 雙方協商公開參數
- p = 大質數
- g = 生成元
2. Client 產生私鑰 a (保密)
計算:A = g^a mod p
發送 A 給 Server
3. Server 產生私鑰 b (保密)
計算:B = g^b mod p
發送 B 給 Client
4. 雙方計算共享金鑰
Client: K = B^a mod p = g^(ab) mod p
Server: K = A^b mod p = g^(ab) mod p
結果:
✅ 雙方得到相同的 K
✅ 中間人只知道 A, B, p, g,無法推算出 K
✅ 即使被監聽,也無法得到金鑰實際 SSH Key Exchange 流程:
1. Algorithm Negotiation(演算法協商)
Client → Server: 我支援這些演算法
{
kex: [curve25519-sha256, diffie-hellman-group14-sha256, ...],
encryption: [aes256-gcm, chacha20-poly1305, ...],
mac: [hmac-sha2-256, hmac-sha2-512, ...],
compression: [none, zlib]
}
Server → Client: 我選擇這些
{
kex: curve25519-sha256,
encryption: aes256-gcm,
mac: hmac-sha2-256,
compression: none
}
2. Diffie-Hellman Exchange
Client → Server: Client's DH public key (ephemeral)
Server → Client:
- Server's DH public key
- Server Host Key (RSA/ED25519 public key)
- Signature (用 Server 私鑰簽署)
3. Client 驗證
- 計算 Shared Secret
- 驗證 Server 簽章
- 檢查 Host Key (known_hosts)
4. 雙方產生 Session Keys
從 Shared Secret 衍生出 6 個金鑰:
- Initial IV client → server
- Initial IV server → client
- Encryption key client → server
- Encryption key server → client
- MAC key client → server
- MAC key server → client
5. 加密通訊開始
後續所有封包都用 Session Key 加密Host Key 驗證(防止中間人攻擊):
首次連線:
The authenticity of host 'example.com (192.168.1.100)' can't be established.
ED25519 key fingerprint is SHA256:jklmnopqrstuvwxyz1234567890abcdef.
Are you sure you want to continue connecting (yes/no)?
→ 輸入 yes 後,Host Key 會儲存在 ~/.ssh/known_hosts
後續連線:
自動比對 known_hosts 中的 Host Key
→ 如果 match:安全,繼續
→ 如果不match:警告!可能是中間人攻擊!
警告訊息:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!階段 4:Authentication(認證)⭐⭐
SSH 支援多種認證方式:
- Password Authentication(密碼認證)
- Public Key Authentication(公私鑰認證) ⭐ 推薦
- Host-based Authentication(主機認證)
- Keyboard-Interactive(鍵盤互動)
方法 1:Password Authentication
流程:
1. Client → Server: "我要用密碼認證"
2. Server → Client: "OK,請輸入密碼"
3. Client → Server: password (加密傳輸)
4. Server 驗證密碼
5. Server → Client: "成功" or "失敗"
注意:
雖然密碼有加密(用 Session Key),但仍有風險:
❌ 密碼可能被暴力破解
❌ 密碼可能被字典攻擊
❌ 伺服器需要儲存密碼(或 hash)
建議:
✅ 使用強密碼(16+ 字元,大小寫數字符號)
✅ 啟用 Fail2ban(防暴力破解)
✅ 更好:改用公私鑰認證!方法 2:Public Key Authentication(推薦)⭐⭐⭐
原理:非對稱加密
公私鑰概念:
Public Key(公鑰):
- 可以公開給所有人
- 用來加密
- 用來驗證簽章
Private Key(私鑰):
- 絕對保密,只有自己知道
- 用來解密
- 用來簽署
特性:
✅ 公鑰加密 → 只有私鑰能解密
✅ 私鑰簽署 → 只有公鑰能驗證SSH 公私鑰認證流程:
準備階段(只需做一次):
1. Client 產生金鑰對
ssh-keygen -t ed25519 -C "your_email@example.com"
產生:
~/.ssh/id_ed25519 ← Private Key(私鑰,保密)
~/.ssh/id_ed25519.pub ← Public Key(公鑰,可分享)
2. 將 Public Key 複製到 Server
ssh-copy-id user@server
或手動:
cat ~/.ssh/id_ed25519.pub | ssh user@server "cat >> ~/.ssh/authorized_keys"
連線階段:
1. Client → Server: "我要用公私鑰認證,這是我的 Public Key"
2. Server 檢查 ~/.ssh/authorized_keys
→ 找到 Client 的 Public Key ✅
3. Server 產生隨機挑戰(Challenge)
challenge = random_bytes()
4. Server → Client: 用 Client 的 Public Key 加密 challenge
5. Client 用 Private Key 解密
decrypted = decrypt_with_private_key(challenge)
6. Client 用 Private Key 簽署
signature = sign_with_private_key(decrypted)
7. Client → Server: signature
8. Server 用 Public Key 驗證簽章
verify_signature(signature, public_key)
✅ 驗證通過 → 認證成功!
❌ 驗證失敗 → 拒絕連線
優點:
✅ 私鑰從不傳輸(非常安全)
✅ 無法被暴力破解
✅ 可以設定 passphrase(雙重保護)
✅ 可以一次設定,到處使用金鑰類型選擇:
| 演算法 | 金鑰長度 | 安全性 | 速度 | 推薦 |
|---|---|---|---|---|
| RSA | 2048-4096 bits | ⭐⭐ | 慢 | ⚠️ 舊標準 |
| DSA | 1024 bits | ⚠️ 弱 | 中 | ❌ 已淘汰 |
| ECDSA | 256-521 bits | ⭐⭐⭐ | 快 | ⭐ 可用 |
| ED25519 | 256 bits | ⭐⭐⭐ | 最快 | ✅ 推薦 |
建議:
# 推薦:ED25519(最新、最安全、最快)
ssh-keygen -t ed25519 -C "your_email@example.com"
# 備選:RSA 4096(相容性好,但較慢)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"階段 5:Session Established(建立會話)
認證成功後,建立 SSH Session
Client 可以:
1. 開啟終端機 (Shell)
ssh user@server
→ 執行命令
2. 執行單一命令
ssh user@server "ls -la"
→ 執行完自動斷開
3. 檔案傳輸 (SCP/SFTP)
scp file.txt user@server:/path/
sftp user@server
4. Port Forwarding(端口轉發)
ssh -L 8080:localhost:80 user@server
→ 本機 8080 → Server 80
5. 動態 Port Forwarding(SOCKS Proxy)
ssh -D 1080 user@server
→ 所有流量透過 Server🚀 SSH 實用功能
1. 基本遠端登入
# 登入遠端伺服器
ssh user@server.com
# 指定 port
ssh -p 2222 user@server.com
# 執行單一命令
ssh user@server.com "ls -la /var/log"
# 執行多個命令
ssh user@server.com "cd /var/log && ls -la"2. 檔案傳輸
SCP (Secure Copy)
# 上傳檔案
scp local_file.txt user@server:/remote/path/
# 下載檔案
scp user@server:/remote/file.txt ./local_path/
# 上傳目錄(遞迴)
scp -r local_folder user@server:/remote/path/
# 指定 port
scp -P 2222 file.txt user@server:/path/
# 顯示進度
scp -v file.txt user@server:/path/SFTP (SSH File Transfer Protocol)
# 進入 SFTP 互動式介面
sftp user@server
SFTP 命令:
sftp> ls # 列出遠端檔案
sftp> lls # 列出本機檔案
sftp> cd /path # 切換遠端目錄
sftp> lcd /path # 切換本機目錄
sftp> get file # 下載檔案
sftp> put file # 上傳檔案
sftp> rm file # 刪除遠端檔案
sftp> mkdir dir # 建立遠端目錄
sftp> bye # 離開3. Port Forwarding(端口轉發)⭐⭐⭐
Local Port Forwarding(本機端口轉發)
場景:存取遠端內網服務
範例:Server 內網有一個 MySQL (localhost:3306)
你在本機想要連線
命令:
ssh -L 3307:localhost:3306 user@server
流程:
你的電腦:3307 → SSH Tunnel → Server → localhost:3306
本機連線:
mysql -h 127.0.0.1 -P 3307 -u root -p
→ 實際連到 Server 的 MySQL!
應用場景:
✅ 存取遠端資料庫(MySQL, PostgreSQL, Redis)
✅ 存取內網網頁(localhost:8080)
✅ 繞過防火牆進階範例:
# 存取 Server 內網的其他機器
ssh -L 8080:internal-server:80 user@jump-server
# 多個端口轉發
ssh -L 3307:localhost:3306 \
-L 6380:localhost:6379 \
-L 8080:localhost:80 \
user@serverRemote Port Forwarding(遠端端口轉發)
場景:讓遠端 Server 存取你本機的服務
範例:你本機有 Web Server (localhost:8000)
想讓 Server 能存取
命令:
ssh -R 9000:localhost:8000 user@server
流程:
Server:9000 → SSH Tunnel → 你的電腦:8000
在 Server 上:
curl http://localhost:9000
→ 實際連到你本機的 Web Server!
應用場景:
✅ Demo 本機開發的網站給遠端
✅ 臨時分享本機服務
✅ Webhook 測試Dynamic Port Forwarding(SOCKS Proxy)
場景:所有流量都透過 Server
命令:
ssh -D 1080 user@server
設定瀏覽器使用 SOCKS Proxy:
Host: localhost
Port: 1080
效果:
所有瀏覽器流量 → SSH Tunnel → Server → Internet
應用場景:
✅ 繞過公司防火牆
✅ 保護隱私(流量經過 Server)
✅ 存取地區限制的服務4. SSH Config(設定檔)
簡化連線設定:
# ~/.ssh/config
Host myserver
HostName 192.168.1.100
User admin
Port 2222
IdentityFile ~/.ssh/id_ed25519
LocalForward 3307 localhost:3306
ServerAliveInterval 60
Host github
HostName github.com
User git
IdentityFile ~/.ssh/github_ed25519
Host jump
HostName jump-server.com
User ops
Port 22
Host internal
HostName 10.0.0.50
User dev
ProxyJump jump # 透過 jump 連線
使用:
ssh myserver # 等於 ssh -p 2222 admin@192.168.1.100 ...
ssh github # 等於 ssh git@github.com -i ~/.ssh/github_ed25519
ssh internal # 自動透過 jump 跳板連線常用設定:
# 全域設定(所有 Host)
Host *
ServerAliveInterval 60 # 每 60 秒發送 keepalive
ServerAliveCountMax 3 # 最多 3 次無回應就斷線
Compression yes # 啟用壓縮
ControlMaster auto # 連線重用
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600 # 持續 10 分鐘
# 特定網域設定
Host *.example.com
User admin
IdentityFile ~/.ssh/example_key5. SSH Tunnel(隧道)
建立持久的 SSH Tunnel:
# 背景執行
ssh -fN -L 3307:localhost:3306 user@server
參數說明:
-f : 背景執行
-N : 不執行遠端命令(只做 port forwarding)
-L : Local port forwarding
# 檢查 Tunnel 是否存活
ps aux | grep "ssh -fN"
# 關閉 Tunnel
pkill -f "ssh -fN"使用 autossh(自動重連):
# 安裝
sudo apt install autossh
# 使用 autossh(自動重連)
autossh -M 0 -f -N -L 3307:localhost:3306 user@server
-M 0 : 不使用監控 port(改用 ServerAliveInterval)🔐 SSH 安全性
1. 伺服器端加固
# /etc/ssh/sshd_config
# 禁用 root 直接登入
PermitRootLogin no
# 禁用密碼登入(只允許公私鑰)
PasswordAuthentication no
PubkeyAuthentication yes
# 禁用空密碼
PermitEmptyPasswords no
# 限制登入使用者
AllowUsers user1 user2
# 或禁止特定使用者
DenyUsers baduser
# 修改預設 port(減少掃描)
Port 2222
# 限制認證嘗試次數
MaxAuthTries 3
# 限制同時連線數
MaxSessions 5
# 設定閒置超時
ClientAliveInterval 300
ClientAliveCountMax 2
# 禁用 X11 Forwarding(如不需要)
X11Forwarding no
# 啟用嚴格模式(檢查檔案權限)
StrictModes yes
# 只允許 SSH Protocol 2
Protocol 2
# 重啟 SSH service
sudo systemctl restart sshd2. 使用 Fail2ban(防暴力破解)
# 安裝
sudo apt install fail2ban
# 設定 /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 22
logpath = /var/log/auth.log
maxretry = 3 # 3 次失敗就封鎖
bantime = 3600 # 封鎖 1 小時
findtime = 600 # 10 分鐘內的嘗試
# 啟動
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
# 檢查被封鎖的 IP
sudo fail2ban-client status sshd3. 使用 SSH 金鑰 Passphrase
# 產生金鑰時設定 passphrase
ssh-keygen -t ed25519 -C "email@example.com"
Enter passphrase (empty for no passphrase): ********
Enter same passphrase again: ********
優點:
✅ 即使私鑰被竊取,沒有 passphrase 也無法使用
✅ 雙重保護
使用 ssh-agent 避免重複輸入:
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519
→ 輸入一次 passphrase,之後自動使用4. 定期審查 authorized_keys
# 檢查誰有權限登入
cat ~/.ssh/authorized_keys
# 刪除不需要的 key
vim ~/.ssh/authorized_keys
# 限制 key 的使用(加上限制)
# 只能從特定 IP
from="192.168.1.100" ssh-ed25519 AAAA...
# 只能執行特定命令
command="/usr/bin/backup.sh" ssh-ed25519 AAAA...
# 禁止 port forwarding
no-port-forwarding ssh-ed25519 AAAA...
# 組合使用
from="192.168.1.100",command="/backup.sh",no-port-forwarding ssh-ed25519 AAAA...🎓 面試常見問題
Q1:SSH 和 Telnet 有什麼差異?為什麼不能用 Telnet?
A:SSH 加密,Telnet 明文
Telnet(已淘汰):
❌ 明文傳輸(包括密碼)
❌ 無伺服器身份驗證
❌ 無完整性保護
❌ Port 23
範例危害:
用 Wireshark 可直接看到:
username: admin
password: myPassword123
→ 帳號密碼直接暴露!
SSH(現代標準):
✅ 加密傳輸(AES-256, ChaCha20)
✅ 伺服器身份驗證(Host Key)
✅ 完整性保護(HMAC)
✅ 多種認證方式(密碼、公私鑰)
✅ Port 22
範例:
即使被監聽,也只能看到:
sD9fj#$kL@mNpQ2vX8wZ... (亂碼)
→ 完全看不懂!
結論:
Telnet 絕對不要使用!
SSH 是現代標準,必須使用!
記憶:
Telnet = 明信片(任何人都能看)
SSH = 密封信件(只有收件人能看)Q2:SSH 連線建立的流程是什麼?
A:5 個階段
1. TCP 連線建立
Client → Server (Port 22)
三次握手
2. Version Exchange(版本交換)
Client: SSH-2.0-OpenSSH_8.9
Server: SSH-2.0-OpenSSH_7.9
→ 確認雙方都用 SSH-2.0
3. Key Exchange(金鑰交換)⭐
a) Algorithm Negotiation(協商演算法)
- 加密:AES-256-GCM
- MAC:HMAC-SHA2-256
- 金鑰交換:Curve25519
b) Diffie-Hellman 金鑰交換
Client: 產生臨時私鑰 a,發送 A = g^a mod p
Server: 產生臨時私鑰 b,發送 B = g^b mod p
雙方計算:K = g^(ab) mod p
c) Server 認證
Server 發送 Host Key + 簽章
Client 驗證 known_hosts
d) 產生 Session Keys
從 Shared Secret 衍生 6 個金鑰
(加密、MAC、IV,雙向各 3 個)
4. Authentication(使用者認證)
方式 1:密碼
方式 2:公私鑰(推薦)
方式 3:Host-based
5. Session Established(建立會話)
✅ 認證成功
→ 開始執行命令、傳輸檔案
面試重點:
- 金鑰交換使用 Diffie-Hellman
- Session Key 是對稱金鑰(AES)
- Host Key 用於驗證伺服器身份
- 公私鑰認證比密碼更安全Q3:SSH 公私鑰認證的原理是什麼?為什麼比密碼安全?
A:非對稱加密 + Challenge-Response
公私鑰概念:
- Public Key(公鑰):可公開,用來加密、驗證簽章
- Private Key(私鑰):保密,用來解密、簽署
特性:
公鑰加密 → 只有私鑰能解密
私鑰簽署 → 只有公鑰能驗證
認證流程:
1. 準備(一次性)
Client 產生金鑰對:
ssh-keygen -t ed25519
→ id_ed25519 (私鑰,保密)
→ id_ed25519.pub (公鑰,可分享)
複製公鑰到 Server:
ssh-copy-id user@server
→ 加到 ~/.ssh/authorized_keys
2. 連線時
a) Client: "我要用公私鑰認證"
b) Server: 產生隨機挑戰,用 Client 公鑰加密
c) Client: 用私鑰解密,簽署,發送簽章
d) Server: 用公鑰驗證簽章
e) ✅ 驗證通過 → 認證成功
為什麼比密碼安全:
密碼認證:
❌ 密碼可能被暴力破解(字典攻擊)
❌ 密碼可能太弱(123456)
❌ 密碼需要在伺服器上儲存(風險)
❌ 每次輸入密碼(不方便)
公私鑰認證:
✅ 私鑰從不傳輸(絕對安全)
✅ 無法暴力破解(2048 位元以上)
✅ 伺服器只儲存公鑰(即使洩漏也無用)
✅ 一次設定,到處使用(方便)
✅ 可加 passphrase(雙重保護)
額外保護:
私鑰加密 (passphrase):
ssh-keygen 時設定 passphrase
→ 即使私鑰被竊取,沒有 passphrase 也無法使用
結論:
公私鑰認證 >> 密碼認證
建議禁用密碼認證(PasswordAuthentication no)Q4:什麼是 SSH Port Forwarding?有哪些類型?
A:透過 SSH 建立加密隧道,轉發流量
3 種類型:
1️⃣ Local Port Forwarding(本機端口轉發)
ssh -L [本機port]:目標host:目標port user@跳板機
範例:
ssh -L 3307:localhost:3306 user@server
流程:
本機:3307 → SSH Tunnel → Server → localhost:3306
使用:
mysql -h 127.0.0.1 -P 3307
→ 連到 Server 的 MySQL
場景:
- 存取遠端資料庫(MySQL, PostgreSQL, Redis)
- 存取內網服務
- 繞過防火牆
2️⃣ Remote Port Forwarding(遠端端口轉發)
ssh -R [遠端port]:本機host:本機port user@server
範例:
ssh -R 9000:localhost:8000 user@server
流程:
Server:9000 → SSH Tunnel → 本機:8000
使用(在 Server 上):
curl http://localhost:9000
→ 存取你本機的服務
場景:
- Demo 本機開發的網站
- Webhook 測試
- 臨時分享本機服務
3️⃣ Dynamic Port Forwarding(動態端口轉發,SOCKS Proxy)
ssh -D [本機port] user@server
範例:
ssh -D 1080 user@server
流程:
所有應用程式 → SOCKS Proxy (localhost:1080)
→ SSH Tunnel → Server → Internet
使用:
設定瀏覽器 SOCKS Proxy: localhost:1080
→ 所有流量透過 Server
場景:
- 繞過防火牆
- 保護隱私
- VPN 替代方案
參數說明:
-L : Local port forwarding
-R : Remote port forwarding
-D : Dynamic port forwarding
-N : 不執行命令(純 forwarding)
-f : 背景執行
實用組合:
ssh -fN -L 3307:localhost:3306 user@server
→ 背景執行,純 port forwarding
應用場景總結:
Local Forward → 存取遠端內網
Remote Forward → 分享本機服務
Dynamic Forward → 全局代理
面試加分:
提到安全性:
✅ 所有流量都經過 SSH 加密
✅ 可以繞過防火牆
⚠️ 需注意授權(公司政策)Q5:如何加固 SSH 伺服器的安全性?
A:10 個最佳實踐
1️⃣ 禁用 root 登入
/etc/ssh/sshd_config:
PermitRootLogin no
原因:
- root 是已知的帳號名稱
- 攻擊者會優先嘗試 root
- 改用一般帳號 + sudo
2️⃣ 禁用密碼登入,只允許公私鑰
PasswordAuthentication no
PubkeyAuthentication yes
原因:
- 公私鑰無法暴力破解
- 密碼可能太弱
3️⃣ 修改預設 port
Port 2222
原因:
- 減少自動化掃描攻擊
- Port 22 是預設目標
4️⃣ 限制登入使用者
AllowUsers alice bob
或
DenyUsers baduser
原因:
- 最小權限原則
- 只允許需要的人
5️⃣ 限制認證嘗試
MaxAuthTries 3
原因:
- 3 次失敗就斷開
- 減緩暴力破解
6️⃣ 使用 Fail2ban
安裝並設定:
[sshd]
maxretry = 3
bantime = 3600
原因:
- 自動封鎖暴力破解 IP
- 3 次失敗 → 封鎖 1 小時
7️⃣ 設定閒置超時
ClientAliveInterval 300
ClientAliveCountMax 2
原因:
- 5 分鐘無活動 → 2 次檢查 → 斷開
- 避免殭屍連線
8️⃣ 使用強金鑰
ssh-keygen -t ed25519 -b 256
原因:
- ED25519 最安全、最快
- 避免 RSA 1024(已不安全)
9️⃣ 金鑰加 passphrase
ssh-keygen 時設定 passphrase
原因:
- 雙重保護
- 私鑰被竊也需要 passphrase
🔟 定期審查 authorized_keys
cat ~/.ssh/authorized_keys
原因:
- 刪除離職員工的 key
- 限制 key 的權限
額外:
11. 啟用 SSH 日誌監控
tail -f /var/log/auth.log
12. 使用防火牆限制來源 IP
ufw allow from 192.168.1.0/24 to any port 22
13. 定期更新
sudo apt update && sudo apt upgrade openssh-server
檢查清單:
✅ 禁用 root 登入
✅ 禁用密碼認證
✅ 改 port
✅ Fail2ban
✅ 強金鑰 + passphrase
✅ 限制使用者
✅ 閒置超時
✅ 監控日誌
記憶口訣:
「禁root改port,鑰ban超限監」
禁root、改port、公鑰、Fail2ban、超時、限制、監控Q6:SSH 金鑰類型(RSA、ED25519)該如何選擇?
A:推薦 ED25519,RSA 4096 備選
金鑰類型對比:
DSA (已淘汰):
❌ 1024 bits(太短)
❌ 安全性已被破解
❌ OpenSSH 7.0+ 已禁用
→ 絕對不要使用
RSA (舊標準):
⭐ 2048 bits 最低
⭐⭐ 4096 bits 推薦
✅ 相容性好(舊系統支援)
✅ 成熟穩定
❌ 效能慢(尤其 4096 bits)
❌ 金鑰檔案大
產生:
ssh-keygen -t rsa -b 4096
ECDSA (橢圓曲線):
⭐⭐⭐ 256-521 bits
✅ 效能好
✅ 金鑰小
⚠️ NIST 曲線(有後門疑慮)
⚠️ 實作複雜(可能有漏洞)
→ 不推薦
ED25519 (最新推薦):
⭐⭐⭐ 256 bits
✅ 最安全(抗量子計算)
✅ 最快
✅ 金鑰最小
✅ 實作簡單(不易出錯)
✅ 現代標準
⚠️ 舊系統可能不支援(OpenSSH 6.5+)
產生:
ssh-keygen -t ed25519
對比表:
| 演算法 | 安全性 | 速度 | 金鑰大小 | 相容性 | 推薦 |
|--------|--------|------|---------|--------|------|
| DSA | ❌ 弱 | 中 | 中 | 好 | ❌ 淘汰 |
| RSA 2048 | ⭐⭐ | 慢 | 大 | 極好 | ⚠️ 可用 |
| RSA 4096 | ⭐⭐⭐ | 很慢 | 很大 | 極好 | ⭐ 備選 |
| ECDSA | ⭐⭐⭐ | 快 | 小 | 好 | ⚠️ 不推薦 |
| ED25519 | ⭐⭐⭐ | 最快 | 最小 | 中 | ✅ 首選 |
效能對比(簽署速度):
ED25519: 10000 次/秒
ECDSA: 8000 次/秒
RSA 2048: 1000 次/秒
RSA 4096: 300 次/秒
金鑰檔案大小:
ED25519: 399 bytes
ECDSA 256: 302 bytes
RSA 2048: 1679 bytes
RSA 4096: 3243 bytes
建議策略:
新系統:
ssh-keygen -t ed25519 -C "your_email@example.com"
→ ED25519(最佳選擇)
需要相容舊系統:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
→ RSA 4096(備選方案)
同時產生兩種(保險):
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
SSH Config:
Host modern-server
IdentityFile ~/.ssh/id_ed25519
Host legacy-server
IdentityFile ~/.ssh/id_rsa
結論:
首選 ED25519(安全、快速、現代)
備選 RSA 4096(相容性)
避免 ECDSA(後門疑慮)
拒絕 DSA(已淘汰)✅ 重點回顧
SSH 定義:
- SSH = Secure Shell
- 加密的遠端登入協定
- Port 22
vs Telnet:
- Telnet:明文、不安全、已淘汰
- SSH:加密、安全、現代標準
連線流程(5 階段):
- TCP 連線建立
- Version Exchange(版本交換)
- Key Exchange(金鑰交換,Diffie-Hellman)
- Authentication(密碼 or 公私鑰)
- Session Established(建立會話)
認證方式:
- Password(密碼):方便但較不安全
- Public Key(公私鑰):推薦,私鑰從不傳輸
實用功能:
- 遠端登入:
ssh user@server - 檔案傳輸:
scp,sftp - Port Forwarding:Local (
-L), Remote (-R), Dynamic (-D)
金鑰類型選擇:
- ✅ ED25519(首選)
- ⭐ RSA 4096(備選)
- ❌ DSA(淘汰)
安全加固:
- 禁用 root 登入
- 禁用密碼認證
- 修改預設 port
- 使用 Fail2ban
- 金鑰加 passphrase
面試重點:
- ✅ SSH vs Telnet 差異
- ✅ 連線建立流程(5 階段)
- ✅ 公私鑰認證原理
- ✅ Port Forwarding 3 種類型
- ✅ 安全加固措施
- ✅ 金鑰類型選擇
記憶口訣:
- 「版鑰認會」= Version, Key Exchange, Authentication, Session
上一篇: 07-3. SCP 檔案複製 下一篇: 08-2. Telnet 協定
相關文章:
最後更新:2025-01-15