Skip to content
This repository was archived by the owner on Aug 7, 2025. It is now read-only.

Commit ab57cc5

Browse files
puneetseahkok
authored andcommitted
Add firewalld support
Adds support to use firewalld if it is running and updates documentation accordingly.
1 parent 96fa692 commit ab57cc5

3 files changed

Lines changed: 109 additions & 28 deletions

File tree

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ Tallow attaches to the journal and subscribes to messages from
1616
/usr/sbin/sshd. The messages are matched against rules and the IP
1717
address is extracted from the message. For each IP address that is
1818
extracted, the last timestamp and count is kept. Once the count exceeds
19-
a threshold, iptables is executed to set a IP-based blocking rule.
19+
a threshold, the offending IP address is added to an ipset and blocked
20+
with a corresponding firewall rule. It will use firewalld or
21+
iptables / ip6tables.
2022

2123
The timestamp is kept for pruning. Records are pruned from the list
2224
if the IP address hasn't been seen by tallow for longer than the
@@ -66,4 +68,4 @@ tallow.
6668

6769
Be very careful if you deploy tallow on systems that expect valid
6870
users to log on from many random source addresses. If your user
69-
mistypes their username, they could find themselves denied access.
71+
mistypes their username, they could find themselves denied access.

man/tallow.conf.5.md

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ tallow will operate with built-in defaults.
2020
## OPTIONS
2121

2222
`ipt_path`=`<string>`
23-
Specifies the location of the ipset(1), iptables(1) or ip6tables(1)
24-
program. By default, tallow will look in "/usr/sbin" for them.
23+
Specifies the location of the ipset(1) program and iptables(1),
24+
ip6tables(1), or firewall-cmd(1) programs. By default, tallow will
25+
look in "/usr/sbin" for them.
2526

2627
`expires`=`<int>`
2728
The number of seconds that IP addresses are blocked for. Note that
@@ -52,13 +53,14 @@ disable ipv6 support if your system does not have ipv6 or is
5253
missing ip6tables. Even with ipv6 disabled, tallow will track
5354
and log ipv6 addresses.
5455

55-
`nocreate`=`<0|1>`
56-
Disable the creation of iptables rules and ipset sets. By default,
57-
tallow will create new iptables(1) and ip6tables(1) rules when needed
58-
automatically. If set to `1`, `tallow(1)` will not create any new
59-
iptables rules or ipset sets to work. You should create them manually
60-
before tallow starts up and remove them afterwards. To create them
61-
manually, you can use the following commands:
56+
`nocreate`=`<0|1>` Disable the creation of firewall rules and ipset sets. By
57+
default, tallow will create new firewall-cmd(1) or iptables(1) and ip6tables(1)
58+
rules when needed automatically. If set to `1`, `tallow(1)` will not create any
59+
new firewall DROP rules or ipset sets that are needed work. You should create
60+
them manually before tallow starts up and remove them afterwards using the sets
61+
of commands below.
62+
63+
Use the following commands if you're using iptables(1):
6264

6365
```
6466
ipset create tallow hash:ip family inet timeout 3600
@@ -68,11 +70,21 @@ manually, you can use the following commands:
6870
ip6tables -t filter -I INPUT 1 -m set --match-set tallow6 src -j DROP
6971
```
7072

73+
Use the following commands if you're using firewalld(1):
74+
75+
```
76+
firewall-cmd --permanent --new-ipset=tallow --type=hash:ip --family=inet --option=timeout=3600
77+
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 1 -m set --match-set tallow src -j DROP
78+
79+
firewall-cmd --permanent --new-ipset=tallow6 --type=hash:ip --family=inet6 --option=timeout=3600
80+
firewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 1 -m set --match-set tallow6 src -j DROP
81+
82+
```
83+
7184
## SEE ALSO
7285

7386
tallow(1)
7487

7588
## AUTHOR
7689

7790
Auke Kok <auke-jan.h.kok@intel.com>
78-

src/tallow.c

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
* of the License.
1212
*/
1313

14+
#define _GNU_SOURCE
15+
1416
#include <stdlib.h>
1517
#include <stdio.h>
1618
#include <string.h>
@@ -66,6 +68,26 @@ static void ext_ignore(char *fmt, ...)
6668
__attribute__((unused)) int ret = system(cmd);
6769
}
6870

71+
static void reset_rules(void)
72+
{
73+
/* reset all rules in case the running fw changes */
74+
ext_ignore("%s/firewall-cmd --permanent --direct --quiet --remove-rule ipv4 filter INPUT 1 -m set --match-set tallow src -j DROP", ipt_path);
75+
ext_ignore("%s/firewall-cmd --quiet --permanent --delete-ipset=tallow", ipt_path);
76+
77+
/* delete iptables ref to set before the ipset! */
78+
ext_ignore("%s/iptables -t filter -D INPUT -m set --match-set tallow src -j DROP 2> /dev/null", ipt_path);
79+
ext_ignore("%s/ipset destroy tallow 2> /dev/null", ipt_path);
80+
81+
if (has_ipv6) {
82+
ext_ignore("%s/firewall-cmd --permanent --direct --quiet --remove-rule ipv6 filter INPUT 1 -m set --match-set tallow6 src -j DROP", ipt_path);
83+
ext_ignore("%s/firewall-cmd --permanent --delete-ipset=tallow6 --quiet", ipt_path);
84+
85+
/* delete iptables ref to set before the ipset! */
86+
ext_ignore("%s/ip6tables -t filter -D INPUT -m set --match-set tallow6 src -j DROP 2> /dev/null", ipt_path);
87+
ext_ignore("%s/ipset destroy tallow6 2> /dev/null", ipt_path);
88+
}
89+
}
90+
6991
static void setup(void)
7092
{
7193
static bool done = false;
@@ -76,31 +98,76 @@ static void setup(void)
7698
if (nocreate)
7799
return;
78100

79-
/* init ipset and iptables */
80-
/* delete iptables ref to set before the ipset! */
81-
ext_ignore("%s/iptables -t filter -D INPUT -m set --match-set tallow src -j DROP 2> /dev/null", ipt_path);
82-
ext_ignore("%s/ipset destroy tallow 2> /dev/null", ipt_path);
83-
if (ext("%s/ipset create tallow hash:ip family inet timeout %d", ipt_path, expires)) {
84-
fprintf(stderr, "Unable to create ipv4 ipset.\n");
101+
/* firewalld */
102+
char *fwd_path;
103+
if (asprintf(&fwd_path, "%s/firewall-cmd", ipt_path) < 0)
104+
{
105+
fprintf(stderr, "Unable to allocate buffer for path to firewall-cmd.\n");
85106
exit(EXIT_FAILURE);
86107
}
87-
if (ext("%s/iptables -t filter -I INPUT 1 -m set --match-set tallow src -j DROP", ipt_path)) {
88-
fprintf(stderr, "Unable to create iptables rule.\n");
89-
exit(EXIT_FAILURE);
108+
109+
if ((access(fwd_path, X_OK) == 0) && ext("%s/firewall-cmd --state --quiet", ipt_path) == 0) {
110+
fprintf(stdout, "firewalld is running and will be used by tallow.\n");
111+
112+
reset_rules();
113+
114+
/* create ipv4 rule and ipset */
115+
if (ext("%s/firewall-cmd --permanent --quiet --new-ipset=tallow --type=hash:ip --family=inet --option=timeout=%d", ipt_path, expires)) {
116+
fprintf(stderr, "Unable to create ipv4 ipset with firewall-cmd.\n");
117+
exit(EXIT_FAILURE);
118+
}
119+
if (ext("%s/firewall-cmd --permanent --direct --quiet --add-rule ipv4 filter INPUT 1 -m set --match-set tallow src -j DROP", ipt_path)) {
120+
fprintf(stderr, "Unable to create ipv4 firewalld rule.\n");
121+
exit(EXIT_FAILURE);
122+
}
123+
124+
/* create ipv6 rule and ipset */
125+
if (has_ipv6) {
126+
if (ext("%s/firewall-cmd --permanent --quiet --new-ipset=tallow6 --type=hash:ip --family=inet6 --option=timeout=%d", ipt_path, expires)) {
127+
fprintf(stderr, "Unable to create ipv6 ipset with firewall-cmd.\n");
128+
exit(EXIT_FAILURE);
129+
}
130+
if (ext("%s/firewall-cmd --permanent --direct --quiet --add-rule ipv6 filter INPUT 1 -m set --match-set tallow6 src -j DROP ", ipt_path)) {
131+
fprintf(stderr, "Unable to create ipv6 firewalld rule.\n");
132+
exit(EXIT_FAILURE);
133+
}
134+
}
135+
136+
/* reload firewalld for ipsets to load */
137+
if (ext("%s/firewall-cmd --reload --quiet", ipt_path, expires)) {
138+
fprintf(stderr, "Unable to reload firewalld rules.\n");
139+
exit(EXIT_FAILURE);
140+
}
90141
}
142+
/* iptables */
143+
else {
91144

92-
if (has_ipv6) {
93-
ext_ignore("%s/ip6tables -t filter -D INPUT -m set --match-set tallow6 src -j DROP 2> /dev/null", ipt_path);
94-
ext_ignore("%s/ipset destroy tallow6 2> /dev/null", ipt_path);
95-
if (ext("%s/ipset create tallow6 hash:ip family inet6 timeout %d", ipt_path, expires)) {
96-
fprintf(stderr, "Unable to create ipv6 ipset.\n");
145+
reset_rules();
146+
147+
/* create ipv4 rule and ipset */
148+
if (ext("%s/ipset create tallow hash:ip family inet timeout %d", ipt_path, expires)) {
149+
fprintf(stderr, "Unable to create ipv4 ipset.\n");
97150
exit(EXIT_FAILURE);
98151
}
99-
if (ext("%s/ip6tables -t filter -I INPUT 1 -m set --match-set tallow6 src -j DROP", ipt_path)) {
100-
fprintf(stderr, "Unable to create ipt6ables rule.\n");
152+
if (ext("%s/iptables -t filter -A INPUT -m set --match-set tallow src -j DROP", ipt_path)) {
153+
fprintf(stderr, "Unable to create iptables rule.\n");
101154
exit(EXIT_FAILURE);
102155
}
156+
157+
/* create ipv6 rule and ipset */
158+
if (has_ipv6) {
159+
if (ext("%s/ipset create tallow6 hash:ip family inet6 timeout %d", ipt_path, expires)) {
160+
fprintf(stderr, "Unable to create ipv6 ipset.\n");
161+
exit(EXIT_FAILURE);
162+
}
163+
if (ext("%s/ip6tables -t filter -A INPUT -m set --match-set tallow6 src -j DROP", ipt_path)) {
164+
fprintf(stderr, "Unable to create ipt6ables rule.\n");
165+
exit(EXIT_FAILURE);
166+
}
167+
}
103168
}
169+
170+
free(fwd_path);
104171
}
105172

106173
static void block(struct block_struct *s, int instant_block)

0 commit comments

Comments
 (0)