一、場景如下:
各個角色的對應關系如下:
角色 | 描述 |
---|---|
APP | 個人筆記本,屬於內網IP |
sshd server | 公網 VPS ( 映射端口: port 2222 ),擁有公網IP |
ssh client | 內網機器,屬於另一個內網IP |
APPSRV | 與 內網 ssh client 是同一台機器 ( 目的端口: |
兩個帳號:admin/password為“內網機器”ssh的登錄帳號密碼,VPS-user
/password為“公網VPS”ssh的登錄帳號密碼
網絡連通情況:“內網機器”可以訪問公網VPS,“個人筆記本”可以訪問“公網VPS”,但是不可以訪問“內網機器”;“公網VPS”不能訪問“內網機器”,也不能訪問“個人筆記本”
二、目標:實現私網的筆記本訪問另一個私網的“內網機器”
三、思路:建立反向代理,把訪問公網VPS某個端口的流量映射到“內網機器”的某個端口;然后建立正向代理,把“個人筆記本”對“內網機器”的訪問流量、訪問請求,通過代理發給“VPS”的那個映射端口
四、步驟:
1、反向代理:“公網VPS”===>"內網機器",通過內網機器反向連接VPS
在內網機器上配置:(ssh clinet) # ssh -CfnNT -R 2222:localhost:22
VPS-user@VPS
(ssh clinet) #
ssh-p 22 -qngfNTR 6666:localhost:22 VPS-user@VPS
這樣就把“內網機器”的22端口轉發到了遠程機器(VPS)的6666端口上
查看內網機器的進程
[ssh clinet ~]# ps aux | grep "ssh -p"
root 14594 0.0 0.0 59856 1056 ? Ss 11:16 0:00 ssh -p 22 -qngfNTR 6666:localhost:22 VPS-user@VPS
查看公網VPS的端口情況,注意端口6666,只有本地環回地址可以訪問
[sshd server ~]# netstat -anpt | grep 6666
tcp 0 0 127.0.0.1:6666 0.0.0.0:* LISTEN 10703/sshd
這時候,在公網VPS上就可以通過ssh連接內網機器,打通了“公網VPS”到“內網機器”的訪問通道
[sshd server ~]# ssh -p 6666 admin@localhost
admin@localhost's password:
輸入“內網機器”ssh帳號的密碼“password”,就可以在公網VPS上實現到內網機器的ssh連接
2、正向代理:“個人筆記本”===>“公網VPS”
在“個人筆記本”上配置:[App ~] # ssh
-p 6666 -qngfNTD 6767
VPS-user@VPS,這樣,訪問“個人筆記本”本機(127.0.0.1)端口6767的流量就流向了“內網機器”
但是目前,上面配置是不生效的,因為“公網VPS”的端口6666,只允許它自己訪問。解決辦法有兩個:
a、思路:修改“公網VPS”的配置sshd_config,使其建立的SSH端口供所有IP訪問
方法:把“公網VPS”配置文件/etc/ssh/sshd_config里的配置“GatewayPorts no”修改為“GatewayPorts yes”,重新執行步驟1,執行完查看“公網VPS”的6666端口如下
[sshd server ~]# netstat -anpt | grep 6666
tcp 0 0 0.0.0.0:6666 0.0.0.0:* LISTEN 10703/sshd
b、思路:不修改“公網VPS”的配置sshd_config,仍然采用默認配置“GatewayPorts no”,在“公網VPS”上增加一個本地端口映射,使新增加的端口供所有IP訪問,或者供特定的IP訪問
方法:在“公網VPS”上配置:[sshd server~] # ssh -fCNL *:6667:localhost:6666 localhost,這一步執行需要“公網VPS”的root帳號密碼
查看“公網VPS”的進程和端口情況:
[sshd server ~]# netstat -anpt | grep 6667
tcp 0 0 0.0.0.0:6667 0.0.0.0:* LISTEN 1073/sshd
[ssh server ~]# ps aux | grep "ssh -p"
root 14594 0.0 0.0 59856 1056 ? Ss 11:16 0:00 ssh -fCNL *:6667:localhost:6666 localhost
然后重復執行步驟2,不過端口由6666修改為6667
[App ~] # ssh
-p 6667 -qngfNTD 6767
VPS-user@VPS,這樣,訪問“個人筆記本”本機(127.0.0.1)端口6767的流量就流向了“內網機器”
這個時候在“內網機器”上開啟80端口的服務[ssh clinet~]# python -m SimpleHTTPServer 80
在“個人筆記本”上配置瀏覽器代理,要選用“socks5”
然后訪問
五、保持連接的網絡穩定
方法一、客服端發“心跳”,配置ssh_config
使用SSH客戶端的ServerAliveInterval和ServerAliveCountMax選項。 ServerAliveInterval會在隧道無通信后的一段設置好的時間后發送一個請求給服務器要求服務器響應。如果服務器在 ServerAliveCountMax次請求后都沒能響應,那么SSH客戶端就自動斷開連接並退出,將控制權交給你的監控程序。這兩個選項的設置方法分別是在ssh時加入-o ServerAliveInterval=n和-o ServerAliveCountMax=m。其中n, m可以自行定義
方法二、服務端發“心跳”:配置sshd_config
ClientAliveInterval 60 服務器端向客戶端請求消息的時間間隔為60秒
ClientAliveCountMax 3 表示服務器發出請求后客戶端沒有響應的次數達到3次, 就自動斷開
這樣的配置就能讓一個SSH的配置保持長連接了
六、ssh配置含義:
-f 后台運行,后台認證用戶/密碼,通常和-N連用,不用登錄到遠程主機,
將ssh轉到后台運行,即認證之后,ssh 自動以后台運行。不再輸出信息 告訴SSH客戶端在后台運行
-C 允許壓縮數據
-R 將端口綁定到遠程服務器,反向代理,將遠程主機(服務器)的某個端口轉發到本地端指定機器的指定端口。工作原理是這樣的, 遠程主機上分配了一個socket偵聽port端口, 一旦這個端口上有了連接, 該連接就經過安全通道轉發出去,同本地主機host的hostport端口建立連接。可以在配置文件中指定端口的轉發。
-L 將端口綁定到本地客戶端,正向代理,將本地機(客戶機)的某個端口轉發到遠端指定機器的指定端口。工作原理是這樣的, 本地機器上分配了一個 socket 偵聽 port 端口, 一旦這個端口上有了連接, 該連接就經過安全通道轉發出去, 同遠程主機host的hostport端口建立連接。可以在配置文件中指定端口的轉發。
-L X:Y:Z的含義是,將IP為Y的機器的Z端口通過中間服務器映射到本地機器的X端口。
-D port指定一個本地機器 “動態的’’應用程序端口轉發,工作原理是這樣的, 本地機器上分配了一個 socket 偵聽 port 端口, 一旦這個端口上有了連接, 該連接就經過安全通道轉發出去, 根據應用程序的協議可以判斷出遠程主機將和哪里連接。
-n 將 stdio 重定向到 /dev/null,與 -f 配合使用
-N 不執行腳本或命令,即通知 sshd 不運行設定的 shell 通常與 -f 連用,告訴SSH客戶端,這個連接不需要執行任何命令。僅僅做端口轉發
-T 不分配 TTY 只做代理用
-q 安靜模式,不輸出錯誤/警告信息
-g 在-L/-R/-D參數中,允許遠程主機連接到建立的轉發的端口,如果不加這個參數,只允許本地主機建立連接
通過遠程主機1跳到遠程主機2:
命令格式:
ssh -t remoteserver1 ssh remoteserver2
說明:當遠程主機remoteserver2無法直接到達時,可以使用-t參數,然后由remoteserver1跳轉到remoteserver2。在此過程中要先輸入remoteserver1的密碼,然后再輸入remoteserver2的密碼,然后就可以操作remoteserver2了。
man sshd_config
man 5 shells
圖示,正向代理:ssh -L
圖示,反向代理:ssh -R
參考:
1、http://lvii.github.io/system/2013/10/08/ssh-remote-port-forwarding/
2、http://bobao.360.cn/learning/detail/4234.html
3、https://segmentfault.com/a/1190000002718360
4、http://www.dirk-loss.de/ssh-port-forwarding.htm