首先先貼些一些關於ssh在端口轉發方面的三個比較重要的命令的基本資料:
首先,認識下這三個很是強大的命令:php
1 ssh -C -f -N -g -L listen_port:DST_Host:DST_port user@Tunnel_Host 2 ssh -C -f -N -g -R listen_port:DST_Host:DST_port user@Tunnel_Host 3 ssh -C -f -N -g -D listen_port user@Tunnel_Host
相關參數的解釋:
-f Fork into background after authentication.
後臺認證用戶/密碼,一般和-N連用,不用登陸到遠程主機。html
-L port:host:hostport
將本地機(客戶機)的某個端口轉發到遠端指定機器的指定端口. 工做原理是這樣的, 本地機器上分配了一個 socket 偵聽 port 端口, 一旦這個端口上有了鏈接, 該鏈接就通過安全通道轉發出去, 同時遠程主機和 host 的 hostport 端口創建鏈接. 能夠在配置文件中指定端口的轉發. 只有 root 才能轉發特權端口. IPv6 地址用另外一種格式說明: port/host/hostportlinux
-R port:host:hostport
將遠程主機(服務器)的某個端口轉發到本地端指定機器的指定端口. 工做原理是這樣的, 遠程主機上分配了一個 socket 偵聽 port 端口, 一旦這個端口上有了鏈接, 該鏈接就通過安全通道轉向出去, 同時本地主機和 host 的 hostport 端口創建鏈接. 能夠在配置文件中指定端口的轉發. 只有用 root 登陸遠程主機才能轉發特權端口. IPv6 地址用另外一種格式說明: port/host/hostport
-D port
指定一個本地機器 「動態的’’ 應用程序端口轉發. 工做原理是這樣的, 本地機器上分配了一個 socket 偵聽 port 端口, 一旦這個端口上有了鏈接, 該鏈接就通過安全通道轉發出去, 根據應用程序的協議能夠判斷出遠程主機將和哪裏鏈接. 目前支持 SOCKS4 協議, 將充當 SOCKS4 服務器. 只有 root 才能轉發特權端口. 能夠在配置文件中指定動態端口的轉發.shell
-C Enable compression.
壓縮數據傳輸。windows
-N Do not execute a shell or command.
不執行腳本或命令,一般與-f連用。安全
-g Allow remote hosts to connect to forwarded ports.
在-L/-R/-D參數中,容許遠程主機鏈接到創建的轉發的端口,若是不加這個參數,只容許本地主機創建鏈接。注:這個參數我在實踐中彷佛始終不起做用。服務器
實例說明:
一臺服務器提供ftp服務(其實任何服務均可以),由於ftp傳輸是明文密碼,若是不作ssh端口以前,咱們能夠經過tcpdump命令很容易的捕捉到明文信息。因此咱們要對21端口進行轉發:ssh
(注:我這裏要使用的功能是鑑於這個理由,好比有三臺電腦主機,A、B和C,它們有這樣的訪問規則:A<------>B<------>C-----x-----A。因此若是想從C登陸到A,必須先登陸到B在登陸到A上,若是上傳下載文件的話,也是很是麻煩,這使咱們想到用ssh轉發,使A的22端口轉發到B的8822,而後再把B的8822端口轉發到B自己的9944端口,端口號只要不被佔用大於1024便可。這樣,咱們直接鏈接B的9944端口實際上就至關於鏈接A的22端口,就像是能夠直接互聯同樣。這是咱們要進行端口轉發的出發點)socket
(注:不用root也能夠,只是一般狀況下,非root用戶限定端口不能使用1024如下的,可是以上的能夠,因此,對於上面我所要求的狀況。首先咱們用傳統的方式登陸到A服務器上,而後可使用以下命令:
ssh -CNfg -R 8822:localhost:22 usernameinB@ipB
而後會讓你輸入密碼,輸入完以後就消失到後臺了
PS:這裏的localhost其實指的A服務器自己
)
而後登陸到100.0.0.50機器,咱們能夠經過netstat -an|grep :2121查看端口已經偵聽tcp
(這裏咱們登陸到ipB的機器,而後就能夠直接使用下面的命令:
ssh -l usernameinA localhost -p 8822
而後就能夠登陸到A服務器上了。
PS:這裏的localhost其實指的是B機器,原理就是在B上連本身的8822,其實就是連A上的22端口,這都是因爲上面第一步的轉發造成的。注意與第一步的比較)
就能夠登陸到ftp-server了,並且tcpdump沒法捕獲到有效的信息。
2121端口任意選擇,只要是機器上沒有佔用的端口就行
來一個稍微複雜一點的,作網關的例子:
(注:它這裏所說的複製的離子,其實就是咱們要達到的目的,從C直接聯到A,固然是經過B。)
假如內網有一臺提供ftp(linux,port is 2121,稱爲A機器)的機器,經過網關服務器(linux,port is 8888,稱爲B機器)進去,如今外網有一臺C機器須要訪問網關服務器的某個端口(port is 21)來訪問內網的ftp服務器。你們能夠看到,其實這就像是一個基於ssh的防火牆程序,好,下面咱們來具體操做:
一、login A 機器
(注:同上,執行命令
ssh -CNfg -R 8822:localhost:22 usernameinB@B機器IP
)
這樣咱們就在B機器上開了一個8888->2121的端口轉換,可是因爲8888端口只能偵聽在localhost主機上,所以,雖然咱們已經能夠在B機器上使用
(注:上面其實咱們也解釋了:這樣咱們就在B機器上開了一個B機器上的8822端口->A機器的22端口轉換,可是因爲8822端口只能偵聽在localhost主機上,所以,雖然咱們已經能夠在B機器上使用
ssh -l usernameinA localhost -p 8822 來訪問A機器,但仍然沒法提供給外網的機器訪問,下面正要解決直接C--->BPS:第一步其實就是上面實例時的那種狀況)
來訪問真正的ftp服務器,但仍然沒法提供給外網的機器訪問
二、login B機器
(注:登上B)
(注:執行命令:
ssh -CNfg -L 9944:localhost:8822 usernameinB@localhost
在這裏插播一個狀況就是可能在登陸的過程當中會出現一個這樣的問題:
ssh_exchange_identification: Connection closed by remote host
出現這種錯誤的緣由是/etc/hosts.allow和/etc/hosts.deny阻止了你的登陸,你要檢查下。沒有出現這個問題固然是最好。作完以後就在B機器上完成了9944--->8822的端口轉換,能夠偵聽在任何地址上的請求。)這樣作,是作本地機器上的21->8888端口轉換,能夠偵聽在任何地址上的請求。
2(1)
若是C機器也是一臺linux機器,那也能夠這樣設置:
(注:在咱們這裏就是執行 ssh -CNfg -R 9944:localhost:8822 usernameinC@C機器IP)
3。使用C機器,
能夠是linux下的ftp命令,也能夠是windows下的客戶端軟件均可以訪問B機器的21端口來鏈接後臺真正的ftp服務器(真正的端口是2121)
(注:對於咱們的狀況,訪問的就是B機器的9944端口,使用C機器上的賬戶)
若是是按照2(1)中的設置,則訪問的地址爲本機IP。
(注:對於2(1)的狀況,可使用
ssh -l usernameinC localhost -p 9944
這裏使用的localhost,實際上對應的C機器)
至此,一般狀況下用端口轉發就能夠實現。
再補充一點,其實對於2(1)的狀況,有些軟件也能夠實現,好比putty,這方面的設置能夠參考:我這裏就不贅述了(http://www.lupaworld.com/batch.download.php?aid=1199)
簡單介紹一個在linux下使用的設置ssh端口轉換的程序
http://gstm.sourceforge.net/?page_id=5
[p_w_upload=1197]
在windows機器下使用putty也能夠創建端口轉發
假設從windows機器上將本地的8888端口轉發到B的21端口,能夠作以下設置
Connection->SSH-Tunnels中能夠設置putty的端口轉發,Source port爲listen_port,填8888,Destionation爲DST_Host:DST_port,填寫B機器IP:21,設置完了點Add.
注意是local仍是remote?
[p_w_upload=1198]
設置好後,咱們能夠在dos下用netstat命令看一下是否開啓了本地的轉發端口
[p_w_upload=1199]
接下來咱們訪問localhost的8888端口來訪問ftp服務器了