Update install.sh

This commit is contained in:
Sefinek committed 2025-12-20 19:21:16 +01:00
1 parent 6d245df7e6
commit 7e409f59d8
1 file changed
+304 -77
+304 -77
View File
@@ -18,7 +18,10 @@ cat << "EOF"
|_|_| |_|\__\___|\__, |_| \__,_|\__|_|\___/|_| |_| |_|_| |_|\__\___|\__, |_| \__,_|\__|_|\___/|_| |_|
|___/ |___/
>> Made by sefinek.net || Last update: 18.05.2025 << 📩 Author : Sefinek <contact@sefinek.net> (https://sefinek.net)
🔵 Discord : https://discord.gg/RVH8UXgmzs
😺 GitHub Issues : https://github.com/sefinek/UFW-AbuseIPDB-Reporter/issues
📦 Last update : 20.12.2025
This installer will configure UFW-AbuseIPDB-Reporter, a tool that analyzes UFW logs and This installer will configure UFW-AbuseIPDB-Reporter, a tool that analyzes UFW logs and
reports to AbuseIPDB the IP addresses that have violated firewall rules. Join my Discord reports to AbuseIPDB the IP addresses that have violated firewall rules. Join my Discord
@@ -75,7 +78,7 @@ check_dependencies() {
if "$dependency" --version &> /dev/null; then if "$dependency" --version &> /dev/null; then
"$dependency" --version | head -n 1 "$dependency" --version | head -n 1
else else
echo "ℹ️ Version information for $dependency is unavailable" echo " Version information for $dependency is unavailable"
fi fi
fi fi
done done
@@ -98,6 +101,82 @@ check_dependencies() {
# Check dependencies before proceeding # Check dependencies before proceeding
check_dependencies curl node git check_dependencies curl node git
# Function to extract value from config.js
extract_config_value() {
local key=$1
local config_file="${2:-config.js}"
if [[ ! -f $config_file ]]; then
echo ""
return
fi
local value
value=$(grep -oP "^\s*${key}:\s*\K.*?(?=,\s*(//|$))" "$config_file" | sed "s/^['\"]//;s/['\"]$//" | sed 's/[[:space:]]*$//')
[[ $value == "null" ]] && value=""
echo "$value"
}
# Function to ask for configuration with validation
ask_config() {
local prompt=$1
local default=$2
local validation_type=${3:-""}
local result
while true; do
read -e -i "$default" -r -p "$prompt" result
result="${result:-$default}"
case $validation_type in
bool)
if [[ $result =~ ^(true|false)$ ]]; then
echo "$result"
return 0
else
echo "❌ Must be 'true' or 'false'"
fi
;;
number)
if [[ $result =~ ^[0-9]+\.?[0-9]*$ ]]; then
echo "$result"
return 0
else
echo "❌ Must be a valid number"
fi
;;
url)
if [[ -z $result ]] || [[ $result =~ ^https?:// ]]; then
echo "$result"
return 0
else
echo "❌ Must be a valid URL starting with http:// or https://"
fi
;;
cron)
if [[ $result =~ ^[0-9*,/-]+\ [0-9*,/-]+\ [0-9*,/-]+\ [0-9*,/-]+\ [0-9*,/-]+$ ]]; then
echo "$result"
return 0
else
echo "❌ Invalid cron format. Expected: 'minute hour day month weekday'"
fi
;;
static_dynamic)
if [[ $result =~ ^(static|dynamic)$ ]]; then
echo "$result"
return 0
else
echo "❌ Must be 'static' or 'dynamic'"
fi
;;
*)
echo "$result"
return 0
;;
esac
done
}
# Function to validate AbuseIPDB API key # Function to validate AbuseIPDB API key
validate_token() { validate_token() {
local api_key=$1 local api_key=$1
@@ -114,10 +193,10 @@ validate_token() {
fi fi
if [[ $response -eq 200 ]]; then if [[ $response -eq 200 ]]; then
echo "✅ Yay! Token is valid." echo "✅ API token validated successfully."
return 0 return 0
else else
echo "❌ Invalid token! Please try again." echo "❌ Invalid token. Please try again."
return 1 return 1
fi fi
} }
@@ -147,43 +226,6 @@ else
echo "✅ UFW logging is already enabled" echo "✅ UFW logging is already enabled"
fi fi
# Check for UFW log file
if [[ ! -f /var/log/ufw.log ]]; then
read -r -p "🔍 /var/log/ufw.log not found. Please enter the path to your log file: " ufw_log_path
if [[ -f $ufw_log_path ]]; then
echo "✅ Log file found at $ufw_log_path"
else
echo "❌ Provided log file path does not exist. Exiting..."
exit 1
fi
else
ufw_log_path="/var/log/ufw.log"
echo "✅ /var/log/ufw.log exists"
fi
# Prompt for API token
while true; do
read -r -p "🔑 Please enter your AbuseIPDB API token: " api_token
if validate_token "$api_token"; then
break
fi
continue
done
# Prompt for server ID
while true; do
read -r -p "🖥️ Enter the server ID (e.g., homeserver1). Leave blank if you do not wish to provide one: " server_id
if [[ -z $server_id ]]; then
server_id=null
break
elif [[ $server_id =~ ^[A-Za-z0-9]{1,16}$ ]]; then
server_id="'$server_id'"
break
else
echo "❌ It must be 1-16 characters long, contain only letters and numbers, and have no spaces or special characters."
fi
done
# Prompt for system update and upgrade # Prompt for system update and upgrade
if yes_no_prompt "🛠️ Do you want the script to run apt update and apt upgrade for you?"; then if yes_no_prompt "🛠️ Do you want the script to run apt update and apt upgrade for you?"; then
echo "🔧 Updating and upgrading the system..." echo "🔧 Updating and upgrading the system..."
@@ -191,26 +233,38 @@ if yes_no_prompt "🛠️ Do you want the script to run apt update and apt upgra
fi fi
# Clone repository & set permissions # Clone repository & set permissions
if [ ! -d "/opt" ]; then echo "📂 Ensuring /opt directory exists..."
mkdir -p /opt mkdir -p /opt
echo "📂 '/opt' has been created"
else
echo "✅ '/opt' directory already exists"
fi
cd /opt || { echo "❌ Failed to change directory to '/opt'. Exiting..."; exit 1; } cd /opt || { echo "❌ Failed to change directory to '/opt'. Exiting..."; exit 1; }
if [ ! -d "UFW-AbuseIPDB-Reporter" ]; then # Migrate from old directory name if exists
echo "📥 Cloning the UFW-AbuseIPDB-Reporter repository..." if [ -d "UFW-AbuseIPDB-Reporter" ] && [ ! -d "ufw-abuseipdb-reporter" ]; then
sudo git clone https://github.com/sefinek/UFW-AbuseIPDB-Reporter.git --recurse-submodules || { echo "❌ Failed to clone the repository. Exiting..."; exit 1; } echo "📦 Migrating from old directory name (UFW-AbuseIPDB-Reporter → ufw-abuseipdb-reporter)..."
else
echo "✨ The UFW-AbuseIPDB-Reporter repository already exists" # Stop UFW-AbuseIPDB reporter process if running
if command -v pm2 &>/dev/null; then
if pm2 list | grep -q "ufw-abuseipdb"; then
echo "⏸️ Stopping ufw-abuseipdb process..."
pm2 stop ufw-abuseipdb &>/dev/null || true
pm2 delete ufw-abuseipdb &>/dev/null || true
fi
fi
sudo mv UFW-AbuseIPDB-Reporter ufw-abuseipdb-reporter
echo "✅ Migration completed"
fi fi
sudo chown "$USER":"$USER" /opt/UFW-AbuseIPDB-Reporter -R if [ ! -d "ufw-abuseipdb-reporter" ]; then
echo "📥 Cloning the repository..."
sudo git clone https://github.com/sefinek/UFW-AbuseIPDB-Reporter.git ufw-abuseipdb-reporter --recurse-submodules || { echo "❌ Failed to clone the repository. Exiting..."; exit 1; }
else
echo "✅ The repository already exists"
fi
sudo chown "$USER":"$USER" /opt/ufw-abuseipdb-reporter -R
echo "📥 Pulling latest changes..." echo "📥 Pulling latest changes..."
cd UFW-AbuseIPDB-Reporter || { echo "❌ Failed to change directory to 'UFW-AbuseIPDB-Reporter'. Exiting..."; exit 1; } cd ufw-abuseipdb-reporter || { echo "❌ Failed to change directory to 'ufw-abuseipdb-reporter'. Exiting..."; exit 1; }
git pull || { echo "❌ Failed to pull the latest changes. Exiting..."; exit 1; } git pull || { echo "❌ Failed to pull the latest changes. Exiting..."; exit 1; }
# Install npm dependencies # Install npm dependencies
@@ -225,34 +279,202 @@ else
cp config.default.js config.js cp config.default.js config.js
fi fi
# Update config.js with API token, Server ID, and UFW log path # Check for UFW log file
config_file="config.js" existing_log_path=$(extract_config_value "UFW_LOG_FILE")
if [[ -f $config_file ]]; then default_log_path="${existing_log_path:-/var/log/ufw.log}"
echo "🔧 Updating $PWD/$config_file..."
sed -i "s|UFW_LOG_FILE: .*|UFW_LOG_FILE: '$ufw_log_path',|" "$config_file" if [[ -f $default_log_path ]]; then
sed -i "s|SERVER_ID: .*|SERVER_ID: $server_id,|" "$config_file" echo "✅ $default_log_path exists"
sed -i "s|ABUSEIPDB_API_KEY: .*|ABUSEIPDB_API_KEY: '$api_token',|" "$config_file" ufw_log_path="$default_log_path"
else else
echo "❌ $config_file not found. Make sure the repository was cloned and initialized correctly." while true; do
read -e -i "$default_log_path" -r -p "> 🔍 Please enter the path to your UFW log file: " ufw_log_path
if [[ -f $ufw_log_path ]]; then
echo "✅ Log file found at $ufw_log_path"
break
else
echo "❌ Provided log file path does not exist. Please try again."
fi
done
fi
echo -e "\n==============================================================================================\n"
# Prompt for API token
existing_api_token=$(extract_config_value "ABUSEIPDB_API_KEY")
while true; do
read -e -i "$existing_api_token" -r -p "> 🔑 Please enter your AbuseIPDB API token: " api_token
if [[ -z $api_token ]]; then
echo "❌ API token cannot be empty. Please try again."
continue
fi
if validate_token "$api_token"; then
break
fi
done
# Prompt for server ID
echo ""
echo " Server ID identifies this machine in AbuseIPDB reports and Discord notifications."
echo " Examples: 'homeserver1', 'vps-de-01', 'production'. Leave blank if not needed."
existing_server_id=$(extract_config_value "SERVER_ID")
while true; do
read -e -i "$existing_server_id" -r -p "> 🖥️ Enter the server ID (1-16 characters, or leave blank): " server_id
if [[ -z $server_id ]]; then
server_id=null
break
elif [[ $server_id =~ ^[A-Za-z0-9]{1,16}$ ]]; then
server_id="'$server_id'"
break
else
echo "❌ Must be 1-16 characters long, only letters and numbers (a-z, A-Z, 0-9)."
fi
done
# Extended logs
echo -e "\n Extended logs show additional debugging information in console output."
existing_extended_logs=$(extract_config_value "EXTENDED_LOGS")
extended_logs=$(ask_config "> 📊 Enable extended logs? (true/false): " "${existing_extended_logs:-false}" "bool")
# Cache file path
echo -e "\n Cache file stores reported IPs to prevent duplicate reports within cooldown period."
existing_cache_file=$(extract_config_value "CACHE_FILE")
cache_file=$(ask_config "> 💾 Cache file path: " "${existing_cache_file:-./tmp/ufw-abuseipdb-reporter.cache}" "")
# IP assignment type
echo -e "\n IP assignment: 'dynamic' if your ISP changes your IP periodically, 'static' if it never changes."
echo " Most home/small business connections are 'dynamic'. VPS/dedicated servers are usually 'static'."
existing_ip_assignment=$(extract_config_value "IP_ASSIGNMENT")
ip_assignment=$(ask_config "> 🌐 IP assignment type (static/dynamic): " "${existing_ip_assignment:-dynamic}" "static_dynamic")
# IP refresh schedule (only if dynamic)
if [[ $ip_assignment == "dynamic" ]]; then
echo -e "\n How often to check your public IP to prevent reporting yourself (cron format)."
echo " Default '0 */6 * * *' = every 6 hours. Format: minute hour day month weekday"
existing_ip_refresh=$(extract_config_value "IP_REFRESH_SCHEDULE")
ip_refresh_schedule=$(ask_config "> ⏰ IP refresh schedule (cron): " "${existing_ip_refresh:-0 */6 * * *}" "cron")
else
ip_refresh_schedule="0 */6 * * *"
fi
# IPv6 support
echo -e "\n Enable if your server has a public IPv6 address assigned by your ISP."
echo " Check with: ip -6 addr | grep 'scope global'"
existing_ipv6=$(extract_config_value "IPv6_SUPPORT")
ipv6_support=$(ask_config "> 🔢 Enable IPv6 support? (true/false): " "${existing_ipv6:-false}" "bool")
# IP report cooldown
echo -e "\n Minimum time (in hours) before reporting the same IP again."
echo " Recommended: 12 hours. Minimum: 0.25 (15 minutes) due to AbuseIPDB rate limits."
existing_cooldown=$(extract_config_value "IP_REPORT_COOLDOWN")
default_cooldown_hours="12"
if [[ -n $existing_cooldown ]]; then
default_cooldown_hours=$(awk "BEGIN {printf \"%.2f\", $existing_cooldown / 3600000}")
fi
while true; do
cooldown_hours=$(ask_config "> ⏱️ IP report cooldown (hours): " "$default_cooldown_hours" "number")
# Check if >= 0.25 (15 minutes)
if awk "BEGIN {exit !($cooldown_hours >= 0.25)}"; then
break
else
echo "❌ Minimum cooldown is 0.25 hours (15 minutes)"
fi
done
ip_report_cooldown=$(awk "BEGIN {printf \"%.0f\", $cooldown_hours * 3600000}")
# Auto-update
echo -e "\n Automatically update script via 'git pull' on schedule. May cause issues with breaking changes."
existing_auto_update=$(extract_config_value "AUTO_UPDATE_ENABLED")
auto_update_enabled=$(ask_config "> 🔄 Enable automatic updates? (true/false): " "${existing_auto_update:-false}" "bool")
# Auto-update schedule (only if enabled)
if [[ $auto_update_enabled == "true" ]]; then
echo -e "\n When to check for updates (cron format)."
echo " Default '0 14,16,20 * * *' = daily at 14:00, 16:00, 20:00"
existing_update_schedule=$(extract_config_value "AUTO_UPDATE_SCHEDULE")
auto_update_schedule=$(ask_config "> 📅 Auto-update schedule (cron): " "${existing_update_schedule:-0 14,16,20 * * *}" "cron")
else
auto_update_schedule="0 14,16,20 * * *"
fi
# Discord webhook
echo -e "\n Receive Discord notifications about important events, daily summaries of blocked IPs, and errors."
existing_discord_enabled=$(extract_config_value "DISCORD_WEBHOOK_ENABLED")
discord_enabled=$(ask_config "> 💬 Enable Discord webhooks? (true/false): " "${existing_discord_enabled:-false}" "bool")
# Discord webhook URL (only if enabled)
if [[ $discord_enabled == "true" ]]; then
echo -e "\n Edit Channel → Integrations → Create Webhook → Click on created webhook → Copy Webhook URL"
discord_url=$(ask_config "> 🔗 Discord webhook URL: " "$(extract_config_value "DISCORD_WEBHOOK_URL")" "url")
echo -e "\n Username shown in Discord messages. 'SERVER_ID' will use your server ID value."
existing_discord_username=$(extract_config_value "DISCORD_WEBHOOK_USERNAME")
discord_username=$(ask_config "> 👤 Discord webhook username: " "${existing_discord_username:-SERVER_ID}" "")
[[ -z $discord_username ]] && discord_username="SERVER_ID"
echo -e "\n Your Discord user ID for @mentions in critical notifications."
echo " User Settings → Advanced → Developer Mode"
echo " Esc → Right-click on your profile → Copy User ID. Leave blank to skip."
discord_user_id=$(ask_config "> 🆔 Discord user ID (optional): " "$(extract_config_value "DISCORD_USER_ID")" "")
else
discord_url=""
discord_username="SERVER_ID"
discord_user_id=""
fi
echo -e "\n==============================================================================================\n"
# Update config.js with all parameters
if [[ ! -f config.js ]]; then
echo "❌ config.js not found. Installation may have failed."
exit 1 exit 1
fi fi
echo "🔧 Updating $PWD/config.js..."
sed -i \
-e "s|UFW_LOG_FILE: .*|UFW_LOG_FILE: '$ufw_log_path',|" \
-e "s|SERVER_ID: .*|SERVER_ID: $server_id,|" \
-e "s|EXTENDED_LOGS: .*|EXTENDED_LOGS: $extended_logs,|" \
-e "s|CACHE_FILE: .*|CACHE_FILE: '$cache_file',|" \
-e "s|IP_ASSIGNMENT: .*|IP_ASSIGNMENT: '$ip_assignment',|" \
-e "s|IP_REFRESH_SCHEDULE: .*|IP_REFRESH_SCHEDULE: '$ip_refresh_schedule',|" \
-e "s|IPv6_SUPPORT: .*|IPv6_SUPPORT: $ipv6_support,|" \
-e "s|ABUSEIPDB_API_KEY: .*|ABUSEIPDB_API_KEY: '$api_token',|" \
-e "s|IP_REPORT_COOLDOWN: .*|IP_REPORT_COOLDOWN: $ip_report_cooldown,|" \
-e "s|AUTO_UPDATE_ENABLED: .*|AUTO_UPDATE_ENABLED: $auto_update_enabled,|" \
-e "s|AUTO_UPDATE_SCHEDULE: .*|AUTO_UPDATE_SCHEDULE: '$auto_update_schedule',|" \
-e "s|DISCORD_WEBHOOK_ENABLED: .*|DISCORD_WEBHOOK_ENABLED: $discord_enabled,|" \
-e "s|DISCORD_WEBHOOK_URL: .*|DISCORD_WEBHOOK_URL: '$discord_url',|" \
-e "s|DISCORD_WEBHOOK_USERNAME: .*|DISCORD_WEBHOOK_USERNAME: '$discord_username',|" \
-e "s|DISCORD_USER_ID: .*|DISCORD_USER_ID: '$discord_user_id',|" \
config.js
# Create directories & set permissions # Create directories & set permissions
echo "📂 Creating directories and setting permissions..." echo "📂 Creating directories and setting permissions..."
sudo mkdir -p /var/log/ufw-abuseipdb sudo mkdir -p /var/log/ufw-abuseipdb
sudo chown -R "$USER":"$USER" /var/log/ufw-abuseipdb sudo chown -R "$USER":"$USER" /var/log/ufw-abuseipdb
# Change permissions for UFW log file # Change permissions for UFW log file
echo "🔒 Changing permissions for $ufw_log_path..." if [[ -f $ufw_log_path ]]; then
sudo chown syslog:"$USER" "$ufw_log_path" echo "🔒 Changing permissions for $ufw_log_path..."
sudo chmod 640 "$ufw_log_path" sudo chown syslog:"$USER" "$ufw_log_path"
sudo chmod 640 "$ufw_log_path"
else
echo "⚠️ Warning: UFW log file not found at $ufw_log_path. Permissions not changed."
fi
# Install PM2 # Install PM2
echo "📦 Installing PM2..." echo "📦 Installing PM2..."
sudo npm install pm2@latest -g --silent sudo npm install pm2@latest -g --silent
# Configure PM2 # Configure PM2
echo "⚙️ Adding PM2 to autostart..." echo "⚙️ Adding PM2 to autostart..."
startup_command=$(pm2 startup | grep "sudo env PATH" | sed 's/^[^s]*sudo/sudo/') startup_command=$(pm2 startup | grep "sudo env PATH" | sed 's/^[^s]*sudo/sudo/')
@@ -270,7 +492,6 @@ echo "⚙️ Running a script with PM2 and saving the current state of all proce
pm2 start --silent pm2 start --silent
pm2 save --silent pm2 save --silent
# Final # Final
echo "🌌 Checking PM2 status..." echo "🌌 Checking PM2 status..."
pm2 status pm2 status
@@ -279,11 +500,17 @@ echo -e "\n🎉 Installation and configuration completed! Use the 'pm2 logs' com
echo -e "⚙️ More settings can be found in the file: $PWD/config.js" echo -e "⚙️ More settings can be found in the file: $PWD/config.js"
echo -e "\n====================================== Summary ======================================" echo -e "\n====================================== Summary ======================================"
echo "🖥️ Server ID : ${server_id:-null}" echo "🖥️ Server ID : ${server_id//\'/}"
echo "🔑 API Key : $api_token" if [[ ${#api_token} -gt 24 ]]; then
echo "📂 Script : $PWD" echo "🔑 API Key : ${api_token:0:20}...${api_token: -4}"
else
echo -e "\n====================================== Support ======================================" echo "🔑 API Key : ${api_token:0:8}...${api_token: -4}"
echo "📩 Email : contact@sefinek.net" fi
echo "🔵 Discord : https://discord.gg/RVH8UXgmzs" echo "📂 UFW Log File : $ufw_log_path"
echo "😺 GitHub Issues : https://github.com/sefinek/UFW-AbuseIPDB-Reporter/issues" echo "💾 Cache File : $cache_file"
echo "🌐 IP Assignment : $ip_assignment"
echo "🔢 IPv6 Support : $ipv6_support"
echo "⏱️ Report Cooldown : $cooldown_hours hours"
echo "🔄 Auto-Updates : $auto_update_enabled"
echo "💬 Discord Webhooks : $discord_enabled"
echo "📂 Script Directory : $PWD"