SSH使用小記

0、是什麼

SSH(Secure Shell)是一種加密的網絡傳輸協議,可在不安全的網絡中爲網絡服務提供安全的傳輸環境。(更多詳情可參閱維基百科 https://zh.wikipedia.org/wiki/Secure_Shell
SSH協議基於的傳輸層協議爲TCP,默認端口22。(與Telnet的區別,Telnet明文傳輸內容故不安全。默認端口FTP 2一、SSH 2二、Telnet 23)html

 

大多數現代操做系統(包括macOS、大部分Linux、OpenBSD、FreeBSD、Solaris等系統)都提供了SSH協議的實現程序,但Windows系統未自帶SSH程序。Windows用戶可使用Cygwin來創建SSH服務。(補註:從 Win10 1809 和 Windows Server 2019 開始 Windows 已支持 OpenSSH Server)linux

SSH命令參數說明:Linux下可經過 man ssh 命令查看(中文翻譯版可參閱 http://linux.51yip.com/search/ssh

web

一、SSH登陸原理及免密登陸設置

先驗知識算法

ssh登陸須要用到公鑰、祕鑰,它們用於對文本內容進行加密或解密。一般用RSA加密方式,其是一種對稱加密,由公鑰加密的內容私鑰可解密、由私鑰加密的內容公鑰也可解密。公鑰能夠對外公開,私鑰則不能。關於RSA加密可參閱:RSA算法原理-阮一峯瀏覽器

 

經過ssh登陸遠程主機一般有兩種登陸方式:安全

一、輸密碼登陸:每次登陸都要輸密碼。內部原理:登陸時服務端發送服務端本身的公鑰給客戶端,客戶端用該公鑰加密密碼併發送到服務端,服務端用對應的私鑰解密,檢查密碼是否正確以肯定是否登陸成功。bash

第一次登陸時會警告公鑰是否可信任,以防止中間人攻擊返回的是中間人的公鑰,若用戶確認信任之則公鑰會保存到客戶端的$HOME/.ssh/known_hosts文件裏,之後再登陸就不會有警告了。服務器

二、祕鑰登陸(免密碼登陸):預先配置好祕鑰,以後每次登陸無需輸密碼。方法是在一臺機器上生成公鑰/私鑰對並將其中一個祕鑰放到另外一個機器上。有兩種:網絡

2.一、公鑰登陸:事先將客戶端的公鑰放到服務端上(本質上至關於配置免密登陸白名單)。內部原理:登陸時服務端發送一個隨機字符串給客戶端,客戶端用本身的私鑰加密併發送到服務端,服務端根據是否有事先存儲的公鑰能進行解密以肯定是否登陸成功。併發

2.二、私鑰登陸:事先將服務端的私鑰放到客戶端上,每次登陸時須要指定私鑰,可見此時私鑰至關於服務端的臨時密碼。

前一種方式須要對服務端進行配置,若要免密登陸的客戶端不少,則須要頻繁修改服務端配置;後一種能夠避免頻繁更改服務端,但比較不安全由於私鑰是不宜外泄的,這種模式只要有私鑰的人就能訪問服務器,可是例如阿里雲服務器就是這種訪問方式。

 

這裏介紹公鑰登陸的配置方法(假設機器A登陸機器B須要密碼,但不想每次登陸都需輸密碼):

一、A上生成密鑰對:  ssh-keygen  ,會在當前用戶目錄 ~/.ssh/ 下生成 id_rsa、id_rsa.pub 兩個文件,裏面內容分別爲私鑰、公鑰

二、將公鑰(id_rsa.pub裏的內容)追加到到B上 ~/.ssh/authorized_keys 文件中,文件不存在則新建。也可在A上經過命令完成該效果:  ssh-copy-id -i ~/.ssh/id_rsa.pub <username of B>@<host of B>  

三、重啓B上的ssh服務:  sudo service sshd restart 

四、以後若還不行,可檢查B上的/etc/ssh/sshd_config文件,確認以下內容沒被註釋:

  RSAAuthentication yes
  PubkeyAuthentication yes
  AuthorizedKeysFile .ssh/authorized_keys

 

參考資料:http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html

 

二、SSH遠程操做

可經過SSH執行遠程命令而不須要登陸遠程主機,示例:(更多可參閱:http://www.javashuo.com/article/p-ofwmixvl-dg.html

# 主要命令格式
ssh
user@10.5.6.47 "ls /home; pwd " # 執行基本命令,可有多個 ssh -t user@10.5.6.47 " top " # 對於須要交互(須要tty)的命令,經過ssh遠程執行時不會爲此會話分配tty,故ssh當即退出遠程主機從而須要交互的命令當即結束。經過 -t 參數顯示聲明須要爲會話分配tty以解決之 ssh user@10.5.6.47 " bash -s " < test.sh helloworld # 遠程執行本地主機上的腳本,參數爲往腳本傳的參數 ssh user@10.5.6.47 /home/user/test.sh helloworld # 遠程執行遠程主機上的腳本,參數爲往該腳本傳的參數

# 其餘trick示例
cd && tar czv src | ssh user@host 'tar xz' # 將$HOME/src/目錄下面的全部文件,複製到遠程主機的$HOME/src/目錄
ssh user@host 'tar cz src' | tar xzv # 將遠程主機$HOME/src/目錄下面的全部文件,複製到用戶的當前目錄

 

三、SSH端口轉發

3.一、是什麼

SSH是安全的,會自動加密和解密全部 SSH 客戶端與服務端之間的網絡數據。此外,SSH 還提供了一個很是有用的功能——端口轉發:它可以將其餘 TCP 端口的網絡數據經過 SSH 鏈接來轉發,並自動提供了相應的加密及解密服務。因 SSH 爲其餘 TCP 鏈接提供了一個安全的通道來進行傳輸,故也被稱做SSH隧道(SSH Tunnel)。例如,Telnet,SMTP,LDAP 這些 TCP 應用均可以從中得益,避免了用戶名,密碼以及隱私信息的明文傳輸。而與此同時,若是工做環境中的防火牆限制了一些網絡端口的使用但容許 SSH 鏈接,則也可經過 TCP 端口轉發來使用 SSH 進行通訊。

總的來講,SSH 端口轉發能提供兩大功能:

一、加密SSH Client與SSH Server間傳輸的數據

二、突破防火牆限制以間接完成一些以前沒法創建的 TCP 鏈接

 從效果上看,端口轉發至關因而反向代理。

 

3.二、類型

SSH端口轉發爲沒法直接任意互通但能經過SSH訪問的兩個網絡或機器間提供了一個互通的橋樑。分爲 本地端口轉發遠程端口轉發動態端口轉發三種。

  • 本地端口轉發與遠程端口轉發的區別在於負責執行端口轉發的是所創建的SSH會話中的SSH Client仍是SSH Server(SSH Client指執行SSH命令的機器,下同
  • 前兩種把對轉發端口的請求轉發到目的機的特定端口、而最後一種則至關於一個代理功能——設置爲該代理後會把對任意端口的請求轉發到目的機的相應端口。

這裏設想一種場景,假設有機器A、B、C、D,其間關係爲:A、B間可互通,C、D間可互通,AB與CD間不能自由互通(因設置了防火牆、白名單等,只有B能經過SSH訪問C、反之則不可。(想象AB、CD分別在不通的網段、兩個網段間只有B能經過SSH訪問到C且C只對B開放SSH的22端口)。

 

3.2.一、本地端口轉發

命令: ssh -L <forward port>:<target host>:<target port> <SSH server addr> 

  • 四個參數分別表示轉發的端口(注意非管理員無權綁定熟知端口0~1023)、目標host、目標主機端口、SSH server地址(如 zsm@10.5.6.47)。若target host與SSH Server是同一個機子則target host可寫爲 "localhost",緣由見下面的原理部分
  • 對於IPV4,前三個參數用冒號 ":" 分隔,對於IPv6則用斜槓 "/" 分隔。
  • 爲了容許其餘機子鏈接轉發端口(不然只有轉發端口所在機器能鏈接該端口),能夠加  -g  參數(listen 0.0.0.0:tarport和listen 127.0.0.1:tarport的區別);SSH鏈接默認會登陸到SSH server(退出登陸後轉發功能會失效),可加 -fN 參數讓命令在後臺執行以免登陸到SSH server。

功能:將對SSH Client所在機器<forward port>端口的請求轉發到指定機器的指定端口(即 <target host>:<target port> )

原理:SSH Client所在機器分配一個 socket 監聽 <forward port> 端口,一旦此端口上有了鏈接,該鏈接就經安全通道轉發出去,同時SSH server所在機器和 <target host>:<target port> 創建鏈接。(請求的內部走向是SSH Client -> SSH Server -> 目標機,返回時原路返回)

應用場景:使得「內網」(SSH Client所在的)能訪問到不能直接訪問的其餘"網絡"

示例:假設D上有個web服務監聽8080端口,顯然,A、B都沒法直接訪問到該服務但C能夠。而B能夠經過SSH訪問C,此時在B上執行: ssh -g -fN -L 1000:hostD:8080 hostCSshAddr ,則A或B經過訪問B的1000端口就能訪問到D的web服務(內部走向是B -> C -> D)。

若沒有-g參數,則A訪問不了B的1000端口,只有B本身能夠。

若web服務在SSH server上(即目標主機與SSH服務端是同一個),則命令可簡爲: ssh -g -fN -L 1000:localhost:8080 hostCSshAddr ,可見這裏的localhost是相對於SSH server而言的。

 

3.2.二、遠程端口轉發

(與本地端口轉發幾乎同樣,只不過轉發端口在SSH Server且請求的內部走向相反)

命令: ssh -R <forward port>:<target host>:<target port> <SSH server addr>  ,注:不支持 -g 參數

  • 若target host與SSH Client是同一個機子則target host可寫爲 "localhost",緣由見下面的原理部分

功能:將對SSH Server所在機器<forward port>端口的請求轉發到指定機器的指定端口(即 <target host>:<target port> )

原理:SSH Server所在機器分配一個 socket 監聽 <forward port> 端口,一旦此端口上有了鏈接,該鏈接就經安全通道轉發出去,同時SSH Client所在機器和 <target host>:<target port> 創建鏈接。(請求的內部走向是SSH Server -> SSH Client -> 目標機,返回時原路返回)

應用場景:使得"外網"能訪問到"內網"(SSH Client所在的)

示例:若上述web服務在A,顯然,C、D沒法直接訪問該服務但B能夠。而B能夠經過SSH訪問C,此時在B上執行: ssh -fN -R 1000:hostA:8080 hostCSshAddr ,則C可經過訪問其1000端口就能訪問到A的web服務(內部走向是C -> B -> A)。

注:遠程端口轉發不支持-g參數故這裏沒法像本地端口轉發那樣經過 -g 參數讓D能訪問到A的web服務。解決:在SSH Server(即C)的/etc/ssh/sshd_config添加一行並重啓SSH服務: GatewayPorts yes 

 

3.2.三、動態端口轉發

命令: ssh -D <foward port> <SSH server addr>  ,可用參數與本地端口轉發的同樣

功能及原理:與本地端口轉發同樣,將對SSH Client所在機器<forward port>端口的請求轉發到SSH Server上,只不過設置時不用指定目的機器的host和port。SSH Client成爲一個反向代理,應用設置代理爲SSH Client後,應用發起請求時請求的內部走向也是SSH Client -> SSH Server -> 目標機,收到SSH Client轉發來的請求時SSH Server會與該請求的目標機鏈接。SSH 動態端口轉發是經過 Socks 協議實現的,建立動態端口轉發時 SSH 服務器就相似一個 Socks 代理服務器,因此這種轉發方式也叫 Socks 轉發

應用場景:

做爲代理:把全部請求都轉發到目的機,以突破防火牆等限制。

提升安全性:讓那些不加密的網絡鏈接,所有改走SSH鏈接,從而提升安全性。

示例: 做爲反向代理——在本節首所述場景下,在B執行: ssh -g -fN -D 1000 hostCSshAddr ,至關於啓動了個反向代理服務。以後在A或B上設置Sockets代理(如在瀏覽器設置Sockets代理),地址爲 hostB:1000,則C、D上的服務均能被A或B訪問到。如A訪問服務hostD:8080,請求會經過 SSH Client B -> SSH Server C -> hostD:8080,由C完成對D的請求後原路返回結果。

 

注:

SSH 端口轉發是經過 SSH 鏈接創建起來的,故必須保持這個 SSH 鏈接以使端口轉發保持生效。一旦關閉了此鏈接,相應的端口轉發也會隨之關閉。

只能在創建 SSH 鏈接的同時建立端口轉發,而不能給一個已經存在的 SSH 鏈接增長端口轉發。

 

參考資料:

http://www.javashuo.com/article/p-sibzutlz-ke.html ssh端口轉發

http://www.ruanyifeng.com/blog/2011/12/ssh_port_forwarding.html

相關文章
相關標籤/搜索