gateway: Add installer for dropbearmulti (for RD18 and etc)

pull/36/head
remittor 7 months ago
parent d6b7d8000a
commit fa9d0d5d8b

@ -0,0 +1,225 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2010 OpenWrt.org
# Copyright (C) 2006 Carlos Sobrinho
START=19
STOP=50
USE_PROCD=1
XDIR=/etc/crontabs/dropbearmulti
PROG=$XDIR/dropbear
NAME=dropbear
PIDCOUNT=0
EXTRA_COMMANDS="killclients"
EXTRA_HELP=" killclients Kill ${NAME} processes except servers and yourself"
append_ports()
{
local ipaddrs="$1"
local port="$2"
[ -z "$ipaddrs" ] && {
procd_append_param command -p "$port"
return
}
for addr in $ipaddrs; 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' \
'BannerFile:file' \
'Port:list(port):22' \
'SSHKeepAlive:uinteger:300' \
'IdleTimeout:uinteger:0' \
'MaxAuthTries:uinteger:3' \
'RecvWindowSize:uinteger:0' \
'mdns:bool:1'
}
dropbear_instance()
{
local PasswordAuth enable Interface GatewayPorts \
RootPasswordAuth RootLogin rsakeyfile \
BannerFile Port SSHKeepAlive IdleTimeout \
MaxAuthTries RecvWindowSize mdns ipaddrs
validate_section_dropbear "${1}" || {
echo "validation failed"
return 1
}
[ -n "${Interface}" ] && {
[ -n "${BOOT}" ] && return 0
network_get_ipaddrs_all ipaddrs "${Interface}" || {
echo "interface ${Interface} has no physdev or physdev has no suitable ip"
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 "${BannerFile}" ] && procd_append_param command -b "${BannerFile}"
append_ports "${ipaddrs}" "${Port}"
[ "${IdleTimeout}" -ne 0 ] && procd_append_param command -I "${IdleTimeout}"
[ "${SSHKeepAlive}" -ne 0 ] && procd_append_param command -K "${SSHKeepAlive}"
[ "${MaxAuthTries}" -ne 0 ] && procd_append_param command -T "${MaxAuthTries}"
[ "${RecvWindowSize}" -gt 0 -a "${RecvWindowSize}" -le 1048576 ] && \
procd_append_param command -W "${RecvWindowSize}"
[ "${mdns}" -ne 0 ] && procd_add_mdns "ssh" "tcp" "$Port" "daemon=dropbear"
procd_set_param respawn
procd_close_instance
}
keygen()
{
for keytype in rsa; 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 $PROG ] && {
$PROG 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
}
load_interfaces()
{
config_get interface "$1" Interface
config_get enable "$1" enable 1
[ "${enable}" = "1" ] && interfaces=" ${interface} ${interfaces}"
}
boot()
{
BOOT=1
start "$@"
}
start_service()
{
#[ -s /etc/dropbear/dropbear_rsa_host_key ] || keygen
rm -f /etc/dropbear/dropbear_rsa_host_key
if [ ! -e /etc/dropbear/dropbear_ed25519_host_key ]; then
$XDIR/dropbear dropbearkey -t ed25519 -f /etc/dropbear/dropbear_ed25519_host_key 0<&- 2>&- >&-
fi
if [ ! -e /etc/dropbear/dropbear_ecdsa_host_key ]; then
$XDIR/dropbear dropbearkey -t ecdsa -f /etc/dropbear/dropbear_ecdsa_host_key 0<&- 2>&- >&-
fi
. /lib/functions.sh
. /lib/functions/network.sh
config_load "${NAME}"
config_foreach dropbear_instance dropbear
}
service_triggers()
{
local interfaces
procd_add_config_trigger "config.change" "dropbear" /etc/init.d/dropbear reload
config_load "${NAME}"
config_foreach load_interfaces dropbear
[ -n "${interfaces}" ] && {
for n in $interfaces ; do
procd_add_interface_trigger "interface.*" $n /etc/init.d/dropbear reload
done
}
procd_add_validation validate_section_dropbear
}
shutdown() {
# close all open connections
killall 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
}

@ -0,0 +1,31 @@
#!/bin/sh
XDIR=/etc/crontabs/dropbearmulti
if [ ! -d /etc/dropbear ]; then
mkdir -p /etc/dropbear
chown root /etc/dropbear
chmod 0700 /etc/dropbear
fi
kill -9 `pgrep dropbear` &>/dev/null
rm -f /etc/dropbear/dropbear_rsa_host_key
rm -f /etc/init.d/dropbear
rm -f /usr/sbin/dropbear
if [ ! -f /etc/config/dropbear ]; then
cp -f $XDIR/uci.cfg /etc/config/dropbear
fi
cp -f $XDIR/init.d.sh /etc/init.d/dropbear
chmod +x /etc/init.d/dropbear
#rm -f /etc/rc.d/K??dropbear
#ln -s /etc/init.d/dropbear /etc/rc.d/K50dropbear &>/dev/null
#rm -f /etc/rc.d/S??dropbear
#ln -s /etc/init.d/dropbear /etc/rc.d/S19dropbear &>/dev/null
kill -9 `pgrep dropbear` &>/dev/null
/etc/init.d/dropbear enable
/etc/init.d/dropbear start

@ -1170,6 +1170,7 @@ class Gateway():
return hasher.hexdigest()
def post_connect(self, exec_cmd, contimeout = 20, passw = 'root'):
telnet_en = False
self.use_ssh = True
if passw is not None:
self.passw = passw
@ -1181,7 +1182,6 @@ class Gateway():
if not ssh_en:
print("")
print('Unlock TelNet server ...')
exec_cmd("bdata set telnet_en=1 ; bdata commit")
print('Run TelNet server on port 23 ...')
exec_cmd("/etc/init.d/telnet enable ; /etc/init.d/telnet restart")
@ -1189,43 +1189,105 @@ class Gateway():
self.use_ssh = False
telnet_en = self.ping(verbose = 2)
if not telnet_en:
# FIXME
print(f"ERROR: TelNet server not responding (IP: {self.ip_addr})")
return -2
print("")
print('#### TelNet server are activated! ####')
#print("")
#print('Run FTP server on port 21 ...')
cmd = r'''#!/bin/sh /etc/rc.common
SERVICE_DAEMONIZE=1
SERVICE_WRITE_PID=1
start() {
service_start /usr/sbin/inetd -f
}
stop() {
service_stop /usr/sbin/inetd
}
'''
cmd = cmd.replace('\r\n', ';')
cmd = cmd.replace('\n', ';')
cfg = r'ftp\tstream\ttcp\tnowait\troot\t/usr/sbin/ftpd\tftpd -w\t/'
self.run_cmd(r"echo -e '" + cfg + "' > /etc/inetd.conf")
self.run_cmd(r"echo '" + cmd + "' | tr ';' '\n' > /etc/init.d/inetd")
self.run_cmd(r"chmod +x /etc/init.d/inetd")
self.run_cmd(r'/etc/init.d/inetd enable')
self.run_cmd(r'/etc/init.d/inetd restart')
ftp_en = self.check_ftp(timeout = 5)
if ftp_en <= -10:
print(f'WARNING: FTP server is running, but upload mode is blocked!')
elif ftp_en != 0:
print(f"WARNING: FTP server not responding (IP: {self.ip_addr})")
else:
self.use_ftp = True
print('#### FTP server are activated! ####')
if ssh_en or telnet_en:
self.run_cmd('nvram set uart_en=1; nvram set boot_wait=on; nvram commit')
self.run_cmd('nvram set bootdelay=3; nvram set bootmenu_delay=5; nvram commit')
return 0
if ssh_en:
return True
if telnet_en:
arch = self.run_cmd("cat /etc/openwrt_release | grep DISTRIB_ARCH=")
if not arch:
die('TELNET: Cannot read remote file /etc/openwrt_release')
pos = arch.find("DISTRIB_ARCH='")
if pos < 0:
die('TELNET: Cannot detect arch for remote device')
arch = arch[pos+1:].split("'")[1]
print(f'ARCH = {arch}')
arch_suffix = None
if arch.startswith('arm_'):
arch_suffix = '_armv7a'
if arch.startswith('aarch64'):
arch_suffix = '_arm64'
if arch.startswith('mips'):
arch_suffix = '_mips'
if not arch_suffix:
die(f'TELNET: Unknown arch = "{arch}"')
self.run_cmd(r'echo -e "root\nroot" | passwd root')
self.run_cmd(r'kill -9 `pgrep dropbearmulti` &>/dev/null')
fn_local = f'data/payload_ssh/dropbearmulti{arch_suffix}'
fn_remote = '/tmp/dropbearmulti'
md5_local = self.get_md5_for_local_file(fn_local)
if not(md5_local) or isinstance(md5_local, int) or len(md5_local) != 32:
die(f'File "{fn_local}" not found')
md5 = self.get_md5_for_remote_file(fn_remote)
if md5 != md5_local:
if not self.upload(fn_local, fn_remote):
die(f'TELNET: Cannot upload file "{fn_local}" to device')
self.run_cmd('chmod +x /tmp/dropbearmulti')
self.run_cmd('[ -d /etc/dropbear ] || { mkdir -p /etc/dropbear ; chown root /etc/dropbear ; chmod 0755 /etc/dropbear; }')
if False:
# generate host keys
fn = '/etc/dropbear/dropbear_ed25519_host_key'
fsize = self.get_remote_file_size(fn)
if not fsize or fsize <= 0:
self.run_cmd(f'rm -f {fn} ; /tmp/dropbearmulti dropbearkey -t ed25519 -f {fn} 2>&- >&-', timeout = 11)
fn = '/etc/dropbear/dropbear_ecdsa_host_key'
fsize = self.get_remote_file_size(fn)
if not fsize or fsize <= 0:
self.run_cmd(f'rm -f {fn} ; /tmp/dropbearmulti dropbearkey -t ecdsa -f {fn} 2>&- >&-', timeout = 11)
# run dropbearmulti
self.run_cmd('/tmp/dropbearmulti -p 122')
pass
print(f'Install XMiR-SSH ...')
xdir = '/etc/crontabs/dropbearmulti'
fn_bin = '/usr/sbin/dropbear'
fn_BIN = f'{xdir}/dropbear'
fn_conf = '/etc/config/dropbear'
fn_CONF = f'{xdir}/uci.cfg'
fn_initd = '/etc/init.d/dropbear'
fn_INITD = f'{xdir}/init.d.sh'
fn_INSTALL = f'{xdir}/install.sh'
fsize_bin = self.get_remote_file_size(fn_bin)
fsize_initd = self.get_remote_file_size(fn_initd)
if fsize_bin and fsize_initd and fsize_bin > 0 and fsize_initd > 0:
die('SSH: dropbear is found, but it cannot run!')
# install XMiR dropbear
self.run_cmd(f'kill -9 `pgrep dropbear` &>/dev/null')
#self.run_cmd(f'rm -f {fn_bin} &>/dev/null')
self.run_cmd(f'rm -f {fn_conf} &>/dev/null')
self.run_cmd(f'mkdir -p {xdir}')
self.run_cmd(f'cp -f /tmp/dropbearmulti {fn_BIN}')
self.run_cmd(f'chmod +x {fn_BIN}')
if not self.upload('data/payload_ssh/dropbear.uci.cfg', fn_CONF):
die(f'TELNET: Cannot upload file "{fn_CONF}" to device')
if not self.upload('data/payload_ssh/dropbear2.init.d.sh', fn_INITD):
die(f'TELNET: Cannot upload file "{fn_INITD}" to device')
if not self.upload('data/payload_ssh/dropbear2.install.sh', fn_INSTALL):
die(f'TELNET: Cannot upload file "{fn_INSTALL}" to device')
uci = [ "uci set firewall.dropbearmulti=include",
"uci set firewall.dropbearmulti.type='script'",
f"uci set firewall.dropbearmulti.path='{fn_INSTALL}'",
"uci set firewall.dropbearmulti.enabled='1'",
"uci commit firewall",
]
self.run_cmd(';'.join(uci))
self.run_cmd(f'chmod +x {fn_INITD} ; chmod +x {fn_INSTALL}')
print(f'Run XMiR-SSH ...')
self.run_cmd(f'{fn_INSTALL}', timeout = 20)
self.use_ssh = True
ssh_en = self.ping(verbose = 0, contimeout = 8)
if ssh_en:
print('#### XMiR-SSH server are activated! ####')
return True
print(f"ERROR: installed XMiR-SSH server not responding (IP: {self.ip_addr})")
return False
#===============================================================================

Loading…
Cancel
Save