Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:18:15 +08:00
commit e85b8b73e8
9 changed files with 1928 additions and 0 deletions

View File

@@ -0,0 +1,293 @@
#!/usr/bin/env python3
"""
Comprehensive Cloudflare configuration checker.
This script diagnoses common Cloudflare issues including:
- SSL/TLS mode mismatches
- DNS configuration problems
- Cache settings
- Page rules and redirect loops
Requires:
- requests library
- Cloudflare API credentials (email + Global API Key OR API Token)
"""
import json
import sys
from typing import Dict, List, Optional, Tuple
def check_ssl_configuration(
zone_id: str, email: str, api_key: str
) -> Tuple[bool, List[str]]:
"""
Check SSL/TLS configuration for common issues.
Returns: (has_issues, issues_list)
"""
try:
import requests
except ImportError:
return True, ["Error: 'requests' library not installed. Install with: pip install requests"]
issues = []
# Get SSL mode
try:
response = requests.get(
f"https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/ssl",
headers={"X-Auth-Email": email, "X-Auth-Key": api_key},
timeout=30
)
if not response.ok:
return True, [f"API Error: {response.status_code} - {response.text}"]
data = response.json()
if not data.get("success"):
return True, [f"API Error: {data.get('errors', 'Unknown error')}"]
ssl_mode = data["result"]["value"]
# Check Always Use HTTPS setting
https_response = requests.get(
f"https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/always_use_https",
headers={"X-Auth-Email": email, "X-Auth-Key": api_key},
timeout=30
)
always_https = "off"
if https_response.ok:
https_data = https_response.json()
if https_data.get("success"):
always_https = https_data["result"]["value"]
# Analyze configuration
if ssl_mode == "flexible":
issues.append(
f"⚠️ SSL Mode is 'flexible' - this can cause redirect loops if your origin "
f"server enforces HTTPS (common with GitHub Pages, Netlify, Vercel, etc.)"
)
issues.append(
" Recommendation: Change SSL mode to 'full' or 'full (strict)' if your "
"origin supports HTTPS"
)
if ssl_mode == "off":
issues.append("⚠️ SSL is disabled - visitors will see 'Not Secure' warnings")
# Report current configuration
if not issues:
issues.append(f"✅ SSL Mode: {ssl_mode} - Configuration looks good")
issues.append(f" Always Use HTTPS: {always_https}")
return len([i for i in issues if i.startswith("⚠️")]) > 0, issues
except requests.RequestException as e:
return True, [f"Network Error: {str(e)}"]
except Exception as e:
return True, [f"Unexpected Error: {str(e)}"]
def check_dns_records(
zone_id: str, domain: str, email: str, api_key: str
) -> Tuple[bool, List[str]]:
"""
Check DNS configuration for common issues.
Returns: (has_issues, issues_list)
"""
try:
import requests
except ImportError:
return True, ["Error: 'requests' library not installed"]
issues = []
try:
response = requests.get(
f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records",
headers={"X-Auth-Email": email, "X-Auth-Key": api_key},
timeout=30
)
if not response.ok:
return True, [f"API Error: {response.status_code}"]
data = response.json()
if not data.get("success"):
return True, [f"API Error: {data.get('errors')}"]
records = data["result"]
# Check for root domain records
root_records = [r for r in records if r["name"] == domain]
if not root_records:
issues.append(f"⚠️ No DNS records found for root domain '{domain}'")
# Check proxy status
proxied_records = [r for r in records if r.get("proxied")]
if proxied_records:
issues.append(f"✅ Found {len(proxied_records)} proxied record(s) (Cloudflare CDN enabled)")
unproxied_important = [
r for r in records
if not r.get("proxied") and r["type"] in ["A", "AAAA", "CNAME"]
]
if unproxied_important:
issues.append(
f" Found {len(unproxied_important)} non-proxied record(s) - "
"these bypass Cloudflare's CDN and security features"
)
return len([i for i in issues if i.startswith("⚠️")]) > 0, issues
except Exception as e:
return True, [f"Error checking DNS: {str(e)}"]
def check_page_rules(
zone_id: str, email: str, api_key: str
) -> Tuple[bool, List[str]]:
"""
Check Page Rules for potential redirect loops.
Returns: (has_issues, issues_list)
"""
try:
import requests
except ImportError:
return True, ["Error: 'requests' library not installed"]
issues = []
try:
response = requests.get(
f"https://api.cloudflare.com/client/v4/zones/{zone_id}/pagerules",
headers={"X-Auth-Email": email, "X-Auth-Key": api_key},
timeout=30
)
if not response.ok:
return True, [f"API Error: {response.status_code}"]
data = response.json()
if not data.get("success"):
return True, [f"API Error: {data.get('errors')}"]
rules = data["result"]
if not rules:
issues.append("✅ No Page Rules configured")
return False, issues
# Check for redirect rules
redirect_rules = []
for rule in rules:
actions = rule.get("actions", [])
for action in actions:
if action.get("id") in ["forwarding_url", "always_use_https"]:
redirect_rules.append({
"url": rule.get("targets", [{}])[0].get("constraint", {}).get("value"),
"action": action.get("id"),
"status": rule.get("status")
})
if redirect_rules:
issues.append(f" Found {len(redirect_rules)} redirect Page Rule(s):")
for r in redirect_rules:
issues.append(f" - {r['url']}: {r['action']} (status: {r['status']})")
issues.append(
" Note: Conflicting redirect rules can cause redirect loops"
)
else:
issues.append("✅ No redirect Page Rules found")
return False, issues
except Exception as e:
return True, [f"Error checking Page Rules: {str(e)}"]
def main():
"""Main diagnostic function."""
if len(sys.argv) < 4:
print("Usage: python check_cloudflare_config.py <domain> <email> <api_key>")
print("\nExample:")
print(" python check_cloudflare_config.py typeof.tech user@example.com abc123...")
print("\nGet your Global API Key from:")
print(" https://dash.cloudflare.com/profile/api-tokens")
sys.exit(1)
domain = sys.argv[1]
email = sys.argv[2]
api_key = sys.argv[3]
try:
import requests
except ImportError:
print("Error: 'requests' library not found")
print("Install with: pip install requests")
sys.exit(1)
print(f"\n🔍 Checking Cloudflare configuration for: {domain}\n")
print("=" * 60)
# Get zone ID
try:
response = requests.get(
f"https://api.cloudflare.com/client/v4/zones?name={domain}",
headers={"X-Auth-Email": email, "X-Auth-Key": api_key},
timeout=30
)
if not response.ok:
print(f"❌ API Error: {response.status_code}")
sys.exit(1)
data = response.json()
if not data.get("success") or not data.get("result"):
print(f"❌ Domain '{domain}' not found in your Cloudflare account")
sys.exit(1)
zone_id = data["result"][0]["id"]
print(f"✅ Found zone: {domain} (ID: {zone_id})\n")
except requests.RequestException as e:
print(f"❌ Network error: {e}")
sys.exit(1)
# Run all checks
all_issues = []
print("\n📋 SSL/TLS Configuration:")
print("-" * 60)
has_ssl_issues, ssl_issues = check_ssl_configuration(zone_id, email, api_key)
for issue in ssl_issues:
print(issue)
print("\n📋 DNS Configuration:")
print("-" * 60)
has_dns_issues, dns_issues = check_dns_records(zone_id, domain, email, api_key)
for issue in dns_issues:
print(issue)
print("\n📋 Page Rules:")
print("-" * 60)
has_rules_issues, rules_issues = check_page_rules(zone_id, email, api_key)
for issue in rules_issues:
print(issue)
# Summary
print("\n" + "=" * 60)
if has_ssl_issues or has_dns_issues or has_rules_issues:
print("⚠️ Issues found - review the warnings above")
sys.exit(1)
else:
print("✅ No critical issues detected!")
sys.exit(0)
if __name__ == "__main__":
main()