Not the best way to protect a server, but surprisingly effective as an additional service
V1 which worked out of the box;
Write a linux batch file program that i can run with a cron job, that will look at all ip addresses connected to the apache webserver, test if they are located in the uk and then add a rule using ufw to block them if they are not in the uk
#!/bin/bash
# Define the Apache access log file path
LOG_FILE="/var/log/apache2/access.log"
# Temporary file to store unique IP addresses
IP_LIST="/tmp/connected_ips.txt"
# API URL for geolocation
API_URL="https://ipinfo.io"
# Extract unique IP addresses from the access log
grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' "$LOG_FILE" | sort | uniq > "$IP_LIST"
# Loop through each IP address
while read -r IP; do
# Skip local and private IPs
if [[ "$IP" =~ ^(10\.|172\.16\.|192\.168\.|127\.|::1) ]]; then
continue
fi
# Get geolocation information
GEO_INFO=$(curl -s "$API_URL/$IP")
COUNTRY=$(echo "$GEO_INFO" | grep -oP '"country":\s*"\K[A-Z]+')
# Check if the country is not UK
if [[ "$COUNTRY" != "GB" ]]; then
echo "Blocking IP: $IP (Country: $COUNTRY)"
# Block the IP using UFW
ufw deny from "$IP"
else
echo "IP: $IP is in the UK (Country: $COUNTRY)"
fi
done < "$IP_LIST"
# Reload UFW to apply rules
ufw reload
# Clean up temporary file
rm -f "$IP_LIST"
Instructions
- Save the Script: Save the script as
block_non_uk_ips.sh
in an appropriate directory (e.g.,/usr/local/bin
). - Make It Executable: Run the command:bashCopyEdit
chmod +x /usr/local/bin/block_non_uk_ips.sh
- Set Up Cron Job: Open the cron configuration using:bashCopyEdit
crontab -e
Add the following line to run the script every hour (adjust as needed):bashCopyEdit0 * * * * /usr/local/bin/block_non_uk_ips.sh
- Test the Script: Run the script manually to ensure it works as expected:bashCopyEdit
sudo /usr/local/bin/block_non_uk_ips.sh
Notes
- API Usage: The script uses the ipinfo.io API, which has free and paid tiers. For heavy usage, consider getting an API key or switching to another API.
- UFW Configuration: Ensure UFW is installed and configured. Use
sudo ufw enable
if it’s not already running. - Log File: Update the
LOG_FILE
path to match your Apache configuration if it differs.
Some adjustments to make it work using port 443 web server port
adjust the script so that countries in mainland Europe are not blocked
adjust the script so that ufw block would block an entire ip address range, for example with an ip address 189.51.32.23 the ufw statement would block 189.51.32.0/24″ and use netstat to get all the ip addresses connected to port 443
#!/bin/bash
# Temporary file to store unique IP addresses
IP_LIST="/tmp/connected_ips.txt"
# Temporary file to store already blocked subnets
BLOCKED_SUBNETS="/tmp/blocked_subnets.txt"
# API URL for geolocation
API_URL="https://ipinfo.io"
# List of mainland European country codes (ISO Alpha-2 format)
EUROPEAN_COUNTRIES=("AL" "AD" "AT" "BE" "BA" "BG" "HR" "CY" "CZ" "DK" "EE" "FI" "FR" "DE" "GR" "HU" "IS" "IE" "IT" "LV" "LI" "LT" "LU" "MT" "MC" "ME" "NL" "NO" "PL" "PT" "RO" "SM" "RS" "SK" "SI" "ES" "SE" "CH" "TR" "VA")
# Ensure the blocked subnets file exists
touch "$BLOCKED_SUBNETS"
# Use netstat to get all IP addresses connected to port 443
netstat -tn | awk '$4 ~ /:443$/ {print $5}' | cut -d':' -f1 | sort | uniq > "$IP_LIST"
# Loop through each IP address
while read -r IP; do
# Skip local and private IPs
if [[ "$IP" =~ ^(10\.|172\.16\.|192\.168\.|127\.|::1) ]]; then
continue
fi
# Calculate the /24 subnet
SUBNET=$(echo "$IP" | sed 's/\.[0-9]*$/\.0\/24/')
# Skip if this subnet has already been blocked
if grep -q "^$SUBNET$" "$BLOCKED_SUBNETS"; then
continue
fi
# Get geolocation information
GEO_INFO=$(curl -s "$API_URL/$IP")
COUNTRY=$(echo "$GEO_INFO" | grep -oP '"country":\s*"\K[A-Z]+')
# Check if the country is not in the UK or mainland Europe
if [[ "$COUNTRY" != "GB" && ! " ${EUROPEAN_COUNTRIES[@]} " =~ " $COUNTRY " ]]; then
echo "Blocking subnet: $SUBNET (Country: $COUNTRY)"
# Block the subnet using UFW
ufw deny from "$SUBNET"
# Add the subnet to the blocked list
echo "$SUBNET" >> "$BLOCKED_SUBNETS"
else
echo "IP: $IP is allowed (Country: $COUNTRY)"
fi
done < "$IP_LIST"
# Reload UFW to apply rules
ufw reload
# Clean up temporary file
rm -f "$IP_LIST"