如何用反向通道連入沒有固定IP躲在防火牆內的主機
===
# TL;DR
`電腦A`是一台在防火牆後面內網的Linux主機(甚至連DHCP都會變),而防火牆則是沒有固定IP的。如果我們想要控制`電腦A`,就需要一台具有固定IP的Linux主機(我用的是GOOGLE雲端主機,`電腦B`),然後從電腦A建立一條反向通道到`電腦B`,以後要從任何地方(`電腦C`)連入`電腦A`,就透過`電腦B`,然後從這條反向通道連回`電腦A`。
# 電腦A的準備
* openssh-server (`sudo apt-get install openssh-server)`
* autossh (`sudo apt-get install autossh)`
* 要先把從電腦A連入電腦B的ssh public key放入電腦B(`ssh-copy-id -i <要放上電腦B的公鑰.pub> <電腦B IP>)`。
* 上面這個動作會在電腦B的`~/.ssh/autohorized_keys`中把公鑰直接寫入,因此就算兩台不同電腦的public key檔案都叫`id_rsa.pub`也沒關係,和檔名無關。
* 放完之後,確定ssh從電腦A連入電腦B不需要密碼直接能進入。
* 不要用ssh建立反向通道的指令`ssh -NfR 12345:localhost:22 joshhu@電腦B`
* 電腦A的`/etc/ssh/sshd_config`中的`GatewayPorts`要放`yes`,改完後重新啟動`sshd`服務。

* 利用`~/.ssh/config`的設定來建立反向通道
* `~/.ssh/config`的設定如下圖

```bash=
Host toComputerB
Hostname <你的公網ip位址>
port 22 #連入電腦B的22 port
user <你的使用者名稱>
IdentityFile /home/<使用者名稱>/.ssh/<你的key file>
RemoteForward 12346 localhost:22 #任何連入電腦B 12346的ssh都連入電腦A的22
# RemoteForward 12346 localhost:5900 # 這是挖vnc用的
ServerAliveInterval 30
ServerAliveCountMax 3
```
* 以後只要在電腦A上輸入`autossh -M 0 -TN toComputerB`就會建立連線至電腦B的反向通道了。
# 電腦B的準備
* 開啟port,如上圖中的`12346`。這個動作要在電腦A上輸入`autossh`之前就要做好。
```shell=
sudo ufw allow 12346
```
如果你的電腦B沒有開防火牆,可以先開好,但要記得放行`ssh`。
```shell=
sudo ufw allow ssh
sudo ufw enable
```
# 電腦C的準備
如果要從電腦C連至電腦A,只要在電腦C上輸入`ssh <電腦B的IP> -p 12346`即可。可以建立在`~/.ssh/config`中。
# 電腦A開機即啟動反向通道,用`systemd`的service完成
```bash
cd /etc/systemd/system
sudo vi create_reverse_tunnel.service
```
內容如下
```
[Unit]
Description=AutoSSH tunnel service to deepmind ssh
After=network-online.target ssh.service
[Service]
Restart=always
RestartSec=20
User=<使用者名稱>
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 0 -TN toComputerB
[Install]
WantedBy=multi-user.target
```
之後出來,輸入
```bash
cd /etc/systemd/system
sudo systemctl enable create_reverse_tunnel.service
sudo systemctl start create_reverse_tunnel.service
sudo systemctl status create_reverse_tunnel.service
```
###### tags: `ssh` `反向通道`