如何增加 SSH 登入前警告提示

SSH是系統中最重要的服務之一,很多伺服器的命令都是透過 SSH 終端機完成的,所以很多人都想趁機登入 SSH 以取得最大權限,真的防不勝防。所以我打算在登入之前提示一些警告提示

首先在 /etc/ 目錄下編輯 issue.net 這個檔案

# nano /etc/issue.net

寫入自己想要的提示警告,例如

###############################################################
#                   Welcome to CubieTruck's World             #
#                                                             #
#      Only Non-Root and Password-less key login allowed      #
###############################################################

存檔後到 /etc/ssh 目錄下編輯 sshd_config 檔案

# nano /etc/ssh/sshd_config

把這一行 # 注釋移除掉

Banner /etc/issue.net

存檔後就可以重啟 ssh 服務即可。

# service ssh restart

這樣登入前就可以看到一些警示標語了。

一些 SSH 雜項設定

ssh 是一個與Ubuntu 終端機聯繫的協議,已經廣泛地取代了 telnet,因為其內容有加密,比起 Telnet 安全多了。以下介紹一些 SSH 的雜項設定,這些設定都在 /etc/ssh/sshd_config 檔案裡面,修改完之後必須重啟服務。

# service sshd restart
欄位 意義
LoginGraceTime 120 代表120秒內沒有輸入密碼則連線關閉。
StrictModes yes 代表會嚴格登入使用者對其家目錄是否有正確使用權限。

如何取消root帳號登入SSH

一般Linux都有一個至高無上的王,就是 root,它的權限大的很,沒有它幹不了的事情。如果這個帳號被駭了,那你的系統也大約沒指望了,只能任人擺佈了。如果真的這麼危險,那麼我們必須讓 ssh 無法用 root 帳號進來,而是用一般帳號,然後在使用 sudo 來間接執行 root 權限的事情。

首先你必須到 /etc/ssh 目錄下編輯 /etc/ssh/sshd_config

#nano /etc/ssh/sshd_config

然後找到下面一行

PermitRootLogin

把參數改為

PermitRootLogin no

然後重新執行 ssh 即可

#service sshd restart

這樣 root 再也不能用 ssh 登入了,至少減少一個被駭客入侵的機會。

如何在 Ubuntu 下避免 SSH/POP3 暴力攻擊

每天檢查 /var/log/auth.log 時,總會看到很多人想要登入這台 CubieTruck(真不明白意圖為何,不就一台小CubieTruck),雖說我已經做了下面保護了

  1. 採用 SSH 金鑰登入,而非一般密碼登入
  2. 嚴禁 root 登入
  3. 限制 IP 位址登入

但總是有那麼多無聊的人想要用暴力攻擊的方式進入試探你的密碼,之前找了很多防止暴力攻擊的方法(用 iptables的方式,而不是用 fail2ban),都不見成效。所以昨晚 Google 一晚,終於找到了,而且還不難。假定你的 SSH Port 是預設的 22的話,用 root 帳號輸入

#iptables -I INPUT 1 -p tcp --dport 22 -m state --state NEW -m recent --name ssh --update --seconds 60 --hitcount 3 -j REJECT
#iptables -I INPUT 2 -p tcp --dport 22 -m state --state NEW -m recent --name ssh --set

這樣就可以在每分鐘內企圖登入(不管登入成功與否)第四次以上,連線都不會建立成功。事實上我也想過是否會有人無聊到一直連線,讓我自己也登不進去呢?畢竟它可不認 IP,且不會管是否事後登入成功。但事實上機率很小的。原因

  1. 我一直都會有一個以上的登入 SSH,而這個方法不會影響到已經登入的 SSH。我可以利用這個 SSH 來禁止那個無聊 IP 登入
  2. 我的 SSH 還有另外一個非 22 Port,而這個 Port 只能內網登入,外網在IP分享器中是沒有開放的。我可以採用 VPN 先登入內網,然後再禁止那個無聊IP進入。
  3. 如果真的有心DDoS你的伺服器,除了這個方法,它還有很多方法可以使用,大可不必大費周章只攻擊你的 SSH。

還有另外一個Port也有可能,就是收信 POP3 Port 110/IMAP Port 143,它也可以用來暴力攻擊試探你的密碼,所以保險起見,也把 POP3 Port 110 /IMAP Port 143一併加入吧!

#iptables -I INPUT 1 -p tcp --dport 110 -m state --state NEW -m recent --name pop3 --update --seconds 60 --hitcount 3 -j REJECT
#iptables -I INPUT 2 -p tcp --dport 110 -m state --state NEW -m recent --name pop3 --set
#iptables -I INPUT 1 -p tcp --dport 143 -m state --state NEW -m recent --name imap --update --seconds 60 --hitcount 3 -j REJECT
#iptables -I INPUT 2 -p tcp --dport 143 -m state --state NEW -m recent --name imap --set

順道附上利用 iptables 禁止 a.b.c.d 的 IP登入你的 CubieTruck 的方法:

#iptables -I INPUT -s 11.22.33.44 -j DROP
#iptables -I OUTPUT -d 11.22.33.44 -j DROP

如何限制 SSH 某些IP無法連線

在寫這篇文章之前,自己本身也是很掙扎的,萬一寫不好,把所有的連線都擋掉了,又得重新安裝系統,那可叫賠了夫人又折兵,小偷沒防著,把自己鎖在門外了。

其實這個功能可以透過Ubuntu內部 Tcpd Wrapper功能就可以達到了,不需要安裝套件,配置檔案位置在 /etc/hosts.allow,和 /etc/hosts.deny。tcpd wrapper的順序是先 allow(允許) 後 deny(不允許),而且擋的不只sshd,連FTP/Telnet協議等等都可以的(Apache HTTP我試過擋不了)。以下提供一些簡單的說明:

# 這樣的設定表示允許本機端某個群族,和允許 example.com 但除了 foobar.example.com以外的機器連線,協議是全部
檔案 /etc/hosts.allow
ALL: LOCAL @some_netgroup
ALL: .example.com EXCEPT foobar.example.com

# 這樣的設定表示阻擋了所有的人,千萬要小心,切記要先設定好 hosts.allow
檔案 /etc/hosts.deny
ALL: ALL

# 這裡提供筆者主機上的設定,供各位參考
檔案 /etc/hosts.allow
ALL: 192.168.1.
ALL: 127.0.0.1
ALL: a.b.c.d

檔案 /etc/hosts.deny
ALL: ALL

tcpd wrapper是連線時讀取檔案內容的,所以不需要重啟服務。但是有些 FQDN 無法解析時,必須要小心應用。凡事必須要留一條通道給自己逃生用。

CubieTruck上的SSH服務一次開兩個Port

很多人一定會覺得莫名其妙,怎麼會突然有這種想法?而且多開一個Port不是多讓別人攻擊的機會嗎?這故事還得從上周五晚上說起。

那晚我登入 CubieTruck,例行看了一下 log,發現有很多人想嘗試暴力攻擊 SSH Port,雖然我是用金鑰保護的,但我還是自己寫了一個 iptables 想要把短時間內產生 SYNC 到 SSH Port的人給擋掉,讓他們趁早死了心,結果一時手誤命令寫錯了。糗了,SSH被自己寫的 iptables 擋住進不去了,而之前 TTY 終端機也被自己給關了。

整身突然直冒冷汗,睡意全無,因為我意識到我再也沒也第二條路進入這台 CubieTruck 了,慘,的確,經過幾個小時奮戰也沒能突破自己建立的那道牆。這下好了,小偷沒防著,反而自己被鎖在門外。

危機也是轉機,心一橫乾脆把CubieTruck系統重灌順便升級到Ubuntu 14.04好了。耗了兩天時間,是整整兩天,我才又把系統給灌回來。這次死活都要把 SSH Port多開一個,以防之後悲劇發生,哪天萬一心血來潮又想用 iptables 來防止暴力攻擊又把 SSH 給鎖死了。而且我想過了,安全性不會有問題,因為我自己家中有一台IP分享器,所以我只要不要把第二個Port對外給打開,外部就沒人可以連進來,內部家裡就只有我一個人會用 SSH,所以不會造成資安問題,反而可以給自己多一條活路。

設定檔案就在 /etc/ssh/sshd_config(注意:不是ssh_config,有多一個d字母),裡面除了原本 Port 22打開,再多一個 Port 8888(假定第二個Port是8888)。讓檔案 /etc/ssh/sshd_config 看起來像是

# What ports, IPs and protocols we listen for
Port 22
Port 8888

存檔後先把防火牆 ufw 打開,只打開內部網域可以連結到8888第二個Port來。

ufw allow proto tcp from 192.168.1.0/24 to any port 8888

然後再重啟服務

service ssh restart

可以試試看改用 ssh 8888 是否可以連結囉!

如何在 CubieTruck 上的 SSH 使用 Putty 免密碼登入

自從架了這台 CubieTruck 伺服器之後,每天不下一百次有人想要登入 SSH,目的做什麼我不知道。所以一開始我就在 /etc/hosts.allow 和  /etc/hosts.deny 上設定了我常用的 IP 位址,讓其他的人無法登入。這可以防止大部分的人攻擊,因為我預設的規則就是 Deny ,除了一兩個我知道的位址可以登入而已。但這有一個問題,如果我要從其他地方也能登入呢?這個位址可能是浮動的呢?這個方法就行不通了。

所以問題又回到 SSH,SSH不同於 Telnet, 是一個 Securtiy  的連線,是可以允許有金鑰的,只是大部分的人都疏忽了,只用帳號密碼登入。所以我決定採用金鑰的方式登入,避免一些閒雜人等登入,又可以免去登入時輸入帳號密碼,我只要確保我的鑰匙不被偷走就可以了。

首先,我們在 CubieTruck 上登入之後想要允許登入的帳號(不是 root 的喔,我的 CubieTruck 預設 root 是不可以由 SSH 登入的),在自己的家目錄或是打入

cd ~

這樣就可以回到自己的家目錄了,然後輸入下面指令就可以得到兩個檔案,一個是公鑰,一個是私鑰。

ssh-keygen -t rsa

一直按確定就可以了。之後在自己加目錄 ~/.ssh/ 裡面會多兩個檔案,id_rsaid_rsa.pub。這兩個檔案要保管好。注意 .ssh 目錄的權限必須是 0700,只有自己可以讀取。id_rsa權限必須是 0600,而 id_rsa.key必須是 0644,你用 ls 看起必須像是

drwx------ 2 yourname yourname 4096 Mar 12 14:48 .ssh
-rw------- 1 yourname yourname 1679 Mar 12 14:38 id_rsa
-rw-r--r-- 1 yourname yourname 400 Mar 12 14:38 id_rsa.pub

如果權限不對,請用 chown 更改它的權限。之後在你的帳號  ~/etc/.ssh 目錄底下,把 id_rsa.pub 檔案複製另外一個檔案,檔名是 authorized_keys,注意,權限也要對。

cp -a ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
-rw-r--r-- 1 yourname yourname 400 Mar 12 14:48 authorized_keys

然後把這兩個 id_rsa 和 id_rsa.pub 檔案,不管是用 FTP/SAMBA/SCP/SDCARD/USB 任何方式,把它拷貝到你電腦的 Putty 目錄底下。之後把 id_rsa 改名成 id_rsa.ppk 名稱。之後再去下載 PuTTYgen.exe 檔案,拷貝回到電腦上的 Putty 的目錄。下載完畢之後,直接執行 PuTTYgen.exe,畫面如下:

ssh1

請選擇 SSH-1(RSA)型態,然後按下 “Load” 載入你剛剛上傳到電腦的私鑰,也就是你剛剛改名字的 id_rsa.ppk,畫面如下

ssh2

其實上面已經告訴你之後要儲存私鑰了(Save private key) ,閱讀完畢之後,按下”確定”。

ssh3

然後按下 “Save private key”,你可以選擇自己想要的檔名,例如 id_pirvate.ppk。這個檔名要記住,因為之後 Putty 設定要使用到。到這裡 PuTTYgen.exe 就已經功成身退了。改設定 Putty 的設定檔。先執行 Putty.exe吧,

ssh4

假定你之前已經有一個以上的 “Saved Session”,這個是紀錄你的 ip 位址的一個設定檔且可以連線到剛剛設定的 CubieTruck 主機,我們要針對這個設定檔作一些修正。按下 “Load” 載入某個設定檔,這個設定檔是連結到你的 CubieTruck 的伺服器。載入完畢之後,先按下左方 “Connection”->”Data” 頁面,然後輸入你之前在 CubieTruck 要登入的帳號名稱(因人而異)。這個帳號就是你剛剛製造金鑰的帳號。

ssh5

之後,在頁面左方點選 SSH選項讓他展開來,再次點選 Auth,勾選 Attempt authentication using PageantAttempt TIS or CryptoCard auth (SSH-1),其他的不要勾選。之後按下 “Browse”按鍵,選取你剛剛儲存的私鑰,上述的例子是 id_pirvate.ppk,不要選錯了。

ssh6

選取好了之後,按下左上方 Session 選項回到主畫面,不要忘了 “Save”存檔紀錄,不然你每次就得重做上述步驟。

ssh7

之後,你就可以 “Load” 你剛剛儲存的 “Save Sessions”了,你可以發現到登入到 CubieTruck 的帳號不必輸入帳號密碼了。但這還不夠,因為別人可以不透過金鑰,採用最原始的帳號密碼方式登入,所以要回到 CubieTruck 上做些設定了。

登入之後,假定你已經轉換成 root 帳號了,到 /etc/ssh 目錄底下編輯 sshd_config (注意,不是 ssh_config ,少一個d),然後修改這兩行

PubkeyAuthentication yes
PasswordAuthentication no

修改完之後,存檔,重啟 ssh 服務。

service ssh restart

你可以試試看,不用剛剛 Putty 的 “Save Sessions”連線時,是不是輸入帳號時就拒絕連線了呢?

後記:妥善保管這些鑰匙檔案,可以拷貝到其他電腦上的 Putty 目錄使用,然後重新設定 “Save Sessions”的設定檔就可以了。

SSH Idle閒置過長解決辦法

我們常常使用 SSH 連線遠端的伺服器,但如果網路品質不好時,ssh 連線可能被中斷,但是伺服器卻不知道,導致很多 session 被閒置在那裏,浪費系統資源。可以輸入 w 指令得知目前有幾個連線登入到伺服器。

我們從 man sshd_config 文件裡面可以得知,有兩個參數可以設定。

  • ClientAliveInterval
  • ClientAliveCountMax

ClientAliveInterval是指伺服器每多少秒向客戶端送一個訊息,預設值是0,也就是不送。ClientAliveCountMax是指依照剛剛設定的頻率發送給客戶端連續幾次之後,客戶端都沒有回應,那sshd就會把這個 session 給斷開,不會讓他 idle。

看了文件之後,我們就可以在 /etc/ssh/sshd_config 編輯我們要的參數,如果沒有就新增這些欄位。

ClientAliveInterval 180
ClientAliveCountMax 3

然後重新啟動 ssd 服務即可。

service ssh restart

CubieTruck SSH SYN Flood 分析

相對於 HTTP,SSH的SYNC Flood也相對比較簡單,因為SSH一旦建立就很少斷線,不像一個網頁裡面含有十幾個連線,如果沒有使用Keep-alive機制,那就意味著要開啟十幾個HTTP連線來取得資料。

所以沒有懸念地,我們還是請出 iptables 大神來,SSH 的 Port 假定是預設的 22,至於每分鐘幾次連線,我想依照個人喜好去修改吧,反正不是常常建立 SSH 連線的,相對的這個方法可以擋掉一些用字典式攻擊密碼的連線。

#iptables -I INPUT 1 -p tcp --dport 22 -m state --state NEW -m recent --name ssh --update --seconds 60 --hitcount 3 -j REJECT
#iptables -I INPUT 2 -p tcp --dport 22 -m state --state NEW -m recent --name ssh --set

上面兩行和之前的http寫法很相像,只是port換成SSH 22 port而已。告訴 iptables 每分鐘如果建立超過 4個新連線(含SYN Flag)就不要處理了,這樣就可以擋掉SSH SYN Flood。

這一講,我們提到很多SYN Flood的攻擊方式,包括HTTP/SSH SYNC Flood,以及基本的防禦方法。這算結束了嘛?我想這才是開始而已吧!