Skip to content

Instantly share code, notes, and snippets.

@TheDcoder
Created December 8, 2025 18:13
Show Gist options
  • Select an option

  • Save TheDcoder/4eb35c1f81ede7ad52d42dddc44e0948 to your computer and use it in GitHub Desktop.

Select an option

Save TheDcoder/4eb35c1f81ede7ad52d42dddc44e0948 to your computer and use it in GitHub Desktop.
Only allow Cloudflare IPs to connect to port 443 (HTTPS) - Created by Gemini 3 Pro

Block non-Cloudflare IPs from accessing HTTPS

  1. Copy .sh script to /usr/local/bin and chmod +x it
  2. Copy the .service and .timer files to /etc/systemd/system
  3. systemctl enable --now cloudflare-nft.{service,timer}
[Unit]
Description=Load Cloudflare NFTables Rules
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/update-cloudflare-nft.sh
[Install]
WantedBy=multi-user.target
[Unit]
Description=Trigger Cloudflare NFTables Update Daily
[Timer]
# Run daily at 03:00 (adjust as preferred)
OnCalendar=*-*-* 03:00:00
# Add a random delay (e.g., up to 15 min) to be polite to Cloudflare's API
RandomizedDelaySec=900
[Install]
WantedBy=timers.target
#!/bin/bash
# Files
TEMP_FILE=$(mktemp)
CLOUDFLARE_V4_URL="https://www.cloudflare.com/ips-v4"
CLOUDFLARE_V6_URL="https://www.cloudflare.com/ips-v6"
# Fetch IPs (fail if download fails)
CF_IPV4=$(curl -sS "$CLOUDFLARE_V4_URL") || exit 1
CF_IPV6=$(curl -sS "$CLOUDFLARE_V6_URL") || exit 1
# Format IPs for nftables (replace newlines with commas)
# We use tr to replace newlines with commas, then sed to remove the trailing comma
CF_IPV4_FMT=$(echo "$CF_IPV4" | tr '\n' ',' | sed 's/,$//')
CF_IPV6_FMT=$(echo "$CF_IPV6" | tr '\n' ',' | sed 's/,$//')
# Write the NFT configuration to a temp file
# We use a separate table "cloudflare_guard" to avoid messing with UFW's table
cat <<EOF > "$TEMP_FILE"
table inet cloudflare_guard {
# 1. Define the sets
set cf_ipv4 {
type ipv4_addr
flags interval
elements = { $CF_IPV4_FMT }
}
set cf_ipv6 {
type ipv6_addr
flags interval
elements = { $CF_IPV6_FMT }
}
# 2. Define the chain
chain inbound {
# Priority -100 runs BEFORE UFW (which is usually priority 0)
type filter hook input priority -100; policy accept;
# 3. The Rules
# If destination is port 443 and Source is NOT in the set -> DROP
tcp dport 443 ip saddr != @cf_ipv4 drop
tcp dport 443 ip6 saddr != @cf_ipv6 drop
}
}
EOF
# Reload ONLY this specific table/file
# Note: Since we are defining the table again, we must flush it first to remove old rules/sets
# strictly associated with this table, or simply rely on the fact that we are redefining it.
# Ideally, we flush the specific table before sourcing the file to ensure clean state.
nft flush table inet cloudflare_guard 2>/dev/null || true
nft -f "$TEMP_FILE"
rm "$TEMP_FILE"
echo "Cloudflare NFTables rules updated successfully."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment