* FIXME: ipset create bouncer6 hash:ip family inet6
* FIXME: sshd_config: UseDNS no
* FIXME: PAM module names should be made configurable
- * FIXME: Parse "N more failures" messages
*/
#undef LOCAL_DEBUG
timer_add(&cleanup_timer, next_cleanup);
}
-static void handle_failed_login(struct addr addr)
+static void handle_failed_login(struct addr addr, int cnt)
{
int is_new;
timestamp_t now = main_get_now();
if (is_new)
{
c->last_fail = now;
- c->fail_count = 1;
+ c->fail_count = cnt;
c->banned = 0;
clist_add_tail(&suspect_list, &c->n);
num_suspects++;
- msg(L_DEBUG, "Suspect %s: new", AFMT(addr));
+ msg(L_DEBUG, "Suspect %s: new, failures=%u", AFMT(addr), c->fail_count);
}
else if (!c->banned)
{
c->last_fail = now;
- c->fail_count++;
+ c->fail_count += cnt;
clist_remove(&c->n);
clist_add_tail(&suspect_list, &c->n);
msg(L_DEBUG, "Suspect %s: failures=%u", AFMT(addr), c->fail_count);
char *p = line;
int c;
// 2016-11-04T17:18:54.825821+01:00 sshd[6733]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=1.2.3.4
+ // 2016-11-05T12:49:52.418880+01:00 sshd[16271]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=116.31.116.26 user=root
// We shall start with 32 non-spaces
for (int i=0; i<32; i++)
DBG("Parse 3: <%s>", p);
// "authentication failure;"
+ int cnt = 1;
if (!check_next(&p, "authentication failure; "))
- return;
- DBG("Parse 4: <%s>", p);
+ {
+ // "PAM <n> more authentication failures;"
+ if (!check_next(&p, "PAM "))
+ return;
+ if (!(*p >= '0' && *p <= '9'))
+ return;
+ cnt = atoi(p);
+ while (*p >= '0' && *p <= '9')
+ p++;
+ if (!check_next(&p, " more authentication failures; "))
+ return;
+ }
+ DBG("Parse 4: <%s> cnt=%d", p, cnt);
// Decode attributes
bool done = 0;
// Act on the message
struct addr addr;
if (addr_parse(&addr, rhost))
- handle_failed_login(addr);
+ handle_failed_login(addr, cnt);
else
msg(L_WARN, "Unable to parse address %s", rhost);
}