利用反向ssh從外網訪問內網主機

利用反向ssh從外網訪問內網主機

前言

最近遇到一個問題,就是過幾天我需要離開學校,而且到時候仍然想登陸校園網裏的一臺服務器進行工作;但是我又沒有校園網網關的操作權限,不能做端口映射,也不能搞到校園網內部主機的外網ip,而且學校自己提供的vpn又根本沒法用。研究了半天,總算找到了一個比較不錯的利用反向ssh(reverse ssh tunnel)進行內網登陸的解決方案。

工作原理

之所以很多轉發的方法無法應用在這裏,就是因爲內網主機對外網其實是不可見的,也就是說外部主機不能用一般的方法訪問到內部主機。那麼我們就想了,能不能用內網主機找外網主機,找到之後再把這條內網主機登陸外網的信道轉換成外網主機登陸內網的信道呢?辛運的是,這個方法的確是可行的,這也就是所謂反向ssh最通俗的理解,這就像寄信一樣,”雖然我不知道你的地址,但是你知道我的地址,那麼你就先給我寫封信,告訴我你的地址,然後我不就可以回信給你了麼?“。

操作步驟

由於我們自己使用的電腦未必有外網ip,因此我們需要一個有固定外網ip的服務器(隨便搞個騰訊雲阿里雲的小機子就行),然後用這臺服務器與內網的機子進行通信,我們到時候要先登陸自己的服務器,然後再利用這個服務器去訪問內網的主機。

1、準備好有固定ip的服務器A,以及待訪問的內網機器B。兩者都開着sshd服務,端口號默認都是22。順便做好ssh免密碼登陸。

2、內網主機B主動連接服務器A,執行以下命令:

1
$ ssh -NfR 1111:localhost:22 username@servername -p 22

這條命令的意思是在後臺執行(-f),不實際連接而是做port forwarding(-N),做反向ssh(-R),將遠程服務器的1111端口映射成連接本機(B)與該服務器的反向ssh的端口。

附:這裏有必要加強一下記憶,這個端口號一不小心就容易搞混。。man文檔中的參數命令是這樣的:

1
-R [bind_address:]port:host:hostport

bind_address以及其後面的port是指遠程主機的ip以及端口,host以及其後的hostport是指本機的ip和端口。由於ssh命令本身需要遠程主機的ip(上上條命令中的servername),因此這個bind_address原則上是可以省略的。

執行完這條命令,我們可以在服務器A上看到他的1111端口已經開始監聽:

1
2
$ ss -ant |grep 1111
LISTEN 0 128 127.0.0.1:1111 *:*

3、在上面的操作中,這個1111端口就已經映射成了內網主機B的22端口了,現在我們只要ssh到自己的這個端口就行了。在服務器A中執行:

1
$ ssh username@localhost -p1111

這樣就成功的登陸了內網的主機了。

功能優化

上面的做法其實有一個問題,就是反向ssh可能會不穩定,主機B對服務器A的端口映射可能會斷掉,那麼這時候就需要主機B重新鏈接,而顯然遠在外地的我無法登陸B。。。這其實有一個非常簡單的解決方案,就是用autossh替代步驟2中的ssh:

1
$ autossh -M 2222 -NfR 1111:localhost:22 username@servername -p 22

後面的參數跟ssh都一樣,只是多了一個-M參數,這個參數的意思就是用本機的2222端口來監聽ssh,每當他斷了就重新把他連起來。。。不過man文檔中也說了,這個端口又叫echo port,他其實是有一對端口的形式出現,第二個端口就是這個端口號加一。因此我們要保證這個端口號和這個端口號加一的端口號不被佔用。

參考資料

SSH反向連接及Autossh

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章