11 Commits
v6 ... v12

Author SHA1 Message Date
Auke Kok dccbfce478 Tune down badness for attempts a small bit.
We're still blocking really agressively. Tune it down a notch
and make timeouts a bit less for human-error like conditions
(forgotten key, ^C etc).
2018-10-04 11:23:09 -07:00
Auke Kok 5503ff0b20 Possibly handle journald restarts better.
I've encountered two runaway tallow daemons now that seem to
coincide with journald restarts that send it spinning tight
on the `continue` statement and hitting the same _get_data()
error (ENOENT).

I'm unsure if the `break` will fix it, but the `continue`
is definitely broken here. Hopefully the `sd_journal_wait()`
will properly reassess the journal state and notify us of
rotations or other issues.
2018-06-25 12:13:30 -07:00
Auke Kok 8655223248 Remove HUP/TERM/INT sighandler, shield USR1 sighandler.
We remove, by default, all signal handlers. The USR1 handler
remains, but is shielded behind `#ifdef DEBUG`.
2018-03-28 09:44:06 -07:00
Auke Kok 76a59df0f1 Fine-tune blocking rules one notch down.
Before, most rules would block on the 3rd rule hit, with this,
it's 4, which means 1 extra failure before a 1hr block is started
and this is a bit more sympathetic towards `typo` failures.
2018-03-23 16:17:34 -07:00
Auke Kok 36946deeee v8 2018-02-05 11:11:17 -08:00
Auke Kok d51577bd4f Add one more preauth disconnect pattern.
This pattern has been recurring a lot recently and does not
get dropped as expected. It is another typical preauth failure.
2018-02-05 11:02:59 -08:00
Auke Kok e15bfe4dc0 Document USR1, update man page output.
Some minor adjustments to Makefile.am to make this passable.
2018-01-19 10:25:20 -08:00
Auke Kok d6e53e6f3a Rename to proper extension. 2018-01-19 09:39:50 -08:00
Auke Kok a2a6d8e9ac v7. 2018-01-10 10:29:53 -08:00
Auke Kok c5569176d2 Allow whitelist patterns.
This allows for some simple form of netmask type patterning
which will work for /8, /16 and /24 subnets to be whitelisted
for ipv4, and for any multiple of /32 subnets for ipv6.
2018-01-08 16:06:26 -08:00
Auke Kok bf81c259b0 Add 'nocreate' option to bypass all rule/set creation.
This may help in situations where external tools are used to maintain
iptables or ipset setups and we should not disturb them by creating
rules.
2018-01-05 12:57:45 -08:00
8 changed files with 112 additions and 54 deletions
+3 -3
View File
@@ -8,7 +8,7 @@ sbin_PROGRAMS = tallow
tallow_SOURCES = tallow.c
tallow_LDADD = $(PCRE_LIBS) $(LIBSYSTEMD_LIBS)
EXTRA_DIST = AUTHORS COPYING INSTALL tallow.service.in tallow.1.md
EXTRA_DIST = AUTHORS COPYING INSTALL README.md tallow.service.in tallow.conf.5.md tallow.1.md
dist_man_MANS = tallow.1 tallow.conf.5
@@ -18,9 +18,9 @@ DISTCHECK_CONFIGURE_FLAGS = \
--with-systemdsystemunitdir=$(DESTDIR)$(SYSTEMDSYSTEMUNITDIR)
docs: tallow.1 tallow.conf.5
tallow.conf.5:
tallow.conf.5: tallow.conf.5.md
ronn -r tallow.conf.5.md --pipe > tallow.conf.5
tallow.1:
tallow.1: tallow.1.md
ronn -r tallow.1.md --pipe > tallow.1
View File
+2 -2
View File
@@ -2,8 +2,8 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.64])
AC_INIT([tallow], [6], [auke-jan.h.kok@intel.com])
AM_INIT_AUTOMAKE([])
AC_INIT([tallow], [12], [auke-jan.h.kok@intel.com])
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_FILES([Makefile])
# Checks for programs.
+4 -1
View File
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "TALLOW" "1" "December 2017" "" ""
.TH "TALLOW" "1" "March 2018" "" ""
.
.SH "NAME"
\fBtallow\fR
@@ -27,6 +27,9 @@ Care should be taken to assure that legitimate users are not blocked inadvertent
.SH "OPTIONS"
The \fBtallow\fR daemon itself has no runtime configuration\. All configuration is done through the tallow\.conf(5) config file\.
.
.SH "SIGNALS"
The \fBUSR1\fR signal causes \fBtallow\fR to print out it\'s internal tracking table of IP addresses\. This requires that tallow is compiled with the \fB\-DDEBUG=1\fR symbol passed to the compiler\.
.
.SH "SEE ALSO"
systemd\-journald(1), iptables(1), ipset(1), tallow\.conf(5)
.
+6
View File
@@ -40,6 +40,12 @@ be whitelisted.
The `tallow` daemon itself has no runtime configuration. All
configuration is done through the tallow.conf(5) config file.
## SIGNALS
The `USR1` signal causes `tallow` to print out it's internal tracking
table of IP addresses. This requires that tallow is compiled with
the `-DDEBUG=1` symbol passed to the compiler.
## SEE ALSO
systemd-journald(1), iptables(1), ipset(1), tallow.conf(5)
+48 -42
View File
@@ -40,7 +40,13 @@ struct tallow_struct {
static struct tallow_struct *head;
static struct tallow_struct *whitelist;
struct whitelist_struct {
char *ip;
size_t len;
struct whitelist_struct *next;
};
static struct whitelist_struct *whitelist;
#define FILTER_STRING "SYSLOG_IDENTIFIER=sshd"
struct pattern_struct {
@@ -50,16 +56,17 @@ struct pattern_struct {
pcre *re;
};
#define PATTERN_COUNT 9
#define PATTERN_COUNT 10
static struct pattern_struct patterns[PATTERN_COUNT] = {
{ 0, 0.4, "MESSAGE=Failed .* for .* from ([0-9a-z:.]+) port \\d+ ssh2", NULL},
{ 0, 0.4, "MESSAGE=error: PAM: Authentication failure for .* from ([0-9a-z:.]+)", NULL},
{15, 0.3, "MESSAGE=Invalid user .* from ([0-9a-z:.]+) port \\d+", NULL},
{15, 0.3, "MESSAGE=Did not receive identification string from ([0-9a-z:.]+) port \\d+", NULL},
{30, 0.3, "MESSAGE=Failed .* for root from ([0-9a-z:.]+) port \\d+ ssh2", NULL},
{15, 0.6, "MESSAGE=Bad protocol version identification .* from ([0-9a-z:.]+)", NULL},
{15, 0.6, "MESSAGE=Connection closed by authenticating user .* ([0-9a-z:.]+) port \\d+", NULL},
{15, 0.6, "MESSAGE=Received disconnect from ([0-9a-z:.]+) port .*\\[preauth\\]", NULL},
{ 0, 0.2, "MESSAGE=Failed .* for .* from ([0-9a-z:.]+) port \\d+ ssh2", NULL},
{ 0, 0.2, "MESSAGE=error: PAM: Authentication failure for .* from ([0-9a-z:.]+)", NULL},
{10, 0.2, "MESSAGE=Invalid user .* from ([0-9a-z:.]+) port \\d+", NULL},
{10, 0.3, "MESSAGE=Did not receive identification string from ([0-9a-z:.]+) port \\d+", NULL},
{15, 0.4, "MESSAGE=Bad protocol version identification .* from ([0-9a-z:.]+)", NULL},
{15, 0.4, "MESSAGE=Connection closed by authenticating user .* ([0-9a-z:.]+) port \\d+", NULL},
{10, 0.3, "MESSAGE=Received disconnect from ([0-9a-z:.]+) port .*\\[preauth\\]", NULL},
{10, 0.3, "MESSAGE=Connection closed by ([0-9a-z:.]+) port .*\\[preauth\\]", NULL},
{30, 0.5, "MESSAGE=Failed .* for root from ([0-9a-z:.]+) port \\d+ ssh2", NULL},
{60, 0.6, "MESSAGE=Unable to negotiate with ([0-9a-z:.]+) port \\d+: no matching key exchange method found.", NULL}
};
@@ -68,6 +75,7 @@ static struct pattern_struct patterns[PATTERN_COUNT] = {
static char ipt_path[PATH_MAX];
static int expires = 3600;
static int has_ipv6 = 0;
static bool nocreate = false;
static sd_journal *j;
static int ext(char *fmt, ...)
@@ -105,6 +113,9 @@ static void setup(void)
return;
done = true;
if (nocreate)
return;
/* init ipset and iptables */
/* delete iptables ref to set before the ipset! */
ext_ignore("%s/iptables -t filter -D INPUT -m set --match-set tallow src -j DROP 2> /dev/null", ipt_path);
@@ -166,21 +177,24 @@ static void block(struct tallow_struct *s, int instant_block)
static void whitelist_add(char *ip)
{
struct tallow_struct *w = whitelist;
struct tallow_struct *n;
struct whitelist_struct *w = whitelist;
struct whitelist_struct *n;
while (w && w->next)
w = w->next;
n = calloc(1, sizeof(struct tallow_struct));
n = calloc(1, sizeof(struct whitelist_struct));
if (!n) {
fprintf(stderr, "Out of memory.\n");
exit(EXIT_FAILURE);
}
n->ip = strdup(ip);
n->next = NULL;
n->blocked = false;
size_t l = strlen(ip);
if ((ip[l-1] == '.') || (ip[l-1] == ':'))
n->len = l;
else
n->len = -1;
if (!whitelist)
whitelist = n;
@@ -192,7 +206,7 @@ static void find(const char *ip, float weight, int instant_block)
{
struct tallow_struct *s = head;
struct tallow_struct *n;
struct tallow_struct *w = whitelist;
struct whitelist_struct *w = whitelist;
if (!ip)
return;
@@ -207,8 +221,13 @@ static void find(const char *ip, float weight, int instant_block)
/* whitelist */
while (w) {
if (!strcmp(w->ip, ip))
return;
if (w->len > 0) {
if (!strncmp(w->ip, ip, w->len))
return;
} else {
if (!strcmp(w->ip, ip))
return;
}
w = w->next;
}
@@ -265,23 +284,7 @@ static void find(const char *ip, float weight, int instant_block)
return;
}
static void sig(int u __attribute__ ((unused)))
{
fprintf(stderr, "Exiting on request.\n");
sd_journal_close(j);
struct tallow_struct *s = head;
while (s) {
struct tallow_struct *n = NULL;
free(s->ip);
n = s;
s = s->next;
free(n);
}
exit(EXIT_SUCCESS);
}
#ifdef DEBUG
static void sigusr1(int u __attribute__ ((unused)))
{
fprintf(stderr, "Dumping score list on request:\n");
@@ -291,6 +294,7 @@ static void sigusr1(int u __attribute__ ((unused)))
s = s->next;
}
}
#endif
static void prune(void)
{
@@ -335,20 +339,17 @@ int main(void)
{
int r;
FILE *f;
struct sigaction s;
int timeout = 60;
strcpy(ipt_path, "/usr/sbin");
memset(&s, 0, sizeof(struct sigaction));
s.sa_handler = sig;
sigaction(SIGHUP, &s, NULL);
sigaction(SIGTERM, &s, NULL);
sigaction(SIGINT, &s, NULL);
#ifdef DEBUG
struct sigaction s;
memset(&s, 0, sizeof(struct sigaction));
s.sa_handler = sigusr1;
sigaction(SIGUSR1, &s, NULL);
#endif
if (access("/proc/sys/net/ipv6", R_OK | X_OK) == 0)
has_ipv6 = 1;
@@ -384,6 +385,8 @@ int main(void)
whitelist_add(val);
if (!strcmp(key, "ipv6"))
has_ipv6 = atoi(val);
if (!strcmp(key, "nocreate"))
nocreate = (atoi(val) == 1);
}
fclose(f);
}
@@ -431,6 +434,9 @@ int main(void)
if (r == SD_JOURNAL_INVALIDATE) {
fprintf(stderr, "Journal was rotated, resetting\n");
sd_journal_seek_tail(j);
} else if (r == SD_JOURNAL_NOP) {
dbg("Timeout reached, waiting again\n");
continue;
}
while (sd_journal_next(j) != 0) {
@@ -438,7 +444,7 @@ int main(void)
if (sd_journal_get_data(j, "MESSAGE", &d, &l) < 0) {
fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
continue;
break;
}
m = strndup(d, l+1);
+22 -2
View File
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "TALLOW" "5" "December 2017" "" ""
.TH "TALLOW" "5" "January 2018" "" ""
.
.SH "NAME"
\fBtallow\fR
@@ -25,11 +25,31 @@ This file is read on startup by the tallow(1) daemon, and can be used to provide
\fBexpires\fR=\fB<int>\fR The number of seconds that IP addresses are blocked for\. Note that due to the implementation, IP addresses may be blocked for much longer than this period\. If IP addresses are seen, but not blocked within this period, they are also removed from the watch list\. Defaults to 3600s\.
.
.P
\fBwhitelist\fR=\fB<ipv4 address>\fR Specify an IP address that should never be blocked\. Multiple IP addresses can be included by repeating the \fBwhitelist\fR option several times\. By default, only 127\.0\.0\.1 is whitelisted\.
\fBwhitelist\fR=\fB<ip address|pattern>\fR Specify an IP address or \fBpattern\fR that should never be blocked\. Multiple IP addresses can be included by repeating the \fBwhitelist\fR option several times\. By default, only 127\.0\.0\.1 is whitelisted\.
.
.P
If the last character of the listed ip adress is a \fB\.\fR or a \fB:\fR, then the matching is only performed on the leftmost characters of an IP address against the whitelist entry\. For instance, if you whitelist \fB10\.\fR then all IP addresses in the \fB10/8\fR subnet mask will match this whitelist entry and never be blocked\.
.
.P
\fBipv6\fR=\fB<0|1>\fR Enable of disable ipv6 (ip6tables) support\. Ipv6 is disabled automatically on systems that do not appear to have ipv6 support and enabled when ipv6 is present\. Use this option to explicitly disable ipv6 support if your system does not have ipv6 or is missing ip6tables\. Even with ipv6 disabled, tallow will track and log ipv6 addresses\.
.
.P
\fBnocreate\fR=\fB<0|1>\fR Disable the creation of iptables rules and ipset sets\. By default, tallow will create new iptables(1) and ip6tables(1) rules when needed automatically\. If set to \fB1\fR, \fBtallow(1)\fR will not create any new iptables rules or ipset sets to work\. You should create them manually before tallow starts up and remove them afterwards\. To create them manually, you can use the following commands:
.
.IP "" 4
.
.nf
iptables \-t filter \-I INPUT \-m set \-\-match\-set tallow src \-j DROP
ipset create tallow hash:ip family inet timeout 3600
ip6tables \-t filter \-I INPUT \-m set \-\-match\-set tallow6 src \-j DROP
ipset create tallow6 hash:ip family inet6 timeout 3600
.
.fi
.
.IP "" 0
.
.SH "SEE ALSO"
tallow(1)
.
+27 -4
View File
@@ -30,10 +30,17 @@ longer than this period. If IP addresses are seen, but not
blocked within this period, they are also removed from the
watch list. Defaults to 3600s.
`whitelist`=`<ipv4 address>`
Specify an IP address that should never be blocked. Multiple IP
addresses can be included by repeating the `whitelist`
option several times. By default, only 127.0.0.1 is whitelisted.
`whitelist`=`<ip address|pattern>`
Specify an IP address or `pattern` that should never be
blocked. Multiple IP addresses can be included by repeating the
`whitelist` option several times. By default, only 127.0.0.1 is
whitelisted.
If the last character of the listed ip adress is a `.` or a `:`, then
the matching is only performed on the leftmost characters of an IP
address against the whitelist entry. For instance, if you whitelist
`10.` then all IP addresses in the `10/8` subnet mask will match this
whitelist entry and never be blocked.
`ipv6`=`<0|1>`
Enable of disable ipv6 (ip6tables) support. Ipv6 is disabled
@@ -43,6 +50,22 @@ disable ipv6 support if your system does not have ipv6 or is
missing ip6tables. Even with ipv6 disabled, tallow will track
and log ipv6 addresses.
`nocreate`=`<0|1>`
Disable the creation of iptables rules and ipset sets. By default,
tallow will create new iptables(1) and ip6tables(1) rules when needed
automatically. If set to `1`, `tallow(1)` will not create any new
iptables rules or ipset sets to work. You should create them manually
before tallow starts up and remove them afterwards. To create them
manually, you can use the following commands:
```
iptables -t filter -I INPUT -m set --match-set tallow src -j DROP
ipset create tallow hash:ip family inet timeout 3600
ip6tables -t filter -I INPUT -m set --match-set tallow6 src -j DROP
ipset create tallow6 hash:ip family inet6 timeout 3600
```
## SEE ALSO
tallow(1)