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(雜湊訊息驗證碼)
   如果被竄改 → 立即發現並拒絕! ✅

對比表:

特性TelnetSSH
傳輸加密❌ 明文✅ 加密
密碼安全❌ 明文✅ 加密
伺服器驗證❌ 無✅ 有
完整性保護❌ 無✅ 有
預設 Port2322
使用場景❌ 已淘汰✅ 現代標準
安全性⚠️ 非常危險✅ 安全

結論:

  • 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 LayerLayer 7TCP (Layer 4)
TCP/IP 4 層Application LayerLayer 4TCP (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 支援多種認證方式:

  1. Password Authentication(密碼認證)
  2. Public Key Authentication(公私鑰認證) ⭐ 推薦
  3. Host-based Authentication(主機認證)
  4. 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(雙重保護)
✅ 可以一次設定,到處使用

金鑰類型選擇:

演算法金鑰長度安全性速度推薦
RSA2048-4096 bits⭐⭐⚠️ 舊標準
DSA1024 bits⚠️ 弱❌ 已淘汰
ECDSA256-521 bits⭐⭐⭐⭐ 可用
ED25519256 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@server

Remote 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_key

5. 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 sshd

2. 使用 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 sshd

3. 使用 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 階段):

  1. TCP 連線建立
  2. Version Exchange(版本交換)
  3. Key Exchange(金鑰交換,Diffie-Hellman)
  4. Authentication(密碼 or 公私鑰)
  5. 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

0%