SSH詳解


ssh的軟件架構是服務器-客戶端模式(Server - Client)

在這個架構中,SSH軟件分成兩個部分:

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

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

SSH 客戶端

執行遠程命令

另一種執行遠程命令的方法,是將命令直接寫在ssh命令的后面。

$ ssh username@hostname command

采用這種語法執行命令的時候,不會提供互動式的shell環境。

如果需要互動式環境需要添加一個參數-t

ssh命令行配置項

-c : 指定加密算法

-C : 表示壓縮數據傳輸

-D : 指定本機的Socks監聽端口,該端口收到的請求,都將轉發到遠程的SSH主機,又稱動態端口轉發

ssh -D 1080 server

將本機1080端口收到的請求,都轉發到服務器server

-f : 表示SSH連接在后台運行

-F : 參數指定配置文件

-i : 指定私鑰

-l : 指定遠程登錄的賬戶名

-L : 設置本地端口轉發

$ ssh  -L 9999:targetServer:80 user@remoteserver

上面命令中,所有發向本地9999端口的請求,都會經過remoteserver發往 targetServer 的 80 端口,這就相當於直接連上了 targetServer 的 80 端口

-m : 指定校驗數據完整性的算法(message authentication code,簡稱MAC)

-N : 用於端口轉發,表示建立的SSH只用於端口轉發,不能執行遠程命令

-o : 指定一個配置命令

-p : 指定ssh客戶端連接的服務器端口

-q : 安靜模式(quiet),不向用戶輸出任何警告信息

-R : 指定遠程端口轉發

$ ssh -R 9999:targetServer:902 local

上面命令需在跳板服務器執行,指定本地計算機local監聽自己的 9999 端口,所有發向這個端口的請求,都會轉向 targetServer 的 902 端口。

-t : 參數在ssh直接運行遠端命令時,提供一個互動式Shell

-v : 參數顯示詳細信息,v可以重復多次,表示信息的詳細程度

-V : 輸出ssh客戶端的版本

客戶端配置文件

個人配置文件的優先級要高於全局配置文件

全局配置文件:/etc/ssh/ssh_config

個人配置文件:~/.ssh/config

功能

按照不同的服務器,列出各自的連接參數,從而不必每一次登錄都輸入重復的參數

Host *
     Port 2222

Host remoteserver
     HostName remote.example.com
     User neo
     Port 2112

Hsot * 代表對所有的主機都生效,縮進不是必須的

remoteserver只是一個別名,可以直接使用ssh remoteserver命令,就會套用config里面的參數進行連接

SSH密鑰登錄

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

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

驗證步驟

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

ssh-keygen -t dsa

-t參數用來指定密鑰的加密算法,一般會選擇dsa算法或者rsa算法,此參數必須要指定

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

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

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

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

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

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

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

手動上傳公鑰

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

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

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

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

ssh-copy-id 自動上傳公鑰

OpenSSH 自帶一個ssh-copy-id命令,可以自動將公鑰拷貝到遠程服務器的~/.ssh/authorized_keys文件。如果~/.ssh/authorized_keys文件不存在,ssh-copy-id命令會自動創建該文件。

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

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

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

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

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

端口轉發

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

主要有兩個作用:

  1. 將不加密數據放在SSH安全連接里面傳輸,增加不安全網絡服務的安全性。
  2. 作為數據通信的加密跳板,繞過網絡防火牆

三種使用方法:

  1. 動態轉發
  2. 本地轉發
  3. 遠程轉發

動態轉發

動態轉發指的是,本機與SSH服務器之間創建一個加密連接,然后本機內部針對某個端口的通信,都通過這個加密連接轉發。對於本地轉發遠程轉發,都存在兩個一一對應的端口,分別位於SSH的客戶端和服務端,而動態轉發只是綁定了一個本地端口,而目標地址:目標端口都是不固定的。目標地址:目標端口是由發起的請求決定的。

使用場景

  1. 訪問所有外部網站,都通過SSH轉發。(可做為簡易VPN)

  2. SSH服務器端運行了多個服務,使用了不同的端口,本地主機需要訪問這些服務

為什么需要動態端口轉發

  1. 由於防火牆的限制,本地主機並不能直接訪問遠程主機上的服務
  2. 存在多個服務的話,為每個端口分別創建本地端口轉發非常麻煩
ssh -D localhost:port tunnel-host
# example
ssh -D localhost:2121 root@112.3.42.245

在本地發起的請求,需要由Socket代理(Socket Proxy))轉發到SSH綁定的2121端口。

以瀏覽器的proxy代理為例,瀏覽器發起的請求都會轉發到2121端口,然后通過SSH轉發到真正的請求地址。

20210803113613

若Node.js服務運行在遠程雲主機上,則在瀏覽器中訪問localhost:3000即可以訪問。如果主機B1能夠訪問外網的話,則可以訪外網……

除了使用瀏覽器外,也可以通過命令行訪問

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

本地轉發

一般來講,雲主機的防火牆默認只打開了22端口,如果需要訪問3000端口的話,需要修改防火牆。為了保證安全,防火牆需要配置允許訪問的IP地址。但是,本地公網IP通常是網絡提供商動態分配的,是不斷變化的。這樣的話,防火牆配置需要經常修改,就會很麻煩。

本地轉發就是將發送到本地端口的請求,轉發到目標端口。這樣就可以通過訪問本地端口,來訪問目標端口的服務。

ssh -L 本機地址:本地端口:目標地址:目標端口

通過本地端口轉發,可以將發送到本地主機端口的請求,轉發到遠程主機端口上。

# 在本地主機登陸遠程主機,並進行本地端口轉發
ssh -L localhost:2000:local:3000 root@103.59.22.17

這樣,在本地主機A1上可以通過訪問http://localhost:2000來訪問遠程雲主機3000端口上的服務。

實際上,-L選項中的本地網卡地址是可以省略的,這時表示2000端口綁定了本地主機的所有網卡:

# 在本地主機A1登陸遠程雲主機B1,並進行本地端口轉發。2000端口綁定本地所有網卡
ssh -L 2000:localhost:3000 root@103.59.22.17

若本地主機A2能夠訪問A1,則A2也可以通過A1訪問遠程遠程雲主機B1上的Node.js服務。

另外,-L選項中的目標地址也可以是其他主機的地址。假設遠程雲主機B2的局域網IP地址為192.168.59.100,則可以這樣進行端口轉發:

# 在本地主機A1登陸遠程雲主機B1,並進行本地端口轉發。請求被轉發到遠程雲主機B2上
ssh -L 2000:192.168.59.100:3000 root@103.59.22.17

遠程轉發

應用場景:本地主機運行了一個服務,端口為3000,而本地主機沒有一個固定的公網ip地址,遠程主機需要訪問這個服務

如果本地主機有一個獨立公網ip,那么我們可以通過本地轉發來訪問本地主機上的服務。

但是大部分的時候本地主機都是在局域網內,與很多設備共享一個ip。

因此遇到這樣的情況,我們需要遠程轉發來解決。

定義

遠程轉發就是將發送到遠程端口的請求,轉發到目標端口。這樣就可以通過訪問遠程端口,來訪問目標端口的服務。

-R 遠程網卡地址:遠程端口:目標地址:目標端口

通過遠程轉發,可以將發送到遠程雲主機2000端口的請求,轉發到本地主機的3000端口。

# 在本地主機A1登陸遠程主機B1,並進行遠程端口轉發
ssh -R localhost:2000:local:3000 root@103.59.22.17

這樣,在遠程主機A1可以通過訪問http://localhost:2000來訪問本地主機的服務。

同理,遠程網卡地址可以省略,目標地址也可以是其他主機地址。假設本地主機A2的局域網IP地址為192.168.0.100

# 在本地主機A1登陸遠程雲主機B1,並進行遠程端口轉發
ssh -R 2000:192.168.0.100:3000 root@103.59.22.17

參考文章

1.https://wangdoc.com/ssh/port-forwarding.html
2.https://blog.fundebug.com/2017/04/24/ssh-port-forwarding/


免責聲明!

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



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