#!/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