SSH全名為Secure SHell。最早是為了取代telnet、rsh、rlogin(遠端OS純文字操作介面)引入連線加密機制,讓第三者無法馬上解析原來的連線數據內容,並阻止駭客利用該連線讓使用者電腦安全受到威脅。由於發展期間考量到要讓使用者也能透過SSH連線運用遠端電腦的其他服務,因此SSH從ver2之後就准許在SSH連線建立之後,讓OS純文字操作介面以外的各種通訊協定也透過這個SSH連線傳輸,而實現上述功能的方法就是forwarding。所謂的forwarding,就是把SSH的一端接收到的封包解開成資料流後,透過SSH連線轉送到另外一端,接著在另外一端以新的address跟port資訊重新包成封包,傳送到目的地。由於SSH連線機制在整個過程中只把TCP封包還原回資料流,透過SSH加密傳輸到遠端,再從資料流包成新的TCP封包而已,因此全部的動作都能在user mode執行,而且整個過程沒有牽涉到網路routing或是datalink的機制,所以也就不需要管理者權限(UNIX的root或是Windows的Administrator)才能啟動。不過forwarding機制當然也有其限制,比如只能支援TCP通訊協定,除了dynamic mode(模擬socks proxy)外得手動一個一個指定欲forward的port等問題,但是只要普通使用者的權限就能運用SSH tunneling,的確是非常便利的方案。
那麼要怎麼使用SSH tunneling呢?只要在啟動SSH遠端登入時多加三種參數"-L/-D/-R"就好了(什麼!這樣就好了!?)。這是因為SSH tunneling本來就是SSH連線的附加功能,在forwarding封包機能啟動的同時,我們還是可以使用SSH連線本身的遠端純文字介面對遠端電腦下指令。除此之外,若我方主機跟遠端主機分別備有X window server和X window client的話,還可以多加個"-X"參數,讓遠端主機GUI程式的X window畫面再現於我方主機上,事實上,遠端主機傳送X window指令給我方主機的功能,也是透過forwarding機制達成的,只不過SSH直接簡化成"-X"而已。
以下就分別說明三種SSH tunneling方法的參數設定。
靜態SSH tunneling:
ssh -L [bind_address:]port:host:hostport username@middlehostusername就是平常登入遠端主機位址middlehost用的使用者名稱,而前面加的參數-L,意思是:把程式傳送給我方主機接口port的封包解開成資料流,透過SSH連線轉送到遠端主機middlehost上,再由遠端主機傳送封包到目的地主機位址host中的接口hostport。要注意的是,當host欄位填入localhost或127.0.0.1時,表示把封包forward到對方的localhost(也就是middlehost自己)的接口hostport,而不是指我方主機。因為TCP通訊協定在建立連線後就會維持雙向傳輸,當連線建立後,由目的地host的接口hostport返回到遠端主機middlehost的封包,也會經過SSH連線回到我方主機,再從我方主機的接口port返回封包給原來的程式。若需要forward多個port,可以重複加上多個"-L"參數並附上不同的位址接口等資訊。舉例來說,啟動SSH client時加上參數"-L 49152:bbs.gamer.com.tw:23"後,接著開啟telnet程式(例如PCMAN、putty),輸入目標位址跟接口localhost:49152,就會看到程式連進
靜態forwarding雖然開啟了跳板,但是只用固定port互相連線的程式才能運用靜態forwarding,如果瀏覽器這種不會只使用固定port的程式想透過跳板連到被擋掉的網站時,該怎麼辦呢?這時就是動態SSH tunneling出場的時機了:
ssh -D [bind_address:]port username@middlehost使用以上參數啟動SSH連線後,SSH client會模擬出socks v5 proxy,並接收抵達我方主機接口port的所有連線,所有的TCP連線都能透過這個虛擬proxy做為跳板連到目的地,只要在瀏覽器的proxy設定項目內的socks proxy填入我方主機的位址以及接口port,就能用這個SSH連線當跳板連到目的地。要注意的是,domain name轉換成位址的動作,基本上瀏覽器還是會透過我方電腦設定的DNS伺服器,所以如果想要把DNS轉譯交給middlehost進行,那就得在瀏覽器中調整設定。至於Gecko體系的瀏覽器(Mozilla/Seamonkey/FireFox)除了在proxy選項中設定socks proxy的位址、接口、以及將通訊協定設為socks v5之外,還得在網址列輸入about:config,接著把network.proxy.socks_remote_dns這個選項的數值設定成true。而Google Chrome則要進入proxy設定,在socks伺服器位址中填入"socks5://socks5host",前面的"socks5://"字串代表Google Chrome會使用socks v5的機能運用socks proxy,並且把DNS轉譯動作轉交給proxy處理。如果在支援socks v5的瀏覽器中使用proxy auto-config檔(*.pac)的話,則確認"function FindProxyForURL(url,host)"的return字串是"SOCKS5 socks5host:port"便可。如此一來,就算我方主機所在網路的DNS伺服器不提供internet上主機的DNS轉譯,我們還是可以直接在網址列輸入目的地主機的domain name瀏覽網頁,而且也不用擔心我方DNS主機的DNS轉譯功能受到cracker惡搞或破壞。
如果使用的瀏覽器(例如Opera)或是網路程式(例如網路遊戲)不支援socks proxy怎麼辦?沒關係,UNIX家族的OS有種工具叫作tsocks,只要自己的電腦有安裝tsocks,執行瀏覽器還是其他網路程式時在指令列輸入:
tsocks program_name program_argument就能讓tsocks把名為program_name的程式的所有TCP網路連線動作修改成透過socks proxy連到目的地,當然tsocks的proxy使用規則要事先設定好。而在Windows,也有相同功能的SocksCap32等工具可以使用。不過以上工具的使用方式在這裡就不多做說明,詳情請自行參考官方使用說明或是看討論區的討論。
以上都只介紹由我方主機接受連線forward到遠端的做法,如果要讓遠端主機接受外來連線,forward回我方主機,以我方主機做為跳板時,要怎麼辦呢?只要使用以下參數就可以開啟反向SSH tunneling了:
ssh -R [bind_address:]port:host:hostport username@middlehost跟參數"-L"剛好完全相反,這個參數就是把抵達遠端主機middlehost接口port的封包,經由SSH連線forward到我方主機,再從我方主機轉送封包到目的地host的接口hostport。要注意的是,當host欄位填入localhost或127.0.0.1時,表示把封包反向forward到我方的localhost(也就是我方主機本身)的接口hostport,而和"-L"參數的意義不同。若需要反向forward多個port,可以重複加上多個"-R"參數並附上不同的位址接口等資訊。舉例來說,若要從遠端主機用SSH登入位在防火牆後方的自家電腦,只要事前在自家電腦先用SSH client登入該遠端主機,並加上參數"-R 49152:localhost:22",此後在遠端主機上執行"ssh username@localhost -p 49152",就能用username這個帳號登入自家電腦的SSH服務。同樣的,bind_address可用來規範抵達遠端主機下哪個位址的封包能forward到自家電腦。當bind_address不填東西,而且省略後面的冒號,或是bind_address填入localhost或127.0.0.1時,只有在middlehost上執行的的程式才能透過SSH連線forward資料流到我方電腦。而參數"-R *:49152:ps3:22"或是"-R :49152:ps3:22",就表示所有抵達遠端電腦的外來連線通通都forward到自家電腦,再以自家電腦當跳板,轉送到PS3的接口22,這樣就可以用自家電腦當跳板,遠端操控PS3上執行的linux了。
即使我們建立反向SSH tunnel,但是"-R"這個參數只能指定遠端主機特定接口的封包forward回我方主機,如果要讓遠端主機接受任意port的連線該怎麼辦呢,很簡單,就是我方主機先建立反向SSH tunneling,把抵達遠端主機middlehost接口49152的連線forward到我方主機上的SSH server服務(通常是port 22):
ssh -R *:49152:localhost:22 middlehost_username@middlehost出門在外的時候,用任何SSH client連到遠端主機middlehost的接口49152:
ssh -D *:65535 localhost_username@middlehost -p 49152就會在反向SSH tunneling連線上建立動態SSH tunneling了,此後只要運用遠端SSH client所在主機上的虛擬socks proxy(接口65535),就會令所有透過socks proxy代理的連線forward到我方主機,也就達到了動態反向SSH tunneling的目的。如果怕反向SSH tunneling斷線後就不再重新連線,可以使用autossh這個工具維持我方主機到遠端主機的反向SSH tunneling連線。只不過autossh不會替你輸入SSH登入密碼,所以必須設定使用key做為SSH連線的認證方式,或者是寫個expect script模擬終端機,每次自動重連時讓expect script自動輸入登入密碼,就可以確保反向SSH tunneling一斷線就會自動重新連線。
如果自己的電腦是微軟的windows系統,又要如何使用SSH tunneling呢?在windows上,putty這套SSH client就能做到SSH tunneling,我們可以執行plink時加上同樣的參數,或者是在putty的起始連線設定中的tunnel頁面設定,開啟SSH連線後就會同時啟動SSH tunneling。
付帶一提,如果家裡的IP分享器是個Linux系統的小型電腦,我們也可以在這台分享器啟動SSH server服務,並且開啟TCP forwarding機能,在防火牆設定中允許來自WAN端的連線登入IP分享器的SSH server,出門在外時,就能使用SSH tunneling連回自己家裡,遙控自己家裡的電腦或是使用家中區域網路的服務。而且上述的"-L/-D/-R"等tunneling方式,或是先在外面的主機建立反向SSH tunneling到家中,再從家中用SSH tunneling連回外面的主機,通通都能使用喔!這樣就不需要特地為了SSH tunneling打開一台電腦,既省電又方便。
沒有留言:
張貼留言