PowerShell scripts to manage Cloudflare IP allowlists used by WAF custom rules. Designed for restricting access to sensitive paths (e.g. admin panels, config files) to only authorized IPs.
- Interactive menu to view, add, and remove IPs from a Cloudflare IP list
- Auto-detect public IP with IPv4 priority (falls back to IPv6 only if no IPv4 is available)
- Multiple detection sources for reliability (api.ipify.org, icanhazip.com, ifconfig.io, checkip.amazonaws.com, ifconfig.me)
- Auto-remove stale IPs after a configurable number of days (default: 3)
- Protected IPs (manually added) are never auto-removed
- Silent mode with file logging for scheduled tasks
- Dry-run mode to preview changes without applying them
- Network-aware: detects gateway + Wi-Fi SSID + network profile to skip updates when still on the same network
- Self-installing background service: one-command setup creates Windows Task Scheduler jobs (hourly + instant on network change)
- Force update: bypass network check on demand
Interactive menu for managing the Cloudflare IP allowlist. View current IPs, add new ones manually or auto-detect, and remove old ones with confirmation.
Automated script that detects the current machine's public IP (IPv4 preferred, IPv6 fallback only), syncs it with the Cloudflare allowlist, and removes IPs that haven't been seen for a configurable number of days (default: 3). Uses 5 detection sources for reliability.
Network-aware mode: On each run, the script builds a fingerprint from the default gateway, Wi-Fi SSID, and Windows network profile name. If the fingerprint matches the previous run, the script skips all Cloudflare API calls (same network = same IP). When the fingerprint changes (e.g. switching from home Wi-Fi to a coffee shop), it detects the new public IP and updates the allowlist automatically.
Background service: Use -Install to create two Windows Task Scheduler tasks — one hourly safety-net check and one event-driven trigger that fires ~30 seconds after any network connection change. Everything runs hidden with no foreground window.
- Windows 10/11 with PowerShell 5.1+
- Cloudflare account with:
- A Cloudflare IP List (kind:
ip) - WAF Custom Rules referencing the list
- Global API Key and account email
- A Cloudflare IP List (kind:
Edit the variables at the top of each script:
$CF_EMAIL = "YOUR_CLOUDFLARE_EMAIL"
$CF_API_KEY = "YOUR_CLOUDFLARE_GLOBAL_API_KEY"
$ACCOUNT_ID = "YOUR_CLOUDFLARE_ACCOUNT_ID"
$LIST_ID = "YOUR_CLOUDFLARE_LIST_ID"How to find these values:
| Variable | Where to find it |
|---|---|
CF_EMAIL |
The email you login to Cloudflare with |
CF_API_KEY |
Cloudflare Dashboard > My Profile > API Tokens > Global API Key |
ACCOUNT_ID |
Cloudflare Dashboard > any domain > Overview > right sidebar under "API" |
LIST_ID |
Create a list via API or Dashboard (Manage Account > Configurations > Lists) |
curl -X POST "https://api.cloudflare.com/client/v4/accounts/YOUR_ACCOUNT_ID/rules/lists" \
-H "X-Auth-Email: admin@example.com" \
-H "X-Auth-Key: your_global_api_key" \
-H "Content-Type: application/json" \
-d '{"name":"allowed_admin_ips","description":"IPs allowed to access admin and sensitive files","kind":"ip"}'Copy the returned id — that's your LIST_ID.
If you get an execution policy error, run this once:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser.\Manage-CloudflareAllowlist.ps1Example Output:
============================================
Cloudflare IP Allowlist Manager
List: allowed_admin_ips
============================================
Current Allowed IPs:
------------------------------------
[1] 203.0.113.45 - Admin - Home
[2] 198.51.100.10 - Web Server - DO NOT REMOVE
[3] 2001:db8::1 - Admin - Office IPv6
------------------------------------
Total: 3 IPs
Options:
[1] Add an IP
[2] Remove an IP
[3] Refresh list
[4] Add my current IP (auto-detect)
[0] Exit
| Option | Action |
|---|---|
| 1 | Enter an IP manually, or type auto to detect your current IP |
| 2 | Select IPs by number to remove (e.g. 1,3) with confirmation |
| 3 | Refresh the list |
| 4 | One-click: detect your public IP and add it |
| 0 | Exit |
Install as background service (requires Administrator):
.\CF-AutoIP-Manager.ps1 -InstallThis creates two Task Scheduler tasks:
CF-AutoIP-Manager— runs every hourCF-AutoIP-Manager-NetworkChange— triggers ~30s after any network connect event
Both run hidden with -Silent and log to %APPDATA%\CF-AutoIP-Manager\cf-autoip.log.
Uninstall (requires Administrator):
.\CF-AutoIP-Manager.ps1 -UninstallCheck status — see current network, saved state, and task status:
.\CF-AutoIP-Manager.ps1 -StatusBasic run — detect IPs, sync list, clean stale entries:
.\CF-AutoIP-Manager.ps1Force update — bypass network-same check:
.\CF-AutoIP-Manager.ps1 -ForceUpdateDry run — preview what would happen without making changes:
.\CF-AutoIP-Manager.ps1 -DryRunCustom stale threshold (e.g. 7 days instead of default 3):
.\CF-AutoIP-Manager.ps1 -StaleDays 7Silent mode (for scheduled tasks, logs to cf-autoip.log):
.\CF-AutoIP-Manager.ps1 -SilentExample Output:
============================================
Cloudflare Auto IP Manager
Stale threshold: 3 days
============================================
Detecting current IP (IPv4 preferred)...
IPv4 detected via api.ipify.org: 203.0.113.45
Current allowlist:
198.51.100.10 - Web Server - DO NOT REMOVE
203.0.113.45 - Admin - Auto IPv4 | seen:2026-03-28
192.0.2.99 - Admin - Auto IPv4 | seen:2026-03-24
Updating IPv4 203.0.113.45 (refreshing seen date)
Checking for stale IPs (>3 days)...
Protected: 198.51.100.10 (Web Server) - no auto-removal
OK: 203.0.113.45 (last seen 0d ago, threshold: 3d)
STALE: 192.0.2.99 (last seen 7d ago) - removing
Final allowlist:
------------------------------------
198.51.100.10 - Web Server - DO NOT REMOVE
203.0.113.45 - Admin - Auto IPv4 | seen:2026-03-31
------------------------------------
Total: 2 IPs
| Comment Format | Behavior |
|---|---|
Admin - Auto IPv4 | seen:2026-03-24 |
Auto-managed. Removed if not seen for N+ days. |
Web Server - DO NOT REMOVE |
Protected. Never auto-removed (no seen: tag). |
Admin - Home |
Protected. Manually added IPs are never auto-removed. |
The script uses the seen:YYYY-MM-DD tag in the Cloudflare list item comment to track when an IP was last active. IPs without this tag are always protected.
These scripts are designed to work with Cloudflare WAF custom rules that reference the IP list. Example rules:
| # | Rule | Action | Allowlist Bypass |
|---|---|---|---|
| 1 | Block sensitive files (config, xmlrpc, debug logs) + admin panel | Block | Yes |
| 2 | Block PHP execution in upload/cache directories | Block | No |
| 3 | Block malicious query strings (SQLi, XSS, LFI) | Block | No |
| 4 | Challenge login page POST requests | Managed Challenge | Yes |
Deploy rules to a zone:
curl -X POST "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rulesets" \
-H "X-Auth-Email: admin@example.com" \
-H "X-Auth-Key: your_global_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Security Rules",
"kind": "zone",
"phase": "http_request_firewall_custom",
"rules": [
{
"action": "block",
"expression": "((http.request.uri.path contains \"/wp-config\") or (http.request.uri.path eq \"/xmlrpc.php\") or (http.request.uri.path contains \"/debug.log\") or (http.request.uri.path contains \"/wp-admin/\" and not http.request.uri.path contains \"/wp-admin/admin-ajax.php\" and not http.request.uri.path contains \"/wp-admin/css/\" and not http.request.uri.path contains \"/wp-admin/js/\")) and not ip.src in $allowed_admin_ips",
"description": "Block sensitive files + admin panel (allowlist bypass)"
},
{
"action": "block",
"expression": "(http.request.uri.path contains \"/wp-content/uploads/\" and http.request.uri.path contains \".php\") or (http.request.uri.path contains \"/wp-content/cache/\" and http.request.uri.path contains \".php\")",
"description": "Block PHP execution in uploads/cache"
},
{
"action": "block",
"expression": "(http.request.uri.query contains \"eval(\") or (http.request.uri.query contains \"base64_decode\") or (http.request.uri.query contains \"<script\") or (http.request.uri.query contains \"../../../\") or (http.request.uri.query contains \"UNION+SELECT\")",
"description": "Block malicious query strings"
},
{
"action": "managed_challenge",
"expression": "(http.request.uri.path contains \"/wp-login.php\" and http.request.method eq \"POST\") and not ip.src in $allowed_admin_ips",
"description": "Challenge login POST (allowlist bypass)"
}
]
}'The script can install itself as a background service with a single command:
# Run as Administrator
.\CF-AutoIP-Manager.ps1 -InstallThis creates two Task Scheduler tasks:
| Task | Trigger | Purpose |
|---|---|---|
CF-AutoIP-Manager |
Every 1 hour | Safety-net periodic check |
CF-AutoIP-Manager-NetworkChange |
Network connect event (30s delay) | Near-instant detection on network switch |
Both tasks run with -WindowStyle Hidden -Silent (no foreground window, log-only).
To remove:
# Run as Administrator
.\CF-AutoIP-Manager.ps1 -UninstallEach run builds a fingerprint from three local values:
| Source | How it's detected |
|---|---|
| Default gateway IP | Get-NetRoute -DestinationPrefix '0.0.0.0/0' |
| Wi-Fi SSID | netsh wlan show interfaces (empty if wired) |
| Network profile name | Get-NetConnectionProfile |
These are hashed (SHA-256) into a single fingerprint. If the fingerprint matches the previous run's saved state, the script exits immediately without calling any external IP detection service or Cloudflare API. When the fingerprint changes, it proceeds with full IP detection and allowlist sync.
State is stored at %APPDATA%\CF-AutoIP-Manager\state.json.
| Problem | Solution |
|---|---|
| "Execution policy" error | Run: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser |
| Can't access admin panel | Your IP changed. Run the menu script and add your new IP. |
| Auto-detect shows wrong IP | VPN/proxy active. Use the menu script to add the correct IP manually. |
| Auto-detect returns IPv6 instead of IPv4 | All 5 IPv4 sources failed (network issue or IPv4 unavailable). Check connectivity to api.ipify.org, icanhazip.com, etc. |
| "Invalid access token" error | Check CF_EMAIL and CF_API_KEY are correct. Global API Key, not API Token. |
| Locked out, can't run script | Login to Cloudflare dashboard > Account > Configurations > Lists > add your IP manually. |
| A plugin/feature stopped working | The server IP may need to be in the allowlist. Add it as a protected entry (no seen: tag). |
CF-AllowList-Manager is intended for educational and authorized use only. Ensure you have the necessary permissions to access and manage the Cloudflare account and resources. The authors are not responsible for any misuse of these scripts.
For any questions or feedback, feel free to open an issue or contact the repository owner.