1. 程式人生 > >SSH的埠轉發:本地轉發Local Forward和遠端轉發Remote Forward

SSH的埠轉發:本地轉發Local Forward和遠端轉發Remote Forward

實戰 SSH 埠轉發

首先要記住一件事情就是:

SSH 埠轉發自然需要 SSH 連線,而 SSH 連線是有方向的,從 SSH Client 到 SSH Server 。

而我們所要訪問的應用也是有方向的,應用連線的方向也是從應用的 Client 端連線到應用的 Server 端。比如需要我們要訪問Internet上的Web站點時,Http應用的方向就是從我們自己這臺主機(Client)到遠處的Web Server。

如果SSH連線和應用的連線這兩個連線的方向一致,那我們就說它是本地轉發。

ssh -L <local port>:<remote host>:<remote port> <SSH hostname>
Chapter 8 Secure Network (ssh埠對映) - linux-ul - unix-EA

如果SSH連線和應用的連線這兩個連線的方向不同,那我們就說它是遠端轉發。

ssh -R <local port>:<remote host>:<remote port> <SSH hostname>
Chapter 8 Secure Network (ssh埠對映) - linux-ul - unix-EA

本地轉發在本地這臺機器上監聽一個埠,然後所有訪問這個埠的資料都會通過ssh 隧道傳輸到遠端的對應埠上,下面是例子。

本地埠轉發繫結的是 lookback 介面,這意味著只有 localhost 或者 127.0.0.1 才能使用本機的埠轉發 , 其他機器發起的連線只會得到“ connection refused. ”。要想讓其他機器也能共享這個隧道來轉發的話需要在配置檔案中使用GatewayPorts 關鍵字,或者直接命令列下使用"-g"引數。

另外本地轉發命令中的 <remote host> 和 <SSH hostname> 可以是不同的主機。

Chapter 8 Secure Network (ssh埠對映) - linux-ul - unix-EA

遠端轉發與本地轉發正好相反,開啟ssh隧道以後,在遠端伺服器監聽一個埠,所有訪問遠端伺服器指定埠都會通過隧道傳輸到本地的對應埠上,下面是例子。

Chapter 8 Secure Network (ssh埠對映) - linux-ul - unix-EA

可以將遠端伺服器一個埠remote_port繫結到本地埠port,其中-C是進行資料壓縮,-f是後臺操作,只有當提示使用者名稱密碼的時候才轉向前臺。-N是不執行遠端命令,在只是埠轉發時這條命令很有用處。-g 是允許遠端主機連線本地轉發埠。-R表明是將遠端主機埠對映到本地埠。如果是-L,則是將本地埠對映到遠端主機埠。

ssh的三個強大的埠轉發命令:

轉發到遠端:ssh -C -f -N -g -L 本地埠:目標IP:目標埠 使用者名稱@目標IP

轉發到本地:ssh -C -f -N -g –R 本地埠:目標IP:目標埠 使用者名稱@目標IP

ssh -C -f -N -g -D listen_port [email protected]_Host

-C:壓縮資料傳輸。

-f :後臺認證使用者/密碼,通常和-N連用,不用登入到遠端主機。

-N :不執行指令碼或命令,通常與-f連用。

-g :在-L/-R/-D引數中,允許遠端主機連線到建立的轉發的埠,如果不加這個引數,只允許本地主機建立連線。

-L 本地埠:目標IP:目標埠

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

-R本地埠:目標IP:目標埠

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

-p :被登入的ssd伺服器的sshd服務埠。

-D port

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

應用舉例

1.將發往本機的80埠訪問轉發到174.139.9.66的8080埠

ssh -C -f -N -g -L 80:174.139.9.66:8080     [email protected]

2.將發往174.139.9.66的8080訪問轉發到本機的80埠

ssh -C -f -N -g -R 80:174.139.9.66:8080            [email protected]

-N - 不使用Shell視窗,純做轉發的時候用,如果你在對映完成後繼續在伺服器上輸入命令,去掉這個引數即可

例子A:我們想遠端管理伺服器上的MySQL,那麼使用下面命令

ssh -L 3306:127.0.0.1:3306   [email protected]    -N  

執行這個命令之後,ssh將會自動將伺服器的3306對映到本機的3306埠,我們就可以使用任意MySQL客戶端連線 localhost:3306即可訪問到伺服器上的MySQL了。

例子B:一次同時對映多個埠

ssh -L 8888:www.host.com:80 -L 110:mail.host.com:110 -L    25:mail.host.com:25 [email protected] -N  

這個命令將自動把伺服器的80,110,25埠對映到本機的8888,110和25埠 以上命令在ubuntu 9.10 上測試通過...

埠對映讓外部使用者同時訪問內部多個應用


如下圖所示,這是企業部署NAT伺服器的典型案例。如果現在企業內部有兩臺伺服器,分別為WEB伺服器(192.168.0.3)與ERP伺服器(192.168.0.2)。現在企業想讓出差在外的員工,也可以通過網際網路訪問企業內部的這兩個應用,該如何設計呢?

Chapter 8 Secure Network (ssh埠對映) - linux-ul - unix-EA

     一、基於埠訪問的一般原理。

  在講解NAT伺服器的具體埠對映配置之前,筆者覺得讀者有必要先了解一下基於埠訪問的一般原理。這有利於讀者瞭解下面的具體配置。下面筆者以員工訪問WEB伺服器為例,談談基於埠訪問的基本步驟。假設現在某個使用者需要訪問WEB伺服器,則客戶端的瀏覽器(假設採用的埠為3000)與WEB伺服器(假設採用的埠為80)是如何來進行通訊的呢?

  第一步:發起連線請求。當用戶需要檢視公司網頁時,使用者所用的主機會像WEB伺服器傳送請求。在這個發起請求的過程中,會有一些引數傳遞。如在傳送請求的過程中,使用者所用的主機需要知道WEB伺服器的IP地址、所採用的協議(HTTP)等。另外就是兩個埠資訊。一是使用者瀏覽器所用的埠,即為3000。二是WEB伺服器網站所用的埠(如果採用的是HTTP服務,則預設為80埠)。

  第二步:WEB伺服器轉發請求。當伺服器接受到這個請求後,會分析資料包。他經過分析包發現,這個請求是要求埠為80的應用軟體來負責的。伺服器確定了負責人之後,就會把這個請求轉發給具體的負責人,即WEB應用伺服器來處理。

  第三步:伺服器會把從WEB應用服務那邊反饋回來的網頁傳送給使用者所用的計算機。在傳送的時候,其也會制定要把這個網頁給你的那個3000埠(瀏覽器)對應的應用軟體。

  第四步:使用者的計算機收到資料包之後,也會對這個資料包進行分析,來判斷需要把這個資料包轉發給哪個埠(應用服務)。分析後發現是轉交給3000埠的,就會把這個資料包轉發給瀏覽器。

二、基於埠對映的NAT伺服器配置。

  其實基於埠對映的NAT伺服器其工作原理就跟上面這個基於埠訪問的工作過程類似。只是這裡的NAT伺服器就相當於使用者主機,而使用者相當於內部的伺服器。由於使用者需要通過外網訪問企業內部應用的話,通常情況下要求內網伺服器也要求有合法的外網IP。只有私網IP地址的伺服器是無法直接跟外部客戶進行通訊的。為此,如果沒有埠對映的話,使用者如果要同時訪問內部的WEB伺服器與ERP伺服器,則就需要有兩個公網IP地址。但是,大家都知道現在公網IP地址嚴重缺乏。在沒有足夠多的IP地址的情況下,該如何實現這種需求呢?那就知道通過埠對映來完成。

  如上圖所示,使用者需要訪問企業內部的WEB服務與ERP伺服器,他只需要知道NAT服務地址與WEB伺服器與ERP伺服器所採用的埠即可。如果

WEB伺服器採用的埠為80,

ERP伺服器所採用的埠為5050。

而NAT伺服器的IP地址假設為202.96.92.100的話,

那麼當用戶訪問WEB伺服器時,只需要輸入http:// 202.96.92.100即可。由於HTTP協議預設採用的是80埠,故這裡不用配置埠號。如果WEB伺服器中把這個埠改為了3000,則在訪問的時候就需要使用http:// 202.96.92.100:3000(地址+埠號)的形式了。使用者要訪問內部的ERP伺服器也是類似的,只要把NAT伺服器的地址以及ERP伺服器所採用的埠在客戶端上進行配置即可。

  可見通過NAT伺服器的埠對映功能,可以讓外部使用者同時訪問企業內部的WEB伺服器與ERP伺服器。

那要實現這個需求具體該如何配置呢?

  NAT伺服器讓內部的區域網使用者可以連線到網際網路,以便使用者能夠收發網際網路郵件、瀏覽網際網路上的網站等等。但是預設情況下外部使用者是不能夠訪問內部的伺服器。如果需要實現以上功能的話,就需要進行專門的配置。

  如上圖中,

內部區域網計算機(192.168.0.2)為WEB伺服器,其採用的埠為80。

如果現在外部使用者需要訪問這個WEB伺服器站點,則使用者只知道這個WEB伺服器的地址為202.96.92.100(NAT伺服器的地址)。

而WEB伺服器預設採用的埠為80。當外部使用者通過瀏覽器訪問企業內部的WEB伺服器時,

他會在瀏覽器中輸入http:// 202.96.92.100路經來連線網站。

NAT伺服器會將此請求傳送給內部的計算機WEB伺服器(192.168.0.2),並由WEB伺服器將這個請求轉發給埠為80的軟體來負責。WEB伺服器會將網頁傳送給NAT伺服器,再由NAT伺服器負責將網頁傳送給外部使用者的計算機。

如果使用者要訪問內部的ERP伺服器,其過程也是如此。

那麼現在的問題是,NAT伺服器怎麼判斷要把使用者HTTP請求傳送給伺服器(192.168.0.2)而不是傳送給(192.168.0.3)呢?

  這主要是根據埠來判斷的。也就是說在NAT伺服器中有一個埠對映的規則,只要使用者訪問的目的埠是80,就把這個請求轉發給WEB伺服器;若請求的埠是5050,則就把這個請求傳送給ERP伺服器。這就是埠對映的實質。瞭解這個內容之後,那麼瞭解下面的配置也就簡單多了。開啟路由和遠端訪問主控制視窗,選擇要配置的伺服器。然後選擇IP路由選擇、NAT/基本防火牆。並雙擊右方對外連線的網路介面(注意這裡不要選擇連線內網的網路介面),選擇服務和埠標籤。然後直接從服務列表中選取要對外開發的服務,如選擇WEB伺服器。在公用地址中選擇在此介面,表示由網際網路服務提供商指派的NAT伺服器的公網IP地址。然後再設定,如果把這個服務請求轉發給內部的IP地址為192.168.0.2的WEB伺服器。通過這個簡單的配置,就實現基於埠的對映。

三、改善NAT伺服器的效能與便利性。

  可見這個埠對映配置是很簡單的。但是其難點在於如何提高這個NAT伺服器的效能,如何讓使用者使用的更加方便。這是網路管理員所需要考慮的。對此筆者有如下幾個建議可供大家參考。

  1、利用域名來代替IP地址。當用戶訪問企業內部的網站伺服器時,如果讓他們輸入伺服器的IP地址,對普通使用者來說可能有點難度。要記住這202.96.92.100十一個沒有絲毫關係的數字有很大的難度。如果能夠把這個IP地址轉換為有實際意義的網址那就最好了。在企業內部,可以自己部屬一個DNS伺服器,把IP地址轉換為網址。那麼內部員工可以直接通過網址來訪問WEB伺服器。但是在網際網路上,企業可不能自己隨便定義域名。為了提高使用者訪問的便捷性,企業網路管理員最好能夠像當地的域名註冊機構,申請一個合適的域名並關聯到自己的NAT伺服器公網IP地址。那麼以後外部使用者訪問內部WEB伺服器時,只需要輸入像新浪那樣的地址就可以了。而不用輸入這些難以記憶的地址。

  2、如果企業可以申請到多個IP地址的話,那麼最好能夠分開來部署。即企業可以申請兩個ADSL帳號。其中一個專門用來連線內部的伺服器;而另外一個用來內部員工跟網際網路的通訊。這麼做主要是為了減輕NAT伺服器的壓力,提高其效能。如企業只有一個ADSL帳號的話,那麼無論是外部使用者訪問企業內部伺服器;還是企業內部員工訪問網際網路,其資料流都要通過這臺NAT伺服器來處理。為此,如果企業資料流量比較大或者NAT伺服器配置不怎麼理想的話,那麼很可能這個NAT伺服器就成為了企業網路訪問的瓶頸資源。如果把他們分開,則可以減輕NAT伺服器的壓力,提高外部使用者訪問企業內部伺服器的效率。

  3、配置合適的ICMP資料包策略,以加強阻擋黑客利用ICMP的攻擊行為。使用ICMP攻擊的原理實際上就是通過Ping大量的資料包使得NAT伺服器的CPU使用率居高不下而崩潰。一般情況下黑客通常在一個時段內連續向計算機發出大量請求而導致CPU佔用率太高而宕機。而且會使用多臺肉雞同時向NAT伺服器傳送資料包。基於ICMP的攻擊可以分為兩大類,一是ICMP攻擊導致拒絕服務;另外一個是基於重定向的路由欺騙技術。無論是哪一類攻擊,都會給NAT伺服器產生致命的影響。為此為了NAT伺服器的安全,最好配置合適的ICMP包策略。如可以拒絕響應別人的ICMP請求。如此攻擊者就無法對NAT伺服器發起ICMP攻擊了。

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

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

SSH/plink命令的基本資料:

首先,認識下這三個非常強大的命令:

ssh -C -f -N -g -L listen_port:DST_Host:DST_port [email protected]_Host 
ssh -C -f -N -g -R listen_port:DST_Host:DST_port [email protected]_Host 
ssh -C -f -N -g -D listen_port [email protected]_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地址。並且根據下面這張圖列出我們的計劃:

Chapter 8 Secure Network (ssh埠對映) - linux-ul - unix-EA
  1. 需要訪問234.234.234.234的FTP服務,也就是埠21
  2. 中間伺服器是123.123.123.123

現在我們使用下面這條命令來達成我們的目的(192.168.0.100上執行)

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代理的時候要特別注意。

@@@@@@@@@@@@@@@@@@@@@@@@@@@

1 > 反向隧道技術

情景:節假日需要回公司加班。但是公司是內網,使用NAT,所以沒辦法連回去。

現在公司機器(LAN_ip)上執行

ssh -NfR 2222:localhost:22 home_ip

-R : 建立反向連線 將 home_ip port轉發

現在,到home_ip上面
ssh localhost -p 2222
就跑在NAT後面的公司機器。就是後門了。灰鴿子木馬用的也是反向連結。

Destination (LAN_ip) <- |NAT| <- Source (home_ip)

2>埠轉發

情景:本機不允許訪問www.xxx.com這個網站,但是遠端主機(remote_ip)可以。

ssh -f -N -L 31609:www.xxx.com:80 [email protected]remote_ip

現在我們就可以在本地開啟 http://localhost:31609 訪問www.xxx.com了。

3> SOCKS代理

情景: 本機不允許訪問某些網站,但是遠端主機(remote_ip)可以,並且公司沒有組織你連線remote_ip。

ssh -NfD 8888 [email protected]remote_ip

現在在瀏覽器socks 5 proxy設定為localhost:8888,所有之前無法訪問的網站現在都可以訪問了。

@@@@@@@@@@@@@@@@@@@

古人以“夜不閉戶”、“路不拾遺”來形容大治之世。他們認為大治時,人們的道德水平已經很高了。而早期Internet的形成似乎也是符合這種思想的。Internet的初衷是相互信任和相互分享,它的這種“信任”建立在“大治”甚至“天下大同”的假想上。隨著網際網路的商業化和平民化,Internet的安全性就顯得越來越脆弱了,不僅網路攻擊、網路詐騙盛行,也有一些網路管理者肆意檢測、更改、阻斷使用者通訊的行為SSH的一些特性在很多場合可以解決這些問題。

ssh的基本用法在命令列也強大之ssh一文中做了最基本的介紹。ssh是安全的遠端登入工具,在與遠端主機進行互動時,ssh協議把原始資料進行了加密並壓縮,從而保證了資料在網路傳輸過程的安全。利用這一原理,我們也可以用ssh把其它的明文傳輸的TCP資料流通過ssh的連線傳輸,這就是本文要講到的ssh轉發/隧道技術。下圖表示一個ssh連線(圖片來自http://www.ssh.com)

ssh連線

ssh的轉發有四類:遠端轉發、本地轉發、動態轉發和X轉發。把TCP流重定向到ssh連線叫做“轉發”,這個ssh連線叫做“隧道”。

假設場景:受限網路內主機A,受限網路防火牆F,受限網路外主機B,受限網路外主機C、D、E。使用者為主機A的管理者且擁有主機B的ssh賬號,B、C、D、E可以正常連線。因為防火牆F的策略,A與C、D、E完全不能連線,A與B受限連線(當A與B的連線內有關鍵字“SB”則阻斷連線,且只能由A與B連線,不能由B主動連線,可類比為NAT)。
下圖為場景圖(用Dia v0.96.1繪製)

場景

一、遠端轉發

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

?[Copy to clipboard]View Code BASH
ssh -R ::

假設主機A提供了HTTP服務,即在受限網路內部可以訪問的網頁伺服器。但這個服務因為防火牆策略或者NAT路由的原因導致在Internet無法訪問。那麼我們就可以將本地的HTTP服務遠端轉發到Internet上的主機B

?[Copy to clipboard]View Code BASH
ssh -fNgR 80:localhost:80 root@host-B

然後在Internet上可以通過訪問 http://host-B來訪問主機A上的HTTP服務了

如果沒有主機B的root賬號,則只能遠端轉發到1024以後的埠號

?[Copy to clipboard]View Code BASH
ssh -fNgR 8080:localhost:80 lige@host-B

然後在Internet上可以通過訪問http://host-B:8080來訪問主機A上的HTTP服務。
值得注意的是搭建了wordpress的主機只能執行在80埠,如果轉發後的埠不是80,那麼將無法使用,這應該算是wp的bug吧

而且因為主機A到主機B之間是通過隧道連線的,即使網頁中含有關鍵字“SB”,也無法被大防火牆檢測到(淚流滿面,終於講到關鍵了)

附加引數簡要說明:

?[Copy to clipboard]View Code BASH
-N      不執行遠端命令. 用於轉發埠.  -n      把 stdin 重定向到 /dev/null (實際上防止從 stdin 讀取資料).  ssh在後臺執行時一定會用到這個選項. 它的常用技巧是遠端執行 X11 程式.  -f      要求 ssh 在執行命令前退至後臺. 它用於當 ssh 準備詢問口令或密語,但是使用者希望它在後臺進行. 該選項隱含了 -n 選項. 在遠端機器上啟動X11 程式的推薦手法就是類似於 ssh -f host xterm 的命令.  -C      要求進行資料壓縮  -g      允許遠端主機連線本地轉發的埠

關於建立隧道和使用隧道的網路原理,見文章末尾

二、本地轉發

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

它的命令格式為

?[Copy to clipboard]View Code BASH
ssh -L ::

和遠端轉發原理類似但方向相反。假設主機B有HTTP服務,但因為受限網路內其它主機因憎惡“大防火牆”F而不願意直接訪問主機B(這種心理我也有)。那就可以通過本地轉發了

?[Copy to clipboard]View Code BASH
ssh -fNgL 80:localhost:80 root@host-B

因為和遠端轉發類似,後面就不再詳述。

三、動態轉發

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

可以這樣理解,遠端轉發和本地轉發都是在隧道上傳輸一個服務,比如例子中的HTTP資料流。而動態轉發則是為了在隧道上傳輸多種不確定的網路服務。它的表現就把遠端ssh伺服器當作了一個安全的代理伺服器。

命令格式為

?[Copy to clipboard]View Code BASH
$ ssh -D

假設主機A想要訪問受限網路所限制訪問的主機C、D、E等,或者想要訪問主機B上的“SB”內容。則可有D選項建立動態隧道

?[Copy to clipboard]View Code BASH
ssh -CfNg -D 8888 lige@host-B

然後你就有了一個安全的socks 5代理。這個代理ip是127.0.0.1,埠為剛才指定的8888。如何使用socks 5代理在本文就不再講了。大防火牆可能還存在一些技術來防止socks 5代理,可以參考socks代理的遠端DNS解析一文

還有一個plink工具,包含在PuTTY軟體包,可以在windows和linux下使用,它的格式為:

?[Copy to clipboard]View Code CMD
PLINK.EXE -C -D 127.0.0.1:7777 -N -pw SSH密碼 SSH使用者名稱@SSH的IP地址

四、X轉發

X轉發是一個令人驚奇但實際上用處不大的功能。因為我所能管理的遠端主機都是無圖形介面的,所以本部分內容我不保證正確。

大家都知道GUI軟體與X之間也是通過TCP連線的,所以X轉發與其它轉發也沒有本質區別,甚至它簡單得都不應該和其它幾種轉發相提並論。X轉發用的選項為”-X”

首先要在客戶端指定X Server的位置

?[Copy to clipboard]View Code BASH
export DISPLAY=:.

然後執行

?[Copy to clipboard]View Code BASH
 ssh -X lige@hot-B

補充:可能的問題:

2. windows下的ssh客戶端
PuTTY和其中的plink

3. 如何檢視隧道是否建立完善
檢視程序:

?[Copy to clipboard]View Code BASH
ps aux | grep ssh

檢視埠:

?[Copy to clipboard]View Code BASH
netstat -ntl

4. 因為F,連線還是不穩定,隧道經常無法使用
去除-N,-n,-f選項,進入遠端shell,輸入一些需要頻繁互動資料的命令,使連線一直處於活動狀態。比如

?[Copy to clipboard]View Code BASH
top

我更推薦用這樣的命令,對系統的負載消耗更小(而且更加美觀)

?[Copy to clipboard]View Code BASH
watch -n1 "date"

附ssh隧道原理

對網路原理不太懂或不感興趣的可以忽略此部分

總的來說:Tunnel實際上是一個TCP連線,這個連線和普通的SSH登入的連線並沒有本質上的區別

假設有兩臺主機A和B,IP分別是IP_A和IP_B,是要把主機A的22埠對映到主機B的10022埠

連線的建立過程是這樣的:

1. 建立TUNNEL (在A主機上執行命令)
ssh命令,把A的埠對映到B主機(ssh -NfR 10022:localhost:22 [email protected]_B)
這個步驟實際上是這樣的:
(1)ssh命令是ssh客戶端,這條命令是指在A主機上登入B主機,並且A主機請求將A主機的22號埠對映到B主機的10022埠。
(2)B主機接受遠端登入請求後,檢測發現使用者的許可權足以建立10022埠,且10022埠並未使用。則B主機開啟一個監聽埠:10022
(3)這條命令成功結束後,A主機有了一個後臺程序登入到B主機,這個登入的連線正是“TUNNEL”。
而B主機相應也有這麼一個後臺程序,此外B主機還增開了一個監聽埠:10022
(4)在這個過程中,B是Server,A是Client。那麼A是以一個任意埠連線到B的ssh監聽埠。所設這個連線是
IP_A:12345 —— IP_B:22

2. 連線對映埠 (在B主機上執行命令)
連線對映埠 ( ssh [email protected] -p 10022)
這個步驟實際上是這樣的:
(1)主機B連線自己的一個監聽埠10022
於是主機B以一個任意的埠連線10022: IP_B:23456 ——- IP_B:10022
(2)10022埠實際是由主機B的sshd來維護的,sshd發現有連線到10022的埠的資料。
將資料封裝成ssh包,通過已經建立好的TUNNEL傳輸到對端主機A的12345埠(TUNNEL建立時的初始埠)
(3)主機A的12345埠收到資料後,經過TUNNEL的建立程序的處理(解開ssh包),把資料轉到主機A的埠22(建立TUNNEL時指定的埠)
(4)因此,這個反向的連線就建立起來了

3. TUNNEL與TCP連線的關係
(1)TUNNEL本質是一個TCP連線
(2)TUNNEL的作用用於傳輸其它TCP連線的資料
(3)對使用者而言,TUNNEL就是它們可見的TCP連線傳輸的一個“隧道”

Chapter 8 Secure Network (ssh埠對映) - linux-ul - unix-EA

題目有點長
其實來自於一個朋友的問題
他的oracle跑在linux伺服器上
遠端的linux伺服器並沒有跑在圖形介面下(runlevel=5)
而是跑在字元模式下(runlevel=3)
而他又想用圖形介面來管理oracle
我翻了翻資料
找出一種方法
在一臺圖形介面的linux下(虛擬機器也行,其實不是linux也行,關鍵是本地得有X server)起一個控制檯
用命令列ssh加引數”-X”連上遠端的linux伺服器
像這樣
ssh -X [email protected]
這裡”1.1.1.1″是遠端linux伺服器的ip地址
這樣連上去之後
直接就可以用以前只有在圖形介面上才能用的命令
如oracle管理的圖形程式”dbca”

這個原理很簡單
因為遠端的sshd支援x11 forward
那麼他起x程式的時候
就會把x的包通過ssh轉回來到ssh客戶端的機器上來
而ssh客戶端這邊跑得有x server
所以就能正確接收x包並顯示出來

其實在windows下也可以通過安裝x server軟體來實現一樣的效果
比如x manager就可以
具體用法不在詳述

這裡的關鍵在於
遠端的sshd需要支援x11 forward
不過不要擔心
一般情況下
預設是支援的

SSH埠轉發(本地埠轉發、遠端埠轉發、動態埠轉發)工作原理、應用詳解

實驗條件:
1.本文所述之實驗,本地主機作業系統基於Ubuntu 10.04,遠端主機作業系統基於BSD發行版
2.本地主機安裝了ssh client(ssh),也安裝了ssh server(sshd)
基礎知識:
文章中客戶端指ssh,用於發出連線請求;服務端指sshd,監聽埠22。
安全通道是指ssh與sshd之間已建立的連線通道,該連線是加密的。

SSH 埠轉發格式[1]

[-L [bind_address:]port:host:hostport]
[-R [bind_address:]port:host:hostport]
[-D [bind_address:]port]


動態埠轉發
-D <port>
這會使本地主機監聽埠port,一旦與該埠建立連線,經過該埠的資料會被轉發到安全通道傳送到遠端主機。遠端主機的sshd會根據資料包的應用層協議(如HTTP)自動建立對應的連線。

$ ssh -D 7070 [email protected]

登陸前本地主機埠監聽狀態:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  

登陸後本地主機埠監聽狀態:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp        0      0 127.0.0.1:7070          0.0.0.0:*               LISTEN      5205/ssh  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  tcp6       0      0 ::1:7070                :::*                    LISTEN      5205/ssh  

登陸後遠端主機埠監聽狀態:

$ sockstat -4l  USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS  (什麼都沒有)  

小結:我們發現,動態埠轉發的時候確實是本地主機的ssh在監聽埠7070的


本地埠轉發
-L <local_port>:<host>:<host_port> <ssh_server>
這會使本地主機監聽埠local_port,一旦與該埠建立連線,經過該埠的資料會被轉發到安全通道,同時遠端主機會與主機host的埠host_port建立連線。

$ ssh -L 7001:localhost:7070 [email protected]

登陸前本地主機埠監聽狀態:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  

登陸後本地主機埠監聽狀態:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp        0      0 127.0.0.1:7001          0.0.0.0:*               LISTEN      3475/ssh  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  tcp6       0      0 ::1:7001                :::*                    LISTEN      3475/ssh  

登陸後遠端主機埠監聽狀態:

$ sockstat -4l  USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS  (什麼都沒有)  

小結:我們從中可以看出,本地埠轉發的時候確實是本地主機的ssh在監聽埠7001


遠端埠轉發
-R <remote_port>:<host>:<host_port> <ssh_server>
這會使ssh_server(遠端端)監聽埠remote_port,一旦與該埠建立連線,經過該埠的資料會被轉發到安全通道,並且本地主機會與主機host的埠host_port建立連線。

$ ssh -R 7001:localhost:7070 [email protected]

登陸前本地主機埠監聽狀態:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  

登陸後本地主機埠監聽狀態:

$ sudo netstat -lnput | grep ssh  tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      927/sshd  tcp6       0      0 :::22                   :::*                    LISTEN      927/sshd  

登陸後遠端主機埠監聽狀態:

$ sockstat -4l  USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS  sisca    sshd       66196 7  tcp4   127.0.0.1:7001        *:*  

小結:很明顯,使用遠端埠轉發時,本地主機的埠監聽並沒有發生變化,相反遠端主機卻開始監聽我們指定的7001埠

小提示:
這裡的remote_port,local_port可以歸併為listen_port,因此我們得到這樣的助記格式:

ssh [-L|-R] <listen_port>:<host>:<host_port>



本地埠轉發應用:[2]
背景:在實驗室裡有一臺 LDAP 伺服器(LDAP Server),但是限制了只有本機上部署的應用才能直接連線此 LDAP 伺服器。現在我們想臨時從本地機器(LDAP Client)直接連線到這個 LDAP 伺服器,只需要在LDAP Client上運用本地埠轉發:

$ ssh -L 7001:localhost:389 LdapServerHost

圖1 本地埠轉發

資料流向:
該命令首先使本地主機(LDAP Client)與遠端主機(LDAP Server)建立一個SSH安全連線(安全通道)
然後本地主機會監聽埠7001(注意是ssh在監聽)
一旦本地LDAP客戶端程式將資料傳送到埠7001(即建立連線),遠端主機上的sshd將主動與埠389(LDAP服務的埠)建立連線
從而來自LDAP客戶端的請求轉發到該埠389上(當然是通過安全通道)
注意:
本地主機有兩個客戶端:
1) ssh – 用於與遠端主機建立ssh連線
2) LDAP客戶端 – 用於與遠端主機的LDAP服務程式進行通訊
遠端主機對應地有兩個服務程序:
1) sshd – 監聽埠22
2) ldapd -監聽埠389


遠端埠轉發應用:[2]
背景:這次假設由於網路或防火牆的原因我們不能用 SSH 直接從 LDAP Client 連線到 LDAP 伺服器(LDAP Server),但是反向連線卻是被允許的。那此時我們的選擇自然就是遠端埠轉發了。我們這次在LDAP Server上運用遠端埠轉發,因此LDAP Client必須安裝了sshd

$ ssh -R 7001:localhost:389 LdapClientHost

圖2 遠端埠轉發

資料流向:
該命令首先使LDAP Server與 LDAP Client 建立一個SSH安全連線(安全通道)
然後LDAP Client開始監聽埠7001(注意是sshd在監聽)
一旦LDAP Client將資料傳送到埠7001(即建立連線),LDAP Server上的ssh將主動與埠389(LDAP服務埠)建立連線
從而來自LDAP客戶端的請求轉發到該埠389上(當然是通過安全通道)


本地轉發與遠端轉發的對比與分析
本地埠轉發:ssh客戶端發起ssh連線,並且監聽指定埠
遠端埠轉發:ssh客戶端發起ssh連線,但是由遠端主機上的sshd監聽指定埠


多主機轉發應用[2]

圖3 多主機埠轉發

$ ssh -g -L 7001:<B>:389 <D>

注意:我們在命令中指定了“ -g ”引數以保證機器(A)能夠使用機器(C)建立的本地埠轉發。

References:
[1] man 1 ssh
[2] IBM DeveloperWorks – 
實戰 SSH 埠轉發

Please support us if you feel this post is useful.

SSH 名為 secure shell, 是專門用來進行安全遠端訪問的協議。它無論從功能上、系統相容性上、還是從安全上和Telnet