1. 程式人生 > >使用 ssh 反向隧道穿透 NAT 訪問 Linux 內網主機

使用 ssh 反向隧道穿透 NAT 訪問 Linux 內網主機

前言

由於公司經常會有專案需要去業主那邊搭建伺服器,基本不需要什麼流量所以就準備用 4G 網絡卡搭建。而該網絡卡無固定公網 ip,只有內網 ip,我們目的就是為了可以遠端操控以避免有時因業務需要往業主那邊跑,要是地方比較遠來回一趟也得花個把星期,不划算。所以就研究了下 ssh 隧道穿透來滿足我們的需求。

場景

現在我們有三臺機子:

  • A:公司內網電腦(Win 10)
  • B:公司內網伺服器(Linux,固定外網 ip:58.247.33.44,ssh 開放埠:8862)
  • C:業主那邊 4G 網絡卡搭建的伺服器(Linux,無固定外網 ip,ssh 開放埠:22)

操作前:A 可以訪問 B,C 能上網也能訪問 B,但是 B 不能訪問 C,A 不能訪問 C 我們需要滿足:A 可以訪問 C

當然,很多遠端桌面軟體可以滿足我們這個需求,但是由於太不方便和不穩定,還是考慮 ssh。(安裝 ssh 可見底文的附加安裝指令

配置

配置 B 伺服器

  • 修改伺服器上的 sshd 設定

vim /etc/ssh/shhd_config 建議使用 vim,vim 比 vi 更強大(安裝 vim 可見底文的附加安裝指令

  • 把 GatewayPorts 開啟(去掉前面的 # 號註釋,沒有就直接在底下新增)

GatewayPorts yes 開啟允許對映埠

  • 存檔後退出,並重新啟動 sshd (不知如何操作檔案的自行上網查閱)

service ssh restart 這個具體得看你 service 的實際名字(Ubuntu 下 service --status-all

可以檢視所有服務狀態)

配置 C 伺服器

可以進行對映操作了

ssh -NfR 1234:localhost:22 [email protected] -p8862

N 引數,表示只連線遠端主機,不開啟遠端shell。 f 引數,表示後臺執行。 R 引數接受三個值,分別是"遠端主機埠:目標主機:目標主機埠"。 p 引數,表示指定 ssh 對外開放的埠號。 user 是 B 伺服器的使用者。 這條命令的意思,就是讓 B 伺服器監聽它自己的 1234 埠,然後將所有資料經由 B 伺服器轉發到 C 伺服器的 22 埠。這就被稱為"遠端埠繫結"。

這裡每次連線需要輸入 B 伺服器的密碼,不太方便,待會再詳細介紹。

對映操作後我們可以發現在 B 伺服器上已經開啟了 1234 埠的監聽,已經可以通過 1234 埠進行 ssh 連線到 C 伺服器了。

金鑰驗證,直接登入

接回上面說的每次需要輸入密碼的問題,我們可以用 ssh 金鑰來實現自動登入。

在 C 伺服器上生成公鑰和私鑰

ssh-keygen (一直 enter)

ls ~ /.ssh/ 檢視是否生成,顯示如下

id_rsa id_rsa.pub known_hosts

ssh-copy-id [email protected] 複製到 B 伺服器中

好了,這樣就不需要每次都輸入 B 伺服器密碼了。

autossh 實現自動重連

由於上述的 ssh 反向連線十分不穩定,可能隨時斷開,一旦斷開就無法進行訪問了。所以我們需要 autossh,它可以實現自動重連。(安裝 autossh 可見底文的附加安裝指令

autossh -M 5678 -NR 1234:localhost:22 [email protected] -p8862

M 引數,指定了 autossh 的監聽埠,監聽是否斷開然後進行重連操作 autossh 本身就是後臺執行,所以就省去了 f 引數。

到這裡就很完美了,可是還不夠。要是 C 伺服器宕機重啟了怎麼辦,autossh 又不會自動執行。

實現開機自啟

這裡以 Ubuntu 18.04 為例。

ls /lib/systemd/system 執行該指令我們可以看到許多啟動指令碼,我們需要操作的就是 rc.local.service

開啟指令碼內容,我們在最後面加上一段:

[Install]  
WantedBy=multi-user.target  
Alias=rc-local.service

儲存退出。

由於 ubuntu-18.04 預設是沒有 /etc/rc.local 這個檔案的,需要自己建立。

sudo touch /etc/rc.local
chmod 755 /etc/rc.local

這裡千萬別忘記給 rc.local 檔案設定可執行許可權,不然沒用。

rc.local 中你就可以編寫指令碼了。注意開頭 #!/bin/bash 不可少

例如我的是:

#!/bin/bash
LOG_TIME=`date "+%Y-%m-%d %H:%M:%S"`
echo '123456' | sudo -S autossh -M 5678 -NR 1234:localhost:2223 [email protected] -p8862
echo "autossh restart:"$LOG_TIME >>/usr/local/autossh.log

這裡我是用 root 許可權執行,123456 是 C 伺服器的使用者密碼。 >> 表示追加,不覆蓋。同時列印了執行的時間。

最後一步,前面我們說 systemd 預設讀取 /etc/systemd/system 下的配置檔案, 所以還需要在 /etc/systemd/system 目錄下建立軟連結。

ln -s /lib/systemd/system/rc.local.service /etc/systemd/system/

可以了,重啟系統檢視指令碼是否執行,日誌中是否有內容。

參考博文

筆者參考瞭如下博文並進行了整理實驗:

附加安裝

  • 更新源列表

sudo apt-get update

  • 安裝 ssh

sudo apt-get install openssh-client 安裝客戶端 (反向隧道需要)

sudo apt-get install openssh-server 安裝服務端

  • 安裝 vim
sudo apt-get remove vim-common
sudo apt-get install vim

Ubuntu 18.04 中 vi 方向鍵有點問題,vim 很好用。

  • 安裝 autossh

sudo apt-get install autossh

  • 安裝 net-tools

當發現輸入 ifconfig 不可用時

sudo apt install net-tools 裝之