20 個 OpenSSH 最佳安全實踐
OpenSSH 是 SSH 協議的一個實現。一般通過 scp
或 sftp
用於遠程登錄、備份、遠程文件傳輸等功能。SSH能夠完美保障兩個網路或系統間數據傳輸的保密性和完整性。儘管如此,它最大的優勢是使用公匙加密來進行伺服器驗證。時不時會出現關於 OpenSSH 零日漏洞的傳言。本文將描述如何設置你的 Linux 或類 Unix 系統以提高 sshd 的安全性。
OpenSSH 默認設置
- TCP 埠 - 22
- OpenSSH 服務配置文件 -
sshd_config
(位於/etc/ssh/
)
1、 基於公匙的登錄
OpenSSH 服務支持各種驗證方式。推薦使用公匙加密驗證。首先,使用以下 ssh-keygen
命令在本地電腦上創建密匙對:
1024 位或低於它的 DSA 和 RSA 加密是很弱的,請不要使用。當考慮 ssh 客戶端向後兼容性的時候,請使用 RSA密匙代替 ECDSA 密匙。所有的 ssh 密鑰要麼使用 ED25519 ,要麼使用 RSA,不要使用其它類型。
$ ssh-keygen -t key_type -b bits -C "comment"
示例:
$ ssh-keygen -t ed25519 -C "Login to production cluster at xyz corp"
或
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_aws_$(date +%Y-%m-%d) -C "AWS key for abc corp clients"
下一步,使用 ssh-copy-id
命令安裝公匙:
$ ssh-copy-id -i /path/to/public-key-file user@host
或
$ ssh-copy-id user@remote-server-ip-or-dns-name
示例:
$ ssh-copy-id vivek@rhel7-aws-server
提示輸入用戶名和密碼的時候,確認基於 ssh 公匙的登錄是否工作:
$ ssh vivek@rhel7-aws-server
更多有關 ssh 公匙的信息,參照以下文章:
- 為備份腳本設置無密碼安全登錄
- sshpass:使用腳本密碼登錄 SSH 伺服器
- 如何為一個 Linux/類 Unix 系統設置 SSH 登錄密匙
- 如何使用 Ansible 工具上傳 ssh 登錄授權公匙
2、 禁用 root 用戶登錄
禁用 root 用戶登錄前,確認普通用戶可以以 root 身份登錄。例如,允許用戶 vivek 使用 sudo
命令以 root 身份登錄。
在 Debian/Ubuntu 系統中如何將用戶 vivek 添加到 sudo 組中
允許 sudo 組中的用戶執行任何命令。 將用戶 vivek 添加到 sudo 組中:
$ sudo adduser vivek sudo
使用 [id 命令](https://www.cyberciti.biz/faq/unix-linux-id-command-examples-usage-syntax/ "See Linux/Unix id command examples for more info") 驗證用戶組。
$ id vivek
在 CentOS/RHEL 系統中如何將用戶 vivek 添加到 sudo 組中
在 CentOS/RHEL 和 Fedora 系統中允許 wheel 組中的用戶執行所有的命令。使用 usermod
命令將用戶 vivek 添加到 wheel 組中:
$ sudo usermod -aG wheel vivek
$ id vivek
測試 sudo 許可權並禁用 ssh root 登錄
測試並確保用戶 vivek 可以以 root 身份登錄執行以下命令:
$ sudo -i
$ sudo /etc/init.d/sshd status
$ sudo systemctl status httpd
添加以下內容到 sshd_config
文件中來禁用 root 登錄:
PermitRootLogin no
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
更多信息參見「如何通過禁用 Linux 的 ssh 密碼登錄來增強系統安全」 。
3、 禁用密碼登錄
所有的密碼登錄都應該禁用,僅留下公匙登錄。添加以下內容到 sshd_config
文件中:
AuthenticationMethods publickey
PubkeyAuthentication yes
CentOS 6.x/RHEL 6.x 系統中老版本的 sshd 用戶可以使用以下設置:
PubkeyAuthentication yes
4、 限制用戶的 ssh 訪問
默認狀態下,所有的系統用戶都可以使用密碼或公匙登錄。但是有些時候需要為 FTP 或者 email 服務創建 UNIX/Linux 用戶。然而,這些用戶也可以使用 ssh 登錄系統。他們將獲得訪問系統工具的完整許可權,包括編譯器和諸如 Perl、Python(可以打開網路埠干很多瘋狂的事情)等的腳本語言。通過添加以下內容到 sshd_config
文件中來僅允許用戶 root、vivek 和 jerry 通過 SSH 登錄系統:
AllowUsers vivek jerry
當然,你也可以添加以下內容到 sshd_config
文件中來達到僅拒絕一部分用戶通過 SSH 登錄系統的效果。
DenyUsers root saroj anjali foo
你也可以通過配置 Linux PAM 來禁用或允許用戶通過 sshd 登錄。也可以允許或禁止一個用戶組列表通過 ssh 登錄系統。
5、 禁用空密碼
你需要明確禁止空密碼賬戶遠程登錄系統,更新 sshd_config
文件的以下內容:
PermitEmptyPasswords no
6、 為 ssh 用戶或者密匙使用強密碼
為密匙使用強密碼和短語的重要性再怎麼強調都不過分。暴力破解可以起作用就是因為用戶使用了基於字典的密碼。你可以強制用戶避開字典密碼並使用約翰的開膛手工具來檢測弱密碼。以下是一個隨機密碼生成器(放到你的 ~/.bashrc
下):
genpasswd() {
local l=$1
[ "$l" == "" ] && l=20
tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${l} | xargs
}
運行:
genpasswd 16
輸出:
uw8CnDVMwC6vOKgW
7、 為 SSH 的 22埠配置防火牆
你需要更新 iptables
/ufw
/firewall-cmd
或 pf 防火牆配置來為 ssh 的 TCP 埠 22 配置防火牆。一般來說,OpenSSH 服務應該僅允許本地或者其他的遠端地址訪問。
Netfilter(Iptables) 配置
更新 /etc/sysconfig/iptables (Redhat 和其派生系統特有文件) 實現僅接受來自於 192.168.1.0/24 和 202.54.1.5/29 的連接,輸入:
-A RH-Firewall-1-INPUT -s 192.168.1.0/24 -m state --state NEW -p tcp --dport 22 -j ACCEPT
-A RH-Firewall-1-INPUT -s 202.54.1.5/29 -m state --state NEW -p tcp --dport 22 -j ACCEPT
如果同時使用 IPv6 的話,可以編輯 /etc/sysconfig/ip6tables
(Redhat 和其派生系統特有文件),輸入:
-A RH-Firewall-1-INPUT -s ipv6network::/ipv6mask -m tcp -p tcp --dport 22 -j ACCEPT
將 ipv6network::/ipv6mask
替換為實際的 IPv6 網段。
Debian/Ubuntu Linux 下的 UFW
UFW 是 Uncomplicated FireWall 的首字母縮寫,主要用來管理 Linux 防火牆,目的是提供一種用戶友好的界面。輸入以下命令使得系統僅允許網段 202.54.1.5/29 接入埠 22:
$ sudo ufw allow from 202.54.1.5/29 to any port 22
更多信息請參見 「Linux:菜鳥管理員的 25 個 Iptables Netfilter 命令」。
*BSD PF 防火牆配置
如果使用 PF 防火牆 /etc/pf.conf 配置如下:
pass in on $ext_if inet proto tcp from {192.168.1.0/24, 202.54.1.5/29} to $ssh_server_ip port ssh flags S/SA synproxy state
8、 修改 SSH 埠和綁定 IP
ssh 默認監聽系統中所有可用的網卡。修改並綁定 ssh 埠有助於避免暴力腳本的連接(許多暴力腳本只嘗試埠 22)。更新文件 sshd_config
的以下內容來綁定埠 300 到 IP 192.168.1.5 和 202.54.1.5:
Port 300
ListenAddress 192.168.1.5
ListenAddress 202.54.1.5
當需要接受動態廣域網地址的連接時,使用主動腳本是個不錯的選擇,比如 fail2ban 或 denyhosts。
9、 使用 TCP wrappers (可選的)
TCP wrapper 是一個基於主機的訪問控制系統,用來過濾來自互聯網的網路訪問。OpenSSH 支持 TCP wrappers。只需要更新文件 /etc/hosts.allow
中的以下內容就可以使得 SSH 只接受來自於 192.168.1.2 和 172.16.23.12 的連接:
sshd : 192.168.1.2 172.16.23.12
在 Linux/Mac OS X 和類 UNIX 系統中參見 TCP wrappers 設置和使用的常見問題。
10、 阻止 SSH 破解或暴力攻擊
暴力破解是一種在單一或者分散式網路中使用大量(用戶名和密碼的)組合來嘗試連接一個加密系統的方法。可以使用以下軟體來應對暴力攻擊:
- DenyHosts 是一個基於 Python SSH 安全工具。該工具通過監控授權日誌中的非法登錄日誌並封禁原始 IP 的方式來應對暴力攻擊。
- RHEL / Fedora 和 CentOS Linux 下如何設置 DenyHosts。
- Fail2ban 是另一個類似的用來預防針對 SSH 攻擊的工具。
- sshguard 是一個使用 pf 來預防針對 SSH 和其他服務攻擊的工具。
- security/sshblock 阻止濫用 SSH 嘗試登錄。
- IPQ BDB filter 可以看做是 fail2ban 的一個簡化版。
11、 限制 TCP 埠 22 的傳入速率(可選的)
netfilter 和 pf 都提供速率限制選項可以對埠 22 的傳入速率進行簡單的限制。
Iptables 示例
以下腳本將會阻止 60 秒內嘗試登錄 5 次以上的客戶端的連入。
#!/bin/bash
inet_if=eth1
ssh_port=22
$IPT -I INPUT -p tcp --dport ${ssh_port} -i ${inet_if} -m state --state NEW -m recent --set
$IPT -I INPUT -p tcp --dport ${ssh_port} -i ${inet_if} -m state --state NEW -m recent --update --seconds 60 --hitcount 5
在你的 iptables 腳本中調用以上腳本。其他配置選項:
$IPT -A INPUT -i ${inet_if} -p tcp --dport ${ssh_port} -m state --state NEW -m limit --limit 3/min --limit-burst 3 -j ACCEPT
$IPT -A INPUT -i ${inet_if} -p tcp --dport ${ssh_port} -m state --state ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -o ${inet_if} -p tcp --sport ${ssh_port} -m state --state ESTABLISHED -j ACCEPT
# another one line example
# $IPT -A INPUT -i ${inet_if} -m state --state NEW,ESTABLISHED,RELATED -p tcp --dport 22 -m limit --limit 5/minute --limit-burst 5-j ACCEPT
其他細節參見 iptables 用戶手冊。
*BSD PF 示例
以下腳本將限制每個客戶端的連入數量為 20,並且 5 秒內的連接不超過 15 個。如果客戶端觸發此規則,則將其加入 abusive_ips 表並限制該客戶端連入。最後 flush 關鍵詞殺死所有觸發規則的客戶端的連接。
sshd_server_ip = "202.54.1.5"
table <abusive_ips> persist
block in quick from <abusive_ips>
pass in on $ext_if proto tcp to $sshd_server_ip port ssh flags S/SA keep state (max-src-conn 20, max-src-conn-rate 15/5, overload <abusive_ips> flush)
12、 使用埠敲門(可選的)
埠敲門是通過在一組預先指定的封閉埠上生成連接嘗試,以便從外部打開防火牆上的埠的方法。一旦指定的埠連接順序被觸發,防火牆規則就被動態修改以允許發送連接的主機連入指定的埠。以下是一個使用 iptables 實現的埠敲門的示例:
$IPT -N stage1
$IPT -A stage1 -m recent --remove --name knock
$IPT -A stage1 -p tcp --dport 3456 -m recent --set --name knock2
$IPT -N stage2
$IPT -A stage2 -m recent --remove --name knock2
$IPT -A stage2 -p tcp --dport 2345 -m recent --set --name heaven
$IPT -N door
$IPT -A door -m recent --rcheck --seconds 5 --name knock2 -j stage2
$IPT -A door -m recent --rcheck --seconds 5 --name knock -j stage1
$IPT -A door -p tcp --dport 1234 -m recent --set --name knock
$IPT -A INPUT -m --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -p tcp --dport 22 -m recent --rcheck --seconds 5 --name heaven -j ACCEPT
$IPT -A INPUT -p tcp --syn -j door
更多信息請參見:
Debian / Ubuntu: 使用 Knockd and Iptables 設置埠敲門
13、 配置空閑超時註銷時長
用戶可以通過 ssh 連入伺服器,可以配置一個超時時間間隔來避免無人值守的 ssh 會話。 打開 sshd_config
並確保配置以下值:
ClientAliveInterval 300
ClientAliveCountMax 0
以秒為單位設置一個空閑超時時間(300秒 = 5分鐘)。一旦空閑時間超過這個值,空閑用戶就會被踢出會話。更多細節參見如何自動註銷空閑超時的 BASH / TCSH / SSH 用戶。
14、 為 ssh 用戶啟用警示標語
更新 sshd_config
文件如下行來設置用戶的警示標語:
Banner /etc/issue
`/etc/issue 示例文件:
-------------------------------------------------------------------------------------------You are accessing a XYZ Government (XYZG) Information System (IS) that is provided for authorized use only.
By using this IS (which includes any device attached to this IS), you consent to the following conditions:
+ The XYZG routinely intercepts and monitors communications on this IS for purposes including, but not limited to,
penetration testing, COMSEC monitoring, network operations and defense, personnel misconduct (PM),
law enforcement (LE), and counterintelligence (CI) investigations.
+ At any time, the XYZG may inspect and seize data stored on this IS.
+ Communications using, or data stored on, this IS are not private, are subject to routine monitoring,
interception, and search, and may be disclosed or used for any XYZG authorized purpose.
+ This IS includes security measures (e.g., authentication and access controls) to protect XYZG interests--not
for your personal benefit or privacy.
+ Notwithstanding the above, using this IS does not constitute consent to PM, LE or CI investigative searching
or monitoring of the content of privileged communications, or work product, related to personal representation
or services by attorneys, psychotherapists, or clergy, and their assistants. Such communications and work
product are private and confidential. See User Agreement for details.
-------------------------------------------------------------------------------------------
以上是一個標準的示例,更多的用戶協議和法律細節請諮詢你的律師團隊。
15、 禁用 .rhosts 文件(需核實)
禁止讀取用戶的 ~/.rhosts
和 ~/.shosts
文件。更新 sshd_config
文件中的以下內容:
IgnoreRhosts yes
SSH 可以模擬過時的 rsh 命令,所以應該禁用不安全的 RSH 連接。
16、 禁用基於主機的授權(需核實)
禁用基於主機的授權,更新 sshd_config
文件的以下選項:
HostbasedAuthentication no
17、 為 OpenSSH 和操作系統打補丁
推薦你使用類似 yum、apt-get 和 freebsd-update 等工具保持系統安裝了最新的安全補丁。
18、 Chroot OpenSSH (將用戶鎖定在主目錄)
默認設置下用戶可以瀏覽諸如 /etc
、/bin
等目錄。可以使用 chroot 或者其他專有工具如 rssh 來保護 ssh 連接。從版本 4.8p1 或 4.9p1 起,OpenSSH 不再需要依賴諸如 rssh 或複雜的 chroot(1) 等第三方工具來將用戶鎖定在主目錄中。可以使用新的 ChrootDirectory
指令將用戶鎖定在其主目錄,參見這篇博文。
19. 禁用客戶端的 OpenSSH 服務
工作站和筆記本不需要 OpenSSH 服務。如果不需要提供 ssh 遠程登錄和文件傳輸功能的話,可以禁用 sshd 服務。CentOS / RHEL 用戶可以使用 [yum 命令](https://www.cyberciti.biz/faq/rhel-centos-fedora-linux-yum-command-howto/ "See Linux/Unix yum command examples for more info") 禁用或刪除 openssh-server:
$ sudo yum erase openssh-server
Debian / Ubuntu 用戶可以使用 [apt 命令](https://www.cyberciti.biz/faq/ubuntu-lts-debian-linux-apt-command-examples/ "See Linux/Unix apt command examples for more info")/[apt-get 命令](https://www.cyberciti.biz/tips/linux-debian-package-management-cheat-sheet.html "See Linux/Unix apt-get command examples for more info") 刪除 openssh-server:
$ sudo apt-get remove openssh-server
有可能需要更新 iptables 腳本來移除 ssh 的例外規則。CentOS / RHEL / Fedora 系統可以編輯文件 /etc/sysconfig/iptables
和 /etc/sysconfig/ip6tables
。最後重啟 iptables 服務:
# service iptables restart
# service ip6tables restart
20. 來自 Mozilla 的額外提示
如果使用 6.7+ 版本的 OpenSSH,可以嘗試下以下設置:
#################[ WARNING ]########################
# Do not use any setting blindly. Read sshd_config #
# man page. You must understand cryptography to #
# tweak following settings. Otherwise use defaults #
####################################################
# Supported HostKey algorithms by order of preference.
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
# Specifies the available KEX (Key Exchange) algorithms.
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
# Specifies the ciphers allowed
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
#Specifies the available MAC (message authentication code) algorithms
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
LogLevel VERBOSE
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
Subsystem sftp /usr/lib/ssh/sftp-server -f AUTHPRIV -l INFO
使用以下命令獲取 OpenSSH 支持的加密方法:
$ ssh -Q cipher
$ ssh -Q cipher-auth
$ ssh -Q mac
$ ssh -Q kex
$ ssh -Q key
如何測試 sshd_config 文件並重啟/重新載入 SSH 服務?
在重啟 sshd 前檢查配置文件的有效性和密匙的完整性,運行:
$ sudo sshd -t
擴展測試模式:
$ sudo sshd -T
最後,根據系統的的版本重啟 Linux 或類 Unix 系統中的 sshd 服務:
$ [sudo systemctl start ssh][38] ## Debian/Ubunt Linux##
$ [sudo systemctl restart sshd.service][39] ## CentOS/RHEL/Fedora Linux##
$ doas /etc/rc.d/sshd restart ## OpenBSD##
$ sudo service sshd restart ## FreeBSD##
其他建議
- 使用 2FA 加強 SSH 的安全性 - 可以使用 OATH Toolkit 或 DuoSecurity 啟用多重身份驗證。
- 基於密匙鏈的身份驗證 - 密匙鏈是一個 bash 腳本,可以使得基於密匙的驗證非常的靈活方便。相對於無密碼密匙,它提供更好的安全性。
更多信息
- OpenSSH 官方 項目。
- 用戶手冊: sshd(8)、ssh(1)、ssh-add(1)、ssh-agent(1)。
如果知道這裡沒用提及的方便的軟體或者技術,請在下面的評論中分享,以幫助讀者保持 OpenSSH 的安全。
關於作者
作者是 nixCraft 的創始人,一個經驗豐富的系統管理員和 Linux/Unix 腳本培訓師。他曾與全球客戶合作,領域涉及 IT,教育,國防和空間研究以及非營利部門等多個行業。請在 Twitter、Facebook、Google+ 上關注他。
via: https://www.cyberciti.biz/tips/linux-unix-bsd-openssh-server-best-practices.html
作者:Vivek Gite 譯者:shipsw 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive