SSH反向连接

序言

有时候我们想在办公室访问家里的机器,或者反之在家里访问办公室的机器,一般有两种解决方案,一种是通过端口映射,另一种则是通过反向连接方式。
两者各有缺点:
端口映射:你需要权限管理上级网关或者路由器或者防火墙
反向连接:你需要有一台运行在互联网上的服务器(VPS)

AutoSSH介绍

autossh
autossh(1) - Linux man page
Autossh is a program to start a copy of ssh and monitor it, restarting it as necessary should it die or stop passing traffic.

AutoSSH安装

Debian / Ubuntu $ sudo apt-get install autossh
CentOS / Fedora / RHEL $ sudo yum install autossh
ArchLinux $ sudo pacman -S autossh
FreeBSD # pkg install autossh
OSX $ brew install autossh

或者从源码安装

1
2
3
4
5
6
wget http://www.harding.motd.ca/autossh/autossh-1.4e.tgz
gunzip -c autossh-1.4e.tgz | tar xvf -
cd autossh-1.4e
./configure
make
sudo make install

网络环境

公司主机A(192.168.1.10)->VPS服务器S(huzhifeng.com)->家里主机B(192.168.8.10)

家里主机B

家里主机B是一台Ubuntu 14.04的服务器

安装openssh-server/autossh

1
huzhifeng@ubuntu1404srv:~$ sudo apt-get install -y openssh-server autossh

自动登录

适用ssh key可以实现免密码登录

1
2
huzhifeng@ubuntu1404srv:~$ ssh-keygen
huzhifeng@ubuntu1404srv:~$ ssh-copy-id root@huzhifeng.com -p 22

启动autossh

1
huzhifeng@ubuntu1404srv:~$ autossh -M 5678 -NR 1234:localhost:22 root@huzhifeng.com -p22

-M 5678: 通过5678端口监视连接状态,连接有问题时就会自动重连
-N:不允许执行远程命令,只做端口转发 Do not execute a remote command. This is useful for just forwarding ports (protocol version 2 only).
-R 1234:localhost:22: 将B主机的22端口和VPS的1234端口绑定,相当于远程端口映射

登录VPS服务器检查反向连接端口是否已经启动

1
2
3
4
5
6
7
8
root@huzhifeng:~# ss -ant | grep 1234
LISTEN 0 0 *:1234 *:*
LISTEN 0 0 :::1234 :::*
root@huzhifeng:~#
root@huzhifeng:~# netstat -ant | grep 1234
tcp 0 0 0.0.0.0:1234 0.0.0.0:* LISTEN
tcp6 0 0 :::1234 :::* LISTEN
root@huzhifeng:~#

公司主机A

公司主机A是一台CentOS机器

1
[huzhifeng@Centos7 ~]$ ssh huzhifeng@huzhifeng.com -p 1234

注意:这里登录使用的帐号密码不是VPS服务器S的,而是家里主机B的帐号密码
可以先把公司主机A的“ ~/.ssh/id_rsa.pub”写入到家里主机B的“ ~/.ssh/authorized_keys”里,实现自动登录

高级技巧

开机启动

参考
Setup autossh script on Raspbian

1
huzhifeng@ubuntu1404srv:~$ /usr/bin/autossh -M 5678 -i /home/huzhifeng/.ssh/id_rsa -NfR 1234:localhost:22 root@huzhifeng.com -p22

我将使用root运行autossh

1
2
huzhifeng@ubuntu1404srv:~$ sudo ssh-keygen 
huzhifeng@ubuntu1404srv:~$ sudo ssh-copy-id root@huzhifeng.com

创建启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
huzhifeng@ubuntu1404srv:~$ sudo cp /etc/init.d/ssh /etc/init.d/autossh
huzhifeng@ubuntu1404srv:~$ ls -l /etc/init.d/autossh
-rwxr-xr-x 1 root root 783 Sep 4 10:57 /etc/init.d/autossh
huzhifeng@ubuntu1404srv:~$ sudo vim /etc/init.d/autossh
huzhifeng@ubuntu1404srv:~$ cat /etc/init.d/autossh
#! /bin/sh

### BEGIN INIT INFO
# Provides: autossh
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the autossh
# Description: starts the autossh
### END INIT INFO

case "$1" in
start)
echo "start autossh"
sudo /usr/bin/autossh -M 5678 -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -o "ServerAliveInterval 6" -o "ServerAliveCountMax 3" -i /home/huzhifeng/.ssh/id_rsa -NfR 1234:localhost:22 root@huzhifeng.com -p22
;;
stop)
echo "stop autossh"
sudo killall autossh
;;

restart)
echo "restart autossh"
sudo killall autossh
sudo /usr/bin/autossh -M 5678 -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -o "ServerAliveInterval 6" -o "ServerAliveCountMax 3" -i /home/huzhifeng/.ssh/id_rsa -NfR 1234:localhost:22 root@huzhifeng.com -p22
;;

*)
echo "Usage: $0 (start|stop|restart)"
exit 1
esac

exit 0
huzhifeng@ubuntu1404srv:~$
huzhifeng@ubuntu1404srv:~$ sudo chmod a+x /etc/init.d/autossh
huzhifeng@ubuntu1404srv:~$ sudo update-rc.d /etc/init.d/autossh defaults
update-rc.d: /etc/init.d//etc/init.d/autossh: file does not exist
huzhifeng@ubuntu1404srv:~$ sudo update-rc.d autossh defaults
Adding system startup for /etc/init.d/autossh ...
/etc/rc0.d/K20autossh -> ../init.d/autossh
/etc/rc1.d/K20autossh -> ../init.d/autossh
/etc/rc6.d/K20autossh -> ../init.d/autossh
/etc/rc2.d/S20autossh -> ../init.d/autossh
/etc/rc3.d/S20autossh -> ../init.d/autossh
/etc/rc4.d/S20autossh -> ../init.d/autossh
/etc/rc5.d/S20autossh -> ../init.d/autossh
huzhifeng@ubuntu1404srv:~$
huzhifeng@ubuntu1404srv:~$ sudo update-rc.d autossh enable
update-rc.d: warning: start runlevel arguments (none) do not match autossh Default-Start values (2 3 4 5)
update-rc.d: warning: stop runlevel arguments (none) do not match autossh Default-Stop values (0 1 6)
Enabling system startup links for /etc/init.d/autossh ...
Removing any system startup links for /etc/init.d/autossh ...
/etc/rc0.d/K20autossh
/etc/rc1.d/K20autossh
/etc/rc2.d/S20autossh
/etc/rc3.d/S20autossh
/etc/rc4.d/S20autossh
/etc/rc5.d/S20autossh
/etc/rc6.d/K20autossh
Adding system startup for /etc/init.d/autossh ...
/etc/rc0.d/K20autossh -> ../init.d/autossh
/etc/rc1.d/K20autossh -> ../init.d/autossh
/etc/rc6.d/K20autossh -> ../init.d/autossh
/etc/rc2.d/S20autossh -> ../init.d/autossh
/etc/rc3.d/S20autossh -> ../init.d/autossh
/etc/rc4.d/S20autossh -> ../init.d/autossh
/etc/rc5.d/S20autossh -> ../init.d/autossh
huzhifeng@ubuntu1404srv:~$

测试

1
2
3
4
5
6
7
8
9
10
huzhifeng@ubuntu1404srv:~$ sudo /etc/init.d/autossh start
start autossh
huzhifeng@ubuntu1404srv:~$ ps -axu | grep ssh
root 1071 0.0 0.0 61376 3044 ? Ss 10:41 0:00 /usr/sbin/sshd -D
root 1264 0.0 0.0 269040 8028 ? Ss 10:42 0:00 sshd: huzhifeng [priv]
huzhife+ 1314 0.0 0.0 269172 3128 ? S 10:42 0:00 sshd: huzhifeng@pts/0,pts/1
root 1945 0.0 0.0 4340 396 ? Ss 11:12 0:00 /usr/lib/autossh/autossh -M 5678 -o PubkeyAuthentication=yes -o PasswordAuthentication=no -i /home/huzhifeng/.ssh/id_rsa -NR 1234:localhost:22 root@huzhifeng.com -p22
root 1946 0.0 0.0 46204 3264 ? S 11:12 0:00 /usr/bin/ssh -L 5678:127.0.0.1:5678 -R 5678:127.0.0.1:5679 -o PubkeyAuthentication=yes -o PasswordAuthentication=no -i /home/huzhifeng/.ssh/id_rsa -NR 1234:localhost:22 -p22 root@huzhifeng.com
huzhife+ 2028 0.0 0.0 11744 936 pts/0 S+ 11:15 0:00 grep --color=auto ssh
huzhifeng@ubuntu1404srv:~$

若有错误,可以通过日志查看

1
huzhifeng@ubuntu1404srv:~$ tail -f /var/log/syslog

参考资料

SSH反向连接及Autossh
SSH TUNNELLING FOR FUN AND PROFIT: AUTOSSH
Persistent reverse (NAT bypassing) SSH tunnel access with autossh
Setup autossh script on Raspbian
反向ssh隧道访问局域网后面的主机
如何通过反向 SSH 隧道访问 NAT 后面的 Linux 服务器

EOF