| Server IP : 104.21.21.239 / Your IP : 216.73.217.99 Web Server : Apache/2.4.68 (Amazon Linux) OpenSSL/3.5.5 System : Linux ip-172-31-69-123.ec2.internal 6.1.176-223.369.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Jul 24 13:34:27 UTC 2026 x86_64 User : ec2-user ( 1000) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /ourscripts/ |
Upload File : |
#!/bin/bash
# ============================================================
# Cloudflare IP Whitelist + Re-enable Hardening
# Run as root: sudo bash /ourscripts/cf-whitelist-and-harden.sh
# ============================================================
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[SKIP]${NC} $1"; }
step() { echo -e "\n${GREEN}==>${NC} $1"; }
fail() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
if [[ $EUID -ne 0 ]]; then
fail "Must be run as root"
fi
echo "============================================================"
echo " Cloudflare Whitelist + Security Hardening Re-enable"
echo "============================================================"
echo " Hostname: $(hostname)"
echo " Date: $(date)"
echo "============================================================"
echo ""
# -----------------------------------------------------------
# 1. Fetch Cloudflare IPs from official API
# -----------------------------------------------------------
step "Fetching Cloudflare IP ranges from api.cloudflare.com..."
CF_API=$(curl -sf https://api.cloudflare.com/client/v4/ips)
if [[ -z "$CF_API" ]]; then
fail "Could not reach Cloudflare API — check network connectivity"
fi
# Parse IPv4 and IPv6 ranges from the API response
CF_IPV4=$(echo "$CF_API" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for ip in data['result']['ipv4_cidrs']:
print(ip)
")
CF_IPV6=$(echo "$CF_API" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for ip in data['result']['ipv6_cidrs']:
print(ip)
")
if [[ -z "$CF_IPV4" ]]; then
fail "Failed to parse Cloudflare IPv4 ranges from API response"
fi
echo ""
echo " Cloudflare IPv4 ranges:"
echo "$CF_IPV4" | sed 's/^/ /'
echo ""
echo " Cloudflare IPv6 ranges:"
echo "$CF_IPV6" | sed 's/^/ /'
echo ""
# Build space-separated list for fail2ban ignoreip
CF_ALL_IPS=$(echo "$CF_IPV4 $CF_IPV6" | tr '\n' ' ')
# -----------------------------------------------------------
# 2. Update fail2ban jail.local with ignoreip
# -----------------------------------------------------------
step "Updating fail2ban jail.local with Cloudflare IPs..."
JAIL_LOCAL="/etc/fail2ban/jail.local"
if [[ ! -f "$JAIL_LOCAL" ]]; then
fail "jail.local not found — run apache-security-setup.sh first"
fi
# Back up current jail.local
cp "$JAIL_LOCAL" "${JAIL_LOCAL}.bak.$(date +%Y%m%d%H%M%S)"
info "Backed up jail.local"
IGNOREIP_LINE="ignoreip = 127.0.0.1/8 ::1 ${CF_ALL_IPS}"
if grep -q "^ignoreip" "$JAIL_LOCAL"; then
# Replace existing ignoreip line
sed -i "s|^ignoreip.*|${IGNOREIP_LINE}|" "$JAIL_LOCAL"
info "Updated existing ignoreip line"
else
# Insert after [DEFAULT]
sed -i "/^\[DEFAULT\]/a ${IGNOREIP_LINE}" "$JAIL_LOCAL"
info "Added ignoreip line under [DEFAULT]"
fi
# Verify it's in there
echo ""
echo " Current ignoreip setting:"
grep "^ignoreip" "$JAIL_LOCAL" | fold -s -w 80 | sed 's/^/ /'
echo ""
# -----------------------------------------------------------
# 3. Re-enable and restart fail2ban
# -----------------------------------------------------------
step "Restarting fail2ban..."
systemctl enable fail2ban 2>/dev/null
systemctl restart fail2ban
F2B_READY=0
for i in {1..5}; do
sleep 3
if fail2ban-client status &>/dev/null; then
F2B_READY=1
break
fi
done
if [[ $F2B_READY -eq 1 ]]; then
JAIL_COUNT=$(fail2ban-client status | grep "Number of jail" | awk '{print $NF}')
info "fail2ban running with ${JAIL_COUNT} jails"
echo ""
echo " Verifying Cloudflare IPs are whitelisted in apache-noscript jail:"
fail2ban-client get apache-noscript ignoreip 2>/dev/null | tr ',' '\n' | head -5 | sed 's/^/ /'
echo " ..."
else
fail "fail2ban failed to start — check: journalctl -u fail2ban"
fi
# -----------------------------------------------------------
# 4. Re-enable Apache hardening conf
# -----------------------------------------------------------
step "Re-enabling Apache security-hardening.conf..."
HARDENING_CONF="/etc/httpd/conf.d/security-hardening.conf"
HARDENING_DISABLED="${HARDENING_CONF}.disabled"
if [[ -f "$HARDENING_DISABLED" ]]; then
mv "$HARDENING_DISABLED" "$HARDENING_CONF"
info "security-hardening.conf re-enabled"
elif [[ -f "$HARDENING_CONF" ]]; then
warn "security-hardening.conf already active — nothing to do"
else
fail "security-hardening.conf not found — run apache-security-setup.sh first"
fi
step "Validating Apache config..."
if apachectl configtest 2>&1 | grep -q "Syntax OK"; then
info "Apache config syntax OK"
else
fail "Apache config test failed — check: apachectl configtest"
fi
step "Reloading Apache..."
systemctl reload httpd
if systemctl is-active httpd &>/dev/null; then
info "Apache reloaded successfully"
else
fail "Apache failed — check: journalctl -u httpd"
fi
# -----------------------------------------------------------
# 5. Install weekly Cloudflare IP refresh cron
# -----------------------------------------------------------
step "Installing weekly Cloudflare IP refresh cron..."
cat > /usr/local/bin/cf-update-ignoreip.sh << 'CRONEOF'
#!/bin/bash
# Refreshes Cloudflare IPs in fail2ban weekly
LOG=/var/log/cf-update-ignoreip.log
echo "$(date) Starting Cloudflare IP refresh" >> $LOG
CF_API=$(curl -sf https://api.cloudflare.com/client/v4/ips)
if [[ -z "$CF_API" ]]; then
echo "$(date) ERROR: Could not reach Cloudflare API" >> $LOG
exit 1
fi
CF_ALL_IPS=$(echo "$CF_API" | python3 -c "
import sys, json
data = json.load(sys.stdin)
ips = data['result']['ipv4_cidrs'] + data['result']['ipv6_cidrs']
print(' '.join(ips))
")
IGNOREIP_LINE="ignoreip = 127.0.0.1/8 ::1 ${CF_ALL_IPS}"
if grep -q "^ignoreip" /etc/fail2ban/jail.local; then
sed -i "s|^ignoreip.*|${IGNOREIP_LINE}|" /etc/fail2ban/jail.local
else
sed -i "/^\[DEFAULT\]/a ${IGNOREIP_LINE}" /etc/fail2ban/jail.local
fi
systemctl reload fail2ban 2>/dev/null || systemctl restart fail2ban
echo "$(date) Done — updated Cloudflare IPs in fail2ban" >> $LOG
CRONEOF
chmod +x /usr/local/bin/cf-update-ignoreip.sh
# Run every Sunday at 3am
if ! crontab -l 2>/dev/null | grep -q "cf-update-ignoreip"; then
(crontab -l 2>/dev/null; echo "0 3 * * 0 root /usr/local/bin/cf-update-ignoreip.sh") | crontab -
fi
info "Weekly CF IP refresh cron installed (Sundays 3am)"
# -----------------------------------------------------------
# Summary
# -----------------------------------------------------------
echo ""
echo "============================================================"
echo " Done"
echo "============================================================"
echo ""
echo " - Cloudflare IPs whitelisted in fail2ban (from live API)"
echo " - fail2ban running with all jails active"
echo " - Apache security-hardening.conf re-enabled"
echo " - Weekly auto-refresh cron installed"
echo ""
echo " Useful commands:"
echo " sudo fail2ban-client get apache-noscript ignoreip # verify whitelist"
echo " sudo fail2ban-client status # jail overview"
echo " sudo tail -f /var/log/fail2ban.log # live ban log"
echo " sudo bash /usr/local/bin/cf-update-ignoreip.sh # refresh CF IPs now"
echo "============================================================"