原文:https://www.jianshu.com/p/388a93b1e7f7
https://blog.csdn.net/qq_34039315/article/details/77510923
首先你得XShell連接到一個其他服務器,然后才能用ssh的端口轉發功能。
統一稱使用的機器為本地機,連接到的服務器為遠程機。
一、Local
這個配置是什么意思呢?
注意這個“類型方向”是Local(Outgoing),所以源主機的localhost指的是本地機,目標主機就是想要建立連接的目的。這個配置的現象就是:你在物理機瀏覽器輸入 http://localhost:8018 就通過 遠程機 訪問了163.com這個地址。配置的意思就是:通過遠程機,將163.com:80映射到物理機的8081端口。
這個有什么應用呢?
和代理差不多,就是將遠程機作為一個跳板,將本地機與目標主機連接起來。
比如下圖的例子,我想連接到 192.168.1.2怎么辦?
我先連接到SSH Server,然后再修改上面的配置(源主機 localhost:8081,目標主機192.168.1.2),然后就能成功連接了(直接ssh連接本機的8081即可)。
二、Remote
這個配置是什么意思呢?
注意這個“類型方向”是Remote(Incoming),所以注意了!!!!源主機的localhost指的是遠程機,目標主機的Localhost指的是物理機。這個配置的現象就是:你訪問遠程機的3000端口的時候,遠程機自己將消息連接到了物理機的80端口來,看到的就是物理機80端口的內容。
這個有什么應用呢?
如下圖所示,如果192.168.1.*是公司的網絡,我白天在192.168.1.2機器上辦公,我並不能登錄SSH Server,晚上還想在家加會班怎們辦呢?
分兩步走:
1、首先192.168.1.2 ssh登錄到10.10.10.10,然后配置(源主機 localhost:3333,目標主機localhost:22)
或者,在192.168.1.2配置如下也可以
ssh -N -f -R 3333:127.0.0.1:22 10.10.10.10
1
2、回家后ssh訪問10.10.10.10的3333端口,即可訪問到192.168.1.2了
---------------------
作者:烏梟
來源:CSDN
原文:https://blog.csdn.net/qq_34039315/article/details/77510923
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
-----------------------------------------------------------------------------------------------------------------------------------------------
使用 SSH TUNNEL 打通公司和家里的網絡
前言
平時經常遇到下面的情況:
- 工作沒做完,想回家繼續做。帶電腦回家?
- 碰到以前做過的功能,想從家里的電腦撈一點代碼。沒獨立 IP 怎么訪問?
- 服務器只允許公司網絡訪問,在外面要登服務器。找領導設置安全組權限(或者防火牆)?
- 在外面想訪問公司局域網中的某個服務,比如
Gitlab
? - 公司網絡不能逛淘寶?
- 想去牆外的世界看一看?
一般情況下的對應方法:
- 遠程連接(比如Windows自帶的)
- NAT內網穿透(比如花生殼,幾年前用過免費版的,不太穩定,Linux下安裝也不太順暢)
- 一般需要正當理由
- 公司有固定公網 IP 的話,路由器設置端口轉發,不過路由器權限呢?
- 代理服務器
- VPN(作用和代理服務器差不多,但原理不一樣)
本文的目的就是使用 SSH TUNNEL
這項技術解決上面的問題,也就是打通所謂的 "公司內網" 和 "家庭內網"。
SSH TUNNEL
簡介
經常遠程連接 Linux 服務器的小伙伴,對於 ssh
這個命令應該不陌生吧。它還可以不執行遠程指令只建立一條和遠程服務器之間的連接,也就是形成了一條通道,在這條通道上我們就可以做一些文章了。
先看下 ssh
命令的參數介紹(需要了解更多請通過命令 man ssh
查看):
-1:強制使用ssh協議版本1;
-2:強制使用ssh協議版本2;
-4:強制使用IPv4地址;
-6:強制使用IPv6地址;
-A:開啟認證代理連接轉發功能;
-a:關閉認證代理連接轉發功能;
-b:使用本機指定地址作為對應連接的源IP地址;
-C:請求壓縮所有數據;
-F:指定ssh指令的配置文件;
-f:后台執行ssh指令;
-g:允許遠程主機連接主機的轉發端口;
-i:指定身份文件;
-l:指定連接遠程服務器登錄用戶名;
-N:不執行遠程指令;
-o:指定ssh客戶端配置選項來覆蓋配置文件中的配置,比如:-o "StrictHostKeyChecking no" 可以去除檢查主機的提示; -p:指定遠程服務器上的ssh端口(默認為22); -q:靜默模式; -X:開啟X11轉發功能; -x:關閉X11轉發功能; -y:開啟信任X11轉發功能。 -D: 監聽本地的指定端口,本機將作為 SOCKS5 服務器使用 -L: 本地監聽指定端口,該端口收到的請求會通過遠程服務器轉發到另一台機器的指定端口上 -R: 遠程服務器上監聽指定端口,該端口收到的請求會通過本地轉發到另一台機器的指定端口上
關鍵的就是最后的三個參數,對應 SSH 隧道
的三種端口轉發模式:本地轉發(-L Local),遠程轉發(-R Remote)和動態轉發(-D Dynamic)
本地轉發
本地監聽指定端口,該端口收到的請求會通過遠程服務器轉發到另一台機器的指定端口上
- 語法:
ssh [-p ssh_port] -L [bind_address:]port:host:hostport user@remote_host
解釋:
port:本地監聽的端口
bind_address:監聽端口使用的本地地址(如:192.168.1.2,127.0.0.1,0.0.0.0), 不設置默認為回環地址 127.0.0.1
host:轉發的目標IP
hostport:轉發的目標端口
注意:
host:hostport 是遠程主機 user@remote_host:ssh_port 所能訪問到的地址(包括 user@remote_host自己),本地主機不一定能訪問該地址
- 示例:
ssh -p 23 -Nf -L 0.0.0.0:3000:123.123.123.124:3001 root@123.123.123.123
說明:
1. 通過 23 端口 ssh 遠程服務器 123.123.123.123,使用帳號 root 登錄
2. 本地監聽端口 0.0.0.0:3000
3. 123.123.123.124 和 123.123.123.123 在一個局域網下,而本地不能直接訪問 123.123.123.124
4. 123.123.123.124 主機通過 3001 端口開放服務
5. 調用鏈路:本地訪問 --> 127.0.0.1:3000 -- ssh 隧道 --> 123.123.123.123 -- 轉發 --> 123.123.123.124:3001
上面示例中相當於將遠程主機 123.123.123.124 的 3001 端口映射為本地的 3000 端口,這樣就可以通過局域網訪問被限制的公網服務了。
遠程轉發
遠程服務器上監聽指定端口,該端口收到的請求會通過本地轉發到另一台機器的指定端口上
- 語法:
ssh [-p ssh_port] -R [bind_address:]port:host:hostport user@remote_host
解釋:
語法和 -L 一樣,只不過監聽側和目標側的網絡對換而已
port:在遠程主機 user@remote_host 上監聽的端口
bind_address:遠程主機 user@remote_host 監聽端口使用的地址(如:remote_host,127.0.0.1,0.0.0.0)。
和 -L 有點區別,指定IP需要在遠程主機上修改 /etc/ssh/sshd_config 中的配置:GatewayPorts。"yes" 表示 強制為 0.0.0.0; 默認為 "no" 表示強制為回環地址 127.0.0.1;"clientspecified" 表示由客戶端決定
host:轉發的目標IP
hostport:轉發的目標端口
注意:
host:hostport 是本地主機所能訪問到的地址(包括本機),遠程主機 user@remote_host:ssh_port 不一定能訪問該地址
- 示例:
ssh -p 23 -Nf -R 172.17.0.1:3000:192.168.1.100:3001 root@123.123.123.123
說明:
1. 通過 23 端口 ssh 遠程服務器 123.123.123.123,使用帳號 root 登錄
2. 123.123.123.123 監聽端口 172.17.0.1:3000 (遠程服務器運行 docker , 多了一個虛擬網絡 172.17.0.0)
3. 192.168.1.100 和 本地主機 在一個局域網下,而 123.123.123.123(外網) 不能直接訪問 192.168.1.100(內網)
4. 192.168.1.100 主機通過 3001 端口開放服務
5. 調用鏈路:遠程服務器中訪問 --> 172.17.0.1:3000 -- ssh 隧道 --> 本地 -- 轉發 --> 192.168.1.100:3001
上面示例中相當於將局域網主機 192.168.1.100 的 3001 端口映射為遠程服務器 123.123.123.123 的 3000 端口,這樣就可以通過公網來訪問局域網中的服務了。
動態轉發
監聽本地的指定端口,本機將作為 SOCKS5 服務器使用
- 語法:
ssh [-p ssh_port] -D [bind_address:]port user@remote_host
解釋:
port:本地監聽的端口
bind_address:監聽端口使用的本地地址(如:192.168.1.2,127.0.0.1,0.0.0.0), 不設置默認為回環地址127.0.0.1
注意:
啟動 socks5 代理
代理使用示例:
curl --socks5 bind_address:port baidu.com
- 示例
ssh -p 23 -Nf -D 127.0.0.1:3000 root@123.123.123.123
說明:
1. 通過 23 端口 ssh 遠程服務器 123.123.123.123,使用帳號 root 登錄
2. 本地監聽端口 127.0.0.1:3000
3. 調用鏈路:本地局域網中訪問任意http服務 -- 使用代理 --> 172.17.0.1:3000 -- ssh 隧道 --> 123.123.123.123 -- 轉發 --> 目標http服務
上面示例中相當於開啟了一個代理服務器,比起 本地轉發
需要指定具體端口來說更加方便。
正文
上面已經介紹了 SSH TUNNEL
的使用方式,接下來就開始干正事了,先上兩張網絡拓撲圖。


對比兩張圖把少的線連上就好了,是不是很easy?
-
原先環境:
三個獨立的網絡:公司內網、家里內網、阿里雲專有網絡,其中可以通過公司網絡訪問阿里雲上的服務器而家里網絡則不行。 -
目標:
- 使家里網絡的主機能訪問公司內局域網中的主機
- 使家里網絡的主機能訪問公司阿里雲上的服務器
-
預備工作:
- 有一台公網的服務器作為跳板機,公司和家里都能訪問到(沒有服務器?阿里雲騰訊雲學生機弄台玩玩)
- 因為
ssh
命令不能添加密碼作為參數,只能手動輸入,而且每次連接都要重新輸入也不是很方便,這里采用公鑰方式登錄就可以免輸密碼了
# 創建ssh密鑰對 ssh-keygen -t rsa -b 4096 -C "備注1" # 遠程服務器上的 ~/.ssh/authorized_keys 權限要是600 # 追加本機公鑰到遠程服務器 cat ~/.ssh/id_rsa.pub | ssh -p 23 root@123.123.123.123 "cat - >> ~/.ssh/authorized_keys" # 或者直接復制本機公鑰到遠程服務器(會覆蓋掉遠程服務器已有的其他公鑰) scp -P 23 -p ~/.ssh/id_rsa.pub root@123.123.123.123:~/.ssh/authorized_keys
-
步驟:
- 將【公司主機A】的端口【22】映射到【跳板機J】的端口【9999】上, 在【公司主機A】按照下面的命令配置(【跳板機J】需要按上文方式將
GatewayPorts
設為true
):
ssh -p 23 -Nf -R 9999:127.0.0.1:22 root@123.123.123.123
當然也可以通過
docker
來運行autossh
來使這個隧道可以自動重連# 暴露本地ssh端口到遠端服務器端口 ssh-to-expose-ssh-server: image: jnovack/autossh container_name: autossh-ssh-to-expose-ssh-server # 使用宿主機的網絡 network_mode: host environment: - SSH_HOSTUSER=root - SSH_HOSTNAME=123.123.123.123 - SSH_HOSTPORT=23 - SSH_TUNNEL_REMOTE=9999 - SSH_TUNNEL_HOST=127.0.0.1 - SSH_TUNNEL_LOCAL=22 restart: always volumes: - ~/.ssh/id_rsa:/id_rsa
這樣在【跳板機J】上就可以通過
ssh -p 9999 root@127.0.0.1
遠程連接到【公司主機A】了- 【跳板機J】設置動態轉發作為代理服務器, 將接收到的請求再轉發到【公司主機A】, 在【跳板機J】上按照下面的命令配置:
ssh -p 9999 -Nf -D 0.0.0.0:1080 root@127.0.0.1
同樣的,要把【跳板機J】的公鑰復制到【公司主機A】上實現免密登錄
# 創建ssh密鑰對 ssh-keygen -t rsa -b 4096 -C "備注2" # 追加本機公鑰到遠程服務器 cat ~/.ssh/id_rsa.pub | ssh -p 9999 root@127.0.0.1 "cat - >> ~/.ssh/authorized_keys"
當然也可以使用
docker
啟動autossh
:# 使用 SSH TUNNEL 創建 SOCKS5 代理 ssh-tunnel-socks5-server: image: jnovack/autossh container_name: ssh-tunnel-socks5-server entrypoint: autossh -M 0 -N -o ServerAliveInterval=5 -o ServerAliveCountMax=1 -o "ExitOnForwardFailure yes" -o "StrictHostKeyChecking no" -t -t -i /id_rsa -D 0.0.0.0:1080 -p 9999 # 使用宿主機的IP root@172.17.0.1 ports: - "1081:1080" restart: always volumes: - ~/.ssh/id_rsa:/id_rsa
這樣【家里主機F】就可以通過設置代理【跳板機J】連接上阿里雲上的服務器了。原理:【公司主機A】和【跳板機J】聯合組成代理層。調用鏈路為:【家里主機F】 -- 使用代理 --> 【跳板機J】 -- ssh 隧道 --> 【公司主機A】 -- 轉發 --> 阿里雲服務器。(注:組成代理層還有另一種方式:【公司主機A】開代理服務同時把端口遠程暴露到【跳板機J】上, 通過這種方式就可以配置代理服務的密碼了, 具體配置參照這里)
- 將【公司主機A】的端口【22】映射到【跳板機J】的端口【9999】上, 在【公司主機A】按照下面的命令配置(【跳板機J】需要按上文方式將
就這么兩步配置已經打通"公司網絡"和"家里網絡"了。不過,貌似實現的效果是單向的誒(只能家里連公司,公司還不能連家里, 如下圖),【家里主機F】按【公司主機A】的步驟再配一下就好啦。

拓展
-
使用代理訪問受限制的網站(比如公司內網的項目):
- 由於代理服務器使用的
SOCKS5
協議,Chrome
上安裝SwitchyOmega
插件配置代理服務器地址,即可通過代理服務器訪問受限制的服務了。 - 將
SOCKS5
協議轉為HTTP
協議,然后通過系統自帶的方式(Win下設置IE的Internet屬性
,移動設備設置WIFI 的 HTTP 代理
)來設置全局代理,docker-compose
配置如下:
# 使用gost代理 SOCKS5 端口 gost-server: image: ginuerzh/gost command: -L=:8080 -F=socks5://ssh-to-local-proxy:1080 ports: - "1082:8080" restart: always # 使用privoxy代理 SOCKS5 端口 privoxy: image: rdsubhas/tor-privoxy-alpine entrypoint: sh -c 'echo "listen-address 0.0.0.0:8118" > /etc/service/privoxy/config && echo "forward-socks5 / ssh-to-local-proxy:1080 ." >> /etc/service/privoxy/config && privoxy --no-daemon /etc/service/privoxy/config' ports: - "1083:8118" restart: always
這里給出兩種轉換方式:
gost
和privoxy
, 選擇其中一種方式即可。privoxy
找不到純凈的鏡像, 都是捆綁tor
的, 就挑一個最精簡的來做修改吧。- 其實還可以在【公司主機A】搭建
SS 服務器
, 然后就可以通過SS 客戶端
來連接代理。具體的本文就不細說了,搭建示例可以看這里對應的 compose 文件
- 由於代理服務器使用的
-
終端工具中使用代理來連接阿里雲服務器
這里的例子使用WinSCP
, 其他工具應該也差不多:新建站點->編輯->高級->連接

- ssh隧道方式:使用【跳板機J】的【9999】端口加【公司主機A】的帳號、密碼、端口。

- 代理方式:可以選擇
SOCKS5
協議或者HTTP
協議,和上面的配置一致即可。

其他問題
- SSH連接可能會中斷(臨時的網絡擁塞、SSH 超時、中繼主機重啟等等),所以可以借助
autossh
實現自動重連來保證可靠的服務 - SSH連接有超時斷開的機制,
WinSCP
有時經常會提示斷開重連,有兩種方式來維持連接:- 設置->面板->遠程->修改刷新面板間隔為30s或者更短
- session設置->高級->連接->keepalives->執行啞命令(空SSH包是沒效果的)
Win10 1803
已經默認集成了SSH 工具
,可以直接使用上面的命令。當然也可以借助終端工具來建立SSH隧道,比如在MobaXterm
上可以使用圖形界面進行設置,比較直觀。- 文中的方法使用兩級代理三次轉發(如果在docker中運行那就是四次轉發)實現不同網絡的訪問,中間代理層的帶寬就限制了整體的訪問速度,需要注意下
- 跳板機提供的
SOCKS5
代理服務沒有密碼,如果被別人知道了 IP 和端口容易被惡意攻擊,所以一定要做好安全措施(比如:安全組或防火牆限制跳板機的入網 IP 為自己指定的 IP) - 你公司其他同事也想連你家里的電腦?總不能把【跳板機】暴露給他吧,太不安全了,你本地再開一層代理,讓他用你的電腦作為代理好了。
倉庫
基於 docker-compose
運行的完整配置已經上傳至GitHub
參考文章
- SSH隧道技術----端口轉發,socket代理
- 通過 SSH 實現 TCP / IP 隧道(端口轉發):使用 OpenSSH 可能的 8 種場景
- winScp如何通過隧道代理進行遠程連接
- ssh tunnel 三種模式
- SSH Tunnel | SSH.COM
- SSH port forwarding - Example, command, server config | SSH.COM
吐槽
發布文章還會莫名其妙被鎖定,也是醉了。好像是出現SS服務的全稱就會被封,要了解更多相關內容的自己去 GitHub
用搜索 SS/SS-windows
( SS 替換為全稱)。