SSH教程


SSH 是 Linux 系統的登錄工具,現在廣泛用於服務器登錄和各種加密通信。

SSH基本知識

SSH(Secure Shell 的縮寫)是一種網絡協議,用於加密兩台計算機之間的通信,並且支持各種身份驗證機制。

實務中,它主要用於保證遠程登錄和遠程通信的安全,任何網絡服務都可以用這個協議來加密。

1、SSH是什么

歷史上,網絡主機之間的通信是不加密的,屬於明文通信。這使得通信很不安全,一個典型的例子就是服務器登錄。登錄遠程服務器的時候,需要將用戶輸入的密碼傳給服務器,如果這個過程是明文通信,就意味着傳遞過程中,線路經過的中間計算機都能看到密碼,這是很可怕的。

SSH 就是為了解決這個問題而誕生的,它能夠加密計算機之間的通信,保證不被竊聽或篡改。它還能對操作者進行認證(authentication)和授權(authorization)。明文的網絡協議可以套用在它里面,從而實現加密。

2、歷史

1995年,芬蘭赫爾辛基工業大學的研究員 Tatu Ylönen 設計了 SSH 協議的第一個版本(現稱為 SSH 1),同時寫出了第一個實現(稱為 SSH1)。
OpenSSH 隨 OpenBSD 2.6 版本一起提供,以后又移植到其他操作系統,成為最流行的 SSH 實現。目前,Linux 的所有發行版幾乎都自帶 OpenSSH。

3、SSH架構

SSH 的軟件架構是服務器-客戶端模式(Server - Client)。在這個架構中,SSH 軟件分成兩個部分:

  • 向服務器發出請求的部分,稱為客戶端(client),OpenSSH 的實現為 ssh;
  • 接收客戶端發出的請求的部分,稱為服務器(server),OpenSSH 的實現為 sshd。

本教程約定,大寫的 SSH 表示協議,小寫的 ssh 表示客戶端軟件。

另外,OpenSSH 還提供一些輔助工具軟件(比如 ssh-keygen 、ssh-agent)和專門的客戶端工具(比如 scp 和 sftp)

SSH客戶端

1、簡介

OpenSSH 的客戶端是二進制程序 ssh。

1.1 Windows 系統的位置是\Program Files\OpenSSH\bin\ssh.exe。【Win10中自帶OpenSSH,在設置->應用->可選功能中開啟,安裝后在:C:\Windows\System32\OpenSSH】

 

利用ssh連接遠程服務器:在windows上cmd,然后ssh 主機用戶@主機ip直接連到遠程,很方便

eg:ssh root@192.168.xx.yy 

 

輸入密碼即可登錄成功。 

1.2 Linux 系統一般都自帶 ssh,如果沒有就需要安裝。它在 Linux/Unix 系統的位置是/usr/local/bin/ssh

# Ubuntu 和 Debian $ sudo apt install openssh-client # CentOS 和 Fedora $ sudo dnf install openssh-clients 

安裝以后,可以使用-V參數輸出版本號,查看一下是否安裝成功。

$ ssh -V

2、基本用法 

ssh 最常見的用途就是登錄服務器,這要求服務器安裝並正在運行 SSH 服務器軟件。

ssh 登錄服務器的命令如下。

$ ssh hostname

上面命令中,hostname是主機名,它可以是域名,也可能是 IP 地址或局域網內部的主機名。不指定用戶名的情況下,將使用客戶端的當前用戶名,作為遠程服務器的登錄用戶名。如果要指定用戶名,可以采用下面的語法。

$ ssh user@hostname 

上面的命令中,用戶名和主機名寫在一起了,之間使用@分隔。

用戶名也可以使用ssh-l參數指定,這樣的話,用戶名和主機名就不用寫在一起了。

$ ssh -l username host

ssh 默認連接服務器的22端口,-p參數可以指定其他端口。

$ ssh -p 8821 foo.com

上面命令連接服務器foo.com的8821端口。

3、連接流程

ssh 連接遠程服務器后,首先有一個驗證過程,驗證遠程服務器是否為陌生地址

如果是第一次連接某一台服務器,命令行會顯示一段文字,表示不認識這台機器,提醒用戶確認是否需要連接。

The authenticity of host 'foo.com (192.168.121.111)' can't be established. ECDSA key fingerprint is SHA256:Vybt22mVXuNuB5unE++yowF7lgA/9/2bLSiO3qmYWBY. Are you sure you want to continue connecting (yes/no)? 

上面這段文字告訴用戶,foo.com這台服務器的指紋是陌生的,讓用戶選擇是否要繼續連接(輸入 yes 或 no)。

所謂“服務器指紋”,指的是 SSH 服務器公鑰的哈希值。每台 SSH 服務器都有唯一一對密鑰,用於跟客戶端通信,其中公鑰的哈希值就可以用來識別服務器

下面的命令可以查看某個公鑰的指紋(哈希值)。

$ ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub
256 da:24:43:0b:2e:c1:3f:a1:84:13:92:01:52:b4:84:ff   (ECDSA)

上面的例子中,ssh-keygen -l -f命令會輸出公鑰/etc/ssh/ssh_host_ecdsa_key.pub的指紋。

 

ssh 會將本機連接過的所有服務器公鑰的指紋,都儲存在本機的~/.ssh/known_hosts文件中【windows上位於 C:\Users\用戶名\.ssh ,存的是公鑰】。每次連接服務器時,通過該文件判斷是否為陌生主機(陌生公鑰)。

在上面這段文字后面,輸入yes,就可以將當前服務器的指紋也儲存在本機~/.ssh/known_hosts文件中,並顯示下面的提示。以后再連接的時候,就不會再出現警告了。

Warning: Permanently added 'foo.com (192.168.121.111)' (RSA) to the list of known hosts 

然后,客戶端就會跟服務器建立連接。接着,ssh 就會要求用戶輸入所要登錄賬戶的密碼。用戶輸入並驗證密碼正確以后,就能登錄遠程服務器的 Shell 了。

之后重新連接就不會提示不認識這台機器了。

4、服務器秘鑰變更

服務器指紋可以防止有人惡意冒充遠程主機。如果服務器的密鑰發生變更(比如重裝了 SSH 服務器),客戶端再次連接時,就會發生公鑰指紋不吻合的情況。這時,客戶端就會中斷連接,並顯示一段警告信息。 

這時,你需要確認是什么原因,使得公鑰指紋發生變更,到底是惡意劫持,還是管理員變更了 SSH 服務器公鑰。 

5、ssh命令行配置項

-c

-c參數指定加密算法。

$ ssh -c blowfish,3des server.example.com
# 或者 $ ssh -c blowfish -c 3des server.example.com 

上面命令指定使用加密算法blowfish3des

-C

-C參數表示壓縮數據傳輸。

$ ssh -C server.example.com

等等...

SSH密鑰登錄

SSH 默認采用密碼登錄,這種方法有很多缺點,簡單的密碼不安全,復雜的密碼不容易記憶,每次手動輸入也很麻煩。密鑰登錄是更好的解決方案。

1、密鑰是什么

密鑰(key)是一個非常大的數字,通過加密算法得到。對稱加密只需要一個密鑰,非對稱加密需要兩個密鑰成對使用,分為公鑰(public key)和私鑰(private key)。

SSH 密鑰登錄采用的是非對稱加密,每個用戶通過自己的密鑰登錄。其中,私鑰必須私密保存,不能泄漏;公鑰則是公開的,可以對外發送。它們的關系是,公鑰和私鑰是一一對應的,每一個私鑰都有且僅有一個對應的公鑰,反之亦然。

如果數據使用公鑰加密,那么只有使用對應的私鑰才能解密,其他密鑰都不行;反過來,如果使用私鑰加密(這個過程一般稱為“簽名”),也只有使用對應的公鑰解密。

2、密鑰登錄的過程

SSH 密鑰登錄分為以下的步驟。

預備步驟,客戶端通過ssh-keygen生成自己的公鑰和私鑰

第一步,手動將客戶端的公鑰放入遠程服務器的指定位置。

第二步,客戶端向服務器發起 SSH 登錄的請求。

第三步,服務器收到用戶 SSH 登錄的請求,發送一些隨機數據給用戶,要求用戶證明自己的身份。

第四步,客戶端收到服務器發來的數據,使用私鑰對數據進行簽名,然后再發還給服務器。

第五步,服務器收到客戶端發來的加密簽名后,使用對應的公鑰解密,然后跟原始數據比較。如果一致,就允許用戶登錄。

3、ssh-key命令:生成密鑰

3.1 基本用法

密鑰登錄時,首先需要生成公鑰和私鑰。OpenSSH 提供了一個工具程序ssh-keygen命令,用來生成密鑰

直接輸入ssh-keygen 【注意要用管理員權限登錄 cmd,程序會詢問一系列問題,然后生成密鑰。

通常做法是使用-t參數,指定密鑰的加密算法。

$ ssh-keygen -t dsa

上面示例中,-t參數用來指定密鑰的加密算法,一般會選擇dsa算法或rsa算法。注意,這個參數沒有默認值。

輸入上面的命令以后,ssh-keygen會要求用戶回答一些問題。

$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_dsa): press ENTER Enter passphrase (empty for no passphrase): ******** Enter same passphrase again: ******** Your identification has been saved in /home/username/.ssh/id_dsa. Your public key has been saved in /home/username/.ssh/id_dsa.pub. The key fingerprint is: 14:ba:06:98:a8:98:ad:27:b5:ce:55:85:ec:64:37:19 username@shell.isp.com 

第一個問題,詢問密鑰保存的文件名,默認是~/.ssh/id_dsa文件,這個是私鑰的文件名,對應的公鑰文件~/.ssh/id_dsa.pub是自動生成的。用戶的密鑰一般都放在主目錄的.ssh目錄里面。

如果選擇rsa算法,生成的密鑰文件默認就會是~/.ssh/id_rsa(私鑰)和~/.ssh/id_rsa.pub(公鑰)。

接着,就會是第二個問題,詢問是否要為私鑰文件設定密碼保護(passphrase)。這樣的話,即使入侵者拿到私鑰,還是需要破解密碼。如果為了方便,不想設定密碼保護,可以直接按回車鍵,密碼就會為空。后面還會讓你再輸入一次密碼,兩次輸入必須一致。注意,這里“密碼”的英文單詞是 passphrase,這是為了避免與 Linux 賬戶的密碼單詞 password 混淆,表示這不是用戶系統賬戶的密碼。

最后,就會生成私鑰和公鑰,屏幕上還會給出公鑰的指紋,以及當前的用戶名和主機名作為注釋,用來識別密鑰的來源。

公鑰文件和私鑰文件都是文本文件,可以用文本編輯器看一下它們的內容。公鑰文件的內容類似下面這樣。

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAvpB4lUbAaEbh9u6HLig7amsfywD4fqSZq2ikACIUBn3GyRPfeF93l/
weQh702ofXbDydZAKMcDvBJqRhUotQUwqV6HJxqoqPDlPGUUyo8RDIkLUIPRyq
ypZxmK9aCXokFiHoGCXfQ9imUP/w/jfqb9ByDtG97tUJF6nFMP5WzhM= username@shell.isp.com

上面示例中,末尾的username@shell.isp.com是公鑰的注釋,用來識別不同的公鑰,表示這是哪台主機(shell.isp.com)的哪個用戶(username)的公鑰,不是必需項。

下面的命令可以列出用戶所有的公鑰。

$ ls -l ~/.ssh/id_*.pub

生成密鑰以后,建議修改它們的權限,防止其他人讀取。

$ chmod 600 ~/.ssh/id_rsa
$ chmod 600 ~/.ssh/id_rsa.pub

3.2 配置項 

ssh-keygen的命令行配置項,主要有下面這些。

(1)-b

-b參數指定密鑰的二進制位數。這個參數值越大,密鑰就越不容易破解,但是加密解密的計算開銷也會加大。

一般來說,-b至少應該是1024,更安全一些可以設為2048或者更高。

......

4、手動上傳公鑰

生成密鑰以后,公鑰必須上傳到服務器,才能使用公鑰登錄。

OpenSSH 規定,用戶公鑰保存在服務器的~/.ssh/authorized_keys文件。你要以哪個用戶的身份登錄到服務器,密鑰就必須保存在該用戶主目錄的~/.ssh/authorized_keys文件。只要把公鑰添加到這個文件之中,就相當於公鑰上傳到服務器了。每個公鑰占據一行。如果該文件不存在,可以手動創建。

用戶可以手動編輯該文件,把公鑰粘貼進去,也可以在本機計算機上,執行下面的命令。

$ cat ~/.ssh/id_rsa.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" 

上面示例中,user@host要替換成你所要登錄的用戶名和主機名。

注意,authorized_keys文件的權限要設為644,即只有文件所有者才能寫。如果權限設置不對,SSH 服務器可能會拒絕讀取該文件。

$ chmod 644 ~/.ssh/authorized_keys

【說明:服務器上SSH服務不用重啟】

只要公鑰上傳到服務器,下次登錄時,OpenSSH 就會自動采用密鑰登錄,不再提示輸入密碼

$ ssh -l username shell.isp.com
Enter passphrase for key '/home/you/.ssh/id_dsa': ************ Last login: Mon Mar 24 02:17:27 2014 from ex.ample.com shell.isp.com> 

上面例子中,SSH 客戶端使用私鑰之前,會要求用戶輸入密碼(passphrase),用來解開私鑰。

5、ssh-copy-id 命令:自動上傳公鑰

OpenSSH 自帶一個ssh-copy-id命令【但是windows上的openssh不自帶,需要另外下載】,可以自動將公鑰拷貝到遠程服務器的~/.ssh/authorized_keys文件。如果~/.ssh/authorized_keys文件不存在,ssh-copy-id命令會自動創建該文件。

用戶在本地計算機執行下面的命令,就可以把本地的公鑰拷貝到服務器。

$ ssh-copy-id -i key_file user@host 

上面命令中,-i參數用來指定公鑰文件,user是所要登錄的賬戶名,host是服務器地址。如果省略用戶名,默認為當前的本機用戶名。執行完該命令,公鑰就會拷貝到服務器。

注意,公鑰文件可以不指定路徑和.pub后綴名,ssh-copy-id會自動在~/.ssh目錄里面尋找。

$ ssh-copy-id -i id_rsa user@host

上面命令中,公鑰文件會自動匹配到~/.ssh/id_rsa.pub

ssh-copy-id會采用密碼登錄,系統會提示輸入遠程服務器的密碼。

注意,ssh-copy-id是直接將公鑰添加到authorized_keys文件的末尾。如果authorized_keys文件的末尾不是一個換行符,會導致新的公鑰添加到前一個公鑰的末尾,兩個公鑰連在一起,使得它們都無法生效。所以,如果authorized_keys文件已經存在,使用ssh-copy-id命令之前,務必保證authorized_keys文件的末尾是換行符(假設該文件已經存在)。

6、ssh-agent 命令,ssh-add 命令

私鑰設置了密碼以后,每次使用都必須輸入密碼,有時讓人感覺非常麻煩。比如,連續使用scp命令遠程拷貝文件時,每次都要求輸入密碼。

ssh-agent命令就是為了解決這個問題而設計的,它讓用戶在整個 Bash 對話(session)之中,只在第一次使用 SSH 命令時輸入密碼,然后將私鑰保存在內存中,后面都不需要再輸入私鑰的密碼了。

省略...

7、關閉密碼登錄

為了安全性,啟用密鑰登錄之后,最好關閉服務器的密碼登錄。

對於 OpenSSH,具體方法就是打開服務器 sshd 的配置文件/etc/ssh/sshd_config,將PasswordAuthentication這一項設為no

PasswordAuthentication no

修改配置文件以后,不要忘了重新啟動 sshd,否則不會生效。

SSH服務器

1、簡介

SSH 的架構是服務器/客戶端模式,兩端運行的軟件是不一樣的。OpenSSH 的客戶端軟件是 ssh,服務器軟件是 sshd。本章介紹 sshd 的各種知識。

如果沒有安裝 sshd,可以用下面的命令安裝。

# Debian $ sudo aptitude install openssh-server # Red Hat $ sudo yum install openssh-server 

一般來說,sshd 安裝后會跟着系統一起啟動。如果當前 sshd 沒有啟動,可以用下面的命令啟動。

$ sshd

上面的命令運行以后,sshd 自動進入后台,

2、sshd配置文件

sshd 的配置文件在/etc/ssh目錄,主配置文件是sshd_config,此外還有一些安裝時生成的密鑰。

  • /etc/ssh/sshd_config:配置文件
  • /etc/ssh/ssh_host_ecdsa_key:ECDSA 私鑰。
  • /etc/ssh/ssh_host_ecdsa_key.pub:ECDSA 公鑰。
  • /etc/ssh/ssh_host_key:用於 SSH 1 協議版本的 RSA 私鑰。
  • /etc/ssh/ssh_host_key.pub:用於 SSH 1 協議版本的 RSA 公鑰。
  • /etc/ssh/ssh_host_rsa_key:用於 SSH 2 協議版本的 RSA 私鑰。
  • /etc/ssh/ssh_host_rsa_key.pub:用於 SSH 2 協議版本的 RSA 公鑰。
  • /etc/pam.d/sshd:PAM 配置文件。

注意,如果重裝 sshd,上面這些密鑰都會重新生成,導致客戶端重新 ssh 連接服務器時,會跳出警告,拒絕連接。為了避免這種情況,可以在重裝 sshd 時,先備份/etc/ssh目錄,重裝后再恢復這個目錄。

配置文件sshd_config的格式是,每個命令占據一行。每行都是配置項和對應的值,配置項的大小寫不敏感,與值之間使用空格分隔。

Port 2034

上面的配置命令指定,配置項Port的值是2034Port寫成port也可。

配置文件還有另一種格式,就是配置項與值之間有一個等號,等號前后的空格可選。

Port = 2034

注意,注釋只能放在一行的開頭,不能放在一行的結尾。

Port 2034 # 此處不允許注釋 

上面的寫法是錯誤的。

修改配置文件以后,可以用 sshd 命令的-t(test)檢查有沒有語法錯誤

$ sshd -t

配置文件修改以后,並不會自動生效,必須重新啟動 sshd。

$ sudo systemctl restart sshd.service

3、sshd密鑰

sshd 有自己的一對或多對密鑰。它使用密鑰向客戶端證明自己的身份。所有密鑰都是公鑰和私鑰成對出現,公鑰的文件名一般是私鑰文件名加上后綴.pub

DSA 格式的密鑰文件默認為/etc/ssh/ssh_host_dsa_key(公鑰為ssh_host_dsa_key.pub),RSA 格式的密鑰為/etc/ssh/ssh_host_rsa_key(公鑰為ssh_host_rsa_key.pub)。如果需要支持 SSH 1 協議,則必須有密鑰/etc/ssh/ssh_host_key

如果密鑰不是默認文件,那么可以通過配置文件sshd_configHostKey配置項指定。默認密鑰的HostKey設置如下。

# HostKey for protocol version 1 # HostKey /etc/ssh/ssh_host_key # HostKeys for protocol version 2 # HostKey /etc/ssh/ssh_host_rsa_key # HostKey /etc/ssh/ssh_host_dsa_ke 

上面命令前面的#表示這些行都是注釋,因為這是默認值,有沒有這幾行都一樣。

如果要修改密鑰,就要去掉行首的#,指定其他密鑰。

HostKey /usr/local/ssh/my_dsa_key HostKey /usr/local/ssh/my_rsa_key HostKey /usr/local/ssh/my_old_ssh1_key

4、sshd 配置項

/etc/ssh/sshd_config文件里面的配置項,省略......

  • PasswordAuthentication

PasswordAuthentication指定是否允許密碼登錄,默認值為yesPasswordAuthentication yes),建議改成no(禁止密碼登錄,只允許密鑰登錄)。

  • Port

Port指定 sshd 監聽的端口,即客戶端連接的端口,默認是22(Port 22)。出於安全考慮,可以改掉這個端口(比如Port 8822)。

配置文件可以使用多個Port命令,同時監聽多個端口。

Port 22
Port 80
Port 443
Port 8080

上面的示例表示同時監聽4個端口。

5、sshd 的命令行配置項

sshd 命令有一些配置項。這些配置項在調用時指定,可以覆蓋配置文件的設置。

(1)-d

-d參數用於顯示 debug 信息。

$ sshd -d

(7)-p

-p參數指定 sshd 的服務端口。

$ sshd -p 2034

上面命令指定 sshd 在2034端口啟動。

-p參數可以指定多個端口。

$ sshd -p 2222 -p 3333

(8)-t

-t參數檢查配置文件的語法是否正確。

SSH端口轉發

1、簡介

SSH 除了登錄服務器,還有一大用途,就是作為加密通信的中介,充當兩台服務器之間的通信加密跳板,使得原本不加密的通信變成加密通信。這個功能稱為端口轉發(port forwarding),又稱 SSH 隧道(tunnel)。

端口轉發有兩個主要作用:

(1)將不加密的數據放在 SSH 安全連接里面傳輸,使得原本不安全的網絡服務增加了安全性,比如通過端口轉發訪問 Telnet、FTP 等明文服務,數據傳輸就都會加密。

(2)作為數據通信的加密跳板,繞過網絡防火牆。

端口轉發有三種使用方法:動態轉發,本地轉發,遠程轉發。下面逐一介紹。

2、本地轉發

本地轉發(local forwarding)指的是,SSH 服務器作為中介的跳板機,建立本地計算機與特定目標網站之間的加密連接。本地轉發是在本地計算機的 SSH 客戶端建立的轉發規則:它會指定一個本地端口(local-port),所有發向那個端口的請求,都會轉發到 SSH 跳板機(tunnel-host),然后 SSH 跳板機作為中介,將收到的請求發到目標服務器(target-host)的目標端口(target-port)。

$ ssh -L local-port:target-host:target-port tunnel-host

上面命令中,-L參數表示本地轉發,local-port是本地端口,target-host是你想要訪問的目標服務器,target-port是目標服務器的端口,tunnel-host是 SSH 跳板機【即 SSH服務器所在的主機, root@ip】。

舉例來說,現在有一台 SSH 跳板機tunnel-host,我們想要通過這台機器,在本地2021端口與目標網站www.example.com的80端口之間建立 SSH 隧道,就可以寫成下面這樣。

$ ssh -L 2021:www.example.com:80 tunnel-host -N

然后,訪問本機的2021端口,就是訪問www.example.com的80端口。

$ curl http://localhost:2021     或者在瀏覽器中直接輸入此地址

注意,本地端口轉發采用 HTTP 協議,不用轉成 SOCKS5 協議。

-N參數,表示不在 SSH 跳板機執行遠程命令,讓 SSH 只充當隧道。另外還有一個-f參數表示 SSH 連接在后台運行。

采用上面的中介方式,只有本機到 tunnel-host 的這一段是加密的,tunnel-host 到mail.example.com的這一段並不加密。

解釋:

當訪問本機的2021的端口時,被加密后轉發到120.79.67.39的ssh服務,再解密被轉發到hutan.vip:80
data < >localhost:2021 < > localhost:XXXXX < > 120.79.67.39:22 < > 120.79.67.39:yyyyy < > hutan.vip:80
流程解釋:
    訪問 http://localhost:2021 ,數據會發送到本機2021端口,再在本機開一個隨機端口,充當ssh客戶端,再把數據流量發送到22端口的ssh服務端,收到數據以后,解密數據,臨時開一個隨機端口充當客戶端,再把流量發送到80端口hutan.vip
 #實驗
  A->C    訪問被限制
    A-B->C   使用B主機作為跳板突破訪問限制

如果經常使用本地轉發,可以將設置寫入 SSH 客戶端的用戶個人配置文件(~/.ssh/config)。

Host test.example.com
LocalForward client-IP:client-port server-IP:server-port

3、動態轉發

動態轉發指的是,本機與 SSH 服務器之間創建了一個加密連接,然后本機內部針對某個端口的通信,都通過這個加密連接轉發。它的一個使用場景就是,訪問所有外部網站,都通過 SSH 轉發。

動態轉發需要把本地端口綁定到 SSH 服務器。至於 SSH 服務器要去訪問哪一個網站,完全是動態的,取決於原始通信,所以叫做動態轉發。

$ ssh -D local-port tunnel-host -N

上面命令中,-D表示動態轉發,local-port是本地端口,tunnel-host是 SSH 服務器,-N表示這個 SSH 連接只進行端口轉發,不登錄遠程 Shell,不能執行遠程命令,只能充當隧道。

舉例來說,如果本地端口是2121,那么動態轉發的命令就是下面這樣。

$ ssh -D 2121 tunnel-host -N

注意,這種轉發采用了 SOCKS5 協議。訪問外部網站時,需要把 HTTP 請求轉成 SOCKS5 協議,才能把本地端口的請求轉發出去。

下面是 SSH 隧道建立后的一個使用實例。

$ curl -x socks5://localhost:2121 http://www.example.com

上面命令中,curl 的-x參數指定代理服務器,即通過 SOCKS5 協議的本地2121端口,訪問http://www.example.com

如果經常使用動態轉發,可以將設置寫入 SSH 客戶端的用戶個人配置文件(~/.ssh/config)。

DynamicForward tunnel-host:local-port

SSH證書登錄

SSH 是服務器登錄工具,一般情況下都采用密碼登錄或密鑰登錄。

但是,SSH 還有第三種登錄方法,那就是證書登錄。某些情況下,它是更合理、更安全的登錄方法。

1、非證書登錄的缺點

密碼登錄需要輸入服務器密碼,這非常麻煩,也不安全,存在被暴力破解的風險。

密鑰登錄需要服務器保存用戶的公鑰,也需要用戶保存服務器公鑰的指紋。這對於多用戶、多服務器的大型機構很不方便,如果有員工離職,需要將他的公鑰從每台服務器刪除。

2、證書登錄是什么?

證書登錄就是為了解決上面的缺點而設計的。它引入了一個證書頒發機構(Certificate Authority,簡稱 CA),對信任的服務器頒發服務器證書,對信任的用戶頒發用戶證書。

登錄時,用戶和服務器不需要提前知道彼此的公鑰,只需要交換各自的證書,驗證是否可信即可

證書登錄的主要優點有兩個:

(1)用戶和服務器不用交換公鑰,這更容易管理,也具有更好的可擴展性。

(2)證書可以設置到期時間,而公鑰沒有到期時間。針對不同的情況,可以設置有效期很短的證書,進一步提高安全性。

3、證書登錄的流程

SSH 證書登錄之前,如果還沒有證書,需要生成證書。具體方法是:

(1)用戶和服務器都將自己的公鑰,發給 CA;

(2)CA 使用服務器公鑰,生成服務器證書,發給服務器;

(3)CA 使用用戶的公鑰,生成用戶證書,發給用戶。

有了證書以后,用戶就可以登錄服務器了。整個過程都是 SSH 自動處理,用戶無感知。

第一步,用戶登錄服務器時,SSH 自動將用戶證書發給服務器。

第二步,服務器檢查用戶證書是否有效,以及是否由可信的 CA 頒發。證實以后,就可以信任用戶。

第三步,SSH 自動將服務器證書發給用戶。

第四步,用戶檢查服務器證書是否有效,以及是否由信任的 CA 頒發。證實以后,就可以信任服務器。

第五步,雙方建立連接,服務器允許用戶登錄。

4、生成 CA 的密鑰

證書登錄的前提是,必須有一個 CA,而 CA 本質上就是一對密鑰,跟其他密鑰沒有不同,CA 就用這對密鑰去簽發證書

雖然 CA 可以用同一對密鑰簽發用戶證書和服務器證書,但是出於安全性和靈活性,最好用不同的密鑰分別簽發。所以,CA 至少需要兩對密鑰,一對是簽發用戶證書的密鑰,假設叫做user_ca,另一對是簽發服務器證書的密鑰,假設叫做host_ca

使用下面的命令,生成user_ca

# 生成 CA 簽發用戶證書的密鑰 $ ssh-keygen -t rsa -b 4096 -f ~/.ssh/user_ca -C user_ca 

上面的命令會在~/.ssh目錄生成一對密鑰:user_ca(私鑰)和user_ca.pub(公鑰)。

這個命令的各個參數含義如下。

  • -t rsa:指定密鑰算法 RSA。
  • -b 4096:指定密鑰的位數是4096位。安全性要求不高的場合,這個值可以小一點,但是不應小於1024。
  • -f ~/.ssh/user_ca:指定生成密鑰的位置和文件名。
  • -C user_ca:指定密鑰的識別字符串,相當於注釋,可以隨意設置。

使用下面的命令,生成host_ca

# 生成 CA 簽發服務器證書的密鑰 $ ssh-keygen -t rsa -b 4096 -f host_ca -C host_ca 

上面的命令會在~/.ssh目錄生成一對密鑰:host_ca(私鑰)和host_ca.pub(公鑰)。

現在,~/.ssh目錄應該至少有四把密鑰。

  • ~/.ssh/user_ca
  • ~/.ssh/user_ca.pub
  • ~/.ssh/host_ca
  • ~/.ssh/host_ca.pub

5、CA 簽發服務器證書

有了 CA 以后,就可以簽發服務器證書了。

簽發證書,除了 CA 的密鑰以外,還需要服務器的公鑰。一般來說,SSH 服務器(通常是sshd)安裝時,已經生成密鑰/etc/ssh/ssh_host_rsa_key了。如果沒有的話,可以用下面的命令生成。

$ sudo ssh-keygen -f /etc/ssh/ssh_host_rsa_key -b 4096 -t rsa

上面命令會在/etc/ssh目錄,生成ssh_host_rsa_key(私鑰)和ssh_host_rsa_key.pub(公鑰)。然后,需要把服務器公鑰ssh_host_rsa_key.pub,復制或上傳到 CA 所在的服務器。

上傳以后,CA 就可以使用密鑰host_ca為服務器的公鑰ssh_host_rsa_key.pub簽發服務器證書。

$ ssh-keygen -s host_ca -I host.example.com -h -n host.example.com -V +52w ssh_host_rsa_key.pub

上面的命令會生成服務器證書ssh_host_rsa_key-cert.pub(服務器公鑰名字加后綴-cert)。這個命令各個參數的含義如下。

  • -s:指定 CA 簽發證書的密鑰。
  • -I:身份字符串,可以隨便設置,相當於注釋,方便區分證書,將來可以使用這個字符串撤銷證書。
  • -h:指定該證書是服務器證書,而不是用戶證書。
  • -n host.example.com:指定服務器的域名,表示證書僅對該域名有效。如果有多個域名,則使用逗號分隔。用戶登錄該域名服務器時,SSH 通過證書的這個值,分辨應該使用哪張證書發給用戶,用來證明服務器的可信性。
  • -V +52w:指定證書的有效期,這里為52周(一年)。默認情況下,證書是永遠有效的。建議使用該參數指定有效期,並且有效期最好短一點,最長不超過52周。
  • ssh_host_rsa_key.pub:服務器公鑰。

生成證書以后,可以使用下面的命令,查看證書的細節。

$ ssh-keygen -L -f ssh_host_rsa_key-cert.pub

最后,為證書設置權限。

$ chmod 600 ssh_host_rsa_key-cert.pub

6、CA 簽發用戶證書

下面,再用 CA 簽發用戶證書。這時需要用戶的公鑰,如果沒有的話,客戶端可以用下面的命令生成一對密鑰。

$ ssh-keygen -f ~/.ssh/user_key -b 4096 -t rsa

上面命令會在~/.ssh目錄,生成user_key(私鑰)和user_key.pub(公鑰)。

然后,將用戶公鑰user_key.pub,上傳或復制到 CA 服務器。接下來,就可以使用 CA 的密鑰user_ca為用戶公鑰user_key.pub簽發用戶證書。

$ ssh-keygen -s user_ca -I user@example.com -n user -V +1d user_key.pub

上面的命令會生成用戶證書user_key-cert.pub(用戶公鑰名字加后綴-cert)。這個命令各個參數的含義如下。

  • -s:指定 CA 簽發證書的密鑰
  • -I:身份字符串,可以隨便設置,相當於注釋,方便區分證書,將來可以使用這個字符串撤銷證書。
  • -n user:指定用戶名,表示證書僅對該用戶名有效。如果有多個用戶名,使用逗號分隔。用戶以該用戶名登錄服務器時,SSH 通過這個值,分辨應該使用哪張證書,證明自己的身份,發給服務器。
  • -V +1d:指定證書的有效期,這里為1天,強制用戶每天都申請一次證書,提高安全性。默認情況下,證書是永遠有效的。
  • user_key.pub:用戶公鑰。

生成證書以后,可以使用下面的命令,查看證書的細節。

$ ssh-keygen -L -f user_key-cert.pub

最后,為證書設置權限。

$ chmod 600 user_key-cert.pub

7、服務器安裝(服務器)證書

CA 生成服務器證書ssh_host_rsa_key-cert.pub以后,需要將該證書發回服務器,可以使用下面的scp命令,將證書拷貝過去。

$ scp ~/.ssh/ssh_host_rsa_key-cert.pub root@host.example.com:/etc/ssh/

然后,將下面一行添加到服務器配置文件/etc/ssh/sshd_config

HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub

上面的代碼告訴 sshd,服務器證書是哪一個文件。

重新啟動 sshd。

$ sudo systemctl restart sshd.service
# 或者 $ sudo service sshd restart 

8、服務器安裝 CA 公鑰

為了讓服務器信任用戶證書,必須將 CA 簽發用戶證書的公鑰user_ca.pub,拷貝到服務器。

$ scp ~/.ssh/user_ca.pub root@host.example.com:/etc/ssh/

上面的命令,將 CA 簽發用戶證書的公鑰user_ca.pub,拷貝到 SSH 服務器的/etc/ssh目錄。

然后,將下面一行添加到服務器配置文件/etc/ssh/sshd_config

TrustedUserCAKeys /etc/ssh/user_ca.pub

上面的做法是將user_ca.pub加到/etc/ssh/sshd_config,這會產生全局效果,即服務器的所有賬戶都會信任user_ca簽發的所有用戶證書。

另一種做法是將user_ca.pub加到服務器某個賬戶的~/.ssh/authorized_keys文件,只讓該賬戶信任user_ca簽發的用戶證書。具體方法是打開~/.ssh/authorized_keys,追加一行,開頭是@cert-authority principals="...",然后后面加上user_ca.pub的內容,大概是下面這個樣子。

@cert-authority principals="user" ssh-rsa AAAAB3Nz...XNRM1EX2gQ== 

上面代碼中,principals="user"指定用戶登錄的服務器賬戶名,一般就是authorized_keys文件所在的賬戶。

重新啟動 sshd。

$ sudo systemctl restart sshd.service
# 或者 $ sudo service sshd restart 

至此,SSH 服務器已配置為信任user_ca簽發的證書。

9、客戶端安裝(用戶)證書

客戶端安裝用戶證書很簡單,就是從 CA 將用戶證書user_key-cert.pub復制到客戶端,與用戶的密鑰user_key保存在同一個目錄即可。

10、客戶端安裝 CA 公鑰

為了讓客戶端信任服務器證書,必須將 CA 簽發服務器證書的公鑰host_ca.pub,加到客戶端的/etc/ssh/ssh_known_hosts文件(全局級別)或者~/.ssh/known_hosts文件(用戶級別)。

具體做法是打開ssh_known_hostsknown_hosts文件,追加一行,開頭為@cert-authority *.example.com,然后將host_ca.pub文件的內容(即公鑰)粘貼在后面,大概是下面這個樣子。

@cert-authority *.example.com ssh-rsa AAAAB3Nz...XNRM1EX2gQ==

上面代碼中,*.example.com是域名的模式匹配,表示只要服務器符合該模式的域名,且簽發服務器證書的 CA 匹配后面給出的公鑰,就都可以信任。如果沒有域名限制,這里可以寫成*。如果有多個域名模式,可以使用逗號分隔;如果服務器沒有域名,可以用主機名(比如host1,host2,host3)或者 IP 地址(比如11.12.13.14,21.22.23.24)。

然后,就可以使用證書,登錄遠程服務器了。

$ ssh -i ~/.ssh/user_key user@host.example.com

上面命令的-i參數用來指定用戶的密鑰。如果證書與密鑰在同一個目錄,則連接服務器時將自動使用該證書。

11、廢除證書

廢除證書的操作,分成用戶證書的廢除和服務器證書的廢除兩種。

服務器證書的廢除,用戶需要在known_hosts文件里面,修改或刪除對應的@cert-authority命令的那一行。

用戶證書的廢除,需要在服務器新建一個/etc/ssh/revoked_keys文件,然后在配置文件sshd_config添加一行,內容如下。

RevokedKeys /etc/ssh/revoked_keys

revoked_keys文件保存不再信任的用戶公鑰,由下面的命令生成。

$ ssh-keygen -kf /etc/ssh/revoked_keys -z 1 ~/.ssh/user1_key.pub

上面命令中,-z參數用來指定用戶公鑰保存在revoked_keys文件的哪一行,這個例子是保存在第1行。

如果以后需要廢除其他的用戶公鑰,可以用下面的命令保存在第2行。

$ ssh-keygen -ukf /etc/ssh/revoked_keys -z 2 ~/.ssh/user2_key.pub

SCP命令

 scp是 SSH 提供的一個客戶端程序,用來在兩台主機之間加密傳送文件(即復制文件)。

1、簡介

scpsecure copy 的縮寫,相當於cp命令 + SSH。它的底層是 SSH 協議,默認端口是22,相當於先使用ssh命令登錄遠程主機,然后再執行拷貝操作。

scp主要用於以下三種復制操作。

  • 本地復制到遠程。
  • 遠程復制到本地。
  • 兩個遠程系統之間的復制。

使用scp傳輸數據時,文件和密碼都是加密的,不會泄漏敏感信息。

2、基本語法

scp的語法類似cp的語法。

$ scp source destination 

上面命令中,source是文件當前的位置,destination是文件所要復制到的位置。它們都可以包含用戶名和主機名。

$ scp user@host:foo.txt bar.txt

上面命令將遠程主機(user@host)用戶主目錄下的foo.txt,復制為本機當前目錄的bar.txt。可以看到,主機與文件之間要使用冒號(:)分隔。

scp會先用 SSH 登錄到遠程主機,然后在加密連接之中復制文件。客戶端發起連接后,會提示用戶輸入密碼,這部分是跟 SSH 的用法一致的。

用戶名和主機名都是可以省略的。用戶名的默認值是本機的當前用戶名,主機名默認為當前主機。注意,scp會使用 SSH 客戶端的配置文件.ssh/config,如果配置文件里面定義了主機的別名,這里也可以使用別名連接。

scp支持一次復制多個文件

$ scp source1 source2 destination

上面命令會將source1source2兩個文件,復制到destination

注意,如果所要復制的文件,在目標位置已經存在同名文件,scp會在沒有警告的情況下覆蓋同名文件

eg:

3、用法示例

(1)本地文件復制到遠程

復制本機文件到遠程系統的用法如下。

# 語法 $ scp SourceFile user@host:directory/TargetFile # 示例 $ scp file.txt remote_username@10.10.0.2:/remote/directory 

下面是復制整個目錄的例子。

# 將本機的 documents 目錄拷貝到遠程主機, # 會在遠程主機創建 documents 目錄 $ scp -r documents username@server_ip:/path_to_remote_directory # 將本機整個目錄拷貝到遠程目錄下 $ scp -r localmachine/path_to_the_directory username@server_ip:/path_to_remote_directory/ # 將本機目錄下的所有內容拷貝到遠程目錄下 $ scp -r localmachine/path_to_the_directory/* username@server_ip:/path_to_remote_directory/ 

(2)遠程文件復制到本地

從遠程主機復制文件到本地的用法如下。

# 語法 $ scp user@host:directory/SourceFile TargetFile # 示例 $ scp remote_username@10.10.0.2:/remote/file.txt /local/directory 

下面是復制整個目錄的例子。

# 拷貝一個遠程目錄到本機目錄下 $ scp -r username@server_ip:/path_to_remote_directory local-machine/path_to_the_directory/ # 拷貝遠程目錄下的所有內容,到本機目錄下 $ scp -r username@server_ip:/path_to_remote_directory/* local-machine/path_to_the_directory/ $ scp -r user@host:directory/SourceFolder TargetFolder 

(3)兩個遠程系統之間的復制

本機發出指令,從遠程主機 A 拷貝到遠程主機 B 的用法如下。

# 語法 $ scp user@host1:directory/SourceFile user@host2:directory/SourceFile # 示例 $ scp user1@host1.com:/files/file.txt user2@host2.com:/files 

系統將提示你輸入兩個遠程帳戶的密碼。數據將直接從一個遠程主機傳輸到另一個遠程主機。

 

參考:https://wangdoc.com/ssh/index.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM