website-scripts/Cloudflare/Fix_IP_Logging.sh

135 lines
4.1 KiB
Bash

#!/bin/bash
# Fix Nginx Cloudflare logging when using CF as a proxy.
# Copyright 2023 Robert Fauls. Licensed under the GNU GPLv3 License.
# Created by Rob Fauls 10/27/2022
# This script will reference Cloudflare's API for a current list of their IP addresses.
# After retrieving the JSON, it will convert into NGINX-friendly format, then apply to /etc/nginx/nginx.conf
# You may want this to write to a different file. If so, please update the script and test in a dev environment.
# Ensure script is run as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
# Check if jq is installed
if ! command -v jq &> /dev/null; then
echo "jq could not be found. Please install jq to continue."
exit 1
fi
create_ip_update_script() {
cat > /tmp/Cloudflare_ip_update.sh << 'EOF'
#!/bin/bash
# Function to print messages to terminal
print_to_terminal() {
echo "$1"
}
# Fetch Cloudflare IP addresses
cf_ipv4=$(curl -s https://api.cloudflare.com/client/v4/ips/ | jq -r '.result.ipv4_cidrs[]')
cf_ipv6=$(curl -s https://api.cloudflare.com/client/v4/ips/ | jq -r '.result.ipv6_cidrs[]')
# Check if curl was successful
if [[ $? -ne 0 ]]; then
print_to_terminal "Failed to fetch IP addresses from Cloudflare."
exit 1
fi
# Modifying /etc/nginx/nginx.conf. Update path if different.
nginx_conf="/etc/nginx/nginx.conf"
# Backup the original nginx config with timestamp
cp "$nginx_conf" "$nginx_conf.bak_$(date +%F_%T)"
# Remove previous Cloudflare IP entries
sed -i '/# BEGIN Cloudflare IP/,/# END Cloudflare IP/d' "$nginx_conf"
# Use temporary files for Cloudflare IPs
echo "$cf_ipv4" > /tmp/cf_ipv4.tmp
echo "$cf_ipv6" > /tmp/cf_ipv6.tmp
# Use awk to insert Cloudflare IPs just before the closing brace of the http block
awk_script=$(cat << 'AWK'
BEGIN {
while (getline ip < "/tmp/cf_ipv4.tmp") {
cf_ipv4[ip] = 1
}
while (getline ip < "/tmp/cf_ipv6.tmp") {
cf_ipv6[ip] = 1
}
}
{
if ($0 ~ /^}$/ && in_http_block) {
print "# BEGIN Cloudflare IP"
for (ip in cf_ipv4) {
print "set_real_ip_from " ip ";"
}
for (ip in cf_ipv6) {
print "set_real_ip_from " ip ";"
}
print "real_ip_header CF-Connecting-IP;"
print "# END Cloudflare IP"
in_http_block = 0
}
if ($0 ~ /http {/) {
in_http_block = 1
}
print $0
}
AWK
)
echo "$awk_script" | awk -f - "$nginx_conf" > "${nginx_conf}.tmp" && mv "${nginx_conf}.tmp" "$nginx_conf"
# Clean up temp files
rm -f /tmp/cf_ipv4.tmp /tmp/cf_ipv6.tmp
# Reload Nginx and check for success
if nginx -s reload; then
print_to_terminal "Configuration updated and Nginx reloaded."
else
print_to_terminal "Failed to reload Nginx. Check for configuration errors."
exit 1
fi
EOF
# Make the script executable
chmod +x /tmp/Cloudflare_ip_update.sh
}
print_to_terminal() {
echo "$1"
}
print_to_terminal "If you are using CloudFlare proxy (do not have DNS only selected), you will see CloudFlare IP Addresses in your logs. If you are using the feature and would like to see the users' real IP, select yes below."
# Prompt user for input
read -p "Would you like to configure Nginx to show the real IP in logs when using Cloudflare? (yes/no): " response
if [[ $response == "y" || $response == "yes" ]]; then
create_ip_update_script
/tmp/Cloudflare_ip_update.sh
read -p "Would you like to schedule a cron job to update the Cloudflare IPs daily? (yes/no): " cron_response
if [[ $cron_response == "y" || $cron_response == "yes" ]]; then
# Copy the script to cron daily folder, set owner to root, and make it executable
cp /tmp/Cloudflare_ip_update.sh /etc/cron.daily/Cloudflare_ip_update.sh &&
chown root:root /etc/cron.daily/Cloudflare_ip_update.sh &&
chmod 755 /etc/cron.daily/Cloudflare_ip_update.sh
if [[ $? -eq 0 ]]; then
print_to_terminal "Cron job scheduled to run daily."
else
print_to_terminal "Failed to schedule cron job. Check permissions and file paths."
exit 1
fi
fi
else
print_to_terminal "Continuing without updating logging to show clients' real IP addresses."
fi
exit 0