10 Commits
v1 ... v2

Author SHA1 Message Date
Auke Kok d590c8f67f v2: ipset release. 2017-05-07 00:17:48 -07:00
Auke Kok ec2b5cbfc0 Make ipset init clean and working. 2017-05-07 00:05:25 -07:00
Auke Kok cb41c16e93 Minor ipset fixes. 2017-05-06 23:38:28 -07:00
Auke Kok 40568eb4cd Man pages and checked out folders. 2017-05-06 23:14:06 -07:00
Auke Kok 992927798d Convert to ipset.
Create `tallow` and `tallow6` ipsets, hook up to iptables
and create a single rule in the INPUT chain of the filter
table.

The ipsets created have `expire` timeouts set by default
which removes the need to do pruning, so we can erase entries
immediately from our LL when blocking.
2017-05-06 23:12:22 -07:00
Arjan van de Ven fba8921952 add to .gitignore 2017-05-06 22:36:55 -07:00
Arjan van de Ven 73e9cd7011 add travis support 2017-05-06 22:36:55 -07:00
Arjan van de Ven a4d9d9688e add -W 2017-05-06 22:35:49 -07:00
Arjan van de Ven 35eeabb146 avoid a large .data section by just initializing the big structures at run time 2017-05-06 22:35:49 -07:00
Auke Kok 08d45d39fd Convert man page to ronn generated .md input format. 2017-05-06 22:12:30 -07:00
8 changed files with 167 additions and 137 deletions
+6 -1
View File
@@ -11,6 +11,11 @@ install-sh
missing
tallow
tallow-*.tar.gz
tallow-1/
tallow-*/
tallow.conf.5
tallow.1
tallow.1.html
tallow.o
tallow.service
*~
DEADJOE
+24
View File
@@ -0,0 +1,24 @@
dist: trusty
compiler:
- gcc
os:
- linux
before_script:
./autogen.sh
language: c
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- valgrind
- autoconf
- automake
script:
- ./configure && make && make distcheck
+12 -3
View File
@@ -1,5 +1,5 @@
AM_CFLAGS = -g $(LIBSYSTEMD_CFLAGS) -Wall -Wno-uninitialized
AM_CFLAGS = -g $(LIBSYSTEMD_CFLAGS) -Wall -Wno-uninitialized -W -D_FORTIFY_SOURCE=2
systemdsystemunitdir = @SYSTEMD_SYSTEMUNITDIR@
systemdsystemunit_DATA = tallow.service
@@ -8,10 +8,19 @@ sbin_PROGRAMS = tallow
tallow_SOURCES = tallow.c
tallow_LDADD = $(LIBSYSTEMD_LIBS)
EXTRA_DIST = AUTHORS COPYING INSTALL tallow.service.in
EXTRA_DIST = AUTHORS COPYING INSTALL tallow.service.in tallow.1.md
dist_man_MANS = tallow.1 tallow.conf.5
dist_doc_DATA = tallow.conf
dist_man_MANS = tallow.1 tallow.conf.5
DISTCHECK_CONFIGURE_FLAGS = \
--with-systemdsystemunitdir=$(DESTDIR)$(SYSTEMDSYSTEMUNITDIR)
docs: tallow.1 tallow.conf.5
tallow.conf.5:
ronn -r tallow.conf.5.md --pipe > tallow.conf.5
tallow.1:
ronn -r tallow.1.md --pipe > tallow.1
+1 -1
View File
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.64])
AC_INIT([tallow], [1], [auke-jan.h.kok@intel.com])
AC_INIT([tallow], [2], [auke-jan.h.kok@intel.com])
AM_INIT_AUTOMAKE([])
AC_CONFIG_FILES([Makefile])
-41
View File
@@ -1,41 +0,0 @@
.TH tallow 1 "31 October 2012" ".1" "Tallow"
.SH NAME
Tallow \- Reduce log clutter due to ssh login attempts.
.SH SYNOPSIS
/usr/sbin/tallow
.SH DESCRIPTION
\fBtallow\fR is a daemon that watches the systemd journal for
messages from the \fBsshd\fR service. It parses the messages
and looks for attempted random logins such as failed logins to the
root account and failed logins to invalid user accounts.
.PP
If such logins were detected, the offending IP address is stored
in a list. Items from this list are regularly purged, but if
the amount of times that a specific IP address is seen exceeds
a threshold (default 3), an iptables(1) rule is inserted in the
\fBTALLOW\fR chain in the \fBfilter\fR netfilter table. The
rule will match all packets from the IP address and \fBDROP\dR
them.
.PP
The system administrator needs to assure that all incoming packets
are routed through the \fBTALLOW\fR chain by inserting a rule
appropriately, e.g. \`iptables -I INPUT -j TALLOW\`. The \fBTALLOW\fR
chain may have to be created manually first with e.g. \`iptables -N
TALLOW\`.
.PP
Care should be taken to assure that legitimate users are not
blocked inadvertently. You may wish to list any valid IP address
with the whitelist option in tallow.conf(5). Multiple addresses
can be whitelisted.
.SH OPTIONS
The \fBtallow\fR daemon itself has no runtime configuration. All
configuration is done through the tallow.conf(5) config file.
.SH SEE ALSO
systemd-journald(1), iptables(1), tallow.conf(5)
.SH BUGS
\fBtallow\fR is \fBNOT A SECURITY SOLUTION\fR, nor does it protect
against random password logins. A attacker may still be able to
logon to your systems if you allow password logins.
.SH AUTHOR
Auke Kok <auke-jan.h.kok@intel.com>
+51
View File
@@ -0,0 +1,51 @@
## tallow
Reduce log clutter due to ssh login attempts.
## SYNOPSIS
`/usr/sbin/tallow`
## DESCRIPTION
`tallow` is a daemon that watches the systemd journal for
messages from the `sshd` service. It parses the messages
and looks for attempted random logins such as failed logins to the
root account and failed logins to invalid user accounts.
If such logins were detected, the offending IP address is stored
in a list. Items from this list are regularly purged, but if
the amount of times that a specific IP address is seen exceeds
a threshold (default 3), an ipset(1) entry is inserted in the
`tallow` or `tallow6` ipset, and further packets from that ip
address will be blocked by an `iptables(1)` or `ip6tables(1)`
rule that tallow creates at startup.
The system administrator needs to assure that the tallow
and tallow6 ipsets are left alone and that the inserted
iptables rules are properly matching on packets.
Care should be taken to assure that legitimate users are not
blocked inadvertently. You may wish to list any valid IP address
with the whitelist option in tallow.conf(5). Multiple addresses
can be whitelisted.
## OPTIONS
The `tallow` daemon itself has no runtime configuration. All
configuration is done through the tallow.conf(5) config file.
## SEE ALSO
systemd-journald(1), iptables(1), tallow.conf(5)
## BUGS
`tallow` is `NOT A SECURITY SOLUTION`, nor does it protect
against random password logins. A attacker may still be able to
logon to your systems if you allow password logins.
## AUTHOR
Auke Kok <auke-jan.h.kok@intel.com>
+36 -64
View File
@@ -35,8 +35,7 @@ static struct tallow_struct *whitelist;
#define FILTER_STRING "SYSLOG_IDENTIFIER=sshd"
static char iptables_path[PATH_MAX] = "/usr/sbin";
static char chain[PATH_MAX] = "TALLOW";
static char ipt_path[PATH_MAX];
static int threshold = 3;
static int expires = 3600;
static int has_ipv6 = 0;
@@ -67,7 +66,7 @@ static void ext_ignore(char *fmt, ...)
vsnprintf(cmd, sizeof(cmd), fmt, args);
va_end(args);
(void) system(cmd);
__attribute__((unused)) int ret = system(cmd);
}
static void block(struct tallow_struct *s)
@@ -77,27 +76,24 @@ static void block(struct tallow_struct *s)
if (strchr(s->ip, ':')) {
if (has_ipv6)
(void) ext("%s/ip6tables -t filter -A %s -s %s -j DROP", iptables_path, chain, s->ip);
(void) ext("%s/ipset -A tallow6 %s", ipt_path, s->ip);
} else {
(void) ext("%s/iptables -t filter -A %s -s %s -j DROP", iptables_path, chain, s->ip);
(void) ext("%s/ipset -A tallow %s", ipt_path, s->ip);
}
fprintf(stderr, "Blocked %s\n", s->ip);
}
static void unblock(struct tallow_struct *s)
{
if (s->count < threshold)
return;
if (strchr(s->ip, ':')) {
if (has_ipv6)
(void) ext("%s/ip6tables -t filter -D %s -s %s -j DROP", iptables_path, chain, s->ip);
/* remove entry from the list */
if (head == s) {
head = s->next;
free(s->ip);
free(s);
} else {
(void) ext("%s/iptables -t filter -D %s -s %s -j DROP", iptables_path, chain, s->ip);
struct tallow_struct *p = s;
s = s->next;
free(p->ip);
free(p);
}
fprintf(stderr, "Unblocked %s\n", s->ip);
}
static void whitelist_add(char *ip)
@@ -214,46 +210,15 @@ static void sig(int s)
}
}
static void prune(void)
{
struct tallow_struct *s = head;
struct tallow_struct *p;
struct timeval tv;
(void) gettimeofday(&tv, NULL);
p = NULL;
while (s) {
if ((tv.tv_sec - s->time.tv_sec) > expires) {
if (p) {
unblock(s);
p->next = s->next;
free(s->ip);
free(s);
s = p->next;
continue;
} else {
unblock(s);
head = s->next;
free(s->ip);
free(s);
s = head;
p = NULL;
continue;
}
}
p = s;
s = s->next;
}
}
int main(int argc, char *argv[])
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(SIGUSR1, &s, NULL);
@@ -288,10 +253,8 @@ int main(int argc, char *argv[])
// todo: filter leading/trailing whitespace
if (!strcmp(key, "iptables_path"))
strncpy(iptables_path, val, PATH_MAX - 1);
if (!strcmp(key, "chain"))
strncpy(chain, val, PATH_MAX - 1);
if (!strcmp(key, "ipt_path"))
strncpy(ipt_path, val, PATH_MAX - 1);
if (!strcmp(key, "threshold"))
threshold = atoi(val);
if (!strcmp(key, "expires"))
@@ -316,17 +279,28 @@ int main(int argc, char *argv[])
exit(1);
}
/* init ip(6)tables chains */
ext_ignore("%s/iptables -t filter -N %s > /dev/null 2>&1", iptables_path, chain);
if (ext("%s/iptables -t filter -F %s", iptables_path, chain)) {
fprintf(stderr, "Unable to create/flush iptables chain \"%s\".\n", chain);
/* 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);
ext_ignore("%s/ipset destroy tallow 2> /dev/null", ipt_path);
if (ext("%s/ipset create tallow hash:ip family inet timeout %d", ipt_path, expires)) {
fprintf(stderr, "Unable to create ipv4 ipset.\n");
exit(1);
}
if (ext("%s/iptables -t filter -A INPUT -m set --match-set tallow src -j DROP", ipt_path)) {
fprintf(stderr, "Unable to create iptables rule.\n");
exit(1);
}
if (has_ipv6) {
ext_ignore("%s/ip6tables -t filter -N %s > /dev/null 2>&1", iptables_path, chain);
if (ext("%s/ip6tables -t filter -F %s", iptables_path, chain)) {
fprintf(stderr, "Unable to create/flush ip6tables chain \"%s\".\n", chain);
ext_ignore("%s/ip6tables -t filter -D INPUT -m set --match-set tallow6 src -j DROP 2> /dev/null", ipt_path);
ext_ignore("%s/ipset destroy tallow6 2> /dev/null", ipt_path);
if (ext("%s/ipset create tallow6 hash:ip family inet6 timeout %d", ipt_path, expires)) {
fprintf(stderr, "Unable to create ipv6 ipset.\n");
exit(1);
}
if (ext("%s/ip6tables -t filter -A INPUT -m set --match-set tallow6 src -j DROP", ipt_path)) {
fprintf(stderr, "Unable to create ipt6ables rule.\n");
exit(1);
}
}
@@ -381,8 +355,6 @@ int main(int argc, char *argv[])
free(m);
}
prune();
}
sd_journal_close(j);
+37 -27
View File
@@ -1,47 +1,57 @@
.TH tallow.conf 5 "31 October 2012" ".5" "The tallow configuration file"
.SH NAME
tallow.conf \- Tallow daemon configuration file
.SH SYNOPSIS
/etc/tallow.conf
.SH DESCRIPTION
## tallow.conf
The tallow configuration file
## NAME
tallow.conf - Tallow daemon configuration file
## SYNOPSIS
`/etc/tallow.conf`
## DESCRIPTION
This file is read on startup by the tallow(1) daemon, and can
be used to provide options to the tallow daemon. If not present,
tallow will operate with built-in defaults.
.SH OPTIONS
.TP
\fBiptables_path\fR=\<string\>
Specifies the location of the iptables(1) or ip6tables(1) program.
By default, tallow will look in "/usr/sbin" for them.
.TP
\fBchain\fR=\<string\>
Specifies the iptables(1) chain name to use for maintaining the
block list. By default, tallow maintains its iptables(1) rules
in the \fBTALLOW\fR chain.
.TP
\fBexpires\fR=\<int\>
## OPTIONS
`ipt_path`=`<string>`
Specifies the location of the ipset(1), iptables(1) or ip6tables(1)
program. By default, tallow will look in "/usr/sbin" for them.
`expires`=`<int>`
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.
.TP
\fBthreshold\fR=\<int\>
`threshold`=`<int>`
Specifies the number of times an IP address may appear before it
is blocked. Defaults to 3.
.TP
\fBwhitelist\fR=\<ipv4 address\>
`whitelist`=`<ipv4 address>`
Specify an IP address that should never be blocked. Multiple IP
addresses can be included by repeating the \fBwhitelist\fR
addresses can be included by repeating the `whitelist`
option several times. By default, only 127.0.0.1 is whitelisted.
.TP
\fBipv6\fR=\<0|1\>
`ipv6`=`<0|1>`
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.
.SH SEE ALSO
## SEE ALSO
tallow(1), iptables(1)
.SH AUTHOR
## AUTHOR
Auke Kok <auke-jan.h.kok@intel.com>