sshlockout - use a PF table instead of IPFW
authorMichael Neumann <mneumann@ntecs.de>
Tue, 13 Jan 2015 12:04:29 +0000 (13:04 +0100)
committerMichael Neumann <mneumann@ntecs.de>
Tue, 13 Jan 2015 12:04:29 +0000 (13:04 +0100)
usr.sbin/sshlockout/sshlockout.8
usr.sbin/sshlockout/sshlockout.c

index c785d53..0d33bef 100644 (file)
 .Nm sshlockout
 .Nd utility to block port 22 on preauth failures
 .Sh SYNOPSIS
-.Cd auth.info;authpriv.info            |exec /usr/sbin/sshlockout
-.Cd 3 3 * * *       ipfw delete 2100
+.Nm
+.Ar table
+.Cd auth.info;authpriv.info            |exec /usr/sbin/sshlockout "lockout"
+.Cd 3 3 * * *       pfctl -tlockout -Tflush
 .Sh DESCRIPTION
 This program is generally installed in
 .Pa /etc/syslog.conf
@@ -46,17 +48,22 @@ as a pipe to parse the
 .Xr sshd 8
 demons error log in realtime.
 In addition, a root crontab entry should generally be created to clean
-out
-.Xr ipfw 8
-rule 2100 at least once a day.
-The
-.Xr ipfw 8
+out the
+.Xr pf 4
+.Ar table
+at least once a day. The
+.Xr pf 4
 module must be loaded and operational as well.
 .Pp
 This program will monitor the ssh syslog output and keep track of attempts
 to login to unknown users as well as preauth failures.
-If 5 attempts fail in any one hour period, a permanent entry is added to
-rule 2100 in ipfw to block port 22 from the associated IP address.
+If 5 attempts fail in any one hour period, a permanent entry is added to the
+.Xr pf 4
+.Ar table
+for the associated IP address.
+You still have to add a rule to
+.Xr pf.conf 5
+to block IP addresses listed in this table.
 The cron entry you create cleans the block list out typically once a day.
 .Pp
 This program generally limits brute-force attempts to break into a machine
@@ -67,7 +74,7 @@ Currently this program only operates on IPV4 addresses.
 .Sh SEE ALSO
 .Xr ssh 1 ,
 .Xr sshd 8 ,
-.Xr ipfw 8 ,
+.Xr pf 4 ,
 .Xr syslog.conf 5
 .Sh HISTORY
 The
index 6da2eb0..ce41418 100644 (file)
  * Use: pipe syslog auth output to this program.
  *
  * Detects failed ssh login attempts and maps out the originating IP and
- * issues 'ipfw add' commands adding a lockout for rule 2100.
+ * issues adds to a PF table <lockout> using 'pfctl -tlockout -Tadd' commands.
  *
  * /etc/syslog.conf line example:
- *     auth.info;authpriv.info                 |exec /usr/sbin/sshlockout
+ *     auth.info;authpriv.info         |exec /usr/sbin/sshlockout lockout
  *
- * Also suggest a cron entry to clean out the ipfw list at least once a day.
- *     3 3 * * *       ipfw delete 2100
+ * Also suggest a cron entry to clean out the PF table at least once a day.
+ *     3 3 * * *       pfctl -tlockout -Tflush
  */
 
 #include <sys/types.h>
@@ -67,11 +67,14 @@ typedef struct iphist {
 #define MAXHIST                100
 #define SSHLIMIT       5               /* per hour */
 
-iphist_t *hist_base;
-iphist_t **hist_tail = &hist_base;
-iphist_t *hist_hash[HSIZE];
-int hist_count;
+static iphist_t *hist_base;
+static iphist_t **hist_tail = &hist_base;
+static iphist_t *hist_hash[HSIZE];
+static int hist_count = 0;
 
+static char *pftable = NULL;
+
+static void init_iphist(void);
 static void checkline(char *buf);
 static int insert_iph(const char *ips);
 static void delete_iph(iphist_t *ip);
@@ -92,10 +95,20 @@ iphash(const char *str)
 }
 
 int
-main(int ac __unused, char **av __unused)
+main(int ac, char **av)
 {
        char buf[1024];
 
+       init_iphist();
+
+       if (ac == 2 && av[1] != NULL) {
+               pftable = av[1];
+       }
+       else {
+               syslog(LOG_ERR, "sshlockout: invalid argument");
+               return(1);
+       }
+
        openlog("sshlockout", LOG_PID|LOG_CONS, LOG_AUTH);
        syslog(LOG_ERR, "sshlockout starting up");
        freopen("/dev/null", "w", stdout);
@@ -135,12 +148,11 @@ checkline(char *buf)
                        if (insert_iph(ips)) {
                                syslog(LOG_ERR,
                                       "Detected ssh password login attempt "
-                                      "for root, locking out %s\n",
+                                      "for root or admin, locking out %s\n",
                                       ips);
                                snprintf(buf, sizeof(buf),
-                                        "ipfw add 2100 deny tcp from "
-                                        "%s to me 22",
-                                        ips);
+                                        "pfctl -t%s -Tadd %s",
+                                        pftable, ips);
                                system(buf);
                        }
                }
@@ -167,9 +179,8 @@ checkline(char *buf)
                                       "for an invalid user, locking out %s\n",
                                       ips);
                                snprintf(buf, sizeof(buf),
-                                        "ipfw add 2100 deny tcp from "
-                                        "%s to me 22",
-                                        ips);
+                                        "pfctl -t%s -Tadd %s",
+                                        pftable, ips);
                                system(buf);
                        }
                }
@@ -191,9 +202,8 @@ checkline(char *buf)
                                       "for an invalid user, locking out %s\n",
                                       ips);
                                snprintf(buf, sizeof(buf),
-                                        "ipfw add 2100 deny tcp from "
-                                        "%s to me 22",
-                                        ips);
+                                        "pfctl -t%s -Tadd %s",
+                                        pftable, ips);
                                system(buf);
                        }
                }
@@ -277,3 +287,14 @@ delete_iph(iphist_t *ip)
        --hist_count;
        free(ip);
 }
+
+static
+void
+init_iphist(void) {
+       hist_base = NULL;
+       hist_tail = &hist_base;
+       for (int i = 0; i < HSIZE; i++) {
+               hist_hash[i] = NULL;
+       }
+       hist_count = 0;
+}