9 Commits

Author SHA1 Message Date
Robert Dower e32017573c archive repository 2025-08-07 14:08:12 -07:00
Auke Kok 03f4d64ff6 Convert to pandoc.
Because pandoc is relatively small, we now create man page output on the
fly on building, which makes pandoc a required build time dependency.
2020-04-01 13:00:21 -07:00
Auke Kok 865ec916aa v21 2020-02-13 11:01:45 -08:00
Auke Kok 6746c4a4db v20 2020-02-13 10:42:53 -08:00
puneetse 7b700cf2a2 Add tallow.patterns man page
Add a tallow.patterns man page which explains the json configuration
files that contain regex patterns and banning thresholds. This
functionality was added by 9174590b04.
2020-02-13 10:31:09 -08:00
Thorsten Kukuk 3ffb46e8e7 Add extra path for firewall-cmd 2020-02-11 13:27:07 -08:00
Auke Kok 4b071b01f6 Need configure in this workflow. 2019-11-06 11:37:06 -08:00
Auke Kok 4212f1dbef Fix dependency. 2019-11-06 11:35:22 -08:00
Auke Kok 9260e519f5 Add github workflow integration. 2019-11-06 11:32:41 -08:00
12 changed files with 227 additions and 164 deletions
+23
View File
@@ -0,0 +1,23 @@
name: C/C++ CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: install dependencies
run: sudo apt-get install check libjson-c-dev libpcre2-dev libsystemd-dev
- name: autogen
run: sh autogen.sh
- name: configure
run: ./configure
- name: make
run: make
- name: make check
run: make check
- name: make distcheck
run: make distcheck
+1
View File
@@ -16,3 +16,4 @@ tallow-*/
tallow.service
*~
DEADJOE
man/*.[0-9]
+10 -5
View File
@@ -25,18 +25,23 @@ EXTRA_DIST = \
data/tallow.service.in \
data/sshd.json \
man/tallow.conf.5.md \
man/tallow.patterns.5.md \
man/tallow.1.md
dist_man_MANS = man/tallow.1 man/tallow.conf.5
dist_doc_DATA = tallow.conf
DISTCHECK_CONFIGURE_FLAGS = \
--with-systemdsystemunitdir=$(DESTDIR)$(SYSTEMDSYSTEMUNITDIR)
docs: $(dist_man_MANS)
man_MANS = man/tallow.1 man/tallow.conf.5 man/tallow.patterns.5
clean-local:
rm -f $(man_MANS)
man/%.5: man/%.5.md
ronn -r $< --pipe > $@
@mkdir -p $$(dirname $@)
pandoc -s -f markdown -t man $< --output $@
man/%.1: man/%.1.md
ronn -r $< --pipe > $@
@mkdir -p $$(dirname $@)
pandoc -s -f markdown -t man $< --output $@
+7
View File
@@ -1,3 +1,10 @@
## DISCONTINUATION OF PROJECT.
This project will no longer be maintained by Intel.
Intel will not provide or guarantee development of or support for this project, including but not limited to, maintenance, bug fixes, new releases or updates. Patches to this project are no longer accepted by Intel. If you have an ongoing need to use this project, are interested in independently developing it, or would like to maintain patches for the community, please create your own fork of the project.
Contact: webadmin@linux.intel.com
tallow
======
+6 -1
View File
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.64])
AC_INIT([tallow], [19], [auke-jan.h.kok@intel.com])
AC_INIT([tallow], [21], [auke-jan.h.kok@intel.com])
AM_INIT_AUTOMAKE([foreign -Wall -Werror -Wno-portability silent-rules subdir-objects color-tests
no-dist-gzip dist-xz])
AC_CONFIG_FILES([Makefile])
@@ -11,6 +11,11 @@ AC_CONFIG_FILES([Makefile])
AC_PROG_CC
AC_PROG_INSTALL
AC_CHECK_PROG([PANDOC],[pandoc],yes)
if test x"${PANDOC}" != x"yes" ; then
AC_MSG_ERROR([Pandoc is required to create manual pages.])
fi
PKG_CHECK_MODULES(PCRE, libpcre)
PKG_CHECK_MODULES(JSON_C, json-c)
PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd,, [PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd-journal)])
-40
View File
@@ -1,40 +0,0 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "TALLOW" "1" "October 2018" "" ""
.
.SH "NAME"
\fBtallow\fR
.
.SH "tallow"
Reduce log clutter due to ssh login attempts\.
.
.SH "SYNOPSIS"
\fB/usr/sbin/tallow\fR
.
.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, and various other obviously malicious login attempts that try things as forcing old protocols, or weak key systems\.
.
.P
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, an ipset(1) entry is inserted in the \fBtallow\fR or \fBtallow6\fR ipset, and further packets from that ip address will be blocked by an \fBiptables(1)\fR or \fBip6tables(1)\fR rule that tallow creates at startup\. Additionally, certain types of login failure will trigger a short term ban of further packets from the offending IP address immediately\.
.
.P
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\.
.
.P
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 "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)
.
.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 \fIauke\-jan\.h\.kok@intel\.com\fR
+10 -12
View File
@@ -1,13 +1,15 @@
% TALLOW(1)
% Auke Kok `<auke-jan.h.kok@intel.com>`
## tallow
# tallow
Reduce log clutter due to ssh login attempts.
## SYNOPSIS
# SYNOPSIS
`/usr/sbin/tallow`
## DESCRIPTION
# DESCRIPTION
`tallow` is a daemon that watches the systemd journal for messages
from the `sshd` service. It parses the messages and looks for
@@ -35,27 +37,23 @@ 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
# OPTIONS
The `tallow` daemon itself has no runtime configuration. All
configuration is done through the tallow.conf(5) config file.
## SIGNALS
# 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
# SEE ALSO
systemd-journald(1), iptables(1), ipset(1), tallow.conf(5)
systemd-journald(1), iptables(1), ipset(1), tallow.conf(5), tallow.patterns(5)
## BUGS
# 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>
-77
View File
@@ -1,77 +0,0 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "TALLOW" "5" "October 2019" "" ""
.
.SH "NAME"
\fBtallow\fR
.
.SH "tallow\.conf"
The tallow configuration file
.
.SH "NAME"
tallow\.conf \- Tallow daemon configuration file
.
.SH "SYNOPSIS"
\fB/etc/tallow\.conf\fR
.
.SH "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"
\fBipt_path\fR=\fB<string>\fR Specifies the location of the ipset(1) program and iptables(1), ip6tables(1), or firewall\-cmd(1) programs\. By default, tallow will look in "/usr/sbin" for them\.
.
.P
\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<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, 127\.0\.0\.1, 192\.168\., and 10\. are whitelisted\. If you create a manual whitelist, you must include these entries if you want to continue them to be whitelisted as well, otherwise they will be omitted from the whitelist\.
.
.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 or 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 firewall rules and ipset sets\. By default, tallow will create new firewall\-cmd(1) or iptables(1) and ip6tables(1) rules when needed automatically\. If set to \fB1\fR, \fBtallow(1)\fR will not create any new firewall DROP rules or ipset sets that are needed work\. You should create them manually before tallow starts up and remove them afterwards using the sets of commands below\.
.
.P
Use the following commands if you\'re using iptables(1):
.
.IP "" 4
.
.nf
ipset create tallow hash:ip family inet timeout 3600
iptables \-t filter \-I INPUT 1 \-m set \-\-match\-set tallow src \-j DROP
ipset create tallow6 hash:ip family inet6 timeout 3600
ip6tables \-t filter \-I INPUT 1 \-m set \-\-match\-set tallow6 src \-j DROP
.
.fi
.
.IP "" 0
.
.P
Use the following commands if you\'re using firewalld(1):
.
.IP "" 4
.
.nf
firewall\-cmd \-\-permanent \-\-new\-ipset=tallow \-\-type=hash:ip \-\-family=inet \-\-option=timeout=3600
firewall\-cmd \-\-permanent \-\-direct \-\-add\-rule ipv4 filter INPUT 1 \-m set \-\-match\-set tallow src \-j DROP
firewall\-cmd \-\-permanent \-\-new\-ipset=tallow6 \-\-type=hash:ip \-\-family=inet6 \-\-option=timeout=3600
firewall\-cmd \-\-permanent \-\-direct \-\-add\-rule ipv6 filter INPUT 1 \-m set \-\-match\-set tallow6 src \-j DROP
.
.fi
.
.IP "" 0
.
.SH "SEE ALSO"
tallow(1)
.
.SH "AUTHOR"
Auke Kok \fIauke\-jan\.h\.kok@intel\.com\fR
+19 -17
View File
@@ -1,28 +1,34 @@
% TALLOW.CONF(5)
% Auke Kok `<auke-jan.h.kok@intel.com>`
## tallow.conf
# tallow.conf
The tallow configuration file
## NAME
# NAME
tallow.conf - Tallow daemon configuration file
## SYNOPSIS
# SYNOPSIS
`/etc/tallow.conf`
## DESCRIPTION
# 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.
## OPTIONS
# OPTIONS
`fwcmd_path`=`<string>`
Specifies the location of the ipset(1) firewall-cmd(1) programs. By
default, tallow will look in "/usr/sbin" for them.
`ipt_path`=`<string>`
Specifies the location of the ipset(1) program and iptables(1),
ip6tables(1), or firewall-cmd(1) programs. By default, tallow will
look in "/usr/sbin" for them.
Specifies the location of the ipset(1) program and iptables(1) or
ip6tables(1) programs. By default, tallow will look in "/usr/sbin"
for them.
`expires`=`<int>`
The number of seconds that IP addresses are blocked for. Note that
@@ -58,7 +64,7 @@ default, tallow will create new firewall-cmd(1) or iptables(1) and ip6tables(1)
rules when needed automatically. If set to `1`, `tallow(1)` will not create any
new firewall DROP rules or ipset sets that are needed work. You should create
them manually before tallow starts up and remove them afterwards using the sets
of commands below.
of commands below.
Use the following commands if you're using iptables(1):
@@ -75,16 +81,12 @@ Use the following commands if you're using firewalld(1):
```
firewall-cmd --permanent --new-ipset=tallow --type=hash:ip --family=inet --option=timeout=3600
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -m set --match-set tallow src -j DROP
firewall-cmd --permanent --new-ipset=tallow6 --type=hash:ip --family=inet6 --option=timeout=3600
firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 1 -m set --match-set tallow6 src -j DROP
```
## SEE ALSO
# SEE ALSO
tallow(1)
## AUTHOR
Auke Kok <auke-jan.h.kok@intel.com>
tallow(1), tallow.patterns(5)
+134
View File
@@ -0,0 +1,134 @@
% TALLOW.PATTERNS(5)
% Auke Kok `<auke-jan.h.kok@intel.com>`
# tallow.patterns
Tallow pattern matching configuration files.
# SYNOPSIS
tallow(1) uses regular expressions to match journal entries and extract an IP
address from them. JSON files are used to configure the patterns and banning
thresholds used by tallow(1).
`/etc/tallow/*.json`
`/usr/share/tallow/*.json`
# DESCRIPTION
tallow(1) uses regular expressions to match journal entries and extract an IP
address from them. JSON files are used to configure the patterns and banning
thresholds used by tallow(1). This adds the ability to extend the patterns
tallow(1) will recognize. Many JSON files can exist for logical grouping. The
tallow(1) daemon will read all JSON files in the configuration directories at
startup.
tallow(1) operates with default pattern definitions
in`/usr/share/tallow/*.json`. Users can add more patterns with their own JSON
files under `/etc/tallow`. The default JSON files can be overridden by creating
the same file under `/etc/tallow`.
# FILE FORMAT
Pattern configuration files use the JavaScript Object Notation (JSON) format.
The JSON must be two levels deep and all properties are required. The root
object is an array containing objects with a `filter` key and an `items` key.
* `filter` is a string that defines a field for filtering the journal file.
This helps make sure patterns are only matched to a subset of journal
entries. See systemd.journal-fields(7) for valid journal fields.
* `items` is an array of objects that contains three elements: `ban`, `score`,
and `pattern`.
* `ban` is an integer that defines the number of seconds to ban originating
IP for. If this value is > 0, the IP address get banned immediately when a
journal entry matches `pattern`.
* `score` is a double that defines a value to add to the accumulated "score"
of an originating IP address each time a journal entry matches
the `pattern`. If the combined score is > 1.0, tallow bans the originating
IP for the default time of 1 hour. The `ban` element value above is not
used for bans made due to `score`.
* `pattern` is a string that defines a Perl Compatible Regular Expressions
(PCRE) to match against the filtered journal entries. The PCRE should
extract exactly one substring: the originating IP address for tallow(1).
See systemd.journal-fields(7) for valid journal fields.
# EXAMPLES
1. The JSON below is a snippet from one of the default pattern configuration
files for blocking certain failed `sshd` connections.
The first pattern will ban an IP address after it fails to login 6 times
causing it to reach a total score > 1.0.
The second pattern will ban an IP address for 10 seconds every time a login is
attempted with an invalid user. Additionally, it will ban the IP address for
1 hour if it attempts to login with an invalid user 6 times causing it to
reach a total score > 1.0.
See the `/usr/share/tallow/sshd.json` file for more `sshd` examples.
```
[
{
"filter": "SYSLOG_IDENTIFIER=sshd",
"items": [
{
"ban": 0,
"score": 0.2,
"pattern": "MESSAGE=Failed .* for .* from ([0-9a-z:.]+) port \\d+ ssh2"
},
{
"ban": 10,
"score": 0.2,
"pattern": "MESSAGE=Invalid user .* from ([0-9a-z:.]+) port \\d+"
}
]
}
]
```
2. The JSON below defines a pattern for blocking connections based on error logs
from `nginx-mainline` if placed in a `/etc/tallow/nginx-mainline.json` file.
The pattern will ban an IP address for 15 seconds every time it attempts to
access a script that does not exist. Additionally, it will ban the IP
address for 1 hour if it attempts to access invalid scripts 4 times causing
it to reach a total score > 1.0.
```
[
{
"filter": "SYSLOG_IDENTIFIER=nginx-mainline",
"items": [
{
"ban": 15,
"score": 0.3,
"pattern": ".Primary script unknown. while reading response header from upstream, client: ([0-9a-z:.]+),"
}
]
}
]
```
# SEE ALSO
tallow(1), tallow.conf(5)
# BUGS
`tallow` is `NOT A SECURITY SOLUTION`, nor does it protect against random
password logins. An attacker may still be able to logon to your systems if you
allow password logins.
+16 -12
View File
@@ -35,6 +35,7 @@
#define MAX_OFFSETS 30
static char ipt_path[PATH_MAX];
static char fwcmd_path[PATH_MAX];
static int expires = 3600;
static int has_ipv6 = 0;
static bool nocreate = false;
@@ -71,17 +72,17 @@ static void ext_ignore(char *fmt, ...)
static void reset_rules(void)
{
/* reset all rules in case the running fw changes */
ext_ignore("%s/firewall-cmd --permanent --direct --remove-rule ipv4 filter INPUT 1 -m set --match-set tallow src -j DROP 2> /dev/null", ipt_path);
ext_ignore("%s/firewall-cmd --permanent --delete-ipset=tallow 2> /dev/null", ipt_path);
ext_ignore("%s/firewall-cmd --permanent --direct --remove-rule ipv4 filter INPUT 1 -m set --match-set tallow src -j DROP 2> /dev/null", fwcmd_path);
ext_ignore("%s/firewall-cmd --permanent --delete-ipset=tallow 2> /dev/null", fwcmd_path);
/* 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 (has_ipv6) {
ext_ignore("%s/firewall-cmd --permanent --direct --remove-rule ipv6 filter INPUT 1 -m set --match-set tallow6 src -j DROP 2> /dev/null", ipt_path);
ext_ignore("%s/firewall-cmd --permanent --delete-ipset=tallow6 2> /dev/null", ipt_path);
ext_ignore("%s/firewall-cmd --permanent --direct --remove-rule ipv6 filter INPUT 1 -m set --match-set tallow6 src -j DROP 2> /dev/null", fwcmd_path);
ext_ignore("%s/firewall-cmd --permanent --delete-ipset=tallow6 2> /dev/null", fwcmd_path);
/* delete iptables ref to set before the ipset! */
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);
@@ -100,39 +101,39 @@ static void setup(void)
/* firewalld */
char *fwd_path;
if (asprintf(&fwd_path, "%s/firewall-cmd", ipt_path) < 0) {
if (asprintf(&fwd_path, "%s/firewall-cmd", fwcmd_path) < 0) {
exit(EXIT_FAILURE);
}
if ((access(fwd_path, X_OK) == 0) && ext("%s/firewall-cmd --state --quiet", ipt_path) == 0) {
if ((access(fwd_path, X_OK) == 0) && ext("%s/firewall-cmd --state --quiet", fwcmd_path) == 0) {
fprintf(stdout, "firewalld is running and will be used by tallow.\n");
reset_rules();
/* create ipv4 rule and ipset */
if (ext("%s/firewall-cmd --permanent --quiet --new-ipset=tallow --type=hash:ip --family=inet --option=timeout=%d", ipt_path, expires)) {
if (ext("%s/firewall-cmd --permanent --quiet --new-ipset=tallow --type=hash:ip --family=inet --option=timeout=%d", fwcmd_path, expires)) {
fprintf(stderr, "Unable to create ipv4 ipset with firewall-cmd.\n");
exit(EXIT_FAILURE);
}
if (ext("%s/firewall-cmd --permanent --direct --quiet --add-rule ipv4 filter INPUT 1 -m set --match-set tallow src -j DROP", ipt_path)) {
if (ext("%s/firewall-cmd --permanent --direct --quiet --add-rule ipv4 filter INPUT 1 -m set --match-set tallow src -j DROP", fwcmd_path)) {
fprintf(stderr, "Unable to create ipv4 firewalld rule.\n");
exit(EXIT_FAILURE);
}
/* create ipv6 rule and ipset */
if (has_ipv6) {
if (ext("%s/firewall-cmd --permanent --quiet --new-ipset=tallow6 --type=hash:ip --family=inet6 --option=timeout=%d", ipt_path, expires)) {
if (ext("%s/firewall-cmd --permanent --quiet --new-ipset=tallow6 --type=hash:ip --family=inet6 --option=timeout=%d", fwcmd_path, expires)) {
fprintf(stderr, "Unable to create ipv6 ipset with firewall-cmd.\n");
exit(EXIT_FAILURE);
}
if (ext("%s/firewall-cmd --permanent --direct --quiet --add-rule ipv6 filter INPUT 1 -m set --match-set tallow6 src -j DROP ", ipt_path)) {
if (ext("%s/firewall-cmd --permanent --direct --quiet --add-rule ipv6 filter INPUT 1 -m set --match-set tallow6 src -j DROP ", fwcmd_path)) {
fprintf(stderr, "Unable to create ipv6 firewalld rule.\n");
exit(EXIT_FAILURE);
}
}
/* reload firewalld for ipsets to load */
if (ext("%s/firewall-cmd --reload --quiet", ipt_path, expires)) {
if (ext("%s/firewall-cmd --reload --quiet", fwcmd_path, expires)) {
fprintf(stderr, "Unable to reload firewalld rules.\n");
exit(EXIT_FAILURE);
}
@@ -292,6 +293,7 @@ int main(void)
json_load_patterns();
strcpy(ipt_path, "/usr/sbin");
strcpy(fwcmd_path, "/usr/sbin");
#ifdef DEBUG
fprintf(stderr, "Debug output enabled. Send SIGUSR1 to dump internal state table\n");
@@ -331,6 +333,8 @@ int main(void)
// todo: filter leading/trailing whitespace
if (!strcmp(key, "ipt_path"))
strncpy(ipt_path, val, PATH_MAX - 1);
if (!strcmp(key, "fwcmd_path"))
strncpy(fwcmd_path, val, PATH_MAX - 1);
if (!strcmp(key, "expires"))
expires = atoi(val);
if (!strcmp(key, "whitelist"))
+1
View File
@@ -1,6 +1,7 @@
# tallow.conf - see `man tallow.conf` for more information
#fwcmd_path=/usr/sbin
#ipt_path=/usr/sbin
#expires=3600
#whitelist=127.0.0.1