# 反向 SSH - SSH Tunneling
###### tags: `IVM` `ssh`
## 原理
- SSH 連線需要固定 IP,但在 NAT 環境不允許這麼做
- NAT:Network Address Translation
- 尤其是 4G 網路基本上都是假的 ipv4
- 連線圖
```sequence
Client->固定 IP Server: 1. 發起 SSH Tunnel 連線
Note right of 固定 IP Server: 2. 建立「指定port與Server SSH port的tunnel」
固定 IP Server->Client: 透過 2. 的 Tunnel 發起 SSH 連線
```
- Client 指令範例
```bash=
ssh -R 19999:localhost:22 -p{port_number} {username}@{host ip or url}
```
- 參數說明
- `-R`:反向連線
- `19999`:Server 待會反向連回 Client 時要使用的 Port
- `22`:Server 本地接收 SSH 連入連線所使用的 Port
- `-p{port_number} {username}@{host ip or url}`:Server 開放給外界 SSH 連線的參數
- 上面的例子特別的點在於,Server 是架在一台 router 後、並使用 Port forwarding 來假裝自己是固定 IP 的 Server,但是在 ssh tunneling 設定使用的參數,填的卻是`22`,這是因為`19999`跟`22`指的都是 Server 本地的 Port,但`{port_number}`是外部裝置真的要用 SSH 連進 Server 所使用的參數。
- ssh tunnel server 是使用 docker container 架設在 host 上,所以 client 執行 ssh 連線時的 host 跟 ssh tunnel 建立的時候設定的 host 不會一樣
- Server 指令範例
Client 建立好 ssh tunnel 之後,Server 就可以用它來反向連回 Client 了
```bash=
ssh -p19999 {client username}@localhost
```
- 上述功能已使用過 MAC 接 4G 網路(其餘網路介面皆關閉及斷線,RJ45 也沒接)測試,只要使用 ssh private key 便可實現無密碼登入。
## 步驟
- Server 建立一個專門給 Client 連線用的帳號,以確保安全性。
- Server 產生一組給 Client 共用的 ssh public/private key,將 private key 傳給 Client。
- Client 使用`autossh`搭配`crontab`在啟動時自動建立 ssh tunnel 給 Server 使用
- `autossh`是用來克服`ssh 連線 timeout`的程式
- Server 隨時可使用`ssh -p19999 {username}@localhost`指令連線到 Client
- ==限制:Server 若要連線不同的 Client 時,必須使用不同的 Port==
## 使用 ssh/autossh 範例
```bash=
# ssh 的 key 可以不用 absolute path
ssh -fN -o "PubkeyAuthentication=yes" -o "StrictHostKeyChecking=false" -o "PasswordAuthentication=no" -o "ServerAliveInterval=60" -o "ServerAliveCountMax=3" -R 19999:localhost:22 -i {key的相對路徑} -p{port} {username}@{ssh host]
# autossh 的 key 得用 absolute path 否則啟動不了
autossh -M 29999 -fN -o "PubkeyAuthentication=yes" -o "StrictHostKeyChecking=false" -o "PasswordAuthentication=no" -o "ServerAliveInterval=60" -o "ServerAliveCountMax=3" -R 19999:localhost:22 -i {key的絕對路徑} -p{port} {username}@{ssh host]
# autossh 加 log
AUTOSSH_DEBUG=1 AUTOSSH_LOGFILE=/home/{username}/autossh.log autossh -M 29999 -fN -o "PubkeyAuthentication=yes" -o "StrictHostKeyChecking=false" -o "PasswordAuthentication=no" -o "ServerAliveInterval=60" -o "ServerAliveCountMax=3" -R 19999:localhost:22 -i {key的絕對路徑} -p{port} {username}@{ssh host]
```
## 參數簡易說明
### SSH
1. -p:連線使用的 port,也就是連線對象所開啟的 port
2. -f:fork,開啟一個背景程序來連線。因為通常我們都是在 terminal 的 shell 下指令,若不使用 fork 開啟背景程序,這樣當 shell 被關掉時、ssh 連線也會斷線
3. -N:不執行指令。指的是不會開啟遠端 shell,因為我們要使用的是 tunnel 功能,所以自然不需要開啟一個 shell。
4. -o:option,後面會再帶選項及參數。
5. -R:反向 tunnel,若執行的是 -L 就是正向的 tunnel,各有不同用途
- 反向 tunnel 後所帶的參數為 ==server上要給tunnel用的port==:==server上要綁定的address==:==server上ssh連線使用的por==