我偷偷挖了一條網路隧道,差點被公司啟用

程式設計三分鐘發表於2019-05-14

​今天用公司環境在測試網路隧道,在寫一半文章的時候突然老闆來找我了,我真的好苦啊!

老闆的聊天記錄

告警郵件

自己好苦命,希望明天不要被懟的太慘。

好了,讓我們開始今天的內容。 你是否常常遇到這些個麻煩,因為公司安全策略的問題,每次要通過跳板機而不能直接連開發環境,使用上面已經搭建好的資料庫服務。為了方便釋出,自己電腦上的服務別人,不能讓開發環境的機器直接連上測試。還有我們在星巴克喝著咖啡連著免費wifi的時候,會不會網路請求都被黑客抓包下來?

概述

SSH 會自動加密和解密所有 SSH 客戶端與服務端之間的網路資料。但是,SSH 還同時提供了一個非常有用的功能,這就是埠轉發。它能夠將其他 TCP 埠的網路資料通過 SSH 連結來轉發,並且自動提供了相應的加密及解密服務。這一過程有時也被叫做“隧道”(tunneling)。這是因為 SSH 為其他 TCP 連線提供了一個安全的通道,避免了使用者名稱,密碼以及隱私資訊的明文傳輸。例如,Telnet,SMTP,LDAP 這些 TCP 應用。

如果工作環境中的防火牆限制了一些網路埠的使用,但是允許 SSH 的連線,那麼也是能夠通過將 TCP 埠轉發來使用 SSH 進行通訊。總的來說 SSH 埠轉發能夠提供兩大功能:

  • 加密 SSH Client 端至 SSH Server 端之間的通訊資料。
  • 突破防火牆的限制完成一些之前無法建立的 TCP 連線。

隧道

本地轉發

當開發機的Mysql只能從跳板機連上,我怎麼才能跳過跳板機來訪問遠端Mysql呢?

訪問遠端伺服器的Mysql
如上圖,我們要明確的是現在有三個角色,客戶端(SSH Client)、跳板機(SSH Server)、和伺服器。

客戶端只能通過ssh連線到跳板機上,跳板機可以直接訪問伺服器的全部埠,伺服器中安裝了Mysql服務並監聽了3306埠。

這個時候,我們肯定是要用本地轉發來連線,命令規則如下

ssh -L [local host:]<local port>:<remote host>:<remote port> <SSH hostname>
複製程式碼

看起來非常的令人費解,不清楚的問題不過就是三個,what? where? how?

  • what : 使用本地轉發,監聽本地的某個埠,當應用訪問這個埠的時候,ssh會將請求擷取到,通過跳板機作為中間媒介,轉發到伺服器上。 伺服器處理完成後,資料再原路返回完成整個鏈路。ssh服務在這個過程中完成了加密,轉發,解密,通訊的操作。
  • where : 在客戶端(也稱本地、SSH Client)上做這個事情
  • how : 使用以下命令配置,就可以達到訪問本地9527埠轉發到伺服器的3306埠啦
ssh -L 9527:伺服器:3306 root@跳板機
複製程式碼

解釋為,當訪問本機的9527的埠時,被加密後轉發到跳板機的ssh服務,伺服器的3306埠

注意的點

  1. SSH 埠轉發是通過 SSH 連線建立起來的,我們必須保持這個 SSH 連線以使埠轉發保持生效。一旦關閉了此連線,相應的埠轉發也會隨之關閉。
  2. 我們只能在建立 SSH 連線的同時建立埠轉發,而不能給一個已經存在的 SSH 連線增加埠轉發。
  3. 好了,我們已經在本地 建立了埠轉發,那麼既然我們在監聽本地的9527埠,那麼其他機器也訪問本地的9523埠會不會自動轉發呢?比如能否新增加一臺客戶端2來直接連線客戶端的9527 埠?答案是不行的,在主流 SSH 實現中,本地埠轉發繫結的是 lookback 介面,這意味著只有 localhost 或者 127.0.0.1 才能使用本機的埠轉發 , 其他機器發起的連線只會得到“ connection refused. ”。好在 SSH 同時提供了 GatewayPorts 關鍵字,我們可以通過指定它與其他機器共享這個本地埠轉發。
ssh -g -L <local port>:<remote host>:<remote port> <SSH hostname>
複製程式碼
  1. 當然了,你可以隨意的指定remote host,假如你要訪問的服務就在跳板機上,因為防火牆又不能直接訪問到,那麼remote hostSSH hostname可以是同一臺

遠端轉發

我的開發機上部署了一個mysql服務,我想回家以後還是連上我處於內網開發機上的mysql服務,這個時候我們怎麼弄呢?

遠端轉發圖示
我們需要藉助一臺公網的伺服器講遠端的流量轉發過來,由於安全策略內網機器可以連通外網機器,但是外網不能訪問內網機器。我們只要轉發遠端的請求到正確的內網的服務上就可以了。它的命令格式是:

ssh -R [ssh server host:]<SSH server port>:<local host>:<local port> <SSH hostname>
複製程式碼
  • what :使用遠端轉發,監聽公網伺服器的某個埠,當應用訪問這個埠的時候,ssh會將請求擷取到,通過ssh客戶端作為中間媒介,轉發到真實提供服務的伺服器上。 伺服器處理完成後,資料再原路返回完成整個鏈路。
  • where : 在內網伺服器上執行此命令
  • how :使用以下命令配置,就可以達到訪問外網機器9527埠轉發到內網伺服器的3306埠啦
ssh -R 9527:內網機器:3306 root@公網機器
複製程式碼

讓公網伺服器監聽9527埠的訪問,如有訪問,就加密後通過ssh服務轉發請求到內網機器ssh客戶端,再由內網機器ssh客戶端解密後轉發到內網機器3306埠。這聽起來有點奇怪,因為這個時間內網伺服器充當了兩個角色,就是ssh客戶端和server端。用下圖的展示看起來更直觀一點

有跳板機的遠端轉發
這個時候我們就可以在跳板機上使用命令

ssh -R 9527:內網機器:3306 root@公網機器
複製程式碼

這個時候就是讓公網伺服器監聽9527埠的訪問,如有訪問,就加密後通過ssh服務轉發請求到跳板機ssh客戶端上,再由ssh客戶端解密後轉發到內網機器3306埠上。

注意的點

  1. 必須保持ssh client到ssh server的 SSH 連線以使埠轉發保持生效。一旦關閉了此連線,相應的埠轉發也會隨之關閉。

  2. 我們只能在建立 SSH 連線的同時建立埠轉發,而不能給一個已經存在的 SSH 連線增加埠轉發。

  3. 對於遠端轉發來說,/etc/ssh/sshd_config裡要把AllowTcpForwarding選項設定為yes,否則-R遠端埠轉發會失敗。把/etc/sysctl.conf裡的net.ipv4.ip_forward = 0設定為1

  4. 預設轉發到遠端主機上的埠繫結的是127.0.0.1,如要繫結0.0.0.0需要把/etc/ssh/sshd_config裡的GatewayPorts選項設定為yes。這個選項如果由於許可權沒法開啟也有辦法,可配合ssh -L將埠繫結到0.0.0.0,如下

ssh -R 127.0.0.1:9527:內網機器:3306 root@公網機器
ssh -L 0.0.0.0:9527:127.0.0.1:9527 root@127.0.0.1
複製程式碼

本地轉發與遠端轉發的區別與共同點

共同點:

  1. 都要保持ssh不要斷掉
  2. 都是在建立連結的同時建立埠轉發
  3. 都是轉發請求
  4. 都是在ssh client上執行

區別:

  1. 本地轉發是ssh client就是client,遠端轉發ssh client是server
  2. 本地轉發是本地請求遠端的服務,遠端轉發是遠端請求本地的服務
  3. 實在理不清,聽我的,轉發是指轉發請求,本地轉發就是把本地的請求轉發出去;遠端轉發就是把遠端的請求轉發過來。

動態轉發

我有一臺香港伺服器能上外網,憑什麼我自己不能上外網!還真就可以。

前面我們已經討論過了本地轉發,遠端轉發,但是前提都是要求有一個固定的應用服務端的埠號。那如果沒有埠號怎麼辦?等等,什麼樣的應用會沒有這個埠號呢?嗯,比如說用瀏覽器,比如說 MSN 等等。

同時當我們在一個不安全的 WiFi 環境下上網,用 SSH 動態轉發來保護我們的網頁瀏覽及 MSN 資訊無疑是十分必要的。

讓我們先來看一下動態轉發的命令格式:

 ssh -D <local port> <SSH Server>
複製程式碼

動態轉發
實際使用如下

ssh -qTFnN  -D 127.0.0.1:9527 root@香港伺服器
複製程式碼

怎麼使用

  1. 在瀏覽器裡設定使用socks5代理127.0.0.1:9527,然後瀏覽器就可以訪問host1所在網路內的任何IP了。推薦chrome瀏覽器switchyOmega外掛設定為下就可以了。

switchyOmega
2. 如果是普通命令列應用,使用proxychains-ng,參考命令如下:

   brew install proxychains-ng
   vim /usr/local/etc/proxychains.conf # 在ProxyList配置段下新增配置 "socks5 	127.0.0.1 9527"
   proxychains-ng wget http://host2 # 在其它命令列前新增proxychains-ng即可
複製程式碼
  1. 如果是ssh,則用以下命令使用socks5代理:
   ssh -o ProxyCommand='/usr/bin/nc -X 5 -x 127.0.0.1:5000 %h %p' user@host2
複製程式碼

轉發常用的引數

用法

ssh -qTfnN -D 127.0.0.1:12345 test@222.333.444.555
複製程式碼

-f 要求 ssh在執行命令前退至後臺.它用於當ssh準備詢問口令或密語,但是使用者希望它在後臺進行.該選項隱含了-n選項.

-N 不執行遠端命令.用於轉發埠.

-C 要求進行資料壓縮 (包括stdin, stdout, stderr以及轉發X11和TCP/IP連線 的資料).壓縮演算法和gzip(1)的一樣,協議第一版中,壓縮級別 “level” 用CompressionLevel選項控制.壓縮技術在modem線路或其他慢速連線上很有用,但是在高速網路上反而 可能降低速度.可以在配置檔案中對每個主機單獨設定這個引數.

-g 允許遠端主機連線本地轉發的埠

-q 安靜模式.消除所有的警告和診斷資訊

-T 禁止分配偽終端

-n 把 stdin重定向到/dev/null (實際上防止從stdin讀取資料). ssh在後臺執行時一定會用到這個選項.它的常用技巧是遠端執行X11程式.

引用

實戰 SSH 埠轉發

jeremy的技術點滴

ssh 埠轉發

ssh隧道與代理

ssh 記ssh的幾種玩法

相關文章