SSH好用的隧道原理解析功能

1向2飛發表於2016-07-22

SSH隧道與埠轉發及內網穿透


大家都知道SSH是一種安全的傳輸協議,用在連線伺服器上比較多。不過其實除了這個功能,它的隧道轉發功能更是吸引人。下面是個人根據自己的需求以及在網上查詢的資料配合自己的實際操作所得到的一些心得。

SSH/plink命令的基本資料:

ssh -C -f -N -g -L listen_port:DST_Host:DST_port user@Tunnel_Host 
ssh -C -f -N -g -R listen_port:DST_Host:DST_port user@Tunnel_Host 
ssh -C -f -N -g -D listen_port user@Tunnel_Host

相關引數的解釋: 
-f Fork into background after authentication. 
後臺認證使用者/密碼,通常和-N連用,不用登入到遠端主機。

-L port:host:hostport 
將本地機(客戶機)的某個埠轉發到遠端指定機器的指定埠. 工作原理是這樣的, 本地機器上分配了一個 socket 偵聽 port 埠, 一旦這個埠上有了連線, 該連線就經過安全通道轉發出去, 同時遠端主機和 host 的 hostport 埠建立連線. 可以在配置檔案中指定埠的轉發. 只有 root 才能轉發特權埠. IPv6 地址用另一種格式說明: port/host/hostport

-R port:host:hostport 
將遠端主機(伺服器)的某個埠轉發到本地端指定機器的指定埠. 工作原理是這樣的, 遠端主機上分配了一個 socket 偵聽 port 埠, 一旦這個埠上有了連線, 該連線就經過安全通道轉向出去, 同時本地主機和 host 的 hostport 埠建立連線. 可以在配置檔案中指定埠的轉發. 只有用 root 登入遠端主機才能轉發特權埠. IPv6 地址用另一種格式說明: port/host/hostport

-D port 
指定一個本地機器 “動態的’’ 應用程式埠轉發. 工作原理是這樣的, 本地機器上分配了一個 socket 偵聽 port 埠, 一旦這個埠上有了連線, 該連線就經過安全通道轉發出去, 根據應用程式的協議可以判斷出遠端主機將和哪裡連線. 目前支援 SOCKS4 協議, 將充當 SOCKS4 伺服器. 只有 root 才能轉發特權埠. 可以在配置檔案中指定動態埠的轉發.

-C Enable compression. 
壓縮資料傳輸。

-N Do not execute a shell or command. 
不執行指令碼或命令,通常與-f連用。

-g Allow remote hosts to connect to forwarded ports. 
在-L/-R/-D引數中,允許遠端主機連線到建立的轉發的埠,如果不加這個引數,只允許本地主機建立連線。注:這個引數我在實踐中似乎始終不起作用。

建立本地SSH隧道例子

在我們計劃建立一個本地SSH隧道之前,我們必須清楚下面這些資料:

  1. 中間伺服器d的IP地址
  2. 要訪問伺服器c的IP地址
  3. 要訪問伺服器c的埠

現在,我們把上面這張圖變得具體一些,給這些機器加上IP地址。並且根據下面這張圖列出我們的計劃:

 

  1. 需要訪問234.234.234.234的FTP服務,也就是埠21
  2. 中間伺服器是123.123.123.123

現在我們使用下面這條命令來達成我們的目的

1.ssh -N -f -L 2121:234.234.234.234:21 123.123.123.123

2.ftp localhost:2121 # 現在訪問本地2121埠,就能連線234.234.234.234的21埠了

這裡我們用到了SSH客戶端的三個引數,下面我們一一做出解釋:

  • -N 告訴SSH客戶端,這個連線不需要執行任何命令。僅僅做埠轉發
  • -f 告訴SSH客戶端在後臺執行
  • -L 做本地對映埠,被冒號分割的三個部分含義分別是
    • 需要使用的本地埠號
    • 需要訪問的目標機器IP地址(IP: 234.234.234.234)
    • 需要訪問的目標機器埠(埠: 21)
  • 最後一個引數是我們用來建立隧道的中間機器的IP地址(IP: 123.123.123.123)

我們再重複一下-L引數的行為。-L X:Y:Z的含義是,將IP為Y的機器的Z埠通過中間伺服器對映到本地機器的X埠。

在這條命令成功執行之後,我們已經具有繞過公司防火牆的能力,並且成功訪問到了我們喜歡的一個FTP伺服器了。

如何建立遠端SSH隧道

通過建立本地SSH隧道,我們成功地繞過防火牆開始下載FTP上的資源了。那麼當我們在家裡的時候想要察看下載進度怎麼辦呢?大多數公司的網路是通過路由器接入網際網路的,公司內部的機器不會直接與網際網路連線,也就是不能通過網際網路直接訪問。通過線路D-B-A訪問公司裡的機器a便是不可能的。也許你已經注意到了,雖然D-B-A這個方向的連線不通,但是A-B-D這個方向的連線是沒有問題的。那麼,我們能否利用一條已經連線好的A-B-D方向的連線來完成D-B-A方向的訪問呢?答案是肯定的,這就是遠端SSH隧道的用途。

與本地SSH一樣,我們在建立遠端SSH隧道之前要清楚下面幾個引數:

  • 需要訪問內部機器的遠端機器的IP地址(這裡是123.123.123.123)
  • 需要讓遠端機器能訪問的內部機器的IP地址(這裡因為是想把本機對映出去,因此IP是127.0.0.1)
  • 需要讓遠端機器能訪問的內部機器的埠號(埠:22)

在清楚了上面的引數後,我們使用下面的命令來建立一個遠端SSH隧道

1.ssh -N -f -R 2222:127.0.0.1:22 123.123.123.123

現在,在IP是123.123.123.123的機器上我們用下面的命令就可以登陸公司的IP是192.168.0.100的機器了。

1.ssh -p 2222 localhost

-N,-f 這兩個引數我們已經在本地SSH隧道中介紹過了。我們現在重點說說引數-R。該引數的三個部分的含義分別是:

  • 遠端機器使用的埠(2222)
  • 需要對映的內部機器的IP地址(127.0.0.1)
  • 需要對映的內部機器的埠(22)

例如:-R X:Y:Z 就是把我們內部的Y機器的Z埠對映到遠端機器的X埠上。

建立SSH隧道的幾個技巧

自動重連

隧道可能因為某些原因斷開,例如:機器重啟,長時間沒有資料通訊而被路由器切斷等等。因此我們可以用程式控制隧道的重新連線,例如一個簡單的迴圈或者使用 djb’s daemontools . 不管用哪種方法,重連時都應避免因輸入密碼而卡死程式。關於如何安全的避免輸入密碼的方法,請參考我的如何實現安全的免密碼ssh登入 。這裡請注意,如果通過其他程式控制隧道連線,應當避免將SSH客戶端放到後臺執行,也就是去掉-f引數。

保持長時間連線

有些路由器會把長時間沒有通訊的連線斷開。SSH客戶端的TCPKeepAlive選項可以避免這個問題的發生,預設情況下它是被開啟的。如果它被關閉了,可以在ssh的命令上加上-o TCPKeepAlive=yes來開啟。

另一種方法是,去掉-N引數,加入一個定期能產生輸出的命令。例如: top或者vmstat。下面給出一個這種方法的例子:

1.ssh -R 2222:localhost:22 123.123.123.123 "vmstat 30"

檢查隧道狀態

有些時候隧道會因為一些原因通訊不暢而卡死,例如:由於傳輸資料量太大,被路由器帶入stalled狀態。這種時候,往往SSH客戶端並不退出,而是卡死在那裡。一種應對方法是,使用SSH客戶端的ServerAliveInterval和ServerAliveCountMax選項。 ServerAliveInterval會在隧道無通訊後的一段設定好的時間後傳送一個請求給伺服器要求伺服器響應。如果伺服器在 ServerAliveCountMax次請求後都沒能響應,那麼SSH客戶端就自動斷開連線並退出,將控制權交給你的監控程式。這兩個選項的設定方法分別是在ssh時加入-o ServerAliveInterval=n和-o ServerAliveCountMax=m。其中n, m可以自行定義。

如何將埠繫結到外部地址上

使用上面的方法,對映的埠只能繫結在127.0.0.1這個介面上。也就是說,只能被本機自己訪問到。如何才能讓其他機器訪問這個埠呢?我們可以把這個對映的埠繫結在0.0.0.0的介面上,方法是加上引數-b 0.0.0.0。同時還需要開啟SSH伺服器端的一個選項-GatewayPorts。預設情況下它應當是被開啟的。如果被關閉的話,可以在/etc /sshd_config中修改GatewayPorts no為GatewayPorts yes來開啟它。

通過SSH隧道建立SOCKS伺服器

如果我們需要藉助一臺中間伺服器訪問很多資源,一個個對映顯然不是高明的辦法(事實上,高明確實沒有用這個方法)。幸好,SSH客戶端為我們提供了通過SSH隧道建立SOCKS伺服器的功能。

通過下面的命令我們可以建立一個通過123.123.123.123的SOCKS伺服器。

1.ssh -N -f -D 1080 123.123.123 # 將埠繫結在127.0.0.1上

2.ssh -N -f -D 0.0.0.0:1080 123.123.123.123 # 將埠繫結在0.0.0.0上

通過SSH建立的SOCKS伺服器使用的是SOCKS5協議,在為應用程式設定SOCKS代理的時候要特別注意。
參考:http://www.kaiyuanba.cn/html/1/131/226/7857.htm

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23890223/viewspace-2122389/,如需轉載,請註明出處,否則將追究法律責任。

相關文章