Perhaps not something to have default in dropbear, put perhaps of interest
for someone...

In order to restrict  access from certain ip addresses only, you can, with
this patch, start a dropbear with option -S
This will only allow password logins if a corresponding file
/etc/dropbear/ip_<ipnumber>_any.allow exists.

It will also check for /etc/dropbear/ip_<ipnumber>_<username>.allow for
granting access to specific usernames only

If you start dropbear with -S -S  it will also use this restriction for
pubkey validation

Example:
# blocking password and pubkey from unknown locations, using a valid pubkey
root@core ~# ./dropbear -S -S  -F  -p 2022
[24472] Oct 04 12:30:21 Not backgrounding
[24473] Oct 04 12:30:40 Child connection from ::ffff:192.168.1.10:49799
[24473] Oct 04 12:30:40 Exit before auth (user 'root', 0 fails): Remote
address ::ffff:192.168.1.10:49799 is not allowed to connect with public key
or password

# blocking password from unknown locations, using a valid pubkey
root@core ~# ./dropbear -S   -F  -p 2022
[24486] Oct 04 12:30:55 Not backgrounding
[24487] Oct 04 12:31:10 Child connection from ::ffff:192.168.1.10:49801
[24487] Oct 04 12:31:11 Pubkey auth succeeded for 'root' with key md5
14:07:9a:1d:d9:64:45:db:88:d8:78:62:45:1e:88:21 from ::ffff:
192.168.1.10:49801

# blocking password from unknown locations, using a valid password
root@core ~# ./dropbear -S   -F  -p 2022
[24551] Oct 04 12:31:25 Not backgrounding
[24552] Oct 04 12:32:06 Child connection from ::ffff:192.168.1.10:49802
[24552] Oct 04 12:32:09 IP access denied : file
/etc/dropbear/ip_192.168.1.10_root.allow not found
[24552] Oct 04 12:32:09 IP access denied : file
/etc/dropbear/ip_192.168.1.10_any.allow not found
[24552] Oct 04 12:32:09 Exit before auth (user 'root', 0 fails): Remote
address ::ffff:192.168.1.10:49802 is not allowed to connect with password

# grant  connections for root from 192.168.1.10, using a valid publickey
root@core ~# touch /etc/dropbear/ip_192.168.1.10_root.allow
root@core ~# ./dropbear -S -S  -F  -p 2022
[24578] Oct 04 12:33:02 Not backgrounding
[24579] Oct 04 12:33:20 Child connection from ::ffff:192.168.1.10:49803
[24579] Oct 04 12:33:20 IP access allowed : file
/etc/dropbear/ip_192.168.1.10_root.allow found
[24579] Oct 04 12:33:20 Pubkey auth succeeded for 'root' with key md5
14:07:9a:1d:d9:64:45:db:88:d8:78:62:45:1e:88:21 from ::ffff:
192.168.1.10:49803


Have fun with it...

Hans
--- ../dropbear-2014.65/options.h       2014-09-11 02:37:28.000000000 -0600
+++ options.h   2014-10-04 01:28:55.000000000 -0600
@@ -20,6 +20,10 @@
 #endif
 
 /* Default hostkey paths - these can be specified on the command line */
+#ifndef CONFIG_DIRECTORY
+#define CONFIG_DIRECTORY "/etc/dropbear"
+#endif
+/* Default hostkey paths - these can be specified on the command line */
 #ifndef DSS_PRIV_FILENAME
 #define DSS_PRIV_FILENAME "/etc/dropbear/dropbear_dss_host_key"
 #endif
--- ../dropbear-2014.65/runopts.h       2014-08-08 07:40:47.000000000 -0600
+++ runopts.h   2014-10-04 01:25:22.000000000 -0600
@@ -87,6 +87,7 @@ typedef struct svr_runopts {
 
        int norootlogin;
 
+       int restrictlogins;
        int noauthpass;
        int norootpass;
        int allowblankpass;
--- ../dropbear-2014.65/svr-runopts.c   2014-08-08 07:40:47.000000000 -0600
+++ svr-runopts.c       2014-10-04 02:58:05.000000000 -0600
@@ -68,6 +68,7 @@ static void printhelp(const char * progn
                                        "-m             Don't display the motd 
on login\n"
 #endif
                                        "-w             Disallow root logins\n"
+                                       "-S             Enable logins from 
restricted addresses\n"
 #if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH)
                                        "-s             Disable password 
logins\n"
                                        "-g             Disable password logins 
for root\n"
@@ -127,6 +128,7 @@ void svr_getopts(int argc, char ** argv)
        svr_opts.forkbg = 1;
        svr_opts.norootlogin = 0;
        svr_opts.noauthpass = 0;
+       svr_opts.restrictlogins = 0;
        svr_opts.norootpass = 0;
        svr_opts.allowblankpass = 0;
        svr_opts.inetdmode = 0;
@@ -244,6 +246,9 @@ void svr_getopts(int argc, char ** argv)
                                case 'I':
                                        next = &idle_timeout_arg;
                                        break;
+                               case 'S':
+                                       svr_opts.restrictlogins++;
+                                       break;
 #if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH)
                                case 's':
                                        svr_opts.noauthpass = 1;
--- ../dropbear-2014.65/svr-auth.c      2014-08-08 07:40:47.000000000 -0600
+++ svr-auth.c  2014-10-04 05:35:21.000000000 -0600
@@ -79,6 +79,46 @@ static void authclear() {
        
 }
 
+/* check if a file  ip_<ipnumber>_<user>.allow or ip_<ipnumber>.allow is found
+ * which determines if access is allowed or not. */
+static int restrictlogin_valid(char *usernm, int log)
+{
+       char address[65], *ptr, fn[256];
+       
+       /* get remote ip:port address IPv4 or IPv6 */
+       if (strncmp(svr_ses.addrstring,"::ffff:",7)==0) {
+               strlcpy(address,&svr_ses.addrstring[7],sizeof(address));
+       } else {
+               strlcpy(address,svr_ses.addrstring,sizeof(address));
+       }
+       ptr=strrchr(address,':');
+       if (ptr!=0) {
+               /* remove the port part, leaving the ip only in the address */
+               *ptr='\0'; 
+               /* change all remaining : characters into . characters (IPv6) */
+               while ( (ptr=strchr(address,':')) !=0 ) {
+                       *ptr='.';
+               }
+               /* test if user from ip is allowed */
+               
snprintf(fn,sizeof(fn),"%s/ip_%s_%s.allow",CONFIG_DIRECTORY,address,usernm);
+               if (access(fn,F_OK)==0) {
+                       dropbear_log(LOG_INFO, "IP access allowed : file %s 
found",fn);
+                       return(1);
+               } else if (log) {
+                       dropbear_log(LOG_INFO, "IP access denied : file %s not 
found",fn);
+               }
+               /* test if any user from ip is allowed */
+               
snprintf(fn,sizeof(fn),"%s/ip_%s_any.allow",CONFIG_DIRECTORY,address);
+               if (access(fn,F_OK)==0) {
+                       dropbear_log(LOG_INFO, "IP access allowed : file %s 
found",fn);
+                       return(1);
+               } else if (log) {
+                       dropbear_log(LOG_INFO, "IP access denied : file %s not 
found",fn);
+               }
+       }
+       return(0);
+}
+
 /* Send a banner message if specified to the client. The client might
  * ignore this, but possibly serves as a legal "no trespassing" sign */
 void send_msg_userauth_banner(buffer *banner) {
@@ -148,6 +188,10 @@ void recv_msg_userauth_request() {
                        strncmp(methodname, AUTH_METHOD_NONE,
                                AUTH_METHOD_NONE_LEN) == 0) {
                TRACE(("recv_msg_userauth_request: 'none' request"))
+               if (svr_opts.allowblankpass && svr_opts.restrictlogins!=0 && 
restrictlogin_valid(username,1)==0) {
+                       dropbear_log(LOG_INFO, "IP access denied for blank 
password" );
+                       valid_user = 0;
+               }
                if (valid_user
                                && svr_opts.allowblankpass
                                && !svr_opts.noauthpass
@@ -176,6 +220,13 @@ void recv_msg_userauth_request() {
                if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
                                strncmp(methodname, AUTH_METHOD_PASSWORD,
                                        AUTH_METHOD_PASSWORD_LEN) == 0) {
+                       if (svr_opts.restrictlogins!=0 && 
restrictlogin_valid(username,1)==0 ) {
+                               /* do not allow retries */
+                               m_free(username);
+                               m_free(servicename);
+                               m_free(methodname);
+                               dropbear_exit("Remote address %s is not allowed 
to connect with password",svr_ses.addrstring);
+                       }
                        if (valid_user) {
                                svr_auth_password();
                                goto out;
@@ -191,6 +242,13 @@ void recv_msg_userauth_request() {
                if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
                                strncmp(methodname, AUTH_METHOD_PASSWORD,
                                        AUTH_METHOD_PASSWORD_LEN) == 0) {
+                       if (valid_user && svr_opts.restrictlogins!=0 && 
restrictlogin_valid(username,1)==0 ) {
+                               /* do not allow retries */
+                               m_free(username);
+                               m_free(servicename);
+                               m_free(methodname);
+                               dropbear_exit("Remote address %s is not allowed 
to connect with pam password",svr_ses.addrstring);
+                       }
                        if (valid_user) {
                                svr_auth_pam();
                                goto out;
@@ -204,6 +262,13 @@ void recv_msg_userauth_request() {
        if (methodlen == AUTH_METHOD_PUBKEY_LEN &&
                        strncmp(methodname, AUTH_METHOD_PUBKEY,
                                AUTH_METHOD_PUBKEY_LEN) == 0) {
+               if (svr_opts.restrictlogins==2 && 
restrictlogin_valid(username,0)==0) {
+                       /* if pubkey is not allowed , so is password not... so 
break off connection */
+                       m_free(username);
+                       m_free(servicename);
+                       m_free(methodname);
+                       dropbear_exit("Remote address %s is not allowed to 
connect with public key or password",svr_ses.addrstring);
+               }
                if (valid_user) {
                        svr_auth_pubkey();
                } else {

Reply via email to