丈母娘想让我解决她们家Wifi信号弱的问题,我决定把家里原来唯一的无线路由器变成纯AP,弱电箱里放一个星际宝盒,另外在客厅放一台K2保证全家的Wifi覆盖。
本来路由器这种东西设置好了就不会再动了,可是我还需要解决他们家网络电视的问题,网络电视这种东西,直播源很容易失效,感觉以后会涉及到远程维护了。
我之前写过Ubuntu下用Autossh建立反向连接的博文,现在想照搬到OpenWrt上。但是OpenWrt上是用Dropbear作为SSH工具,与OpenSSH有些许不同,记录一下过程。

前期准备

  • 公网服务器A 开放端口5680(转发ssh连接),开放端口5681(监听连接状态),开放端口22,用OpenSSH做SSH服务器
  • 内网机器B OpenWrt with Dropbear,注意在“SSH访问”中开启“网关端口”。

修改公网服务器A的SSH配置文件/etc/ssh/sshd_config

1
2
3
4
5
6
GatewayPorts yes
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

这样可以把监听的端口绑定到任意IP 0.0.0.0上,否则只有本机127.0.0.1可以访问。
添加ssh-rsa算法兼容老板版本dropbear
记得重启SSH服务器

1
sudo service restart sshd

用内网B机器保存公网服务器A的密钥,以便免密连接

这里就跟OpenSSH不一样了,因为Dropbear没有ssh-id-copy这个命令,而Dropbear的private key又不是以明文方式存储的。

1
2
#You can get the key using
dropbearkey -y -f /etc/dropbear/dropbear_rsa_host_key | grep "^ssh-rsa " > /etc/dropbear/authorized_keys

然后将key从authorized_keys复制添加到到公网服务器的~/.ssh/authorized_keys中

在内网B机器上尝试建立反向代理

1
2
#注意Dropbear在建立SSH连接时不会自己带着私钥,需要指定
ssh -NR 5678:127.0.0.1:22 公网服务器A的用户名@公网服务器A的IP -i /etc/dropbear/dropbear_rsa_host_key

正常情况下,不用输入密码,通道即建立成功。 

  • -N:只建立连接,不打开shell 
  • -R:指定端口映射

AutoSSH 自动重连

使用SSH的方式不够稳定,使用AutoSSH可以自动在连接断开时自动重连,再把AutoSSH加入系统服务自动启动,则可以做到稳定的连接。

安装AutoSSH

1
opkg install autossh

将AutoSSH添加到开机自启

注意在OpenWrt里,官方的autossh早就给你准备好了 /etc/init.d/autossh 文件,你只需要在/etc/config/autossh中修改参数即可,下面贴出我的配置

1
2
3
4
5
6
7
8
config autossh
option localport '22'
option remoteport '5676'
option ssh '-N -i /etc/dropbear/dropbear_rsa_host_key 公网服务器A的用户名@公网服务器A的IP'
option gatetime '0'
option monitorport '5679'
option poll '60'
option enabled '1'

修复Dropbear的一个小bug

必须要指定HOME目录,详见Github
修改/etc/init.d/autossh,添加procd_set_param env HOME=/root,全文见下

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
75
76
77
78
79
80
81
#!/bin/sh /etc/rc.common
# Copyright (C) 2007-2011 OpenWrt.org

USE_PROCD=1
START=80

start_instance() {
local section="$1"
local forwarding

config_get_bool enabled "$section" enabled 1
[ "$enabled" != "1" ] && return 0

config_get ssh "$section" ssh
if [ -z "$ssh" ]; then
echo "autossh: ssh option is required"
return 1
fi

config_get localhost "$section" localhost localhost
config_get localport "$section" localport
config_get remotehost "$section" remotehost
config_get remoteport "$section" remoteport
config_get monitorport "$section" monitorport 20000
config_get poll "$section" poll 600
config_get gatetime "$section" gatetime 30
config_get first_poll "$section" first_poll
config_get loglevel "$section" loglevel
config_get logfile "$section" logfile
config_get maxlifetime "$section" maxlifetime
config_get maxstart "$section" maxstart
config_get message "$section" message
config_get_bool ntservice "$section" ntservice 0
config_get path "$section" path
config_get pidfile "$section" pidfile

if [ -n "$localport" ] && [ -n "$remoteport" ]; then
if [ -n "$remotehost" ]; then
forwarding="-L ${localport}:${remotehost}:${remoteport}"
else
forwarding="-R ${remoteport}:${localhost}:${localport}"
fi
elif [ -n "$localport" ] || [ -n "$remoteport" ]; then
echo "autossh: both localport and remoteport options are required"
return 1
fi

procd_open_instance "$section"
procd_set_param env HOME=/root
procd_set_param command /usr/sbin/autossh ${forwarding} ${ssh}
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
[ -n "$pidfile" ] && procd_set_param pidfile "$pidfile"

[ -n "$monitorport" ] && procd_append_param env "AUTOSSH_PORT=$monitorport"
[ -n "$poll" ] && procd_append_param env "AUTOSSH_POLL=$poll"
[ -n "$gatetime" ] && procd_append_param env "AUTOSSH_GATETIME=$gatetime"
[ -n "$first_poll" ] && procd_append_param env "AUTOSSH_FIRST_POLL=$first_poll"
[ -n "$loglevel" ] && procd_append_param env "AUTOSSH_LOGLEVEL=$loglevel"
[ -n "$logfile" ] && procd_append_param env "AUTOSSH_LOGFILE=$logfile"
[ -n "$maxlifetime" ] && procd_append_param env "AUTOSSH_MAXLIFETIME=$maxlifetime"
[ -n "$maxstart" ] && procd_append_param env "AUTOSSH_MAXSTART=$maxstart"
[ -n "$message" ] && procd_append_param env "AUTOSSH_MESSAGE=$message"
[ "$ntservice" == "1" ] && procd_append_param env "AUTOSSH_NTSERVICE=yes"
[ -n "$path" ] && procd_append_param env "AUTOSSH_PATH=$path"
[ -n "$pidfile" ] && procd_append_param env "AUTOSSH_PIDFILE=$pidfile"

procd_close_instance
}

start_service() {
local instance=$1

config_load 'autossh'

if [ -n "$instance" ]; then
start_instance "$1"
else
config_foreach start_instance 'autossh'
fi
}

然后开机启动Autossh
/etc/init.d/autossh enable