SSH Tunnel
前言
工作上時不時會用到 ssh tunnel,但要用的時候又會忘記需要複習,寫一篇比較完整的筆記給自己參考
另外大部分的內容跟圖片是參考另一個 文章,只是嘗試用自己的話再寫一次
Outline
Intro
Tunneling 指的是將網路上的 A、B 兩個端點用某種方式連接起來,形成一個「隧道」,讓兩端的通訊能夠穿透某些限制(例如防火牆),或是能將通訊內容加密避免洩漏
SSH tunnel 用起來感覺很像把某個 port 映射到另一個 port 上面,所以 ssh tunneling 又叫做 ssh port fowarding
Local Forwarding 是將 Client 上的 Port 打開以供連線;Remote Forwarding 則是將 SSH Server 上的 Port 打開
Local Port Forwarding
1 | ssh -L [bind_address:]<port>:<host>:<host_port> <SSH Server> |
要特別注意 host 是 ==相對於 ssh server 的 hostname==
bind_address
沒有指定的話預設會 bind 在 localhost 上面,如果想把 port 9090 開放給所有人用可以把他改成 0.0.0.0
範例一
在 server 上有個服務開 8080 port,但防火牆上只有開 port 22 給你用
這時候就可以建立 ssh tunnel
tunnel 建立起來之後,連到自己電腦的 9090 port 就等於連到伺服器上的 8080 port
1 | ssh -L 9090:localhost:8080 johnliu@my-server |
在這個例子中,因為想要在本地端開這個 port,因此 bind_address
是 localhost,可以省略不寫
想要把本地的 9090 port 拿來用對應到 server 那個 port,所以 port
是 9090
對於那一台 my-server
來說,host 是他的本地端,所以 host
一樣是 localhost
,然後 hostport
是 8080
範例二
如果今天你想連到伺服器的 8080 port,而這個伺服器沒辦法透過本機連
但是有另一台機器可以連到他,而你可以 ssh 這台機器
1 | ssh -L 9090:192.168.1.101:8080 johnliu@my-server |
因為這個 8080 的 port 對於這台 ssh server 來說是 192.168.1.101,所以 host
是 192.168.1.101
Remote Port Forwarding
1 | ssh -R [bind_address:]<port>:<host>:<host_port> <SSH Server> |
在 SSH Server 上開啟 bind_address:port 等待連線,當有人連上時,將所有資料轉送到 host:host_port 去。 注意, ==host 是相對於 Client 的位址,也就是送出 ssh command 的電腦==,而不是 SSH Server !
雖然理論上是這樣,但實際上因為安全性考量,要調整
/etc/ssh/sshd_config
這檔案的一些設定才能把 port expose 給外部使用
範例一
比方說今天你的電腦有個服務開在 8080 要給客戶用,你有一個有 public ip 的機器可以 ssh 進去
1 | ssh -R 0.0.0.0:9090:localhost:8080 johnliu@external-server |
因為對外機器想要給所有人連,所以 bind adress
是 0.0.0.0
,對外的 port
是 9090
自己這邊要給外面連的 port 是 8080
,然後這時候 host
是相對於送出 ssh command 的這台電腦而言,所以是 localhost
這樣子,客戶只要連上對外機器的 Port 9090 就等於是連上了你電腦的 Port 8080。
範例二
如果今天這個服務不是開在自己電腦,但可以 access 的到,而想透過 public ip 開給自己家裡可以用的話
1 | ssh -R 0.0.0.0:9090:192.168.1.100:8080 johnliu@external-server |
這個 192.169.1.100 是相對於你的電腦這台主機的 host
Often used options
-N
不要執行任何遠端指令。沒有加這個參數時,建立 Port Forwarding 的同時也會開啟 Remote Shell,讓你可以對 SSH Server 下指令,而這個參數可以讓 Remote Shell 不要打開。
-f
讓 ssh 指令在背景執行,讓你可以繼續用 Shell 做事情。通常會搭上面的 -N 使用。
-C
把所有溝通內容做過壓縮處理
-p
指定 ssh server 的 port,只有在不是 22 的時候需要指定
Examples
透過 ad-gateway 連到背後的 db
1 | ssh -f ec2-user@ad-gateway -L 3308:<rds host>:3306 -N |
某台 ssh server 的 ssh port 開 3000,透過他連到背後 db,並且把通道的內容作壓縮傳送
1 | ssh -f -N -C -L $port:<dbhost>:3306 ec2-user@ad-gateway -p 3000 |
Note
使用結束記得把 ssh tunnel 關掉
1 | pkill -f $port |
References
超棒講解 ssh tunnel 的文章
如何抓所有正在聽的 port