1. 程式人生 > >SSH 埠轉發 - 你不讓我看,我也能看

SSH 埠轉發 - 你不讓我看,我也能看

在之前 [GRE](https://www.cnblogs.com/michael9/p/13403435.html) 的文章中,我們知道隧道技術可以解決異種網路的通訊問題。在今天這篇文章中,將認識隧道技術的另一應用 - SSH 埠轉發。 首先我們對 SSH 並不陌生,是應該非常普遍的加密協議,用於在不安全的網路中提供安全的傳輸環境,常見的用途是用於遠端登入。而今天要介紹的埠轉發,原理類似。 埠轉發解決的問題: 1. 增加安全性,加密 Client 到 Server 端的通訊資料 2. 突破防火牆限制,完成一些被禁止的 TCP 連線 ## 埠轉發的型別 在此之前,我們先了解一下埠轉發的概念,埠轉發是 SSH 的一種應用,可以理解成在本地 SSH Client 和遠端 SSH Server 建立了一條安全的隧道,而這條隧道傳輸的內容可以是執行的其他 TCP 埠的流量。在隧道傳輸這些流量時,會進行加密,常見的 Telnet, SMTP, LDAP, HTTP 等等使用 TCP 作為傳輸層的協議都可以進行埠轉發。 通常來說,埠轉發分為三種類型,本地埠轉發,遠端埠轉發,動態不定埠轉發。會依次從應用場景和如何實現來介紹。 ## 本地埠轉發 在給客戶部署應用時,通過來說訪問的都是客戶的內網環境,一般需要我們掛上客戶的 VPN 然後通過提供的跳板機來訪問目標伺服器。但這樣的配置,就給在一些 debug 場景帶來很大的不便。 來看這樣一個場景: ![](https://img2020.cnblogs.com/blog/1861307/202008/1861307-20200813140713654-971655585.png) 這裡 Client A 需要依賴於 Server B 上一個 TCP 應用才能進行開發,但是由於防火牆的設定,Client A 的流量會被 Deny 掉。但提供了一臺 Server A,而 Server A 到 Server B 卻是可達的。這時我們就可以利用埠轉發技術,通過 Server A 間接地實現和 Server B 的通訊。這時 Server A 也就是常說的 Jump Server. 可以將 Client A 和 Server A 之間看成一條隧道,而隧道傳輸的內容就是 Server A 訪問 Server B 的流量。 下面來配置一下: ```` ssh -L :: # local port 相當於 ssh client 埠 # remote host 是目標主機 Server B 的地址 # remote port 是目標主機 Server B 的埠 # ssh hostname 是跳板機,也就是 Server A 的地址 # 在 Client A 上 ssh -NfL 65001:10.124.207.152:8000 [email protected] -f 表示後臺執行 -N 表示不輸入命令 -L 表示本地埠轉發 ```` 需要注意的內容: * Server A 到 Server B 一定是可達的 * 另外在繫結埠時,要選擇沒有被使用的埠 * 選用 1024-65535 之間的埠,之前的埠是給管理員使用的。 如何關閉: ``` like-unix: ps 找到程序 kill 掉 windows: netstat -ano | findstr "65001" taskkill /f /t /im 19036 ``` ## 遠端埠轉發 遠端埠轉發和本地埠轉發很像,只不過調換了 ssh server 和 ssh client 的位置。 考慮下面的場景,還是 Client A 無法訪問 Server B,但是 Server A 可以訪問 Server B, 與之前不同的是,Client A 也不能訪問 Server A 了,但 Server A 可以訪問 Client. ![](https://img2020.cnblogs.com/blog/1861307/202008/1861307-20200813140902531-1173435653.png) 這時我們可以在 Server A 進行配置,把 Client A 作為 SSH Server 而自己作為 SSH Client 建立隧道。和之前本地一樣,在 Client A 上訪問配置的埠,就會把流量轉發給 SSH Client 也就是 SSH Server A,這時 Sever A 再將流量轉發至 Server B. ```   $ ssh -R ::      # Server B 進行配置   ssh -NfR 65001:10.124.207.152:8000 [email protected] ``` 這時我們就可以達到和本地埠轉發相同的效果,在 Client A 上訪問 Server B. **如果分不清本地還是遠端埠轉發,可以通過 SSH Client 和 SSH server 來在加上訪問應用的順序加以區分** 比如這裡 Client A 想要訪問 Server B 的 HTTP。 那麼 Client A 上的瀏覽器作為 HTTP 的客戶端,Server B 作為 HTTP 的服務端。也就是在 HTTP 應用視角,是從 Client A 給 Server B 傳送請求。這個無論是本地還是遠端,方向都一樣。 接著再看 SSH 的客戶端和服務端。 如果 SSH 的客戶端在 Client A,則說明是本地埠轉發。和 HTTP client 和 server 同向。由於建立的轉發埠在本地,所以叫本地轉發。 否則如果是 SSH 的客戶端在 Server A,則說明是遠端埠轉發。和 HTTP client 和 server 反向。由於建立的轉發埠在遠端,所以叫遠端埠轉發。 其實無論是同向和反向,都是建立了一條隧道,只不過發起者不一樣,實現的目的都是一樣的。 ## 本地和遠端埠轉發的共享 有時我們會希望共享 SSH Client 和 SSH Server 建立的隧道,提供給其他主機同時使用。這時我們可以通過 `-g` 引數來實現。 比如對本地埠轉發進行共享: ``` ssh -g -NfL 65001:10.124.207.152:8000 [email protected] ``` 原來僅對 localhost 和 127.0.0.1 生效,現在對當前主機的所有地址都會生效,也就是 0.0.0.0 的範圍。在其他主機上可以通過訪問 SSH Client IP:65001 來進行服務的訪問。 遠端埠轉發同理: ```  ssh -g -NfR 65001:10.124.207.152:8000 [email protected] ``` ## 動態埠轉發 動態埠轉發的原理和本地及遠端沒有任何的區別,唯一的不同是,對於本地和遠端來說我們需要固定訪問應用的埠號,比如 80,443 等等。 但假設應用的埠不固定或者需要很多的埠號怎麼辦?這時就需要動態埠轉發。 ```` ssh -D # local port - ssh client 開啟的代理轉發埠 # ssh server - ssh server 的ip及埠 ssh -g -Nf -D 65001 [email protected] ```` 可以用 curl 進行測試: ``` curl --socks5 127.0.0.1:6500 http://10.124.207.152:8000/api-token-auth/ ``` ## 總結 最後我們完成了本地,遠端,共享,動態的埠轉發配置。 從整體來看,其實實現的都是相同的功能。在 SSH Client 和 SSH Server 中建立隧道。只不過有時隧道連線的方向是不