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. 服務端使用對應的私鑰解密,如果正確則允許登錄。

image-20201124100759989

總結@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會發生什麼 ?

image-20201124101823953

image-20201124105045282

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

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

爲什麼會出現這個提示?

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

image-20201124110657223

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

image-20201124112642180

實際上,可以不用帶 -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. 服務端驗證字符串是否是之前生成的,如果正確則允許連接。

asdasdasd

H4 - **完整實驗 - 密鑰認證 - 從servera 連接至 serverb **

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

image-20201124133410758

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

    image-20201124133557056

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

    image-20201124134049863

    可以驗證一下:

    image-20201124134446753

  3. 嘗試連接:

    image-20201124134608495

    完整的連接應該是: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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章