fix in action_nftBan documentation
parent
60b7f11176
commit
e8d7d8df5c
|
@ -38,6 +38,7 @@ The most interesting [filtering or informational entries](https://www.freedeskto
|
||||||
|
|
||||||
* `PRIORITY`: see [Syslog at Wikipedia](https://en.wikipedia.org/wiki/Syslog#Severity_level) for the definitions
|
* `PRIORITY`: see [Syslog at Wikipedia](https://en.wikipedia.org/wiki/Syslog#Severity_level) for the definitions
|
||||||
* `SYSLOG_FACILITY`: see [Syslog at Wikipedia](https://en.wikipedia.org/wiki/Syslog#Facility) for the definitions
|
* `SYSLOG_FACILITY`: see [Syslog at Wikipedia](https://en.wikipedia.org/wiki/Syslog#Facility) for the definitions
|
||||||
|
* `SYSLOG_IDENTIFIER`: short name for the program that produced the log entry (better accuracy than `_SYSTEMD_UNIT`)
|
||||||
* `_HOSTNAME`: short hostname of the machine where the log entry occurred
|
* `_HOSTNAME`: short hostname of the machine where the log entry occurred
|
||||||
* `_UID`: user ID of the systemd service that produced the log entry
|
* `_UID`: user ID of the systemd service that produced the log entry
|
||||||
* `_GID`: group ID of the systemd service that produced the log entry
|
* `_GID`: group ID of the systemd service that produced the log entry
|
||||||
|
|
|
@ -69,7 +69,7 @@ table ip6 Inet6 {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Then the values for `nftSetIPv4` and `nftSetIPv6` will be respectively “`Inet4 mail_ban`” and “`Inet6 mail_ban`”.
|
Then the values for `nftSetIPv4` and `nftSetIPv6` will be respectively “`ip Inet4 mail_ban`” and “`ip6 Inet6 mail_ban`”.
|
||||||
|
|
||||||
Optionally, a number may be specified with `banSeconds` to limit the time this ban will last.
|
Optionally, a number may be specified with `banSeconds` to limit the time this ban will last.
|
||||||
The nice thing with nftables, is that it handles the timeouts itself: no need to keep track of the active bans and remove them using a Python program; the only reason why bans are recorded in a file, is to be able to restore them on reboot.
|
The nice thing with nftables, is that it handles the timeouts itself: no need to keep track of the active bans and remove them using a Python program; the only reason why bans are recorded in a file, is to be able to restore them on reboot.
|
||||||
|
@ -79,12 +79,12 @@ Here are examples:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"action": "action_nftBan",
|
"action": "action_nftBan",
|
||||||
"args": { "IP": "thatIP", "banSeconds": 86400, "nftSetIPv4": "Inet4 mail_ban", "nftSetIPv6": "Inet6 mail_ban" }
|
"args": { "IP": "thatIP", "banSeconds": 86400, "nftSetIPv4": "ip Inet4 mail_ban", "nftSetIPv6": "ip6 Inet6 mail_ban" }
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
"action": "action_nftBan",
|
"action": "action_nftBan",
|
||||||
"args": { "IP": "thatIP", "nftSetIPv4": "Inet4 sshd_ban", "nftSetIPv6": "Inet6 sshd_ban" }
|
"args": { "IP": "thatIP", "nftSetIPv4": "ip Inet4 sshd_ban", "nftSetIPv6": "ip6 Inet6 sshd_ban" }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ Here are examples:
|
||||||
To see what IP addresses are currently banned, here is the `nft` command:
|
To see what IP addresses are currently banned, here is the `nft` command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ sudo nft 'list set Inet4 mail_ban'
|
$ sudo nft 'list set ip Inet4 mail_ban'
|
||||||
table ip Inet4 {
|
table ip Inet4 {
|
||||||
set mail_ban {
|
set mail_ban {
|
||||||
type ipv4_addr
|
type ipv4_addr
|
||||||
|
@ -121,10 +121,34 @@ It is bound to happen some day: you will want to un-ban a banned IP address.
|
||||||
Since `action_nftBan` does not keep the current bans in memory, it is enough to remove the ban using the `nft` command:
|
Since `action_nftBan` does not keep the current bans in memory, it is enough to remove the ban using the `nft` command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ sudo nft 'delete element Inet4 mail_ban {10.0.0.10}'
|
$ sudo nft 'delete element ip Inet4 mail_ban {10.0.0.10}'
|
||||||
```
|
```
|
||||||
|
|
||||||
However, the ban may be restored when restarting Pyruse.
|
However, the ban may be restored when restarting Pyruse.
|
||||||
To avoid that, also delete the corresponding record from the `action_nftBan.py.json` file in Pyruse’s [storage directory](conffile.md).
|
To avoid that, also delete the corresponding record from the `action_nftBan.py.json` file in Pyruse’s [storage directory](conffile.md).
|
||||||
|
|
||||||
To go further, you could tweak your configuration, so that your trusted IP addresses never reach `action_nftBan`.
|
To go further, you could tweak your configuration, so that your trusted IP addresses never reach `action_nftBan`.
|
||||||
|
|
||||||
|
### Manual ban of an IP address
|
||||||
|
|
||||||
|
To add a ban yourself, run a command like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ sudo nft 'add element ip Inet4 ssh_ban {192.168.1.1 timeout 5d}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `timeout …` part can be omitted to add a permanent ban. The timeout can be any combination of days (`d`), hours (`h`), minutes (`m`), and seconds (`s`), eg. “`3d31m16s`”.
|
||||||
|
|
||||||
|
In order to make the ban persistent across reboots, a corresponding record should also be appended to the `action_nftBan.py.json` file in Pyruse’s [storage directory](conffile.md) (the IP address, nft Set, days, hours, minutes, seconds, and actual path to the file should be adapted to your needs):
|
||||||
|
|
||||||
|
* either a time-limited ban:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ sudo sed -i "\$s/.\$/$(date +', {"IP": "192.168.1.1", "nftSet": "ip Inet4 ssh_ban", "timestamp": %s.000000}' -d 'now +3day +31minute +16second')]/" /var/lib/pyruse/action_nftBan.py.json
|
||||||
|
```
|
||||||
|
|
||||||
|
* or an unlimited ban:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ sudo sed -i '$s/.$/, {"IP": "192.168.1.1", "nftSet": "ip Inet4 ssh_ban", "timestamp": 0}]/' /var/lib/pyruse/action_nftBan.py.json
|
||||||
|
```
|
||||||
|
|
|
@ -120,7 +120,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"action": "action_nftBan",
|
"action": "action_nftBan",
|
||||||
"args": { "IP": "thatIP", "banSeconds": 900, "nftSetIPv4": "Inet4 https_ban", "nftSetIPv6": "Inet6 https_ban" }
|
"args": { "IP": "thatIP", "banSeconds": 900, "nftSetIPv4": "ip Inet4 https_ban", "nftSetIPv6": "ip6 Inet6 https_ban" }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"… Let Nextcloud core messages pass-through": [
|
"… Let Nextcloud core messages pass-through": [
|
||||||
|
@ -297,7 +297,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"action": "action_nftBan",
|
"action": "action_nftBan",
|
||||||
"args": { "IP": "thatIP", "banSeconds": 7200, "nftSetIPv4": "Inet4 https_ban", "nftSetIPv6": "Inet6 https_ban" }
|
"args": { "IP": "thatIP", "banSeconds": 7200, "nftSetIPv4": "ip Inet4 https_ban", "nftSetIPv6": "ip6 Inet6 https_ban" }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"… Immediate warning for connectivity errors": [
|
"… Immediate warning for connectivity errors": [
|
||||||
|
@ -438,7 +438,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"action": "action_nftBan",
|
"action": "action_nftBan",
|
||||||
"args": { "IP": "thatIP", "banSeconds": 432000, "nftSetIPv4": "Inet4 mail_ban", "nftSetIPv6": "Inet6 mail_ban" }
|
"args": { "IP": "thatIP", "banSeconds": 432000, "nftSetIPv4": "ip Inet4 mail_ban", "nftSetIPv6": "ip6 Inet6 mail_ban" }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"… Discard Dovecot debug entries": [
|
"… Discard Dovecot debug entries": [
|
||||||
|
@ -520,7 +520,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"action": "action_nftBan",
|
"action": "action_nftBan",
|
||||||
"args": { "IP": "thatIP", "banSeconds": 432000, "nftSetIPv4": "Inet4 mail_ban", "nftSetIPv6": "Inet6 mail_ban" }
|
"args": { "IP": "thatIP", "banSeconds": 432000, "nftSetIPv4": "ip Inet4 mail_ban", "nftSetIPv6": "ip6 Inet6 mail_ban" }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"… Detect some SMTP spammers": [
|
"… Detect some SMTP spammers": [
|
||||||
|
@ -799,7 +799,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"action": "action_nftBan",
|
"action": "action_nftBan",
|
||||||
"args": { "IP": "thatIP", "banSeconds": 432000, "nftSetIPv4": "Inet4 sshd_ban", "nftSetIPv6": "Inet6 sshd_ban" }
|
"args": { "IP": "thatIP", "banSeconds": 432000, "nftSetIPv4": "ip Inet4 sshd_ban", "nftSetIPv6": "ip6 Inet6 sshd_ban" }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Warn of SpamAssassin update failures": [
|
"Warn of SpamAssassin update failures": [
|
||||||
|
|
|
@ -17,45 +17,45 @@ def _clean():
|
||||||
|
|
||||||
def whenBanIPv4ThenAddToIPv4Set():
|
def whenBanIPv4ThenAddToIPv4Set():
|
||||||
_clean()
|
_clean()
|
||||||
Action({"IP": "ip", "nftSetIPv4": "I4 ban", "nftSetIPv6": "I6 ban"}).act({"ip": "10.0.0.1"})
|
Action({"IP": "ip", "nftSetIPv4": "ip I4 ban", "nftSetIPv6": "ip6 I6 ban"}).act({"ip": "10.0.0.1"})
|
||||||
assert os.path.exists(nftBanCmd)
|
assert os.path.exists(nftBanCmd)
|
||||||
assert os.path.exists(nftBanState)
|
assert os.path.exists(nftBanState)
|
||||||
nbLines = 0
|
nbLines = 0
|
||||||
with open(nftBanCmd, "rt") as c:
|
with open(nftBanCmd, "rt") as c:
|
||||||
for line in c:
|
for line in c:
|
||||||
assert line == "add element I4 ban {10.0.0.1}\n", line
|
assert line == "add element ip I4 ban {10.0.0.1}\n", line
|
||||||
nbLines += 1
|
nbLines += 1
|
||||||
assert nbLines == 1, nbLines
|
assert nbLines == 1, nbLines
|
||||||
nbBans = 0
|
nbBans = 0
|
||||||
with open(nftBanState) as s:
|
with open(nftBanState) as s:
|
||||||
for ban in json.load(s):
|
for ban in json.load(s):
|
||||||
assert ban["IP"] == "10.0.0.1" and ban["nftSet"] == "I4 ban", str(ban)
|
assert ban["IP"] == "10.0.0.1" and ban["nftSet"] == "ip I4 ban", str(ban)
|
||||||
nbBans += 1
|
nbBans += 1
|
||||||
assert nbBans == 1, nbBans
|
assert nbBans == 1, nbBans
|
||||||
_clean()
|
_clean()
|
||||||
|
|
||||||
def whenBanIPv6ThenAddToIPv6Set():
|
def whenBanIPv6ThenAddToIPv6Set():
|
||||||
_clean()
|
_clean()
|
||||||
Action({"IP": "ip", "nftSetIPv4": "I4 ban", "nftSetIPv6": "I6 ban"}).act({"ip": "::1"})
|
Action({"IP": "ip", "nftSetIPv4": "ip I4 ban", "nftSetIPv6": "ip6 I6 ban"}).act({"ip": "::1"})
|
||||||
assert os.path.exists(nftBanCmd)
|
assert os.path.exists(nftBanCmd)
|
||||||
assert os.path.exists(nftBanState)
|
assert os.path.exists(nftBanState)
|
||||||
nbLines = 0
|
nbLines = 0
|
||||||
with open(nftBanCmd, "rt") as c:
|
with open(nftBanCmd, "rt") as c:
|
||||||
for line in c:
|
for line in c:
|
||||||
assert line == "add element I6 ban {::1}\n", line
|
assert line == "add element ip6 I6 ban {::1}\n", line
|
||||||
nbLines += 1
|
nbLines += 1
|
||||||
assert nbLines == 1, nbLines
|
assert nbLines == 1, nbLines
|
||||||
nbBans = 0
|
nbBans = 0
|
||||||
with open(nftBanState) as s:
|
with open(nftBanState) as s:
|
||||||
for ban in json.load(s):
|
for ban in json.load(s):
|
||||||
assert ban["IP"] == "::1" and ban["nftSet"] == "I6 ban", str(ban)
|
assert ban["IP"] == "::1" and ban["nftSet"] == "ip6 I6 ban", str(ban)
|
||||||
nbBans += 1
|
nbBans += 1
|
||||||
assert nbBans == 1, nbBans
|
assert nbBans == 1, nbBans
|
||||||
_clean()
|
_clean()
|
||||||
|
|
||||||
def whenBanTwoIPThenTwoLinesInState():
|
def whenBanTwoIPThenTwoLinesInState():
|
||||||
_clean()
|
_clean()
|
||||||
action = Action({"IP": "ip", "nftSetIPv4": "I4 ban", "nftSetIPv6": "I6 ban"})
|
action = Action({"IP": "ip", "nftSetIPv4": "ip I4 ban", "nftSetIPv6": "ip6 I6 ban"})
|
||||||
action.act({"ip": "10.0.0.1"})
|
action.act({"ip": "10.0.0.1"})
|
||||||
action.act({"ip": "::1"})
|
action.act({"ip": "::1"})
|
||||||
action.act({"ip": "10.0.0.1"})
|
action.act({"ip": "10.0.0.1"})
|
||||||
|
@ -64,9 +64,9 @@ def whenBanTwoIPThenTwoLinesInState():
|
||||||
with open(nftBanState) as s:
|
with open(nftBanState) as s:
|
||||||
for ban in json.load(s):
|
for ban in json.load(s):
|
||||||
if ban["IP"] == "10.0.0.1":
|
if ban["IP"] == "10.0.0.1":
|
||||||
assert ban["nftSet"] == "I4 ban", str(ban)
|
assert ban["nftSet"] == "ip I4 ban", str(ban)
|
||||||
elif ban["IP"] == "::1":
|
elif ban["IP"] == "::1":
|
||||||
assert ban["nftSet"] == "I6 ban", str(ban)
|
assert ban["nftSet"] == "ip6 I6 ban", str(ban)
|
||||||
else:
|
else:
|
||||||
assert false, str(ban)
|
assert false, str(ban)
|
||||||
nbBans += 1
|
nbBans += 1
|
||||||
|
@ -75,7 +75,7 @@ def whenBanTwoIPThenTwoLinesInState():
|
||||||
|
|
||||||
def whenBanAnewThenNoDuplicate():
|
def whenBanAnewThenNoDuplicate():
|
||||||
_clean()
|
_clean()
|
||||||
action = Action({"IP": "ip", "nftSetIPv4": "I4 ban", "nftSetIPv6": "I6 ban"})
|
action = Action({"IP": "ip", "nftSetIPv4": "ip I4 ban", "nftSetIPv6": "ip6 I6 ban"})
|
||||||
action.act({"ip": "10.0.0.1"})
|
action.act({"ip": "10.0.0.1"})
|
||||||
action.act({"ip": "10.0.0.1"})
|
action.act({"ip": "10.0.0.1"})
|
||||||
assert os.path.exists(nftBanCmd)
|
assert os.path.exists(nftBanCmd)
|
||||||
|
@ -85,24 +85,24 @@ def whenBanAnewThenNoDuplicate():
|
||||||
for line in c:
|
for line in c:
|
||||||
lineCount += 1
|
lineCount += 1
|
||||||
if lineCount == 1:
|
if lineCount == 1:
|
||||||
assert line == "add element I4 ban {10.0.0.1}\n", line
|
assert line == "add element ip I4 ban {10.0.0.1}\n", line
|
||||||
elif lineCount == 2:
|
elif lineCount == 2:
|
||||||
assert line == "delete element I4 ban {10.0.0.1}\n", line
|
assert line == "delete element ip I4 ban {10.0.0.1}\n", line
|
||||||
elif lineCount == 3:
|
elif lineCount == 3:
|
||||||
assert line == "add element I4 ban {10.0.0.1}\n", line
|
assert line == "add element ip I4 ban {10.0.0.1}\n", line
|
||||||
assert lineCount == 3, lineCount
|
assert lineCount == 3, lineCount
|
||||||
nbBans = 0
|
nbBans = 0
|
||||||
with open(nftBanState) as s:
|
with open(nftBanState) as s:
|
||||||
for ban in json.load(s):
|
for ban in json.load(s):
|
||||||
if ban["IP"] == "10.0.0.1":
|
if ban["IP"] == "10.0.0.1":
|
||||||
assert ban["nftSet"] == "I4 ban", str(ban)
|
assert ban["nftSet"] == "ip I4 ban", str(ban)
|
||||||
nbBans += 1
|
nbBans += 1
|
||||||
assert nbBans == 1, nbBans
|
assert nbBans == 1, nbBans
|
||||||
_clean()
|
_clean()
|
||||||
|
|
||||||
def whenFinishedBanThenAsIfNotThere():
|
def whenFinishedBanThenAsIfNotThere():
|
||||||
_clean()
|
_clean()
|
||||||
action = Action({"IP": "ip", "nftSetIPv4": "I4 ban", "nftSetIPv6": "I6 ban", "banSeconds": 1})
|
action = Action({"IP": "ip", "nftSetIPv4": "ip I4 ban", "nftSetIPv6": "ip6 I6 ban", "banSeconds": 1})
|
||||||
action.act({"ip": "10.0.0.1"})
|
action.act({"ip": "10.0.0.1"})
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
action.act({"ip": "10.0.0.1"})
|
action.act({"ip": "10.0.0.1"})
|
||||||
|
@ -112,15 +112,15 @@ def whenFinishedBanThenAsIfNotThere():
|
||||||
for line in c:
|
for line in c:
|
||||||
lineCount += 1
|
lineCount += 1
|
||||||
if lineCount == 1:
|
if lineCount == 1:
|
||||||
assert line == "add element I4 ban {10.0.0.1 timeout 1s}\n", line
|
assert line == "add element ip I4 ban {10.0.0.1 timeout 1s}\n", line
|
||||||
elif lineCount == 2:
|
elif lineCount == 2:
|
||||||
assert line == "add element I4 ban {10.0.0.1 timeout 1s}\n", line
|
assert line == "add element ip I4 ban {10.0.0.1 timeout 1s}\n", line
|
||||||
assert lineCount == 2, lineCount
|
assert lineCount == 2, lineCount
|
||||||
_clean()
|
_clean()
|
||||||
|
|
||||||
def whenUnfinishedBanThenTimeoutReset():
|
def whenUnfinishedBanThenTimeoutReset():
|
||||||
_clean()
|
_clean()
|
||||||
action = Action({"IP": "ip", "nftSetIPv4": "I4 ban", "nftSetIPv6": "I6 ban", "banSeconds": 2})
|
action = Action({"IP": "ip", "nftSetIPv4": "ip I4 ban", "nftSetIPv6": "ip6 I6 ban", "banSeconds": 2})
|
||||||
action.act({"ip": "10.0.0.1"})
|
action.act({"ip": "10.0.0.1"})
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
action.act({"ip": "10.0.0.1"})
|
action.act({"ip": "10.0.0.1"})
|
||||||
|
@ -130,11 +130,11 @@ def whenUnfinishedBanThenTimeoutReset():
|
||||||
for line in c:
|
for line in c:
|
||||||
lineCount += 1
|
lineCount += 1
|
||||||
if lineCount == 1:
|
if lineCount == 1:
|
||||||
assert line == "add element I4 ban {10.0.0.1 timeout 2s}\n", line
|
assert line == "add element ip I4 ban {10.0.0.1 timeout 2s}\n", line
|
||||||
elif lineCount == 2:
|
elif lineCount == 2:
|
||||||
assert line == "delete element I4 ban {10.0.0.1}\n", line
|
assert line == "delete element ip I4 ban {10.0.0.1}\n", line
|
||||||
elif lineCount == 3:
|
elif lineCount == 3:
|
||||||
assert line == "add element I4 ban {10.0.0.1 timeout 2s}\n", line
|
assert line == "add element ip I4 ban {10.0.0.1 timeout 2s}\n", line
|
||||||
assert lineCount == 3, lineCount
|
assert lineCount == 3, lineCount
|
||||||
_clean()
|
_clean()
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
add element I4 bans {1.2.3.4 timeout 100s}
|
add element ip I4 bans {1.2.3.4 timeout 100s}
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"action": "action_nftBan",
|
"action": "action_nftBan",
|
||||||
"args": { "IP": "ip", "banSeconds": 100, "nftSetIPv4": "I4 bans", "nftSetIPv6": "I6 bans" },
|
"args": { "IP": "ip", "banSeconds": 100, "nftSetIPv4": "ip I4 bans", "nftSetIPv6": "ip6 I6 bans" },
|
||||||
"then": "… finalize after last action"
|
"then": "… finalize after last action"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue