13.8. OpenSSH

Contributed by Chern Lee.

OpenSSH 是一套網路連線工具,可安全的存取遠端的主機,此外,透過 SSH 連線可以建立 TCP/IP 連線通道或安全的轉送 TCP/IP 的封包。OpenSSH 會對所有傳輸的資料做加密,可有效的避免竊聽 (Eavesdropping)、或連線劫持 (Connection hijacking) 與其他網路層的攻擊。

OpenSSH 由 OpenBSD 專案所維護且在 FreeBSD 預設會安裝,它可同時相容 SSH 版本 1 與 2 通訊協定。

當以未加密的方式在網路上傳送資料時,任何在客戶端與伺服器之間的網路竊聽程式 (Network sniffer) 皆可竊取使用者/密碼資訊或者在連線階段傳送的資料,OpenSSH 提供了數種認証與加密方式來避免這種事情發生。更多有關 OpenSSH 的資訊可於 http://www.openssh.com/ 取得。

本節會簡單介紹如何使用內建的客戶端工具安全的存取其他系統及安全的傳輸檔案到 FreeBSD 系統,然後會說明如何設定在 FreeBSD 系統上的 SSH 伺服器。更多的資訊可於本章節所提及的操作手冊 (Man page) 取得。

13.8.1. 使用 SSH 客戶端工具

要登入一台 SSH 伺服器,可使用 ssh 然後指定在伺服器上存在的使用者名稱與 IP 位址或伺服器的主機名稱。若這是第一次連線到指定的伺服器,會提示該使用者伺服器的指紋做第一次檢驗:

# ssh user@example.com
The authenticity of host 'example.com (10.0.0.1)' can't be established.
ECDSA key fingerprint is 25:cc:73:b5:b3:96:75:3d:56:19:49:d2:5c:1f:91:3b.
Are you sure you want to continue connecting (yes/no)? yes
Permanently added 'example.com' (ECDSA) to the list of known hosts.
Password for user@example.com: user_password

SSH 會在客戶端連線時利用金鑰指紋 (Key fingerprint) 系統來驗證伺服器的真偽,當使用者在第一次連線時輸入 yes 接受了這個金鑰指紋,便會將該金鑰的複本儲存到使用者家目錄的 .ssh/known_hosts,未來嘗試登入時便會以這個存好的金鑰來驗證,若伺服器的金鑰與儲存的金鑰不同將會顯示警告訊息。若出現這個警告時,使用者應在繼續連線之前檢查金鑰變動的原因。

最近版本的 OpenSSH 預設只會接受 SSHv2 的連線。客戶端預設會盡可能使用版本 2 的通訊協定,若伺服器不支援版本 2 的通訊協定便會向下相容版本 1 的協定。要強制 ssh 只能使用指定的通訊協定,可使用 -1-2,其他的選項在 ssh(1) 中有說明。

使用 scp(1) 可從遠端主機安全的複製一個檔案,以下範例會複製在遠端主機的 COPYRIGHT 到本地主機的目前目錄:

# scp user@example.com:/COPYRIGHT COPYRIGHT
Password for user@example.com: *******
COPYRIGHT            100% |*****************************|  4735
00:00
#

由於這個主機的指紋已驗證過,在提示用者輸入密碼之前伺服器的金鑰已自動檢查。

傳給 scp 的參數與傳給 cp 的參數相似。第一個參數是要複製的檔案,第二個參數是目地,由於檔案是透過網路取得,檔案參數需要使用 user@host:<path_to_remote_file> 格式。注意,在 scp 要遞迴複製目錄是使用 -r,如同 cp 使用 -R

要開啟可互動的連線來複製檔案可使用 sftp,請參考 sftp(1) 來取得在 sftp 連線時可用的指令清單。

13.8.1.1. 以金鑰為基礎的認證

除了使用密碼之外,客戶端可以設定成使用金鑰來連線到遠端的主機。要產生 RSA 認証金鑰可使用 ssh-keygen。要產生成對的公鑰與私鑰,可指定金鑰的類型並依提示操作。建議使用容易記住但較難猜出的密碼來保護這個金鑰。

% ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):  1
Enter same passphrase again:                 2
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:54Xm9Uvtv6H4NOo6yjP/YCfODryvUU7yWHzMqeXwhq8 user@host.example.com
The key's randomart image is:
+---[RSA 2048]----+
|                 |
|                 |
|                 |
|        . o..    |
|       .S*+*o    |
|      . O=Oo . . |
|       = Oo= oo..|
|      .oB.* +.oo.|
|       =OE**.o..=|
+----[SHA256]-----+

1

在此輸入密碼,密碼不可含有空白或符號。

2

再輸入一次密碼驗證。

私鑰會儲存於 ~/.ssh/id_rsa 而公鑰會儲存於 ~/.ssh/id_rsa.pub公鑰必須複製到遠端主機的~/.ssh/authorized_keys 來讓以金鑰為基礎的認証可以運作。

警告:

許多使用者認為金鑰的設計是安全的並在產生金鑰時未使用密碼,這樣的行為其實很危險。管理者可以手動查看私鑰來檢查金鑰對是否受密碼保護,如果私鑰檔案中包含 ENCRYPTED 字詞,則代表金鑰的擁有者有使用密碼。此外,要更進一步保護最終使用者的安全,可在公鑰檔案中放入 from,例如,在 ssh-rsa 前加上 from="192.168.10.5" 將只允許指定的使用者由該 IP 位址登入。

不同版本 OpenSSH 的選項與檔案會不同,要避免發生問題請參考 ssh-keygen(1)

若使用了密碼,在每次連線到伺服器時都會提示使用者輸入密碼。要將 SSH 金鑰載入到記憶體並讓每次連線時不必再輸入密碼,可使用 ssh-agent(1)ssh-add(1)

認証可用 ssh-agent 來管理,只要將私鑰載入,ssh-agent 可用在執行其他應用程式,如 Shell 或視窗管理程式。

要在 Shell 使用 ssh-agent,使用 Shell 做為參數來啟動 ssh-agent。執行 ssh-add 來加入識別碼,然後輸入私鑰的密碼。使用者將可使用 ssh 連線到任何有安裝對應公鑰的主機,例如:

% ssh-agent csh
% ssh-add
Enter passphrase for key '/usr/home/user/.ssh/id_rsa':  1
Identity added: /usr/home/user/.ssh/id_rsa (/usr/home/user/.ssh/id_rsa)
%

1

輸入金鑰的密碼。

要在 Xorg 使用 ssh-agent 可在 ~/.xinitrc 加入一個設定項目,這可讓 ssh-agent 對所有在 Xorg 中執行的程式提供服務。~/.xinitrc 範例如下:

exec ssh-agent startxfce4

這會在每次啟動 Xorg 時,反過來先執行 ssh-agent 再由執行 XFCE,一但 Xorg 被重新啟動,要讓所有變更生效需執行 ssh-add 來載入所有的 SSH 金鑰。

13.8.1.2. SSH 通道

OpenSSH 可以建立一個通道 (Tunnel) 來封裝其他通訊協定到一個加密的連線。

以下指令會告訴 ssh 建立一個供 telnet 使用的通道:

% ssh -2 -N -f -L 5023:localhost:23 user@foo.example.com
%

這個例子使用了以下選項:

-2

強制 ssh 使用版本 2 的通訊協定連線到伺服器。

-N

代表不需下指令、只建立通道。若省略這個選項 ssh 會初始化一個正常的連線。

-f

強制 ssh 在背景執行。

-L

代表這是一個本地通道,使用 localport:remotehost:remoteport 格式。

user@foo.example.com

在指定的遠端 SSH 伺服器要使用的登入名稱。

SSH 通道會建立一個傾聽 localhost 指定 localport 的 Socket ,然後會透過 SSH 連線轉送任何在 localport 接收的連線。以這個例子來說在客戶端的 Port 5023 會被轉送到遠端主機的 Port 23,由於 Port 23 是由 telnet 使用,所以這會透過 SSH 通道建立一個加密的 telnet 連線。

這個方法可用來包裝許多不安全的 TCP 通訊協定,例如 SMTP, POP3 以及 FTP,如下例所示。

範例 13.1. 建立供 SMTP 使用的安全通道
% ssh -2 -N -f -L 5025:localhost:25 user@mailserver.example.com
user@mailserver.example.com's password: *****
% telnet localhost 5025
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mailserver.example.com ESMTP

這可配合 ssh-keygen 與另一個使用者帳號與來建立一個更無縫的 SSH 通道環境,可使用金鑰來代替手動輸入密碼,然後該通道便可以另一個使用者執行。


範例 13.2. 安全存取 POP3 伺服器

在這個例子中有一個 SSH 伺服器會接受來自外部的連線,在同個網段下有一個郵件伺服器執行 POP3 伺服器。要使用較安全的方式檢查有沒有新郵件可建立一個 SSH 連線到 SSH 伺服器然後透過通道連線到郵件伺服器:

% ssh -2 -N -f -L 2110:mail.example.com:110 user@ssh-server.example.com
user@ssh-server.example.com's password: ******

一但通道啟動並執行後,指定郵件客戶端將 POP3 請求傳送到 localhost 的 Port 2110,這個連線將會被安全的透過通道轉送到 mail.example.com


範例 13.3. 跳過防火牆

有些防火牆會同時過濾傳入與傳出的連線。例如,防火牆很可能會限制來自遠端主機只能存取 Port 22 與 80 來只讓 SSH 與網頁瀏覽器連線,這會使得 Port 使用 22 或 80 以外的服務無法存取。

這問題的解決方法是建立一個 SSH 連線到在防火牆防護之外主機然後使用該連線的通道連到想要使用的服務:

% ssh -2 -N -f -L 8888:music.example.com:8000 user@unfirewalled-system.example.org
user@unfirewalled-system.example.org's password: *******

在這個例子中,串流 Ogg Vorbis 客戶端現在可以指向 localhost Port 8888,連線將會被轉送到 music.example.com 於 Port 8000,成功的跳過防火牆。


13.8.2. 開啟 SSH 伺服器

除了提供內建的 SSH 客戶端工具外,還可以設定 FreeBSD 系統為一個 SSH 伺服器,以接受來自其他 SSH 客戶端的連線。

要查看 sshd 是否正在運作,可使用 service(8) 指令:

# service sshd status

若服務未執行,請加入下行到 /etc/rc.conf

sshd_enable="YES"

這會讓下次系統開機時啟動 OpenSSH 的 Daemon 程式 sshd。若要立即啟動:

# service sshd start

在 FreeBSD 系統第一次啟動 sshd 時便會自動產生系統的主機金鑰且會顯示指紋在 Console 上,這個指紋可供使用者在第一次連線到伺服器時驗證用。

請參考 sshd(8) 可取得在啟動 sshd 時可用選項的清單以及更多完整有關認証、登入程序與各種設定檔的資訊。

現在,sshd 應可供所有在系統上有使用者名稱及密碼的使用者使用。

13.8.3. SSH 伺服器安全性

在 FreeBSD 廣泛使用 sshd 做為遠端管理基礎設施的同時,所有暴露在公有網路上的系統也會時常受到暴力攻擊 (Brute force attack) 與路過攻擊 (Drive by attack)。在本節會介紹一些可用來避免這些攻擊的參數。

使用在 OpenSSH 伺服器設定檔的 AllowUsers 關鍵字限制可以登入到 SSH 伺服器的使用者及來源是一個不錯的方式。例如要只允許來自 192.168.1.32root 登入,可加入下行到 /etc/ssh/sshd_config

AllowUsers root@192.168.1.32

要允許來自任何地方的 admin 登入,可只列出使用者名稱,不指定 IP 位址:

AllowUsers admin

有多位使用者也應列在同一行,例如:

AllowUsers root@192.168.1.32 admin

在對 /etc/ssh/sshd_config 做完變更後,執行以下指令告訴 sshd 重新載入設定檔:

# service sshd reload

注意:

在使用了這個關鍵字時,列出每一位需要登入此主機的使用者很重要,任何未被在該行指定的使用者將無法登入。同時,在 OpenSSH 伺服器設定檔使用的關鍵字是區分大小寫的,若關鍵字未正確的拼寫 (含其大小寫),則將會被忽略,永遠要記得測試對這個檔案所做的更改來確保伺服器有如預期的方式運作。請參考 sshd_config(5) 來檢查拼寫以及可用的關鍵字。

此外,使用者可能被強制要透過公鑰與私鑰使用雙重認證 (Two factor authentication)。當需要時,使用者可以透過使用 ssh-keygen(1) 產生一堆金鑰然後將公鑰傳送給管理者,這個金鑰檔會如以上在客戶端章節所述的被放在 authorized_keys。要強制使用者只能使用這個金鑰,可能需要設定以下選項:

AuthenticationMethods publickey

提示:

請不要將 /etc/ssh/sshd_config 以及 /etc/ssh/ssh_config 搞混 (注意在第一節檔名有多出個 d),第一個檔案用來設定伺服器,而第二個檔案用來設定客戶端。請參考 ssh_config(5) 來取得可用的客戶端設定清單。

本文及其他文件,可由此下載: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/

若有 FreeBSD 方面疑問,請先閱讀 FreeBSD 相關文件,如不能解決的話,再洽詢 <questions@FreeBSD.org>。

關於本文件的問題,請洽詢 <doc@FreeBSD.org>。