Without timeout mechanism, if ssh client disconnected without sending FIN or RST, forked dropbear servers would hang there for KEX_RETRY_TIMEOUT seconds (8 hours). TCP keepalive is not implemented in dropbear yet, thus the name SSHKeepAlive. 300 seconds in this patch is selected from the default value of ServerAliveInterval for Debian ssh client (See man ssh_config). Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com> SVN-Revision: 40299
177 lines
4 KiB
Bash
Executable file
177 lines
4 KiB
Bash
Executable file
#!/bin/sh /etc/rc.common
|
|
# Copyright (C) 2006-2010 OpenWrt.org
|
|
# Copyright (C) 2006 Carlos Sobrinho
|
|
|
|
START=50
|
|
STOP=50
|
|
|
|
USE_PROCD=1
|
|
PROG=/usr/sbin/dropbear
|
|
NAME=dropbear
|
|
PIDCOUNT=0
|
|
EXTRA_COMMANDS="killclients"
|
|
EXTRA_HELP=" killclients Kill ${NAME} processes except servers and yourself"
|
|
|
|
append_ports()
|
|
{
|
|
local ifname="$1"
|
|
local port="$2"
|
|
|
|
grep -qs "^ *$ifname:" /proc/net/dev || {
|
|
procd_append_param command -p "$port"
|
|
return
|
|
}
|
|
|
|
for addr in $(
|
|
ifconfig "$ifname" | sed -ne '
|
|
/addr: *fe[89ab][0-9a-f]:/d
|
|
s/.* addr: *\([0-9a-f:\.]*\).*/\1/p
|
|
'
|
|
); do
|
|
procd_append_param command -p "$addr:$port"
|
|
done
|
|
}
|
|
|
|
validate_section_dropbear()
|
|
{
|
|
uci_validate_section dropbear dropbear "${1}" \
|
|
'PasswordAuth:bool:1' \
|
|
'enable:bool:1' \
|
|
'Interface:string' \
|
|
'GatewayPorts:bool:0' \
|
|
'RootPasswordAuth:bool:1' \
|
|
'RootLogin:bool:1' \
|
|
'rsakeyfile:file' \
|
|
'dsskeyfile:file' \
|
|
'BannerFile:file' \
|
|
'Port:list(port):22' \
|
|
'SSHKeepAlive:uinteger:300' \
|
|
'IdleTimeout:uinteger:0'
|
|
return $?
|
|
}
|
|
|
|
dropbear_instance()
|
|
{
|
|
local PasswordAuth enable Interface GatewayPorts \
|
|
RootPasswordAuth RootLogin rsakeyfile \
|
|
dsskeyfile BannerFile Port
|
|
|
|
validate_section_dropbear "${1}" || {
|
|
echo "validation failed"
|
|
return 1
|
|
}
|
|
|
|
[ "${enable}" = "0" ] && return 1
|
|
PIDCOUNT="$(( ${PIDCOUNT} + 1))"
|
|
local pid_file="/var/run/${NAME}.${PIDCOUNT}.pid"
|
|
|
|
procd_open_instance
|
|
procd_set_param command "$PROG" -F -P "$pid_file"
|
|
[ "${PasswordAuth}" -eq 0 ] && procd_append_param command -s
|
|
[ "${GatewayPorts}" -eq 1 ] && procd_append_param command -a
|
|
[ "${RootPasswordAuth}" -eq 0 ] && procd_append_param command -g
|
|
[ "${RootLogin}" -eq 0 ] && procd_append_param command -w
|
|
[ -n "${rsakeyfile}" ] && procd_append_param command -r "${rsakeyfile}"
|
|
[ -n "${dsskeyfile}" ] && procd_append_param command -d "${dsskeyfile}"
|
|
[ -n "${BannerFile}" ] && procd_append_param command -b "${BannerFile}"
|
|
[ -n "${Interface}" ] && network_get_device Interface "${Interface}"
|
|
append_ports "${Interface}" "${Port}"
|
|
[ "${IdleTimeout}" -ne 0 ] && procd_append_param command -I "${IdleTimeout}"
|
|
[ "${SSHKeepAlive}" -ne 0 ] && procd_append_param command -K "${SSHKeepAlive}"
|
|
procd_close_instance
|
|
}
|
|
|
|
keygen()
|
|
{
|
|
for keytype in rsa dss; do
|
|
# check for keys
|
|
key=dropbear/dropbear_${keytype}_host_key
|
|
[ -f /tmp/$key -o -s /etc/$key ] || {
|
|
# generate missing keys
|
|
mkdir -p /tmp/dropbear
|
|
[ -x /usr/bin/dropbearkey ] && {
|
|
/usr/bin/dropbearkey -t $keytype -f /tmp/$key 2>&- >&- && exec /etc/rc.common "$initscript" start
|
|
} &
|
|
exit 0
|
|
}
|
|
done
|
|
|
|
lock /tmp/.switch2jffs
|
|
mkdir -p /etc/dropbear
|
|
mv /tmp/dropbear/dropbear_* /etc/dropbear/
|
|
lock -u /tmp/.switch2jffs
|
|
chown root /etc/dropbear
|
|
chmod 0700 /etc/dropbear
|
|
}
|
|
|
|
start_service()
|
|
{
|
|
[ -s /etc/dropbear/dropbear_rsa_host_key -a \
|
|
-s /etc/dropbear/dropbear_dss_host_key ] || keygen
|
|
|
|
. /lib/functions.sh
|
|
. /lib/functions/network.sh
|
|
|
|
config_load "${NAME}"
|
|
config_foreach dropbear_instance dropbear
|
|
}
|
|
|
|
service_triggers()
|
|
{
|
|
procd_add_reload_trigger "dropbear"
|
|
procd_add_validation validate_section_dropbear
|
|
}
|
|
|
|
killclients()
|
|
{
|
|
local ignore=''
|
|
local server
|
|
local pid
|
|
|
|
# if this script is run from inside a client session, then ignore that session
|
|
pid="$$"
|
|
while [ "${pid}" -ne 0 ]
|
|
do
|
|
# get parent process id
|
|
pid=`cut -d ' ' -f 4 "/proc/${pid}/stat"`
|
|
[ "${pid}" -eq 0 ] && break
|
|
|
|
# check if client connection
|
|
grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" && {
|
|
append ignore "${pid}"
|
|
break
|
|
}
|
|
done
|
|
|
|
# get all server pids that should be ignored
|
|
for server in `cat /var/run/${NAME}.*.pid`
|
|
do
|
|
append ignore "${server}"
|
|
done
|
|
|
|
# get all running pids and kill client connections
|
|
local skip
|
|
for pid in `pidof "${NAME}"`
|
|
do
|
|
# check if correct program, otherwise process next pid
|
|
grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" || {
|
|
continue
|
|
}
|
|
|
|
# check if pid should be ignored (servers, ourself)
|
|
skip=0
|
|
for server in ${ignore}
|
|
do
|
|
if [ "${pid}" == "${server}" ]
|
|
then
|
|
skip=1
|
|
break
|
|
fi
|
|
done
|
|
[ "${skip}" -ne 0 ] && continue
|
|
|
|
# kill process
|
|
echo "${initscript}: Killing ${pid}..."
|
|
kill -KILL ${pid}
|
|
done
|
|
}
|