mirror of
https://github.com/openwrt-xiaomi/xmir-patcher.git
synced 2026-09-22 22:57:55 +03:00
gateway: Add installer for dropbearmulti (for RD18 and etc)
This commit is contained in:
@@ -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
|
||||
+93
-31
@@ -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
|
||||
|
||||
|
||||
#===============================================================================
|
||||
|
||||
Reference in New Issue
Block a user