家裡或公司的防火牆裡面有一部 24 小時開機的電腦 H, 沒有對外的 IP 位址。
另外有一部具有公開位址的伺服器 PubS。
這時可以從 H 向 PubS 啟動一個 反向 ssh 隧道連線, 像這樣:
ssh -4fNR '4380:localhost:22' ckhung@PubS
這裡的 4380 是任選的 port。
接下來就可以隨時隨地 (從網路其他任何地方) 先登入 PubS,
再從 PubS 登入 H: ssh -p 4380 localhost
。
可是, 只要家裡跳電或分享器關機一陣子, 連線就斷掉, 哭哭了。
這時你需要 autossh, 它可以定時檢查連線是否暢通,
有必要時就會自動重新啟動連線。
先在 PubS 上面作一些準備。 這部分都採用 root 的身份做事。
我喜歡建立一個拉管線專用、 最低權限的機器人帳號:
useradd sshbot -m -s /bin/rbash
詳見 The Restricted Shell。
又, 確認它無法用密碼登入: grep sshbot /etc/shadow
(密碼欄是一個 "!" )
再來, 以 root 的身份幫 sshbot 建立一些檔案與目錄:
cd /home/sshbot echo 'export PATH=$HOME/bin' > .bashrc mkdir .ssh bin ln -s /usr/bin/ls bin/ # 非必要。 只是示範如何授權指令給 sshbot touch .ssh/authorized_keys chown -R sshbot:sshbot .ssh chmod -R 700 .ssh
原本的 .bashrc 被蓋掉沒關係, 反正我們這個帳號沒有要執行指令, 只是用來拉管線而已。 很多檔案與目錄的擁有人都保持是 root 沒關係, 反正本來就不希望 sshbot 有什麼修改權限。
然後回到 H。 以下動作如果沒有特別說明, 都是在 H 上執行。
- 要讓 autossh 可以自動重建連線, 前提是它必須可以無密碼登入 PubS。 請先 (用誰的帳號都可以, 我是在常用的 ckhung 帳號底下執行 ssh-keygen) 建立一個 「只有公鑰、私鑰, 沒有密碼」 的 ssh 身份, 例如產生了 $HOME/.ssh/id_bot.pub 跟 $HOME/.ssh/id_bot 這一對公鑰私鑰。
- 把 $HOME/.ssh/id_bot.pub 的內容剪貼到 sshbot@PubS 的 $HOME/.ssh/authorized_keys 裡面, 讓它信任這把公鑰的持有者。
- 安裝套件:
apt install autossh
。
先手動測試:
ps x | grep ssh autossh -f -o "ServerAliveInterval 20" -o "ServerAliveCountMax 3" -NR 4380:localhost:22 -i $HOME/.ssh/id_bot sshbot@PubS ps x | grep ssh
啟動後, 會多出兩個 processes, 長得像這樣:
21156 ? Ss 0:00 /usr/lib/autossh/autossh -o ServerAliveInterval 20 -o ServerAliveCountMax 3 -NR 4380:localhost:22 -i /home/ckhung/.ssh/id_bot sshbot@PubS 21257 ? S 0:00 /usr/bin/ssh -L 57605:127.0.0.1:57605 -R 57605:127.0.0.1:57606 -o ServerAliveInterval 20 -o ServerAliveCountMax 3 -NR 4380:localhost:22 -i /home/ckhung/.ssh/id_bot sshbot@PubS
那個 autossh 是主要的程序; 而很帶有長一串 (抄自 autossh 命令列)
參數的那個 ssh 反向隧道則是由 autossh 啟動的。
此時即可在 PubS 上面用 ssh -p 4380 ckhung@localhost
測試連線。 注意: 用戶名稱 "ckhung" 是 H 機器上的 ckhung,
不是 PubS 上的 sshbot。
要測試自動重新連線, 不可以把上述兩個程序砍掉。 即使只是砍 ssh, autossh 也會跟著死掉。 請把網路線拔掉。 每隔 20 秒 (ServerAliveInterval) autossh 會試著測試連向 PubS 的 ssh 反向隧道是否還正常運作。 失敗 3 次 (ServerAliveCountMax) 之後, autossh 會試著重新啟動一個新的 ssh 反向隧道, 此時那個 ssh 程序的 pid 會改變。 再把網路線接回去。 應該又可以從 PubS 連回 H 了。
測試成功之後, 在 H 建一個文字檔 /etc/systemd/system/autossh-tunnel.service 裡面填入以下:
[Unit] Description=AutoSSH tunnel service After=network.target [Service] Environment="AUTOSSH_GATETIME=0" ExecStart=/usr/bin/autossh -o "ServerAliveInterval 60" -o "ServerAliveCountMax 5" -NR 4380:localhost:22 -i /home/ckhung/.ssh/id_cronbots sshbot@PubS [Install] WantedBy=multi-user.target # 從某處抄來的; 忘記寫下網址 (^_^;)
這裡我改成 「每 60 秒測一次連線、 連續五次失敗, 就重啟 ssh」,
還有 $HOME 也改成完整的路徑。
實際上我的 PubS 跟 H 的 ssh 服務都不是開在預設的 port 22,
所以還要再加上 -p 參數等等。
最後: systemctl enable autossh-tunnel
設定它一開機就自動啟動。
然後就可以重開機 H 測試看看。
以前我不知道有 autossh 這個東西, 還自己寫亂七八糟的 cron, 太辛苦啦~ (中文世界好像多半是簡中的文章。) 趕快幫忙向命令列控們推廣一下吧!
沒有留言:
張貼留言
因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。