2010/03/04

用 ssh tunnel 建立分身

網路上可找到很多用 ssh tunnel 突破防火牆的 文章。此概念其實很簡單:若你能用 ssh 從 host L 連到 host R,那你就可以「人在 host L,但分身在 host R」或「人在 host R,但分身在 host L」。

舉例來說,公司的內部網站只能從公司內網的電腦連接 (如 host L);家中的內部網站只能從家庭網路的電腦連接 (如 host R)。若 host L 能 ssh 連到 host R,你在公司時就可以透過 host L 派遣分身到 host R,由 host R 去連接家中的網路;反之亦然 。

若要由 host L 派遣分身到 host R,就要在 host L 執行以下指令。這樣,連到 host L 的 port 5678 就相當於從 host R 連結到 host X 的 port 1234:
ssh -Nf -L 5678:host-X:1234 user@host-R
若要由 host R 派遣分身到 host L,就要在 host L 執行以下指令。這樣,連到 host R 的 port 5678 就相當於從 host L 連結到 host X 的 port 1234:
ssh -Nf -R 5678:host-X:1234 user@host-R
在實際的環境中,連結通常是單向的。當你人在 host R 時,並不一定能夠登入 host L 去建立通道。因此,你必須先在公司 (host L) 建好 ssh tunnel,然後回家時才能透過 host R 派遣分身。

在實際的環境中,連結通常也是脆弱的。你辛辛苦苦在 host L 建立的 ssh tunnel 可能因為各種原因斷掉而無法使用。要解此問題,可以利用 autossh。autossh 能夠偵測通道是否中斷,並在中斷時自動重建立。安裝方法:
apt-get install autossh
此時建立 ssh tunnel 的指令變成:
autossh -f -M 20000 \
-o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" \
-N -R 5678:host-X:1234 user@host-R
其中 -M 20000 以及後續的 -o 是 autossh 偵測 tunnel 是否斷掉的參數。

因為安全的考量,"-R 5678:host-X:1234" 這種設定只允許從 host R 連接到 localhost 的 5678,這代表你無法從其他機器透過 host R 來派遣分身。以下方法,可以關閉此限制。
  1. 修改 host R 的 /etc/ssh/sshd_config,在其中新增一行 "GatewayPorts clientspecified"
  2. 在 host R 執行 "sudo /etc/init.d/ssh reload"
  3. 在 host L 將 "-R 5678:host-X:1234" 改成 "-R *:5678:host-X:1234" 然後重新執行前述 ssh 或 autossh 指令
PS: 若重新開機後也要保持這個 tunnel 不斷,可將 authssh 指令放在 /etc/rc.local。

沒有留言: