Skip to content

Instantly share code, notes, and snippets.

@tvidal-net
Last active September 14, 2025 13:37
Show Gist options
  • Select an option

  • Save tvidal-net/a552e6413d5a8cd3f3dbddf80ea938ba to your computer and use it in GitHub Desktop.

Select an option

Save tvidal-net/a552e6413d5a8cd3f3dbddf80ea938ba to your computer and use it in GitHub Desktop.
update list of addresses attempting to break-in into my local server
#!/usr/bin/env zsh
#############################################################
# /usr/local/bin/abusing
#############################################################
set -eo pipefail
zparseopts -D -E -a ARGS -- v f
[ "${ARGS[(r)-v]}" ] && set -x
function ips () {
journalctl --unit 'ssh' --grep 'invalid' | \
grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}'
}
function nftables () {
local networks=()
networks=( $( ips | supernet - ) )
cat <<EOF
table inet firewall {
set abusing {
typeof ip saddr
flags interval
comment "networks trying to break-in"
counter
elements = {
${(pj.,\n\t\t\t.)networks}
}
}
}
EOF
}
[ "${ARGS[(r)-f]}" ] && nftables || ips | sort -uV
#!/usr/bin/nft -f
# /etc/nftables/abusing.nft
# IPv4/IPv6 Simple & Safe firewall ruleset.
# More examples in /usr/share/nftables/ and /usr/share/doc/nftables/examples/.
define internal = { 192.168.0.0/16, }
destroy table inet firewall
include "/etc/nftables/abusing.nft"
table inet firewall {
chain input {
type filter hook input priority filter
policy drop
ct state invalid drop comment "early drop of invalid connections"
ct state {established, related} accept comment "allow tracked connections"
iif "lo" accept
ip saddr @abusing counter drop
ip protocol icmp accept comment "ICMP"
meta l4proto ipv6-icmp accept comment "ICMPv6"
ip saddr $internal accept comment "allow from internal network"
}
}
# vim:ts=2:sw=2:et:
##
# /etc/systemd/system/shutdown@.service
[Unit]
Description=Runs /etc/default/%i before shutdown
RequiresMountsFor=/
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/true
ExecStop=/etc/default/%i
TimeoutSec=infinity
[Install]
WantedBy=basic.target
## from:
# https://unix.stackexchange.com/questions/739363/a-systemd-service-that-runs-just-before-shutdown-and-uses-a-mounted-filesystem
#!/usr/bin/env python3
#############################################################
# /usr/local/bin/supernet
#############################################################
# sudo pip install --user --break-system-packages ipaddress
#############################################################
import sys
from ipaddress import IPv4Network, collapse_addresses
def supernets(networks: list[IPv4Network]) -> set[IPv4Network]:
min_size = len(networks)
smallest = networks
for bits in range(32, 14, -1):
addresses = [net.supernet(new_prefix=bits) for net in networks]
collapsed = list(collapse_addresses(addresses))
size = len(collapsed)
if size < min_size:
min_size = size
smallest = collapsed
return set(smallest)
def group_addresses(networks: dict[str, int]):
abusing: list[IPv4Network] = []
for ip, count in networks.items():
if count > 16:
net32 = IPv4Network(ip)
abusing.append(net32)
for netmask in supernets(abusing):
print(netmask.compressed)
def main() -> int:
addresses = {}
for file_name in sys.argv[1:]:
file = open(file_name, "r") if file_name != "-" else sys.stdin
try:
for line in file:
address = line.strip()
if not address:
continue
if address not in addresses:
addresses.setdefault(address, 0)
addresses[address] += 1
finally:
file.close()
group_addresses(addresses)
return 0
if __name__ == '__main__':
sys.exit(main())
# vi:sts=2:sw=2:et:
#!/usr/bin/env zsh
#############################################################
# /etc/default/update-abusing
#############################################################
set -eo pipefail
/usr/local/bin/abusing -f | tee /etc/nftables/abusing.nft
# sudo systemctl enable --now shutdown@update-abusing.service
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment