保護 SSH 的三把鎖

作者: Federico Kereki  來源: IBM  發布時間: 2010-12-05 14:44  閱讀: 967 次  推薦: 0   原文鏈接   [收藏]  

  簡介
 

   如果需要遠程訪問計算機并啟用了 Secure Shell (SSH) 連接,黑客就會嘗試突破您的防線并控制您的計算機,您必須接受這個事實。盡管不能保證計算機不會被 “黑客” 占領,但是一些簡單的解決方案有助于保護 SSH,可以讓攻擊困難一些。本文討論三種技術:

  把 SSH 的標準端口改為不常用的值并增強 SSH 配置,從而擋住最簡單的攻擊。

  定義有限的用戶列表,只允許這些用戶登錄。

  完全隱藏允許 SSH 訪問的事實,要求根據特殊的 “敲門” 序列識別有效用戶。

  要想應用這些技術,需要能夠訪問根賬戶。另外,可能必須安裝一些包,需要配置防火墻和路由器(如果有路由器的話),打開和關閉特定的端口并把數據包轉發到您的計算機。

  加強保護

  “隱匿產生安全” 這個概念盡人皆知而且受到大家的嘲笑,因為采用隱匿的方式,希望沒人了解您的方法,這只是一廂情愿的想法。但是,在某些場景中,隱匿一點兒會有幫助。盡管簡單的措施無法阻止下定決心的黑客,但是至少能夠擋住那些 “腳本小子”,他們的腳本往往水平很一般。
  人人都知道 SSH 連接的標準端口是 22。因此,為了讓計算機更安全,應該采取的第一個措施是把端口改為另一個不常用的非標準端口號,比如 22960。1024 以上的號碼通常都可以使用,但是應該查閱參考資料以避免導致問題。這一修改對您的影響僅僅是必須使用下面的命令連接計算機:

 
ssh -p 22960 your.machine.url

  為了實現這個小措施,只需在 /etc/ssh/sshd_config 文件中做簡單的修改。編輯此文件(必須作為根用戶),尋找 Port 22 行,把端口號改為您選擇的號碼(如果這一行以鎊符 [#] 開頭,表示它被注釋掉了,那么應該取消注釋標志)。保存文件,用 /etc/init.d/sshd restart 命令重新啟動 SSH。應該在防火墻上打開您選擇的端口并關閉端口 22。

  但是,還可以更進一步。編輯配置文件,在其中包含 清單 1 所示的行。注意,其中一些行可能已經存在,但是可以把它們注釋掉。

 

  清單 1. 通過修改 SSH 配置文件簡便地增強安全性

 
Port 22960
LoginGraceTime 30
MaxAuthTries 3
Protocol 2
PermitRootLogin no

  LoginGraceTime 允許一次登錄花費 30 秒;如果用戶花費的時間超過 30 秒,就不允許他訪問,必須重新登錄。MaxAuthTries 把錯誤嘗試的次數限制為 3 次,3 次之后拒絕登錄嘗試。上面的 Protocol 2 行禁止使用比較弱的協議。最后一行不允許任何人作為根用戶登錄,這會讓黑客攻擊更困難。還可以使用 DenyUsers、AllowUsers、DenyGroups 和 AllowGroups 選項實現其他限制。這些修改不會顯著增強計算機的安全性,但是只嘗試強力攻擊標準端口 22 的一般腳本會失敗,不會造成損害。無論如何,這是向正確的方向邁出了第一步。在本文后面,我們將使用更安全的方法,不僅修改端口號,而且完全隱藏它。

 

  誰可以進入?
  對于大多數人,PAM 是一種罐裝的烹調油。但是作為 Linux® 安全術語,PAM 代表可插入身份驗證模塊(Pluggable Authentication Modules)。這些模塊提供額外的身份驗證規則,保護對計算機的訪問。
  首先討論一個基本問題:究竟為什么要使用 PAM?如果每個程序不得不定義自己的身份驗證邏輯,就會很混亂。如何確定所有應用程序都實現了相同的測試和檢查?如果需要額外的控制手段,那么怎么辦?難道要重新編寫所有程序嗎?在計算機科學領域,有時候可以用額外的一層解決所有問題,至少在安全方面是這樣。如果一個程序需要驗證用戶的身份,它可以調用 PAM API。這個 API 負責執行在 PAM 配置文件中指定的所有檢查。這種方法還允許方便地修改身份驗證規則,所有感知 PAM 的程序都會自動地應用新規則,不需要修改它們的代碼。如果希望使用某種生物學檢查(比如虹膜掃描器或指紋采集器),而且生產商提供了 PAM,就可以方便地設置它。在配置文件中包含模塊調用,所有應用程序就可以使用這個設備了。
  配置 PAM
  PAM 提供四個安全領域的特性,但是應用程序不太可能同時需要所有這些方面。例如,passwd 命令只需要下面列表中的第三組:
  account 處理賬戶限制。對于有效的用戶,允許他做什么?
  auth 處理用戶識別 — 例如,通過輸入用戶名和密碼。
  password 只處理與密碼相關的問題,比如設置新密碼。
  session 處理連接管理,包括日志記錄。
  在 /etc/pam.d 目錄中為將使用 PAM 的每個應用程序創建一個配置文件,文件名與應用程序名相同。例如,login 命令的配置文件是 /etc/pam.d/login。
  必須定義將應用哪些模塊,創建一個動作 “堆”。PAM 運行堆中的所有模塊,根據它們的結果允許或拒絕用戶的請求。還必須定義檢查是否是必需的。最后,other 文件為沒有特殊規則的所有應用程序提供默認規則。
  optional 模塊可以成功,也可以失敗;PAM 根據模塊是否最終成功返回 success 或 failure。
  required 模塊必須成功。如果失敗,PAM 返回 failure,但是會在運行堆中的其他模塊之后返回。
  requisite 模塊也必須成功。但是,如果失敗,PAM 立即返回 failure,不再運行其他模塊。
  sufficient 模塊在成功時導致 PAM 立即返回 success,不再運行其他模塊。
  配置文件的結構很簡單。可以包含注釋,注釋以散列符 (#) 開頭;通過在換行處加上反斜杠 (\),可以把長的行分為多行。行有三個字段:領域 (account、auth、password 或 session)、控制標志(optional、required、requisite 或 sufficient)、將運行的模塊的路徑和參數。注意,第二個字段可以更復雜;更多信息見 參考資料。另外,可以使用 include 規則以包含其他文件中的規則,比如 auth include common-account。
  特殊的 /etc/pam.d/other 文件是 “默認的” 配置文件(見 清單 2),其中的規則自動地應用于沒有自己的配置文件的所有應用程序。為了確保安全,應該快速檢查 /etc/pam.d 目錄,把您不使用的所有配置文件改為其他名稱(這樣就會使用 other 配置)。如果認為確實需要某個應用程序,那么只需把配置文件改回原來的名稱。默認配置通常拒絕所有請求(通過使用 pam_deny.so 模塊)并警告管理員(通過 pam_warn.so 模塊),讓管理員解決問題。
標準的 “other” 配置文件為沒有自己的配置文件的所有應用程序提供安全的默認規則(拒絕所有請求)。

  清單 2. 標準的 “other” 配置文件

 
account required pam_deny.so
auth required pam_deny
.so
auth required pam_warn
.so
password required pam_deny
.so
password required pam_warn
.so
session required pam_deny
.so

  如果把 pam_deny.so 替換為 pam_unix.so,就應用標準的身份驗證方法(輸入用戶名和密碼)。如果您不關心安全性,那么使用 pam_permit.so,這會允許任何請求!

一些可用方法
  盡管沒有標準的模塊列表,但是所有發行版都包含以下模塊中的大多數。請檢查駐留模塊的 /lib/security 或 /usr/lib/security 目錄。對于 64 位操作系統,用 lib64 替換 lib。如果需要更多信息,可以嘗試執行 man the.name.of.the.module,而不要直接執行它;PAM 不是可執行的二進制代碼。
  pam_access 根據 /etc/security/access.conf 文件允許或拒絕訪問。稍后將使用此模塊決定允許哪些用戶登錄。
  pam_cracklib 和 pam_pwcheck 檢查新密碼的強度。
  pam_deny 和 pam_permit 是基本模塊,分別拒絕或允許訪問。
  pam_echo 向用戶顯示指定文件的內容。
  pam_lastlog 向用戶顯示他上一次登錄的日期和時間。
  pam_ldap.so 讓用戶根據 LDAP 服務器進行身份驗證,提供跨網絡的集中式身份驗證。
  pam_limits 模塊允許指定系統資源限制,限制在 /etc/security/limits.conf 文件中定義。
  pam_listfile 提供根據一個文件的內容允許或拒絕服務的另一種方法。
  pam_mail 檢查用戶是否有未處理的郵件。
  pam_motd 向用戶顯示 “message of the day” 文件。
  如果 /etc/nologin 文件存在,pam_nologin 阻止所有登錄。
  pam_rootok 允許根用戶訪問,不執行進一步檢查。/etc/pam.d/su 中常常包含這個模塊;必需的行是 auth sufficient pam_rootok.so。根用戶可以作為任何用戶操作,不需要提供密碼。
  pam_succeed_if 檢查賬戶的特定屬性,比如是否是某個組的成員。
  pam_time 可以根據 /etc/security/time.conf 中的規則限制對服務的訪問。
  pam_unix(或 pam_unix2)提供基于 /etc/passwd 和 /etc/shadow 文件的傳統 UNIX® 身份驗證。
  pam_userdb 根據一個 Berkeley 數據庫執行身份驗證。
  pam_warn 在系統日志中記錄信息。
  pam_wheel 只向 wheel 組的成員提供根訪問權;必需的行是 auth required pam_wheel.so。
  關于其他模塊和編寫自己的模塊的信息,請查閱 參考資料。現在,使用 PAM 決定誰可以登錄您的計算機。
  用 PAM 限制訪問
  現在,我們來使用 PAM 限制誰可以連接您的服務器。必須編輯 /etc/pam.d/sshd 文件,讓它像清單 3 這樣。

 

清單 3. 在 sshd PAM 文件中添加 pam_access.so

 
#%PAM-1.0
account include common-account
account required pam_access.so
auth include common
-auth
auth required pam_nologin.so
password include common
-password
session include common
-session

 

在 sshd PAM 文件中添加 pam_access.so,就可以輕松地定義誰可以使用 SSH 連接您的計算機。pam_access.so 模塊實現基于 /etc/security/access.conf 文件的安全控制,見清單 4。

 

清單 4. 通過使用 pam_access.so,定義誰可以或不可以使用 SSH             

 
+ : ALL : 192.168.1.
+ : jack : ALL
+ : jill : ALL
- : ALL : ALL

第一行允許任何用戶 (ALL) 從內部網絡登錄。后兩行允許用戶 jack 和 jill 從任何地方訪問服務器。最后一行拒絕其他任何用戶從其他任何地方訪問。允許多個用戶訪問的另一種方法是使用 pam_listfile.so,這需要創建一個允許訪問的用戶列表(例如 /etc/ssh_users)。在 /etc/pam.d/sshd 文件中添加以下行:
  auth required pam_listfile.so item=user sense=allow
   file=/etc/ssh_users onerr=fail

 

這還沒有完。必須修改 /etc/ssh/sshd_config 文件,讓它使用 PAM。在此文件中添加 UsePAM yes 行,重新啟動 sshd 守護進程,這樣就行了!

  究竟是否有門?

  即使應用了前兩節中的方法,無論您怎么預防,黑客仍然會嘗試穿越您系統中任何開放的門戶。改變 SSH 端口號對于經驗豐富的黑客只能造成小小的麻煩。限制允許訪問的用戶會有幫助,但前提是沒有用戶落入黑客或社會工程攻擊的圈套而泄露密碼。無論如何,只要您的系統中有門,就會吸引黑客。
  增強計算機安全性的最后一種方案是最激進的:關閉打開的端口,這會讓任何攻擊都無法攻破您的計算機。只向能夠提供 “秘密敲門暗號” 的用戶開放所需的端口,讓用戶能夠輸入密碼并訪問計算機。
  這種技術稱為端口敲門,適用于需要訪問不向公眾開放的服務器的用戶。服務器可以關閉所有端口,直到用戶提供一個秘密的敲門序列 (序列很容易實現,而且需要的資源不多)。
  打開秘密端口之后,應用常用的安全機制(比如密碼或證書)。只需在防火墻級上提供一個額外的安全層,需要秘密端口的所有服務就會正常工作。
  這種方法的要點在于關閉所有端口并監視外部連接嘗試。當識別出預定義的嘗試序列(稱為敲門序列 )時,可以執行打開端口等操作,讓外部的用戶能夠進來。敲門序列的復雜程度由您決定,從簡單的列表(比如依次嘗試 TCP 端口 7000、UDP 端口 7100 和 TCP 端口 7200)到一次性序列集合都可以。(按密碼學術語來說,一次性序列與 “一次一密” 相似,這是已知最安全的加密方法。)外面的用戶必須知道使用 SSH 所需的端口號和密碼,還必須知道打開端口并啟用密碼所需的敲門序列。如果沒有這個序列,連接嘗試就會靜悄悄地失敗。
  這為什么是非常安全的方案?因為有 65,535 個端口(見 參考資料)。即使考慮到已經分配的端口,仍然有超過 60,000 個可用端口。如果敲門序列只包含四次 “敲門”,黑客要想通過強力攻擊猜出序列,就必須測試大約 13,000,000,000,000,000,000 個序列(13 后面 18 個零)。這樣的攻擊顯然不太可能奏效!當然,強力攻擊或胡亂猜測并不是猜出正確序列的惟一方法。因此,不要只使用單一安全方法;而是使用一系列安全層來增加攻擊的難度。
必須安裝敲門守護進程 knockd;它監視敲門序列,當發現有效的序列時執行相應的操作。如果愿意,可以從頭構建它,但是大多數(如果不是所有的話)發行版中都有這個包。最好使用包管理工具安裝它。例如,在 OpenSUSE 中,可以使用

  Yast2 或通過執行 sudo zypper install knockd 安裝它。在 Ubuntu 中可以使用 sudo apt-get install knockd,在 Debian 中使用 sudo aptitude install knockd。用發行版的軟件安裝工具搜索 knockd 往往能夠找到它。
安裝這個包之后,必須編輯 /etc/knockd.conf 文件以指定端口敲門規則,然后啟動守護進程。為了完成所需的設置,必須了解您的防火墻的工作方式。例如,在 OpenSUSE 中,可以使用 清單 5 這樣的設置。

清單 5. 針對 OpenSUSE 防火墻設計的示例配置文件                

 
[opencloseSSH]
sequence
= 7000,8000,9000
tcpflags= syn
seq_timeout
= 15
cmd_timeout= 30
start_command= /usr/sbin/iptables -s %IP% -I input_ext 1 -p tcp --dport 22960 -j ACCEPT
stop_command
= /usr/sbin/iptables -s %IP% -D input_ext -p tcp --dport 22960 -j ACCEPT

  這個示例在用戶依次在端口 7000、8000 和 9000 上敲門之后啟用 SSH 訪問。在啟動 knockd 之前,關閉端口 22960 并嘗試遠程登錄。這個嘗試應該會失敗,見清單 6。

 

  清單 6. 如果禁用 SSH 訪問而且不啟動敲門守護進程,登錄嘗試會失敗

 
> ssh the.url.for.your.site -p 22960 -o ConnectTimeout=15
ssh: connect to host the.url.for.your.site port 22960: Connection timed out

  現在,使用 sudo /etc/init.d/knockd start 或 sudo knockd -d 啟動端口敲門守護進程(這兩個命令是等效的),然后再試一下;端口敲門序列要求在端口 7000、8000 和 9000 上敲門。必須在 15 秒內完成這個序列。識別出序列之后端口打開,必須在 30 秒內登錄。否則,端口再次關閉。

  為了檢驗這個過程,回到您的遠程機器上并登錄。這一次提供所需的敲門序列,見 清單 7。注意,在安裝 knockd 時通常也會安裝 knock 命令。如果不是這樣,只需用發行版的包管理工具搜索它。

 

  清單 7. 提供所需的敲門序列之后登錄成功

 
> knock the.url.for.your.site 7000
> knock the.url.for.your.site 8000
> knock the.url.for.your.site 9000
> ssh the.url.for.your.site -p 22960 -o ConnectTimeout=10
Password:

  如果提供了錯誤的敲門序列(或根本沒有敲門),會收到 “Connection timed out” 消息,SSH 端口仍然完全關閉,看不出它是存在的。 
  敲門配置
  /etc/knockd.conf 文件有一個一般選項小節 options,希望使用的每個敲門序列各有一個小節。選項可以是大寫、小寫或大小寫混合形式。
  在默認情況下,knockd 監視 eth0 接口。要想使用另一個接口(例如 eth1),可以包含 Interface=eth1 行。注意,只使用設備名而不是設備的完整路徑。
  如果希望啟用日志記錄,可以通過包含 useSyslog 行使用標準的 Linux 日志文件,也可以通過包含 LogFile=/the/full/path/to/your/file 使用自己的文件。但是,應該認識到日志記錄是一個漏洞;如果黑客獲得了日志,入侵者就會掌握端口敲門序列。
  如果希望能夠檢查 knockd 是否仍然在運行,那么包含 PidFile=/the/full/path/to/a/PID/file。這個守護進程的進程 ID (PID) 將存儲在這個文件中。應該通過一個 cron 任務定期檢查 knockd 是否仍然在運行并在需要時重新啟動它。注意,當這個守護進程停止運行時,系統是安全的;所有端口關閉,不可訪問。在守護進程重新啟動之前,用戶無法登錄。
  可以讓 knockd 監聽多個序列并以不同方式響應各個序列。在前面的示例中,讓 knockd 打開 SSH 端口;可以簡單地啟用 HTTP 端口,讓用戶能夠訪問 web 服務器,也可以運行特定的進程。在配置文件中,每個序列都有相應的小節。
使用 sequence 定義敲門序列,比如 7000,8000,9000。在默認情況下,敲門使用 TCP,但是可以添加 UDP 以增加復雜性,比如 7000,8000:udp,9000。
  除了使用固定的序列之外,還可以指定一個包含 “一次性序列” 的文件,這些序列在使用之后就會刪除,不能再次使用。指定這種序列的方法如下:
  one_time_sequences=/the/full/path/to/a/sequences/file

 

  使用任何文本編輯器創建此文件;其中每行包含一個序列(按照上面所示的格式)。應該在遠程計算機上保存此文件的拷貝以便記住如何登錄。
  可以指定應該掃描哪些到達的 TCP 數據包,丟棄不與 ACK、FIN、PSH、RST、SYN 或 URG 標志匹配的數據包。對于 SSH 連接,應該使用 TCPFlags=SYN。
  可以用 Seq_Timeout=seconds.to.wait 指定完成一個序列的最大時間。如果在此時間內沒有輸入完整的序列,就不會識別出它,訪問被拒絕。
  可以用 Cmd_Timeout=seconds.to.wait 指定在識別出序列之后用戶執行第二個命令的最大時間。如果提供了敲門序列的用戶沒有快速地輸入下一個命令(例如登錄),端口會再次關閉。
  最重要的參數是 Start_command=some.command.to.execute,它指定成功地識別出敲門序列之后要執行的命令或腳本。如果需要引用敲門者的 IP 地址(例如為了允許從他的計算機連接您的計算機),可以使用 %IP%。在運行時,它會替換為正確的值。在上面的示例中指定:
  /usr/sbin/iptables -s %IP% -I input_ext 1 -p tcp --dport 22960 -j ACCEPT

  iptables 向提供敲門序列的 IP 地址上的用戶開放端口 22960。
  另一個重要的參數是 Stop_command=some.command.to.execute;當超過 Cmd_timeout 時間之后,執行它指定的命令或腳本。
  在這里,因為只希望打開或關閉端口 22960,所以使用單一命令就夠了。如果需要更復雜的操作,可以通過調用腳本執行所需的任何操作 — 操作甚至可以完全不涉及打開端口。可以觸發任何操作,比如運行進程或執行備份。當然,了解要使用的命令可能有點兒難度。例如,因為我運行 OpenSUSE,它提供自己的防火墻前端,所以我不得不通過查看 iptables -l 的輸出了解應該執行哪個命令來打開或關閉端口 22960。
  對于 knockd 本身,有幾個選項需要考慮:
  -c:允許指定默認配置文件 /etc/knockd.conf 之外的另一個配置文件
  -d:讓 knockd 作為后臺守護進程運行,這是標準運行方式
  -D:提供輸出調試消息
  -h:提供關于語法和選項的幫助
  -i:允許指定默認的 eth0 接口之外的其他接口
  -l:為日志項啟用 DNS 查找 — 這是一種不好的做法,因為這強迫計算機使用 DNS 通信流,會產生漏洞
  -v:提供更詳細的消息和解釋
  -V:提供程序的版本號
  最后,可以使用多種方法產生敲門序列本身,編寫 knock 命令是最簡單的方法。
  以下命令在 TCP 端口 7000 上敲門:

 
knock the.url.for.your.site 7000

  以下命令在 UDP 端口 8000 上敲門:

 
knock the.url.for.your.site -u 8000

  或

 
knock the.url.for.your.site 8000:udp

  -h 參數提供這個命令的幫助。

0
0
 
標簽:SSH
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()