雖然現(xiàn)在辦公PC大都是筆記本,輕便易攜帶,但是作為追求自由不希望有任何束縛的碼農(nóng),就是希望下班之后雙手插口袋,直接回家。不過(guò)有時(shí)回家后想看看辦公PC上的文檔,怎么辦,難道要返回辦公室或者拜托他人?本文討論的方法,讓你自己搞定不求人(雖然如此,但企業(yè)都有規(guī)章制度。。。另請(qǐng)大家遵紀(jì)守法)。

場(chǎng)景假設(shè)
- 辦公PC處在防火墻后面,通過(guò)NAT路由訪(fǎng)問(wèn)互聯(lián)網(wǎng)
- 普通員工,無(wú)權(quán)觸碰防火墻和路由設(shè)置,管理員不會(huì)接受申請(qǐng)
目標(biāo)
絕大多數(shù)同學(xué)應(yīng)該符合上述場(chǎng)景的,現(xiàn)在目標(biāo)就是在家遠(yuǎn)程連接辦公室PC。
步驟
根據(jù)家庭網(wǎng)關(guān)的情況,有以下2種情況:
- 家庭網(wǎng)關(guān)有公網(wǎng)IP
- 家庭網(wǎng)關(guān)沒(méi)有公網(wǎng)IP(現(xiàn)在有些運(yùn)營(yíng)商小區(qū)上網(wǎng)方式是NAT,不過(guò)你可以要求免費(fèi)分配公網(wǎng)IP,但一般不固定,不過(guò)只要不重啟網(wǎng)關(guān),一般不會(huì)變)
本文討論第一種情況,第二種情況另文討論:家庭網(wǎng)關(guān)有公網(wǎng)IP
(請(qǐng)自行登陸家庭網(wǎng)關(guān)查看WAN側(cè)IP,即公網(wǎng)IP)
步驟如下:
1, 家庭電腦上安裝OpenSSH服務(wù)器并開(kāi)啟,準(zhǔn)備好登陸用戶(hù)名和密碼(筆者使用Ubuntu16.04LTS,Windows也可以,安裝設(shè)置方法不在此討論)
2,家庭網(wǎng)關(guān)(帶路由功能)設(shè)置端口轉(zhuǎn)發(fā):網(wǎng)關(guān)把WAN側(cè)22端口請(qǐng)求轉(zhuǎn)發(fā)到LAN的OpenSSH服務(wù)器(請(qǐng)?jiān)O(shè)置固定IP),筆者使用的聯(lián)通&烽火通信的HG220GS-U家庭網(wǎng)關(guān),設(shè)置如下

3, 在辦公室電腦上用SSH設(shè)置遠(yuǎn)端端口轉(zhuǎn)發(fā)連接家庭OpenSSH服務(wù)器(SSH轉(zhuǎn)發(fā)原理,見(jiàn)參考連接):辦公電腦如果是Windows,可以用Putty(開(kāi)源圖形化SSH客戶(hù)端),這里不具體介紹設(shè)置。筆者考慮到后續(xù)編寫(xiě)自動(dòng)重連腳本方便,利用了辦公室的另一臺(tái)Linux機(jī)器作為轉(zhuǎn)發(fā)平臺(tái)
- 首先設(shè)置SSH客戶(hù)端即使非Known Host也無(wú)需確認(rèn),直接連接,方便后續(xù)腳本自動(dòng)執(zhí)行,無(wú)需人工值守。
sudo vim /etc/ssh/ssh_config
找到并設(shè)置
StrictHostKeyChecking no
- 接下來(lái),在該機(jī)器上運(yùn)行命令如下:
sshpass -p 123 ssh -gfN -C -R 3389:10.100.99.207:3389 simon@1.2.3.4
上述sshpass是設(shè)置ssh登陸密碼(123)以后續(xù)自動(dòng)登陸不再提示輸入密碼(更好的做法是用公鑰登陸)。
ssh后面R 3389:10.100.99.207:3389,表示遠(yuǎn)端機(jī)器在3389上監(jiān)聽(tīng),通過(guò)SSH通道到達(dá)本地后,轉(zhuǎn)發(fā)到10.100.99.207:3389,也就是筆者的Windows PC(請(qǐng)?zhí)崆霸O(shè)置后允許遠(yuǎn)程桌面,并開(kāi)放防火墻端口)。
另外-gfN分別是g表示遠(yuǎn)端主機(jī)接受任何ip的轉(zhuǎn)發(fā)請(qǐng)求,否則之接受本機(jī)的,f表示后臺(tái)執(zhí)行,N表示不執(zhí)行遠(yuǎn)端命令,只是轉(zhuǎn)發(fā)。
simon@1.2.3.4部分,請(qǐng)根據(jù)公網(wǎng)IP和自己ssh服務(wù)器用戶(hù)設(shè)置。
- 好了,上述命令執(zhí)行成功后,你就可以在家庭PC上連接辦公室電腦了
如何查看是否與遠(yuǎn)程SSH服務(wù)器連接成功?
simon@jenkins:~$ netstat -an -t | grep :22
...省略...
tcp 0 0 192.168.1.102:44124 1.2.3.4:22 ESTABLISHED
...省略...
simon@jenkins:~$
發(fā)現(xiàn)本機(jī)(Linux)與遠(yuǎn)程1.2.3.4的tcp連接已經(jīng)ESTABLISHED,就說(shuō)明連接成功了。
在家庭電腦(筆者是Ubuntu)上打開(kāi)Remmina(Linux桌面遠(yuǎn)程連接客戶(hù)端,支持RDP,VNC,SSH等多種協(xié)議),編寫(xiě)連接

并點(diǎn)擊連接,奇跡出現(xiàn),辦公室PC的桌面出現(xiàn)了

優(yōu)化
- 考慮到辦公室和家庭所在地的物理距離限制,本實(shí)驗(yàn)很難同時(shí)在辦公室和家里操作,筆者寫(xiě)了段腳本運(yùn)行在辦公室的Linux機(jī)器上,思路時(shí),如果與遠(yuǎn)程家庭SSH服務(wù)連接成功,則退出,否則嘗試連接。然后設(shè)置cron每隔10分鐘執(zhí)行該腳本。
crontab設(shè)置
simon@jenkins:~$ crontab -l
*/10 * * * * ~/create_remote_foward_tun.sh 1.2.3.4 >> ~/create_remote_foward_tun.sh.log 2>&1
simon@jenkins:~$
create_remote_foward_tun.sh內(nèi)容如下:
#!/bin/bash
#
#Usage:
# create_remote_foward_tun.sh remote_host_ip
# remote_host_ip - public ip where you want to connect from.
# Description:
# create a remote foward tunnel to connect pc in lan without special setting on firewall and router.
#
###########################################################################
if [[ -z $1 ]]; then
cat <<EOF
#Usage:
# create_remote_foward_tun.sh remote_host_ip
# remote_host_ip - public ip where you want to connect from.
EOF
exit 1
fi
#check route is ok
ping -n -c 2 $1 || { echo "no route to $1"; exit 2; }
is_connected=$(netstat -an -t | grep $1 | awk '{if(NR == 1) print $6}')
[[ $is_connected = "ESTABLISHED" ]] && { echo "already connected"; exit 3; }
sshpass -p 123 ssh -gfN -C -R 3389:10.100.99.207:3389 simon@$1
- 還可以,申請(qǐng)動(dòng)態(tài)域名,這樣就不用擔(dān)心網(wǎng)關(guān)重啟,公網(wǎng)IP變化了。
總結(jié)
通過(guò)SSH遠(yuǎn)端端口轉(zhuǎn)發(fā),實(shí)現(xiàn)了不需要安裝特殊軟件透明穿透公司防火墻即可在家連接辦公室PC。注意是透明穿透哦,還可以把家里網(wǎng)關(guān)端口設(shè)置為80偽裝成訪(fǎng)問(wèn)普通網(wǎng)站的樣子,一般防火墻是無(wú)法檢測(cè)到的,除非有異常長(zhǎng)連接檢測(cè)功能。有些軟件如teamviewer,可以實(shí)現(xiàn)同樣的功能,不過(guò)限制是只能在圖形界面下使用,而且必須經(jīng)過(guò)第3方服務(wù)器,管理員是很容易設(shè)置防火墻屏蔽到服務(wù)器之間的通訊,因?yàn)樗且阎摹A硗?,?duì)于喜歡折騰,愛(ài)好全手工打造的同學(xué),不妨嘗試也一下。最后為方便理解奉上網(wǎng)絡(luò)拓?fù)淙缦拢?/p>

通訊過(guò)程如下:
- 連接家庭SSH服務(wù)器,建立轉(zhuǎn)發(fā)通道
A -> C -> D -> E - 連接辦公室Windows PC,以及后續(xù)通訊
E -> D -> C -> A -> B
B -> A -> C -> D -> E
B和E的通訊,始終要經(jīng)過(guò)A,為什么,因?yàn)橹挥蠥和E之間建立了通道,如果繞過(guò)A,則無(wú)法通訊,當(dāng)然如果直接在B上連接SSH服務(wù)器,則沒(méi)有A什么事了。
下一步
如果互聯(lián)的2臺(tái)終端都處在受保護(hù)的防火墻后面,都不能設(shè)置特權(quán)端口,還有沒(méi)有辦法呢?
答案是肯定的,不過(guò)也需要設(shè)置第3臺(tái)服務(wù)器:
設(shè)置一臺(tái)公網(wǎng)云服務(wù)器(VPS),客戶(hù)端C(遠(yuǎn)程連接發(fā)起端)設(shè)置SSH本地轉(zhuǎn)發(fā)連接到VPS,遠(yuǎn)程桌面R(遠(yuǎn)程連接接受端,也就是你的辦公PC)設(shè)置遠(yuǎn)程轉(zhuǎn)發(fā)連接到VPS。這樣就實(shí)現(xiàn) C -> VPS -> R
優(yōu)化,C和R通過(guò)VPS建立通信之后,每次傳輸都要經(jīng)過(guò)VPS,效率不高,可以通過(guò)VPS修改C和R的包頭(目的IP:PORT,和源IP:PORT),讓C和R后續(xù)直接通信(P2P)。估計(jì)不行,因?yàn)橥ǖ朗荢SH Over TCP/IP且加密的,VPS連接C和R是2個(gè)不同的加密通道,替換IP包的源和目的之后,即使C和R之間的包可以互相到達(dá),但無(wú)法解密,依然無(wú)法通訊,需要VPS通知通訊雙方采用某種一致的加密方式。。。慢慢研究。高人路過(guò)不吝賜教。