這篇本是 「Ubuntu Server 安裝後的安全設定」其中一部份。但因篇幅略長,於是抽取了出來。
環境:Ubuntu Server 20.04 (LTS)
若你見到 <橙色>,代表你需要轉換內容。
這裡會對 SSHD CONFIG 作出兩個改動,分別為:
- 禁止 SSH 使用密碼登入(慎選)
- 修改 SSH 登入 Port
在任何修改前,先備份現有的設定檔:
mkdir ~/ssh_backup/
sudo cp -a /etc/ssh ~/ssh_backup/
Table of Contents
禁止 SSH 使用密碼登入(慎選)
很多人都認為需要禁用密碼登入,改以私鑰登入。我個人是視乎情況選擇用密碼/私鑰登入。
密碼登入的話,我會使用密碼管理器( e.g. Bitwarden),產生數十位長度的隨機密碼。在我眼中,只要密碼夠長(≥20),便足夠安全了。
以下我們會禁用密碼登入,改為以私鑰登入:
- 首先,你需要在你的電腦(不是伺服器!)裡建立一對密鑰(公鑰和私鑰),在 Terminal 輸入:
ssh-keygen -t ed25519
基本上所有問題都用預設值便可。
可以設置 passphrase (每次使用私鑰登入,都需要打一次 passphrase, 嫌麻煩可外 Google ssh-agent
)。不建議此 passphrase 與你伺服器上的用戶密碼一樣。
完成後,你會見到類似的畫面:
# 例子:我輸入了 ssh-keygen -t ed25519 -C "[email protected]"
Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/oldestdream/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/oldestdream/.ssh/id_ed25519
Your public key has been saved in /Users/oldestdream/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX [email protected]
從上面的畫面可以得知公鑰和私鑰的位置
私鑰:/Users/oldestdream/.ssh/id_ed25519
公鑰: /Users/oldestdream/.ssh/id_ed25519.pub
- 把創建的公鑰放上你的伺服器
注意:是公鑰,不是私鑰!
在 macOS,可以輸入:
ssh-copy-id -i $HOME/.ssh/id_ed25519.pub <username_of_new_acct>@<your_server_ip>
成功後會見到以下訊息:
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/Users/oldestdream/.ssh/id_ed25519.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh '[email protected]'"
and check to make sure that only the key(s) you wanted were added.
在 Windows 可以輸入:
type $env:USERPROFILE\\.ssh\\id_ed25519.pub | ssh <username_of_new_acct>@<your_server_ip> "if umask 077 && mkdir -p .ssh && cat >> .ssh/authorized_keys; then echo success; else echo failure; fi;"
# 見到 success 而不是 failure 便代表成功了。
如果你希望多部電腦都能登入伺服器,建議你在下一步開始前,先在那些電腦都重復剛才的兩個步驟。
不然之後你想從別的電腦登入,會略有點麻煩。
我會把桌上電腦、手提電腦,甚至手機都的公鑰放上去。那樣其中一部電腦壞了,我依然能登入。
以上的步驟會在伺服器上的 ~/.ssh/authorized_keys
裡加上你提供的公鑰,你也可以人手更改該檔案,自行添加。
- 之後測試登入伺服器
不用輸入密碼便能登入便是成功了:
ssh <username_of_new_acct>@<your_server_ip>
若你發現需要輸入密碼,而你又是使用 Windows 的話,有機會是 Windows 的換行符號導致。
可以用密碼登入後,用 vi 把伺服器上 ~/.ssh/authorized_keys
行末見到的 ^M 刪掉再試試看。
接著,我們去更改 sshd 的設定檔改為只用私鑰登入。
先輸入以下 command, 會協助我們接下來選擇用簡單方法還是傳統方法:
grep "^Include /etc/ssh/sshd_config.d/\*.conf" /etc/ssh/sshd_config
輸入後,如果出現了下面這句,
Include /etc/ssh/sshd_config.d/*.conf
代表我們接下來可以跟從簡單方法,不然跟從傳統方法。
簡單方法:
只需要輸入:
sudo nano /etc/ssh/sshd_config.d/10-restrict-login.conf
檔案名稱的橙色部份,可以隨意改。但 .conf
不能改。
然後把下面的抄進去:
ChallengeResponseAuthentication no
PasswordAuthentication no
PermitRootLogin prohibit-password
PermitEmptyPasswords no
然後保存:
按 Command /Ctrl
+ O
, 再 Enter 保存。
按 Command /Ctrl
+ X
, 退出 nano。
完成~ 請跳過下面的「傳統方法」
傳統方法:
輸入以下 command 開始修改設定檔:
sudo nano /etc/ssh/sshd_config
以下有數處地方需要修改:
注意:如需要修改該行的第一個為井號 #
, 記得刪掉該井號。
找到 ChallengeResponseAuthentication
那行,修改成這樣:
ChallengeResponseAuthentication no
找到 PasswordAuthentication
那行,修改成這樣:
PasswordAuthentication no
找到 PermitRootLogin
那行,修改成這樣:
PermitRootLogin prohibit-password
找到 PermitEmptyPasswords
那行,修改成這樣:
PermitEmptyPasswords no
按 Command /Ctrl
+ O
, 再 Enter 保存。
按 Command /Ctrl
+ X
, 退出 nano。
傳統方法完成!請繼續往下。
不論你用簡單方法,還是傳統方法,我們都應該檢查有沒有出錯:
- 檢查有沒有錯誤:
sudo sshd -t
沒有訊息出現便代表沒有出錯。
若有錯誤,因為我們先前有備份在 ~/ssh_backup/
。所以可以取回備份,重新再改。
- 最後重啓 sshd 讓設定生效:
sudo systemctl restart sshd
- 請先別關閉目前的 Terminal, 我們得測試是否真的能成功登入
回到你的電腦(不是伺服器)裡開一個新 terminal, 嘗試登入一遍,看是否不用密碼就能夠登入了。
ssh <username_of_new_acct>@<your_server_ip>
再試一下,驗證使用密碼登入是否會失敗:
ssh -o PubkeyAuthentication=no <username_of_new_acct>@<your_server_ip>
如有出現 Permission denied (publickey).
,恭喜你成功了。
更改 SSH Port
SSH 默認用的 Port 為 22. 根據經驗,更改為其他 Port 減低些滋擾。
舉個比喻就是大家的家門口都是預裝在同一個方位 (Port 22),而你把這個門口給堵上了,然後在別的方位建個門口,回家時便改為從新門口進入。
事實上,不懷好意的人還是可以環繞一圈去找你的門口。只是他們通常不會花那麼多時間精力去找,有時間寧可去別家沒改裝的門口擰下把手、看看有沒有窗沒有關好,碰碰運氣。
建議把 ssh port 改為 1024 至 49151 之間的隨機一個數字。但要避開下面網頁裡列出的 Port, 減少衝突的機會。
List of TCP and UDP port numbers – Wikipedia
想好了的話,輸入以下 command, 確保防火牆允許該 Port 作登入,免出意外。
sudo ufw allow <number_from_1024_to_49151>/tcp
先輸入以下 command, 會協助我們接下來選擇用簡單方法還是傳統方法:
grep "^Include /etc/ssh/sshd_config.d/\*.conf" /etc/ssh/sshd_config
輸入後,如果出現了下面這句,
Include /etc/ssh/sshd_config.d/*.conf
代表我們接下來可以跟從簡單方法,不然跟從傳統方法。
簡單方法:
只需要輸入:
sudo nano /etc/ssh/sshd_config.d/10-custom-port.conf
檔案名稱的橙色部份,可以隨意改。但 .conf
不能改。
輸入 Port
和選好的數字,例如 Port 42468
。
Port <number_from_1024_to_49151>
# e.g. Port 42468
然後保存:
按 Command /Ctrl
+ O
, 再 Enter 保存。
按 Command /Ctrl
+ X
, 退出 nano。
完成~ 請跳過下面的「傳統方法」。
傳統方法:
輸入以下 command 開始修改設定檔:
sudo nano /etc/ssh/sshd_config
找到 Port
, 改其改為:
Port <number_from_1024_to_49151>
# e.g. Port 42468
按 Command /Ctrl
+ O
, 再 Enter 保存。
按 Command /Ctrl
+ X
, 退出 nano。
傳統方法完成!請繼續往下。
不論你用簡單方法,還是傳統方法,我們都應該檢查有沒有出錯:
- 檢查有沒有錯誤:
sudo sshd -t
沒有訊息出現便代表沒有出錯。
若有錯誤,因為我們先前有備份在 ~/ssh_backup/
。所以可以取回備份,重新再改。
- 最後重啓 sshd 讓設定生效:
sudo systemctl restart sshd
- 請先別關閉目前的 Terminal, 我們得測試是否真的能成功登入
回到你的電腦(不是伺服器)裡開一個新 Terminal, 嘗試登入一遍,測試是否能成功登入。
ssh -p <port_number> <username_of_new_acct>@<your_server_ip>
# e.g. ssh -p 42468 [email protected]
若果你曾經改過密鑰的存放位置,你可能需要加上 -i
ssh -p <port_number> -i <path_of_private_key> <username_of_new_acct>@<your_server_ip>
# e.g. ssh -p 42468 -i $HOME/.ssh/blog_oldestdream [email protected]
成功登入便完成了。
保存 config, 減省重復輸入
我們可以用一個檔案保存 IP, Port, 登入的用戶名等資訊,免得我們每次登入都找一遍。
ssh 的設定檔保存位置:
macOS 用家可以在自己電腦輸入:
echo $HOME/.ssh/
# e.g. /home/oldestdream/.ssh/
Windows 用家可以輸入:
echo $env:USERPROFILE\\.ssh\\
# e.g. C:\\Users\\oldestdream\\.ssh\\
在上面顯示的路徑裡,建立一個新檔案名為 config
, 再把下面的抄進去,再修改。
若你沒有改用私鑰登入,可刪掉 IdentityFile
該行。
若你沒有更改 SSH Port,可刪掉 Port
該行,或者輸入Port 22
.
Host <alias_of_this_host>
HostName <your_server_ip>
User <username_of_new_acct>
IdentityFile <path_of_private_key>
Port <port_number>
例子:
macOS: /home/oldestdream/.ssh/config
Windows: C:\\Users\\oldestdream\\.ssh\\config
Host blog
HostName 123.123.123.123
User oldestdream
IdentityFile ~/.ssh/id_ed25519
Port 42468
以後登入伺服器時,只需輸入以下的即可。
ssh <alias_of_this_host>
# e.g. ssh blog