0

I see things like this in my /var/log/auth.log

sshd[2173]: Unable to negotiate with 218.92.0.205 port 21029: no matching host key type found. Their offer: ssh-rsa,ssh-dss [preauth]

sshd[1964]: Unable to negotiate with 218.92.0.205 port 26342: no matching host key type found. Their offer: ssh-rsa,ssh-dss [preauth]

sshd[3031]: Unable to negotiate with 218.92.0.205 port 25903: no matching host key type found. Their offer: ssh-rsa,ssh-dss [preauth]

fail2ban doesn't filter these issues.

for reference my jail.local config:

[sshd]


enabled = true
filter = sshd
port = 0:65535
banaction = ufw
bantime = -1
maxretry = 1
logpath = %(sshd_log)s
backend = %(sshd_backend)s

I think I need to update my regex, how can I block this spam?

Woodstock
  • 103
  • 1
  • 1
  • 10

2 Answers2

1

When looking into /etc/fail2ban/filter.d/sshd.conf there'll hopefully be according regular expressions for the Unable to negotiate with log entries.

sshd runs in normal mode, in order to detect ddos (additionally there are extra and aggressive) that mode has to be defined in jail.local.

For the scenario you pointed out, it would be extra:

[sshd]
mode = extra
# same as filter with argument
# filter = sshd[mode=extra]
# ... rest of your configuration, findtime, maxretry ...

Besides that it also would be possible to define another jail with different settings:

[sshd-custom]
enabled = true
filter = sshd[mode=extra]
# ... rest of your configuration, findtime, maxretry ...
Oliver Hader
  • 111
  • 4
  • side-note: depending on your fail2ban version IPv6 might not be supported which might be an issue when trying to mitigate DoS scenarios (fail2ban v0.10.0 does support IPv6) – Oliver Hader Sep 18 '19 at 20:23
0

NOTE: Be sure to run as root

The theory is very simple:

  1. Read the /var/secure/log and filter the ssh password mismatch (need root)
  2. Create a python script able to create an 'iptables ban' command based on a treshold (hardcoded)

If you have python installed (and you have if you have fail2ban) you can run this simple script

import sys
import re

# Save the input data into a string
raw = sys.stdin.read().strip()

BAN_COUNT = 3
# Split the lines of the log
data = raw.split("\n")
to_ban = {}
# Iterate the lines
for item in data:
    # Extract IP
    ip = re.findall(r"[0-9]+(?:\.[0-9]+){3}", item)
    # Due to the filter, we can have only 1 IP
    if len(ip) == 1:
        # print("Found IP to BAN -> {}".format(ip[0]))
        # If IP alredy found increase counter
        if ip[0] in to_ban:
            to_ban[ip[0]] += 1
        # First time that we encounter the IP, create new entry in dict
        else:
            to_ban[ip[0]] = 1
# Create iptables mask for ban
for keys in to_ban.keys():
    if to_ban[keys] >= BAN_COUNT:
        # BAN MASK
        # Use this for ban
        # ban_mask = 'iptables -A INPUT -s {} -j DROP'.format(keys)
        # Use this for test purpouse
        ban_mask = 'echo "iptables -A INPUT -s {} -j DROP"'.format(keys)
        print(ban_mask)

Now that we have a python script that take the input lines, extract the ip, count how many times they compare in text and print the iptables command for ban the ip, we can parse the secure log.

Save the script as ban.py

cat /var/log/secure | egrep 'Failed password for' | python ban.py | xargs command 
alessiosavi
  • 131
  • 5