創建私人登入憑證 - 幾種安全的SSH驗證方式
最近不少友人開始使用自己的VPS,也遇上各種各樣的問題。不過拿到伺服器的第一件事,就是要保證自己伺服器的安全性。
端口掃描腳本是一個很厲害的東西,也十分讓人煩惱。初次購買的VPS默認SSH端口為22,如果有看登入記錄會發現一旦IP地址暴露到網絡,每時每刻都有人在嘗試破解密碼。
所以,當拿到VPS之後,務必第一時間進行一些安全防範的操作,update所有軟件包倒是其次了。
本文介紹以下方式
- 修改端口
- 公鑰 / 私鑰
- fail2ban
- port knocking
1 修改端口
修改ssh配置文件並重啟ssh服務
vi /etc/ssh/sshd_config
找到Port行,去掉頭部的#,修改為自定義端口
# Debian / Ubuntu
service ssh restart
# CentOS / RHEL
service sshd restart
這是最簡單的一種方式,也是效率最高的一種方式。90%以上的通過腳本的暴力破解都盯著22端口去,很少有人願意耗費成本去掃描其他的端口。如果是防範專門盯著你的伺服器去的人,下文將介紹其他方法。
2 使用公鑰/私鑰密鑰對登入
公鑰/私鑰對是很安全的登入方式之一,用戶只需要在伺服器創建公鑰/私鑰對,然後將私鑰用於身份驗證即可。
依賴openssl,一般系統自帶,在生成之前可以upgrade一下。
可以透過
man ssh-keygen
查看具體操作命令。這裡提供一個配置ECC 521bit登入憑證的配置樣例。
vi /etc/ssh/sshd_config
找到
#AuthorizedKeysFile .ssh/authorized_keys
將頭部的#去掉,保存退出。
之後進入用戶目錄(可以通過命令cd直接進入),創建一個.ssh目錄(如果不存在)。然後使用命令
ssh-keygen -t ecdsa -b 521
提示保存位置時,直接保存在默認目錄下即可。passphrase也不是必須的,只需要保證自己的私鑰保存在安全的位置。
生成完成之後進入.ssh目錄
cp id_ecdsa.pub authorized_keys
將id_ecdsa保存至本地,推薦刪除位於伺服器的私鑰。最後重啟ssh保存設置,就可以使用私鑰登入了。
3 使用fail2ban防止暴力破解密碼
如果不希望使用密鑰對登入(因為不可能隨身攜帶私鑰),可以透過fail2ban防止暴力破解。fail2ban是一個被廣泛使用的入侵保護開源框架,透過分析日誌文件來對特定入侵來源進行封鎖。期間需要使用iptables。
安裝
一般自帶rpm包,可以透過
# Debian / Ubuntu
apt-get install fail2ban iptables-persistent
# CentOS / RHEL
yum install fail2ban iptables
cd /etc/fail2ban
可以看到,fail2ban配置文件包括了filter,action,jail,config四個部分。filter為監控log文件的部分,透過正則匹配日誌文件找到攻擊源。action為操作部分,進行fail2ban被激活之後的操作。fail2ban.conf無需進行修改。jail.d為監獄的配置文件,默認配置文件為jail.local,下面提供一個防止ssh暴力破解的範例。
配置
iptables
首先配置iptables。fail2ban用的是黑名單的模式,所以如果沒有使用過iptables,只需要
iptables -P INPUT ACCEPT
iptables -F
千萬不能直接全部清除!否則可能導致再也連接不上伺服器。
fail2ban
vi /etc/fail2ban/jail.local
[DEFAULT]
# 以空格分隔的列表,可以是 IP CIDR 前綴或者 rDNS
# 忽略fail2ban防護的ip地址
ignoreip = 127.0.0.1 172.31.0.0/24 10.10.0.0/24 192.168.0.0/24
# 默認禁止時間(second)
bantime = 3600
# 到達多少次後禁用
maxretry = 5
# 檢查多少時間內的日誌(second)
findtime = 600
mta = sendmail
[ssh-iptables]
enabled = true
filter = sshd
action = iptables[name=SSH, port=*SSH端口*, protocol=tcp]
sendmail-whois[name=SSH, dest=admin@example.com, sender=fail2ban@example.com]
# Debian / Ubuntu
logpath = /var/log/auth.log
# CentOS / RHEL
logpath = /var/log/secure
# 到達多少次後禁用(優先於默認配置)
maxretry = 3
保存退出,重啟fail2ban
service fail2ban restart
檢查服務運行狀態
fail2ban-client ping
本配置文件中,檢測到ssh log中某ip十分鐘內連續登入失敗三次,就會調用iptables,把目標IP ban一個小時。
注: 配置文件中[DEFAULT]為默認配置區塊,優先度低於[ssh-iptables]。bantime,maxretry,findtime等如果衝突,以[ssh-iptables]為準。
之後可以進行隨意的鏈接來測試fail2ban服務。如果多次密碼錯誤,你就會發現無法連上目標伺服器了。
當然fail2ban的用處遠不止這些,具體可以根據filter.d和action.d內文件來編寫。
4 Port Knocking
這是一個創造性的發明,可以稱作是 '為自己開的後門'。如果說fail2ban是黑名單模式的話,port knocking就是白名單模式。服務端的SSH端口封閉,監聽部分特定端口。如果需要連接上伺服器,需要使用tcp udp或者icmp包進行 '敲打'。當符合一定的包特征和順序,服務端自動為當前IP開放指定端口。
有很多相似的程式,在這裡可以找到。這裡提供一個knockd的配置範例。
需要註意的是,這個方法需要一定的iptables知識。
安裝
部分發行版提供rpm。如果沒有(例如這台Debian8),可以到這裡下載對應的包,然後用dpkg -i安裝。也需要iptables的安裝,上文提及過。
配置
下面提供我自己配置的方法
iptables for test
| Port | Usage | Policy |
|---|---|---|
| 22 | SSH | Accept |
| 985 | for SSH test | Drop |
| 233 | Listen(knockd) | Accept |
| 2333 | Listen(knockd) | Accept |
| 23333 | Listen(knockd) | Accept |
Knockd配置測試
首先為了防止誤操作導致無法連接,使用HAproxy,將985端口的請求轉發至22端口。
默認的配置文件一般包括了兩個步驟 打開和關閉。這裡稍作修改,讓它可以自動關閉端口。
已經建立的SSH連接不會因為iptables修改為DROP而被中斷。
以下是配置文件,可以根據需求修改網卡(ovz一般是venet0,阿里雲似乎是eth1),敲打端口的順序。國內骨幹網對出國的udp包似乎有特殊的嗜好,所以這裡全部使用tcp包進行認證。
部分OpenVZ主機因為網卡問題,似乎無法正常監聽
[options]
LogFile = /var/log/knockd.log
[opencloseSSH]
Interface = eth0
sequence = 233:tcp,2333:tcp,23333:tcp seq_timeout = 5
command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 985 -j ACCEPT
tcpflags = syn
cmd_timeout = 15
stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 985 -j ACCEPT
配置完成之後,輸入
knockd -v -D
config: new section: 'options'
config: log file: /var/log/knockd.log
config: interface: eth0
config: new section: 'opencloseSSH'
config: opencloseSSH: sequence: 233:tcp,2333:tcp,23333:tcp
config: opencloseSSH: seq_timeout: 5
config: opencloseSSH: start_command: /sbin/iptables -A INPUT -s %IP% -p tcp --dport 985 -j ACCEPTconfig: tcp flag: SYN
config: opencloseSSH: cmd_timeout: 15
config: opencloseSSH: stop_command: /sbin/iptables -D INPUT -s %IP% -p tcp --dport 985 -j ACCEPT
ethernet interface detected
Local IP: xx.xx.xx.xx
listening on eth0...
表示正在監聽。接下來進行敲打測試。
敲打測試
如果是Linux,直接安裝knockd。Windows則下載http://www.zeroflux.org/proj/knock/files/knock-win32.zip,將Releases文件夾下的knock.exe放置在C:\Windows下。然後透過命令
knock -v xx.xx.xx.xx 233:tcp 2333:tcp 23333:tcp
hitting tcp xx.xx.xx.xx:233
hitting tcp xx.xx.xx.xx:2333
hitting tcp xx.xx.xx.xx:23333
如果成功,剛才開啟的-D模式的窗口會打印
opencloseSSH: running command: /sbin/iptables -I INPUT -s xx.xx.xx.xx -p tcp --dport 985 -j ACCEPT
這時迅速連接上SSH即可。
開啟服務
測試成功後,就可以透過
service knockd restart
chkconfig knockd on
開啟服務
之後將knockd打開的端口指向22,設置22端口為DROP。使用時先敲打,後迅速透過xx.xx.xx.xx:22來訪問SSH
iptables(Final)
| Port | Usage | Policy |
|---|---|---|
| 22 | SSH | Drop |
| 985 | for SSH test | Drop |
| 233 | Listen(knockd) | Accept |
| 2333 | Listen(knockd) | Accept |
| 23333 | Listen(knockd) | Accept |
敲打之後
| Port | Usage | Policy |
|---|---|---|
| 22 | SSH | Accept (temporarily) |
| 985 | for SSH test | Drop |
| 233 | Listen(knockd) | Accept |
| 2333 | Listen(knockd) | Accept |
| 23333 | Listen(knockd) | Accept |
突發情況處理
如果knockd掛了怎麼辦?我們需要防范於未然
可以透過cron定時重啟knockd,或者在SSH端口ACCEPT時iptables-save一下,一旦出錯reboot就好了