mirror of
https://github.com/clearlinux/tallow.git
synced 2026-06-16 01:15:48 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ea958fd2b5 | |||
| 4547892d56 | |||
| c661a20e33 | |||
| 9f37520c72 | |||
| dc8f37e41f | |||
| d590c8f67f | |||
| ec2b5cbfc0 | |||
| cb41c16e93 | |||
| 40568eb4cd | |||
| 992927798d | |||
| fba8921952 | |||
| 73e9cd7011 | |||
| a4d9d9688e | |||
| 35eeabb146 | |||
| 08d45d39fd |
+6
-1
@@ -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
@@ -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
|
||||
+13
-4
@@ -1,17 +1,26 @@
|
||||
|
||||
AM_CFLAGS = -g $(LIBSYSTEMD_CFLAGS) -Wall -Wno-uninitialized
|
||||
AM_CFLAGS = -g $(LIBSYSTEMD_CFLAGS) $(LIBSYSTEMD_JOURNAL_CFLAGS) -Wall -Wno-uninitialized -W -D_FORTIFY_SOURCE=2
|
||||
|
||||
systemdsystemunitdir = @SYSTEMD_SYSTEMUNITDIR@
|
||||
systemdsystemunit_DATA = tallow.service
|
||||
|
||||
sbin_PROGRAMS = tallow
|
||||
tallow_SOURCES = tallow.c
|
||||
tallow_LDADD = $(LIBSYSTEMD_LIBS)
|
||||
tallow_LDADD = $(LIBSYSTEMD_LIBS) $(LIBSYSTEMD_JOURNAL_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
|
||||
|
||||
|
||||
+4
-2
@@ -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], [3], [auke-jan.h.kok@intel.com])
|
||||
AM_INIT_AUTOMAKE([])
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
|
||||
@@ -10,9 +10,11 @@ AC_CONFIG_FILES([Makefile])
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
|
||||
PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd])
|
||||
PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd,, [PKG_CHECK_MODULES(LIBSYSTEMD_JOURNAL, libsystemd-journal)])
|
||||
AC_SUBST(LIBSYSTEMD_CFLAGS)
|
||||
AC_SUBST(LIBSYSTEMD_LIBS)
|
||||
AC_SUBST(LIBSYSTEMD_JOURNAL_CFLAGS)
|
||||
AC_SUBST(LIBSYSTEMD_JOURNAL_LIBS)
|
||||
|
||||
AC_ARG_WITH([systemdsystemunitdir], AC_HELP_STRING([--with-systemdsystemunitdir=DIR],
|
||||
[path to systemd system service directory]), [path_systemdsystemunit=${withval}],
|
||||
|
||||
@@ -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
@@ -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>
|
||||
@@ -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)
|
||||
@@ -129,6 +125,9 @@ static void find(char *ip)
|
||||
struct tallow_struct *n;
|
||||
struct tallow_struct *w = whitelist;
|
||||
|
||||
if (!ip)
|
||||
return;
|
||||
|
||||
/*
|
||||
* not validating the IP address format here, just
|
||||
* making sure we're not passing special characters
|
||||
@@ -226,14 +225,12 @@ static void prune(void)
|
||||
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);
|
||||
@@ -247,13 +244,15 @@ static void prune(void)
|
||||
}
|
||||
}
|
||||
|
||||
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 +287,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 +313,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);
|
||||
}
|
||||
}
|
||||
@@ -379,6 +387,14 @@ int main(int argc, char *argv[])
|
||||
find(t);
|
||||
}
|
||||
|
||||
|
||||
if (strstr(m, "MESSAGE=Received disconnect from ")) {
|
||||
t = strtok(m, " ");
|
||||
for (i = 0; i < 4; i++)
|
||||
t = strtok(NULL, " ");
|
||||
find(t);
|
||||
}
|
||||
|
||||
free(m);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user