fix(fail2ban): Multiple fixes
- fix: quotes removed from `emptylog` in jail.local - refactor: Remove separate fn for Linux fail2ban - fix: Check fail2ban config validity before starting the service - fix: FreeBSD: enable fail2ban before starting the service
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
SCRIPT_NAME=server-init-harden
|
SCRIPT_NAME=server-init-harden
|
||||||
SCRIPT_VERSION=3.1
|
SCRIPT_VERSION=3.7
|
||||||
TIMESTAMP=$(date '+%Y-%m-%d-%H-%M-%S')
|
TIMESTAMP=$(date '+%Y-%m-%d-%H-%M-%S')
|
||||||
LOG_FILE_NAME="/var/log/${SCRIPT_NAME}_${TIMESTAMP}.log"
|
LOG_FILE_NAME="/var/log/${SCRIPT_NAME}_${TIMESTAMP}.log"
|
||||||
|
|
||||||
@@ -731,133 +731,6 @@ configure_firewall() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
fail2ban_jail_settings() {
|
|
||||||
JAIL_LOCAL=$1
|
|
||||||
|
|
||||||
# Backup jail.local if it exists
|
|
||||||
if [ -f "$JAIL_LOCAL" ]; then
|
|
||||||
JAIL_LOCAL_BACKUP="${JAIL_LOCAL}.bak.${TIMESTAMP}"
|
|
||||||
cp "$JAIL_LOCAL" "$JAIL_LOCAL_BACKUP"
|
|
||||||
file_log "INFO" "Created backup of existing jail.local at $JAIL_LOCAL_BACKUP"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get server's public IP
|
|
||||||
file_log "Getting server's public IP..."
|
|
||||||
PUBLIC_IP=$(curl -s -4 --max-time 10 --fail https://ifconfig.me 2>&1)
|
|
||||||
file_log "INFO" "Server public IP: $PUBLIC_IP"
|
|
||||||
|
|
||||||
file_log "INFO" "Adding jails to $JAIL_LOCAL..."
|
|
||||||
|
|
||||||
cat <<EOF >"$JAIL_LOCAL"
|
|
||||||
[DEFAULT]
|
|
||||||
backend = auto
|
|
||||||
banaction = firewallcmd-rich-rules[actiontype=<multiport>]
|
|
||||||
banaction_allports = firewallcmd-rich-rules[actiontype=<allports>]
|
|
||||||
ignoreip = 127.0.0.1/8 ::1 $PUBLIC_IP
|
|
||||||
bantime = 1h
|
|
||||||
findtime = 10m
|
|
||||||
maxretry = 5
|
|
||||||
# Action: ban only (action_) or ban and email (action_mwl)
|
|
||||||
action = %(action_)s
|
|
||||||
|
|
||||||
#
|
|
||||||
# SSH Jail
|
|
||||||
#
|
|
||||||
[sshd]
|
|
||||||
enabled = true
|
|
||||||
port = ssh
|
|
||||||
filter = sshd
|
|
||||||
logpath = %(sshd_log)s
|
|
||||||
/var/log/auth.log
|
|
||||||
/var/log/secure
|
|
||||||
maxretry = 5
|
|
||||||
bantime = 1h
|
|
||||||
findtime = 10m
|
|
||||||
|
|
||||||
#
|
|
||||||
# Nginx Bot Search - Blocks bots searching for vulnerabilities (404 errors)
|
|
||||||
#
|
|
||||||
[nginx-botsearch]
|
|
||||||
enabled = true
|
|
||||||
port = http,https
|
|
||||||
filter = nginx-botsearch
|
|
||||||
logpath = %(nginx_access_log)s
|
|
||||||
/var/log/nginx/access.log
|
|
||||||
$(dirname "$JAIL_LOCAL_BACKUP")/emptylog
|
|
||||||
maxretry = 5
|
|
||||||
bantime = 6h
|
|
||||||
findtime = 10m
|
|
||||||
|
|
||||||
#
|
|
||||||
# Nginx HTTP Authentication
|
|
||||||
#
|
|
||||||
[nginx-http-auth]
|
|
||||||
enabled = true
|
|
||||||
port = http,https
|
|
||||||
filter = nginx-http-auth
|
|
||||||
logpath = %(nginx_error_log)s
|
|
||||||
/var/log/nginx/error.log
|
|
||||||
$(dirname "$JAIL_LOCAL_BACKUP")/emptylog
|
|
||||||
maxretry = 3
|
|
||||||
bantime = 6h
|
|
||||||
findtime = 10m
|
|
||||||
|
|
||||||
#
|
|
||||||
# Nginx Limit Request (DDoS protection)
|
|
||||||
#
|
|
||||||
[nginx-limit-req]
|
|
||||||
enabled = true
|
|
||||||
port = http,https
|
|
||||||
filter = nginx-limit-req
|
|
||||||
logpath = %(nginx_error_log)s
|
|
||||||
/var/log/nginx/error.log
|
|
||||||
$(dirname "$JAIL_LOCAL_BACKUP")/emptylog
|
|
||||||
maxretry = 10
|
|
||||||
bantime = 6h
|
|
||||||
findtime = 10m
|
|
||||||
|
|
||||||
#
|
|
||||||
# HAProxy HTTP Authentication Failures
|
|
||||||
#
|
|
||||||
[haproxy-http-auth]
|
|
||||||
enabled = true
|
|
||||||
port = http,https
|
|
||||||
filter = haproxy-http-auth
|
|
||||||
logpath = /var/log/haproxy.log
|
|
||||||
/var/log/haproxy/haproxy.log
|
|
||||||
/var/log/haproxy/*.log
|
|
||||||
$(dirname "$JAIL_LOCAL_BACKUP")/emptylog
|
|
||||||
maxretry = 3
|
|
||||||
bantime = 6h
|
|
||||||
findtime = 10m
|
|
||||||
|
|
||||||
#
|
|
||||||
# Recidive Jail - Ban repeat offenders
|
|
||||||
# This jail monitors fail2ban.log for IPs that have been banned multiple times
|
|
||||||
#
|
|
||||||
[recidive]
|
|
||||||
enabled = true
|
|
||||||
filter = recidive
|
|
||||||
logpath = /var/log/fail2ban.log
|
|
||||||
banaction = %(banaction_allports)s
|
|
||||||
bantime = 1w
|
|
||||||
findtime = 1d
|
|
||||||
maxretry = 3
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# FreeBSD specific ban-actions
|
|
||||||
if [ -f /etc/pf.conf ]; then
|
|
||||||
sed -i.bak -E 's/(^banaction = )firewallcmd.*/\1pf[actiontype=<allports>]/' "$JAIL_LOCAL"
|
|
||||||
sed -i.bak -E 's/(^banaction_allports = )firewallcmd.*/\1pf[actiontype=<allports>]/' "$JAIL_LOCAL"
|
|
||||||
rm "$JAIL_LOCAL".bak >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Dummy logfile so the configuration doesn't fail
|
|
||||||
touch "$(dirname "$JAIL_LOCAL")"/emptylog && chmod 644 "$(dirname "$JAIL_LOCAL")"/emptylog
|
|
||||||
|
|
||||||
file_log "INFO" "Jails added to $JAIL_LOCAL"
|
|
||||||
}
|
|
||||||
|
|
||||||
revert_fail2ban_jail_file() {
|
revert_fail2ban_jail_file() {
|
||||||
if [ -f "$JAIL_LOCAL_BACKUP" ]; then
|
if [ -f "$JAIL_LOCAL_BACKUP" ]; then
|
||||||
console_log "INFO" "Reverting jail.local using [ $JAIL_LOCAL_BACKUP ]..."
|
console_log "INFO" "Reverting jail.local using [ $JAIL_LOCAL_BACKUP ]..."
|
||||||
@@ -885,19 +758,142 @@ revert_fail2ban_jail_file() {
|
|||||||
console_log "INFO" "Restarted fail2ban with original configuration"
|
console_log "INFO" "Restarted fail2ban with original configuration"
|
||||||
file_log "INFO" "Restarted fail2ban with original configuration"
|
file_log "INFO" "Restarted fail2ban with original configuration"
|
||||||
else
|
else
|
||||||
|
manage_service fail2ban disable
|
||||||
console_log "ERROR" "Failed to restart fail2ban service even with original configuration"
|
console_log "ERROR" "Failed to restart fail2ban service even with original configuration"
|
||||||
file_log "ERROR" "Failed to restart fail2ban service even with original configuration"
|
file_log "ERROR" "Failed to restart fail2ban service even with original configuration"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_fail2ban_linux() {
|
fail2ban_jail_settings() {
|
||||||
fail2ban_jail_settings "/etc/fail2ban/jail.local"
|
JAIL_LOCAL=$1
|
||||||
|
|
||||||
|
# Backup jail.local if it exists
|
||||||
|
if [ -f "$JAIL_LOCAL" ]; then
|
||||||
|
JAIL_LOCAL_BACKUP="${JAIL_LOCAL}.bak.${TIMESTAMP}"
|
||||||
|
cp "$JAIL_LOCAL" "$JAIL_LOCAL_BACKUP"
|
||||||
|
file_log "INFO" "Created backup of existing jail.local at $JAIL_LOCAL_BACKUP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get server's public IP
|
||||||
|
file_log "Getting server's public IP..."
|
||||||
|
PUBLIC_IP=$(curl -s -4 --max-time 10 --fail https://ifconfig.me 2>&1)
|
||||||
|
file_log "INFO" "Server public IP: $PUBLIC_IP"
|
||||||
|
|
||||||
|
# Dummy logfile so the configuration doesn't fail when nginx/haproxy are not installed
|
||||||
|
JAIL_LOCAL_DIR=$(dirname "$JAIL_LOCAL")
|
||||||
|
touch "$JAIL_LOCAL_DIR"/emptylog && chmod 644 "$JAIL_LOCAL_DIR"/emptylog
|
||||||
|
|
||||||
|
file_log "INFO" "Adding jails to $JAIL_LOCAL..."
|
||||||
|
|
||||||
|
cat <<EOF >"$JAIL_LOCAL"
|
||||||
|
[DEFAULT]
|
||||||
|
backend = auto
|
||||||
|
banaction = firewallcmd-rich-rules[actiontype=<multiport>]
|
||||||
|
banaction_allports = firewallcmd-rich-rules[actiontype=<allports>]
|
||||||
|
ignoreip = 127.0.0.1/8 ::1 $PUBLIC_IP
|
||||||
|
bantime = 1h
|
||||||
|
findtime = 10m
|
||||||
|
maxretry = 5
|
||||||
|
# Action: ban only (action_) or ban and email (action_mwl)
|
||||||
|
action = %(action_)s
|
||||||
|
|
||||||
|
#
|
||||||
|
# SSH Jail
|
||||||
|
#
|
||||||
|
[sshd]
|
||||||
|
enabled = true
|
||||||
|
port = ssh
|
||||||
|
filter = sshd
|
||||||
|
logpath = %(sshd_log)s
|
||||||
|
/var/log/auth.log
|
||||||
|
/var/log/secure
|
||||||
|
maxretry = 5
|
||||||
|
bantime = 1h
|
||||||
|
|
||||||
|
#
|
||||||
|
# Nginx Bot Search - Blocks bots searching for vulnerabilities (404 errors)
|
||||||
|
#
|
||||||
|
[nginx-botsearch]
|
||||||
|
enabled = true
|
||||||
|
port = http,https
|
||||||
|
filter = nginx-botsearch
|
||||||
|
logpath = %(nginx_access_log)s
|
||||||
|
$JAIL_LOCAL_DIR/emptylog
|
||||||
|
maxretry = 5
|
||||||
|
bantime = 6h
|
||||||
|
|
||||||
|
#
|
||||||
|
# Nginx HTTP Authentication
|
||||||
|
#
|
||||||
|
[nginx-http-auth]
|
||||||
|
enabled = true
|
||||||
|
port = http,https
|
||||||
|
filter = nginx-http-auth
|
||||||
|
logpath = %(nginx_error_log)s
|
||||||
|
$JAIL_LOCAL_DIR/emptylog
|
||||||
|
maxretry = 3
|
||||||
|
bantime = 6h
|
||||||
|
|
||||||
|
#
|
||||||
|
# Nginx Limit Request (DDoS protection)
|
||||||
|
#
|
||||||
|
[nginx-limit-req]
|
||||||
|
enabled = true
|
||||||
|
port = http,https
|
||||||
|
filter = nginx-limit-req
|
||||||
|
logpath = %(nginx_error_log)s
|
||||||
|
$JAIL_LOCAL_DIR/emptylog
|
||||||
|
maxretry = 10
|
||||||
|
bantime = 6h
|
||||||
|
|
||||||
|
#
|
||||||
|
# HAProxy HTTP Authentication Failures
|
||||||
|
#
|
||||||
|
[haproxy-http-auth]
|
||||||
|
enabled = true
|
||||||
|
port = http,https
|
||||||
|
filter = haproxy-http-auth
|
||||||
|
logpath = /var/log/haproxy.log
|
||||||
|
/var/log/haproxy/haproxy.log
|
||||||
|
/var/log/haproxy/*.log
|
||||||
|
$JAIL_LOCAL_DIR/emptylog
|
||||||
|
maxretry = 3
|
||||||
|
bantime = 6h
|
||||||
|
|
||||||
|
#
|
||||||
|
# Recidive Jail - Ban repeat offenders
|
||||||
|
# This jail monitors fail2ban.log for IPs that have been banned multiple times
|
||||||
|
#
|
||||||
|
[recidive]
|
||||||
|
enabled = true
|
||||||
|
filter = recidive
|
||||||
|
logpath = /var/log/fail2ban.log
|
||||||
|
$JAIL_LOCAL_DIR/emptylog
|
||||||
|
banaction = %(banaction_allports)s
|
||||||
|
bantime = 1w
|
||||||
|
findtime = 1d
|
||||||
|
maxretry = 3
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# FreeBSD specific ban-actions
|
||||||
|
if [ -f /etc/pf.conf ]; then
|
||||||
|
sed -i.bak -E 's/(^banaction = )firewallcmd.*/\1pf[actiontype=<allports>]/' "$JAIL_LOCAL"
|
||||||
|
sed -i.bak -E 's/(^banaction_allports = )firewallcmd.*/\1pf[actiontype=<allports>]/' "$JAIL_LOCAL"
|
||||||
|
rm "$JAIL_LOCAL".bak >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
|
||||||
|
file_log "INFO" "Jails added to $JAIL_LOCAL"
|
||||||
|
|
||||||
|
output=$(fail2ban-client -t 2>&1 && manage_service fail2ban enable && manage_service fail2ban start)
|
||||||
|
command_status=$?
|
||||||
|
|
||||||
|
file_log "INFO" "$output"
|
||||||
|
|
||||||
# Restart fail2ban
|
# Restart fail2ban
|
||||||
if ! manage_service fail2ban restart; then # Error in configuration
|
if [ $command_status -ne 0 ]; then
|
||||||
console_log "ERROR" "Failed to restart fail2ban service"
|
console_log "ERROR" "Failed to start fail2ban service"
|
||||||
file_log "ERROR" "Failed to restart fail2ban service"
|
file_log "ERROR" "Failed to start fail2ban service"
|
||||||
|
|
||||||
revert_fail2ban_jail_file
|
revert_fail2ban_jail_file
|
||||||
|
|
||||||
@@ -905,32 +901,10 @@ configure_fail2ban_linux() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_fail2ban_freebsd() {
|
fail2ban_freebsd_pf_conf() {
|
||||||
RC_CONF_FILE="/etc/rc.conf"
|
|
||||||
PF_CONF_FILE="/etc/pf.conf"
|
PF_CONF_FILE="/etc/pf.conf"
|
||||||
fail2ban_jail_settings "/usr/local/etc/fail2ban/jail.local"
|
|
||||||
|
|
||||||
# Auto start fail2ban on boot and restart with new configuration
|
|
||||||
output=$(sysrc fail2ban_enable="YES" 2>&1 && manage_service fail2ban restart 2>&1)
|
|
||||||
command_output=$?
|
|
||||||
|
|
||||||
file_log "INFO" "$output"
|
|
||||||
|
|
||||||
# Revert fail2ban & rc.conf changes if fail2ban starting failed
|
|
||||||
if [ $command_output -ne 0 ]; then
|
|
||||||
file_log "ERROR" "Could not start fail2ban service. Reverting changes..."
|
|
||||||
|
|
||||||
# Don't start fail2ban on boot
|
|
||||||
sed -i.bak '/^fail2ban_enable/d' $RC_CONF_FILE
|
|
||||||
rm "$RC_CONF_FILE".bak >/dev/null 2>&1
|
|
||||||
|
|
||||||
file_log "INFO" "Reverted $RC_CONF_FILE"
|
|
||||||
|
|
||||||
revert_fail2ban_jail_file
|
|
||||||
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
# Backup the pf configuration file
|
||||||
if [ -f "$PF_CONF_FILE" ]; then
|
if [ -f "$PF_CONF_FILE" ]; then
|
||||||
PF_CONF_BACKUP_FILE="${PF_CONF_FILE}.bak.${TIMESTAMP}"
|
PF_CONF_BACKUP_FILE="${PF_CONF_FILE}.bak.${TIMESTAMP}"
|
||||||
output=$(cp "$PF_CONF_FILE" "$PF_CONF_BACKUP_FILE" 2>&1)
|
output=$(cp "$PF_CONF_FILE" "$PF_CONF_BACKUP_FILE" 2>&1)
|
||||||
@@ -954,7 +928,7 @@ EOF
|
|||||||
command_status=$?
|
command_status=$?
|
||||||
file_log "INFO" "$output"
|
file_log "INFO" "$output"
|
||||||
|
|
||||||
if [ $command_output -ne 0 ]; then
|
if [ $command_status -ne 0 ]; then
|
||||||
console_log "ERROR" "Failed to restart pf post fail2ban. Reverting pf.config..."
|
console_log "ERROR" "Failed to restart pf post fail2ban. Reverting pf.config..."
|
||||||
file_log "ERROR" "Failed to restart pf post fail2ban. Reverting pf.config..."
|
file_log "ERROR" "Failed to restart pf post fail2ban. Reverting pf.config..."
|
||||||
|
|
||||||
@@ -985,11 +959,16 @@ configure_fail2ban() {
|
|||||||
file_log "INFO" "Configuring Fail2ban..."
|
file_log "INFO" "Configuring Fail2ban..."
|
||||||
|
|
||||||
if command -v firewall-cmd >/dev/null 2>&1; then # Linux
|
if command -v firewall-cmd >/dev/null 2>&1; then # Linux
|
||||||
configure_fail2ban_linux
|
fail2ban_jail_settings "/etc/fail2ban/jail.local"
|
||||||
command_status=$?
|
command_status=$?
|
||||||
elif [ -f /etc/pf.conf ]; then # FreeBSD
|
elif [ -f /etc/pf.conf ]; then # FreeBSD
|
||||||
configure_fail2ban_freebsd
|
if fail2ban_jail_settings "/usr/local/etc/fail2ban/jail.local"; then
|
||||||
command_status=$?
|
# Perform additional pf specific configuration
|
||||||
|
fail2ban_freebsd_pf_conf
|
||||||
|
command_status=$?
|
||||||
|
else
|
||||||
|
command_status=1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$command_status" -eq 0 ]; then
|
if [ "$command_status" -eq 0 ]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user