Browse Source

fix in action_nftBan documentation

master
Y 3 years ago
parent
commit
e8d7d8df5c
6 changed files with 58 additions and 33 deletions
  1. +1
    -0
      doc/intro_func.md
  2. +29
    -5
      doc/logandban.md
  3. +5
    -5
      extra/examples/full_pyruse.json
  4. +21
    -21
      tests/action_nftBan.py
  5. +1
    -1
      tests/nftBan.cmd.test_ref
  6. +1
    -1
      tests/pyruse.json

+ 1
- 0
doc/intro_func.md View File

@ -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
* `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
* `_UID`: user ID of the systemd service that produced the log entry
* `_GID`: group ID of the systemd service that produced the log entry


+ 29
- 5
doc/logandban.md View File

@ -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.
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
{
"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",
"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:
```bash
$ sudo nft 'list set Inet4 mail_ban'
$ sudo nft 'list set ip Inet4 mail_ban'
table ip Inet4 {
set mail_ban {
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:
```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.
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`.
### 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
```

+ 5
- 5
extra/examples/full_pyruse.json View File

@ -120,7 +120,7 @@
},
{
"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": [
@ -297,7 +297,7 @@
},
{
"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": [
@ -438,7 +438,7 @@
},
{
"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": [
@ -520,7 +520,7 @@
},
{
"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": [
@ -799,7 +799,7 @@
},
{
"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": [


+ 21
- 21
tests/action_nftBan.py View File

@ -17,45 +17,45 @@ def _clean():
def whenBanIPv4ThenAddToIPv4Set():
_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(nftBanState)
nbLines = 0
with open(nftBanCmd, "rt") as 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
assert nbLines == 1, nbLines
nbBans = 0
with open(nftBanState) as 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
assert nbBans == 1, nbBans
_clean()
def whenBanIPv6ThenAddToIPv6Set():
_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(nftBanState)
nbLines = 0
with open(nftBanCmd, "rt") as 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
assert nbLines == 1, nbLines
nbBans = 0
with open(nftBanState) as 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
assert nbBans == 1, nbBans
_clean()
def whenBanTwoIPThenTwoLinesInState():
_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": "::1"})
action.act({"ip": "10.0.0.1"})
@ -64,9 +64,9 @@ def whenBanTwoIPThenTwoLinesInState():
with open(nftBanState) as s:
for ban in json.load(s):
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":
assert ban["nftSet"] == "I6 ban", str(ban)
assert ban["nftSet"] == "ip6 I6 ban", str(ban)
else:
assert false, str(ban)
nbBans += 1
@ -75,7 +75,7 @@ def whenBanTwoIPThenTwoLinesInState():
def whenBanAnewThenNoDuplicate():
_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"})
assert os.path.exists(nftBanCmd)
@ -85,24 +85,24 @@ def whenBanAnewThenNoDuplicate():
for line in c:
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:
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:
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
nbBans = 0
with open(nftBanState) as s:
for ban in json.load(s):
if ban["IP"] == "10.0.0.1":
assert ban["nftSet"] == "I4 ban", str(ban)
assert ban["nftSet"] == "ip I4 ban", str(ban)
nbBans += 1
assert nbBans == 1, nbBans
_clean()
def whenFinishedBanThenAsIfNotThere():
_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"})
time.sleep(1)
action.act({"ip": "10.0.0.1"})
@ -112,15 +112,15 @@ def whenFinishedBanThenAsIfNotThere():
for line in c:
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:
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
_clean()
def whenUnfinishedBanThenTimeoutReset():
_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"})
time.sleep(1)
action.act({"ip": "10.0.0.1"})
@ -130,11 +130,11 @@ def whenUnfinishedBanThenTimeoutReset():
for line in c:
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:
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:
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
_clean()


+ 1
- 1
tests/nftBan.cmd.test_ref View File

@ -1 +1 @@
add element I4 bans {1.2.3.4 timeout 100s}
add element ip I4 bans {1.2.3.4 timeout 100s}

+ 1
- 1
tests/pyruse.json View File

@ -58,7 +58,7 @@
},
{
"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"
}
],


Loading…
Cancel
Save