1. 程式人生 > 其它 >OpenSSH 密碼和公鑰認證原理探究

OpenSSH 密碼和公鑰認證原理探究

目錄

使用 OpenSSH配置遠端系統上的安全命令列服務

目標:

  • 使用ssh登入遠端系統並執行命令
  • 為使用者賬戶配置基於金鑰的身份驗證,以使其無需密碼就能安全的登入遠端系統
  • 限制直接以root身份登入,併為OpenSSH 服務禁用基於密碼的身份驗證。

1. 使用SSH 訪問遠端命令列

1.1 什麼是OpenSSH ?

實際工作中,管理的都是遠端伺服器,例如,雲主機。所以都是需要遠端的登入到主機,管理伺服器。而且也不可能直接操作物理控制檯,因為雲主機都是虛擬機器。

通過web頁面登入的實際上走的是vnc協議。

以前的時候,多使用telnet,但是現在淘汰了,用telnet一般也就是用來判斷埠是不是偵聽的。登入一般都是用SSH(OpenSSH,開源的)

引入:

以現有的實驗環境舉例:

workstation 和 servera,serverb 之間配置了OpenSSH,所以通過ssh協議登入的時候直接走金鑰認證,根本不需要使用登入密碼。 但是servera和serverb之間沒有OpenSSH金鑰認證,因此互相登入必須使用密碼。

1.1.1 登入方式:

以student賬戶登入到servera主機:

  • 省略寫法 :ssh student@servera # 這裡沒有指定埠號,是因為ssh協議預設埠就是22
  • 選項寫法:ssh servera -l student -p 22 # -l 即 --login 登入名

1.1.2 登入並執行臨時命令:

1.1.3 檢視登入使用者

當從workstation上通過ssh 連線到servera,在servera上可以通過w 命令檢視:

該命令實際上是檢視所有線上使用者,無論是否遠端登入,也包括了本地登入的使用者。

⭐還可以用過以下命令檢視更加 詳細的情況:

$ ss -tlna | grep :22

還可以通過rsyslog的安全日誌檢視登入記錄

$ sudo grep sshd /var/log/secure

1.2 登入原理

1.2.1 密碼連線過程

在理解一次ssh連線的原理之間,需要先了解以下一些關鍵點:

公鑰:加密

私鑰:解密

預設SSH 的連線方式為密碼認證:

過程:

  1. 客戶端發動連線請求時,服務端將最新的公鑰傳送給客戶端
  2. 客戶端檢視當前家目錄下的檔案 ~/.ssh/known_hosts 是否存在對方的公鑰,如果存在,則第三步,如果不存在,則詢問是否新增公鑰。
  3. 詢問客戶端輸入賬戶的密碼,然後使用服務端的公鑰進行加密,併發送給服務端
  4. 服務端使用對應的私鑰解密,如果正確則允許登入。

總結@jayce:

總結一下,以上的ssh連線過程:
當從servera 嘗試連線到serverb, serverb會將自己最新的公鑰傳送給 servera 。 servera 收到了傳送過來的公鑰, 首先在servera:~/.ssh/known_hosts 檔案中去查詢,是否存在該歷史公鑰,如果有直接下一步,如果沒有,就將其內容寫入到 servera:~/.ssh/known_hosts 檔案(如果沒有該檔案,會自動建立,前提是存在sshd服務。)

在確保servera的主機上(know_hosts)存在有serverb主機的公鑰之後, 此時嘗試登入的使用者將會被詢問遠端登入賬戶的密碼, 使用者輸入密碼之後, 將使用 serverb 的公鑰進行加密。 然後傳送給serverb

serverb在接收到了加密過後的密碼, 嘗試使用私鑰進行解密然後核對密碼是否正確, 如果正確,才會准許servera 通過ssh 遠端連線。

如果對連線過程還是不清楚,可以檢視【附屬】/第十章 SSH連線過程實驗.md 中有詳細的實驗過程。

1.2.1.1 服務端更新金鑰:
$ rm -f /etc/ssh ssh_host_* #刪除公鑰私鑰
$ systemctl restart sshd #會重新生成

生成的金鑰對存放在 /etc/ssh 目錄下, 輸入刪除了金鑰對,然後再嘗試從servera 連線 serverb會發生什麼 ?

提示:遠端主機人正已經修改,有可能是中間人挾持攻擊(略)所以一般在更新金鑰的時候,遠端連線的時候需要向管理員確認。

有三種不同的金鑰對,區別在於使用了不同的演算法

為什麼會出現這個提示?

當servera 嘗試 ssh 遠端連線到serverb, serverb傳送公鑰給servera, 而servera之前是連線過serverb的,所有存在歷史的公鑰,但是現在,serverb的公鑰修改了, 所以在 servera 上,比對歷史公鑰和最新的公鑰的時候存在差異,所以就會報這個提示。

1.2.1.2 移除某主機的認證資訊 : ssh-keygen -R hostname

ssh-keygen -R serverb 移除掉serverb的歷史認證資訊

移除掉之後,然後servera 重新連線serverb 就能夠正常連線上了。

1.2.2 ⭐⭐金鑰認證(公鑰認證)

工作中,金鑰人正更加安全,方便。

1.2.2.1 引入:

以實驗環境為例引入, 有虛擬機器workstation 和 servera, serverb 。 workstation 和servera,serverb 之間就是走的公鑰認證。 公鑰認證使得ssh連線不需要輸入密碼。

示例:

$ ssh -i ./.ssh/lab_rsa student@servera

實際上,可以不用帶 -i 選項, 因為當服務端開放了金鑰(或者說公鑰)認證(前提),那麼在ssh 連線的時候,預設會走金鑰認證, 如果認證失敗,才會走密碼認證。
所以實際上,一般是這樣登入的:

$ssh student@servera

workstation:~/.ssh/lab_rsa 和 workstation:~/.ssh/lab_rsa.pub 是金鑰對。

1.2.2.2 金鑰認證原理

在客戶端和服務端是相互信任的情況下(絕對沒有中間人)

  1. 客戶端使用 ssh-keygen 命令生成金鑰對 : ssh-keygen

    $ ssh-keygen # 預設如果不加 -t 選項設定演算法,預設的會以sha256 演算法
    
    # -t 選項選定特定的演算法
    $ ssh-keygen -t ecdsa
    
     #ubuntu 示例
     jayce@DESKTOP-JASQLDM:~$ ssh-keygen
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/jayce/.ssh/id_rsa):#金鑰對存放的位置
    Created directory '/home/jayce/.ssh'.
    Enter passphrase (empty for no passphrase):#對私鑰加密 ? 多了一把鎖,洩露別人也用不了(如果是為了免密碼認證,這裡就不要加密了)
    Enter same passphrase again:
    Your identification has been saved in /home/jayce/.ssh/id_rsa
    Your public key has been saved in /home/jayce/.ssh/id_rsa.pub
    The key fingerprint is:
    SHA256:IyCSLQHKsHZykIFc7gaQfihunvz+dWOTs8dJxFB9UIQ jayce@DESKTOP-JASQLDM
    The key's randomart image is: # 雜湊圖
    +---[RSA 3072]----+
    |O++.      ....=o |
    |BBo      .   E . |
    |B=++.     o   .  |
    |o=*o .     o     |
    |o .o  . S .      |
    | o.    . ...     |
    |+ .    . Bo .    |
    | +    . o =+     |
    |  oo..   ..      |
    +----[SHA256]-----+
    
  2. 客戶端將公鑰傳送服務端 user@host:~/.ssh/authorized_keys/ ssh-copy-id

    $ ssh-copy-id -i 私鑰 使用者@主機
    #eg: ssh-copy-id -i id_ecdsa.pub student@serverb
    

    輸入完命令之後,將會走密碼完成複製。(拷貝到了 student@serverb:~/.ssh/authorized_keys/ )

  3. 連線時:

    1. 客戶端發起連線

    2. 服務端收到訊號後,隨機生成字串(每次連線都重新生成)並使用客戶端提供的公鑰進行加密,然後返回給客戶端

    3. 客戶端使用私鑰進行解密。並將解密後的字串再返回給服務端

      客戶端只知道公鑰,私鑰時正確的,服務端只知道字串是否正確。兩者都只知道自己的

    4. 服務端驗證字串是否是之前生成的,如果正確則允許連線。

H4 - **完整實驗 - 金鑰認證 - 從servera 連線至 serverb **

準備:初始狀態:從servera 連線到serverb 需要密碼認證:

  1. servera 作為客戶端,通過 ssh-keygen 生成 金鑰對:

  2. 通過ssh-copy-id 命令,將 公鑰 通過密碼認證複製(傳送)到預連線的 使用者@主機

    可以驗證一下:

  3. 嘗試連線:

    完整的連線應該是:ssh -i id_rsa

⚠️ 普通密碼認證,是server 傳送 public key 到client, 而金鑰認證是 client 生成金鑰對,併發送 public key 到server

使得SSH 連線更加的安全:自定義 OPENSSH 服務配置

服務端: /etc/ssh/sshd_config

這裡注意一下,補一個小概念:
SSH 作為多端程式,有客戶端和服務端, 一般來講,服務端應該是常駐程序,(也就是Linux 中的守護程序),這裡的sshd就是守護程序。 為什麼呢? 因為服務端應該時刻等待被連線,時刻都能都被連線上。 如果並不是單向連線,需要頻繁的相互連線,那麼各端都應該有守護程序。

#Port 22					//自定義埠,預設是22,修改設計Selinux 和防火牆
#AddressFamily any			 //區域網中偵聽的埠型別, inet(ipv4) 、inet (ipv6)、any(ipv4 & ipv6)
#ListenAddress 0.0.0.0		 //偵聽埠,制定了埠就只能聽到所偵聽埠的登入申請。
#ListenAddress ::


PubkeyAuthentication yes 	  //預設是否開啟公鑰認證,強烈建議開啟
PermitRootLogin no 			  //⭐⭐⭐⭐⭐強烈建議關閉(每時每刻都有在黑客在掃面是否有埠開放了root登入)
AuthorizedKeysFile  .ssh/authorized_keys .ssh/authorized_keys2 //金鑰預設存放位置,如果公鑰認證開了 這裡一定要保證是開著的
PasswordAuthenticatoin no	  //是否開啟密碼認證,如果同時開啟了,  公鑰認證和密碼認證,那麼將優先使用公鑰認證。  如果公鑰認證方式登入失敗會使用密碼認證, 而使用密碼認證就有中間人挾持攻擊的可能,所以一般正式生產環境,建議是關閉密碼認證的。
.......
自定義sshd的配置

/etc/ssh/sshd_config

Port 22  //埠號
AddressFamily inet  //IP協議型別 inet inet6 any
ListenAddress 172.25.250.11   // 介面
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
PermitRootLogin no  //關閉root遠端登入
PubkeyAuthentication yes //啟用公鑰認證
AuthorizedKeysFile  .ssh/authorized_keys
PasswordAuthentication no  //關閉密碼認證
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
X11Forwarding yes
PrintMotd no
ClientAliveInterval 60
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem sftp	/usr/libexec/openssh/sftp-server

設定完成之後,重啟 sshd 服務

$ systemctl restart sshd