Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "cloudflare-troubleshooting",
|
||||||
|
"description": "Investigate and resolve Cloudflare configuration issues using API-driven evidence gathering. Use when troubleshooting ERR_TOO_MANY_REDIRECTS, SSL errors, DNS issues, or any Cloudflare-related problems",
|
||||||
|
"version": "0.0.0-2025.11.28",
|
||||||
|
"author": {
|
||||||
|
"name": "daymade",
|
||||||
|
"email": "daymadev89@gmail.com"
|
||||||
|
},
|
||||||
|
"skills": [
|
||||||
|
"./skills/cloudflare-troubleshooting"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# cloudflare-troubleshooting
|
||||||
|
|
||||||
|
Investigate and resolve Cloudflare configuration issues using API-driven evidence gathering. Use when troubleshooting ERR_TOO_MANY_REDIRECTS, SSL errors, DNS issues, or any Cloudflare-related problems
|
||||||
64
plugin.lock.json
Normal file
64
plugin.lock.json
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:daymade/claude-code-skills:cloudflare-troubleshooting",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "f3354e95bdc12cac7c7318d9f9a2474dc7ecfe50",
|
||||||
|
"treeHash": "5b104d7fb8b9902806d947cec1eafa57d44cde501cf9481cc1c7e7f91f4a7047",
|
||||||
|
"generatedAt": "2025-11-28T10:16:14.473354Z",
|
||||||
|
"toolVersion": "publish_plugins.py@0.2.0"
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||||
|
"branch": "master",
|
||||||
|
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||||
|
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"name": "cloudflare-troubleshooting",
|
||||||
|
"description": "Investigate and resolve Cloudflare configuration issues using API-driven evidence gathering. Use when troubleshooting ERR_TOO_MANY_REDIRECTS, SSL errors, DNS issues, or any Cloudflare-related problems"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "e16bb5d3670b339cedb840b0b74b54341246d21c26c3b6f1f034e780a9dbd365"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "0b532cfe10501cc14f7f6e2b21ca667919444b54003485b0e2df66dc9b987193"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/cloudflare-troubleshooting/SKILL.md",
|
||||||
|
"sha256": "d9c5b1f38e55067a090c10abe4679ca507bdf69e1998d792869f0e3f0dd41e17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/cloudflare-troubleshooting/references/ssl_modes.md",
|
||||||
|
"sha256": "5cf6d9d5c76a903fc9e5cc11469a7b1c16fa6f775c00945feb3f15045ecde392"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/cloudflare-troubleshooting/references/common_issues.md",
|
||||||
|
"sha256": "6a35f9bec753487a4961a2a9e8b0cf38f329cc1a69b388446aa44ec8d41942b5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/cloudflare-troubleshooting/references/api_overview.md",
|
||||||
|
"sha256": "4dbe6aef7402cd26a30a166252335f64a952ee5ec3b307cb105218a0064fe59d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/cloudflare-troubleshooting/scripts/fix_ssl_mode.py",
|
||||||
|
"sha256": "e9f48e283189137f0402cde63d826afa560a2566c5ed1707fb47597ddd3024d1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/cloudflare-troubleshooting/scripts/check_cloudflare_config.py",
|
||||||
|
"sha256": "af949f88d1db660125ff9a977bf15fb55796a244a92d00f049123b80decd46c6"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "5b104d7fb8b9902806d947cec1eafa57d44cde501cf9481cc1c7e7f91f4a7047"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
325
skills/cloudflare-troubleshooting/SKILL.md
Normal file
325
skills/cloudflare-troubleshooting/SKILL.md
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
---
|
||||||
|
name: cloudflare-troubleshooting
|
||||||
|
description: Investigate and resolve Cloudflare configuration issues using API-driven evidence gathering. Use when troubleshooting ERR_TOO_MANY_REDIRECTS, SSL errors, DNS issues, or any Cloudflare-related problems. Focus on systematic investigation using Cloudflare API to examine actual configuration rather than making assumptions.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Cloudflare Troubleshooting
|
||||||
|
|
||||||
|
## Core Principle
|
||||||
|
|
||||||
|
**Investigate with evidence, not assumptions.** Always query Cloudflare API to examine actual configuration before diagnosing issues. The skill's value is the systematic investigation methodology, not predetermined solutions.
|
||||||
|
|
||||||
|
## Investigation Methodology
|
||||||
|
|
||||||
|
### 1. Gather Credentials
|
||||||
|
|
||||||
|
Request from user:
|
||||||
|
- Domain name
|
||||||
|
- Cloudflare account email
|
||||||
|
- Cloudflare Global API Key (or API Token)
|
||||||
|
|
||||||
|
Global API Key location: Cloudflare Dashboard → My Profile → API Tokens → View Global API Key
|
||||||
|
|
||||||
|
### 2. Get Zone Information
|
||||||
|
|
||||||
|
First step for any Cloudflare troubleshooting - obtain the zone ID:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=<domain>" \
|
||||||
|
-H "X-Auth-Email: <email>" \
|
||||||
|
-H "X-Auth-Key: <api_key>" | jq '.'
|
||||||
|
```
|
||||||
|
|
||||||
|
Extract `zone_id` from `result[0].id` for subsequent API calls.
|
||||||
|
|
||||||
|
### 3. Investigate Systematically
|
||||||
|
|
||||||
|
For each issue, gather evidence before making conclusions. Use Cloudflare API to inspect:
|
||||||
|
- Current configuration state
|
||||||
|
- Recent changes (if audit log available)
|
||||||
|
- Related settings that might interact
|
||||||
|
|
||||||
|
## Common Investigation Patterns
|
||||||
|
|
||||||
|
### Redirect Loops (ERR_TOO_MANY_REDIRECTS)
|
||||||
|
|
||||||
|
**Evidence gathering sequence:**
|
||||||
|
|
||||||
|
1. **Check SSL/TLS mode:**
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/ssl" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
Look for: `result.value` - tells current SSL mode
|
||||||
|
|
||||||
|
2. **Check Always Use HTTPS setting:**
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/always_use_https" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Check Page Rules for redirects:**
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/pagerules" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
Look for: `forwarding_url` or `always_use_https` actions
|
||||||
|
|
||||||
|
4. **Test origin server directly (if possible):**
|
||||||
|
```bash
|
||||||
|
curl -I -H "Host: <domain>" https://<origin_ip>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Diagnosis logic:**
|
||||||
|
- SSL mode "flexible" + origin enforces HTTPS = redirect loop
|
||||||
|
- Multiple redirect rules can conflict
|
||||||
|
- Check browser vs curl behavior differences
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
```bash
|
||||||
|
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/ssl" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data '{"value":"full"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Purge cache after fix:
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key" \
|
||||||
|
-d '{"purge_everything":true}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### DNS Issues
|
||||||
|
|
||||||
|
**Evidence gathering:**
|
||||||
|
|
||||||
|
1. **List DNS records:**
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check external DNS resolution:**
|
||||||
|
```bash
|
||||||
|
dig <domain>
|
||||||
|
dig @8.8.8.8 <domain>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Check DNSSEC status:**
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/dnssec" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Look for:**
|
||||||
|
- Missing A/AAAA/CNAME records
|
||||||
|
- Incorrect proxy status (proxied vs DNS-only)
|
||||||
|
- TTL values
|
||||||
|
- Conflicting records
|
||||||
|
|
||||||
|
### SSL Certificate Errors
|
||||||
|
|
||||||
|
**Evidence gathering:**
|
||||||
|
|
||||||
|
1. **Check SSL certificate status:**
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/ssl/certificate_packs" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check origin certificate (if using Full Strict):**
|
||||||
|
```bash
|
||||||
|
openssl s_client -connect <origin_ip>:443 -servername <domain>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Check SSL settings:**
|
||||||
|
- Minimum TLS version
|
||||||
|
- TLS 1.3 status
|
||||||
|
- Opportunistic Encryption
|
||||||
|
|
||||||
|
**Common issues:**
|
||||||
|
- Error 526: SSL mode is "strict" but origin cert invalid
|
||||||
|
- Error 525: SSL handshake failure at origin
|
||||||
|
- Provisioning delay: Wait 15-30 minutes for Universal SSL
|
||||||
|
|
||||||
|
### Origin Server Errors (502/503/504)
|
||||||
|
|
||||||
|
**Evidence gathering:**
|
||||||
|
|
||||||
|
1. **Check if origin is reachable:**
|
||||||
|
```bash
|
||||||
|
curl -I -H "Host: <domain>" https://<origin_ip>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check DNS records point to correct origin:**
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Review load balancer config (if applicable):**
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/load_balancers" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Check firewall rules:**
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/firewall/rules" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Learning New APIs
|
||||||
|
|
||||||
|
When encountering issues not covered above, consult Cloudflare API documentation:
|
||||||
|
|
||||||
|
1. **Browse API reference:** https://developers.cloudflare.com/api/
|
||||||
|
2. **Search for relevant endpoints** using issue keywords
|
||||||
|
3. **Check API schema** to understand available operations
|
||||||
|
4. **Test with GET requests** first to understand data structure
|
||||||
|
5. **Make changes with PATCH/POST** after confirming approach
|
||||||
|
|
||||||
|
**Pattern for exploring new APIs:**
|
||||||
|
```bash
|
||||||
|
# List available settings for a zone
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/settings" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Reference Overview
|
||||||
|
|
||||||
|
Consult `references/api_overview.md` for:
|
||||||
|
- Common endpoints organized by category
|
||||||
|
- Request/response schemas
|
||||||
|
- Authentication patterns
|
||||||
|
- Rate limits and error handling
|
||||||
|
|
||||||
|
Consult `references/ssl_modes.md` for:
|
||||||
|
- Detailed SSL/TLS mode explanations
|
||||||
|
- Platform compatibility
|
||||||
|
- Security implications
|
||||||
|
|
||||||
|
Consult `references/common_issues.md` for:
|
||||||
|
- Issue patterns and symptoms
|
||||||
|
- Investigation checklists
|
||||||
|
- Platform-specific notes
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Evidence-Based Investigation
|
||||||
|
|
||||||
|
1. **Query before assuming** - Use API to check actual state
|
||||||
|
2. **Gather multiple data points** - Cross-reference settings
|
||||||
|
3. **Check related configurations** - Settings often interact
|
||||||
|
4. **Verify externally** - Use dig/curl to confirm
|
||||||
|
5. **Test incrementally** - One change at a time
|
||||||
|
|
||||||
|
### API Usage
|
||||||
|
|
||||||
|
1. **Parse JSON responses** - Use `jq` or python for readability
|
||||||
|
2. **Check success field** - `"success": true/false` in responses
|
||||||
|
3. **Handle errors gracefully** - Read `errors` array in responses
|
||||||
|
4. **Respect rate limits** - Cloudflare API has limits
|
||||||
|
5. **Use appropriate methods:**
|
||||||
|
- GET: Retrieve information
|
||||||
|
- PATCH: Update settings
|
||||||
|
- POST: Create resources / trigger actions
|
||||||
|
- DELETE: Remove resources
|
||||||
|
|
||||||
|
### Making Changes
|
||||||
|
|
||||||
|
1. **Gather evidence first** - Understand current state
|
||||||
|
2. **Identify root cause** - Don't guess
|
||||||
|
3. **Apply targeted fix** - Change only what's needed
|
||||||
|
4. **Purge cache if needed** - Especially for SSL/redirect changes
|
||||||
|
5. **Verify fix** - Re-query API to confirm
|
||||||
|
6. **Inform user of wait times:**
|
||||||
|
- Edge server propagation: 30-60 seconds
|
||||||
|
- DNS propagation: Up to 48 hours
|
||||||
|
- Browser cache: Requires manual clear
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Never log API keys in output
|
||||||
|
- Warn if user shares credentials in public context
|
||||||
|
- Recommend API Tokens with scoped permissions over Global API Key
|
||||||
|
- Use read-only operations for investigation
|
||||||
|
|
||||||
|
## Workflow Template
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Gather: domain, email, API key
|
||||||
|
2. Get zone_id via zones API
|
||||||
|
3. Investigate:
|
||||||
|
- Query relevant APIs for evidence
|
||||||
|
- Check multiple related settings
|
||||||
|
- Verify with external tools (dig, curl)
|
||||||
|
4. Analyze evidence to determine root cause
|
||||||
|
5. Apply fix via appropriate API endpoint
|
||||||
|
6. Purge cache if configuration change affects delivery
|
||||||
|
7. Verify fix via API query and external testing
|
||||||
|
8. Inform user of resolution and any required actions
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example: Complete Investigation
|
||||||
|
|
||||||
|
When user reports "site shows ERR_TOO_MANY_REDIRECTS":
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Get zone ID
|
||||||
|
curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=example.com" \
|
||||||
|
-H "X-Auth-Email: user@example.com" \
|
||||||
|
-H "X-Auth-Key: abc123" | jq '.result[0].id'
|
||||||
|
|
||||||
|
# 2. Check SSL mode (primary suspect for redirect loops)
|
||||||
|
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/ssl" \
|
||||||
|
-H "X-Auth-Email: user@example.com" \
|
||||||
|
-H "X-Auth-Key: abc123" | jq '.result.value'
|
||||||
|
|
||||||
|
# If returns "flexible" and origin is GitHub Pages/Netlify/Vercel:
|
||||||
|
|
||||||
|
# 3. Fix by changing to "full"
|
||||||
|
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/ssl" \
|
||||||
|
-H "X-Auth-Email: user@example.com" \
|
||||||
|
-H "X-Auth-Key: abc123" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data '{"value":"full"}'
|
||||||
|
|
||||||
|
# 4. Purge cache
|
||||||
|
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/purge_cache" \
|
||||||
|
-H "X-Auth-Email: user@example.com" \
|
||||||
|
-H "X-Auth-Key: abc123" \
|
||||||
|
-d '{"purge_everything":true}'
|
||||||
|
|
||||||
|
# 5. Inform user: Wait 60 seconds, clear browser cache, retry
|
||||||
|
```
|
||||||
|
|
||||||
|
## When Scripts Are Useful
|
||||||
|
|
||||||
|
The bundled scripts (`scripts/check_cloudflare_config.py`, `scripts/fix_ssl_mode.py`) serve as:
|
||||||
|
- **Reference implementations** of investigation patterns
|
||||||
|
- **Quick diagnostic tools** when Python is available
|
||||||
|
- **Examples** of programmatic API usage
|
||||||
|
|
||||||
|
However, **prefer direct API calls via Bash/curl** for flexibility and transparency. Scripts should not limit capability - use them when convenient, but use raw API calls when needed for:
|
||||||
|
- Unfamiliar scenarios
|
||||||
|
- Edge cases
|
||||||
|
- Learning/debugging
|
||||||
|
- Operations not covered by scripts
|
||||||
|
|
||||||
|
The investigation methodology and API knowledge is the core skill, not the scripts.
|
||||||
538
skills/cloudflare-troubleshooting/references/api_overview.md
Normal file
538
skills/cloudflare-troubleshooting/references/api_overview.md
Normal file
@@ -0,0 +1,538 @@
|
|||||||
|
# Cloudflare API Overview
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
### Global API Key (used in examples)
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/..." \
|
||||||
|
-H "X-Auth-Email: user@example.com" \
|
||||||
|
-H "X-Auth-Key: abc123..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Token (recommended for production)
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/..." \
|
||||||
|
-H "Authorization: Bearer <token>"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Response Format
|
||||||
|
|
||||||
|
All API responses follow this structure:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true/false,
|
||||||
|
"errors": [],
|
||||||
|
"messages": [],
|
||||||
|
"result": { ... },
|
||||||
|
"result_info": { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Always check `success` field before processing `result`.
|
||||||
|
|
||||||
|
## Core Endpoints by Category
|
||||||
|
|
||||||
|
### Zone Management
|
||||||
|
|
||||||
|
**List zones:**
|
||||||
|
```bash
|
||||||
|
GET /zones?name=<domain>
|
||||||
|
```
|
||||||
|
Returns zone information including `id`, `name`, `status`, `name_servers`
|
||||||
|
|
||||||
|
**Get zone details:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Get all zone settings:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings
|
||||||
|
```
|
||||||
|
Returns all configurable settings for the zone
|
||||||
|
|
||||||
|
### SSL/TLS
|
||||||
|
|
||||||
|
**Get SSL mode:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/ssl
|
||||||
|
```
|
||||||
|
Result: `{"value": "flexible"|"full"|"strict"|"off"}`
|
||||||
|
|
||||||
|
**Update SSL mode:**
|
||||||
|
```bash
|
||||||
|
PATCH /zones/{zone_id}/settings/ssl
|
||||||
|
Content-Type: application/json
|
||||||
|
{"value": "full"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Get Always Use HTTPS:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/always_use_https
|
||||||
|
```
|
||||||
|
|
||||||
|
**Update Always Use HTTPS:**
|
||||||
|
```bash
|
||||||
|
PATCH /zones/{zone_id}/settings/always_use_https
|
||||||
|
{"value": "on"|"off"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**List SSL certificates:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/ssl/certificate_packs
|
||||||
|
```
|
||||||
|
|
||||||
|
**Get SSL verification details:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/ssl/verification
|
||||||
|
```
|
||||||
|
|
||||||
|
**Get SSL settings (universal, dedicated, etc):**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/ssl/analyze
|
||||||
|
```
|
||||||
|
|
||||||
|
**TLS 1.3 setting:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/tls_1_3
|
||||||
|
PATCH /zones/{zone_id}/settings/tls_1_3
|
||||||
|
{"value": "on"|"off"|"zrt"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Minimum TLS version:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/min_tls_version
|
||||||
|
PATCH /zones/{zone_id}/settings/min_tls_version
|
||||||
|
{"value": "1.0"|"1.1"|"1.2"|"1.3"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### DNS Records
|
||||||
|
|
||||||
|
**List DNS records:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/dns_records
|
||||||
|
```
|
||||||
|
Returns array of DNS records with type, name, content, proxied status, TTL
|
||||||
|
|
||||||
|
**Filter by type:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/dns_records?type=A
|
||||||
|
GET /zones/{zone_id}/dns_records?type=CNAME
|
||||||
|
```
|
||||||
|
|
||||||
|
**Get specific record:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/dns_records/{record_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Create DNS record:**
|
||||||
|
```bash
|
||||||
|
POST /zones/{zone_id}/dns_records
|
||||||
|
{
|
||||||
|
"type": "A",
|
||||||
|
"name": "example.com",
|
||||||
|
"content": "192.0.2.1",
|
||||||
|
"ttl": 3600,
|
||||||
|
"proxied": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Update DNS record:**
|
||||||
|
```bash
|
||||||
|
PATCH /zones/{zone_id}/dns_records/{record_id}
|
||||||
|
{"proxied": true}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Delete DNS record:**
|
||||||
|
```bash
|
||||||
|
DELETE /zones/{zone_id}/dns_records/{record_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**DNSSEC status:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/dnssec
|
||||||
|
```
|
||||||
|
|
||||||
|
### Page Rules
|
||||||
|
|
||||||
|
**List page rules:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/pagerules
|
||||||
|
```
|
||||||
|
|
||||||
|
**Get specific page rule:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/pagerules/{rule_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Create page rule:**
|
||||||
|
```bash
|
||||||
|
POST /zones/{zone_id}/pagerules
|
||||||
|
{
|
||||||
|
"targets": [{"target": "url", "constraint": {"operator": "matches", "value": "*example.com/*"}}],
|
||||||
|
"actions": [{"id": "always_use_https"}],
|
||||||
|
"priority": 1,
|
||||||
|
"status": "active"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Update page rule:**
|
||||||
|
```bash
|
||||||
|
PATCH /zones/{zone_id}/pagerules/{rule_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Delete page rule:**
|
||||||
|
```bash
|
||||||
|
DELETE /zones/{zone_id}/pagerules/{rule_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cache
|
||||||
|
|
||||||
|
**Purge everything:**
|
||||||
|
```bash
|
||||||
|
POST /zones/{zone_id}/purge_cache
|
||||||
|
{"purge_everything": true}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Purge by URL:**
|
||||||
|
```bash
|
||||||
|
POST /zones/{zone_id}/purge_cache
|
||||||
|
{"files": ["https://example.com/style.css", "https://example.com/script.js"]}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Purge by tag:**
|
||||||
|
```bash
|
||||||
|
POST /zones/{zone_id}/purge_cache
|
||||||
|
{"tags": ["tag1", "tag2"]}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Purge by host:**
|
||||||
|
```bash
|
||||||
|
POST /zones/{zone_id}/purge_cache
|
||||||
|
{"hosts": ["example.com", "www.example.com"]}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Cache settings:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/cache_level
|
||||||
|
GET /zones/{zone_id}/settings/browser_cache_ttl
|
||||||
|
GET /zones/{zone_id}/settings/development_mode
|
||||||
|
```
|
||||||
|
|
||||||
|
### Firewall
|
||||||
|
|
||||||
|
**List firewall rules:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/firewall/rules
|
||||||
|
```
|
||||||
|
|
||||||
|
**List WAF rules:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/firewall/waf/packages
|
||||||
|
GET /zones/{zone_id}/firewall/waf/packages/{package_id}/rules
|
||||||
|
```
|
||||||
|
|
||||||
|
**IP Access Rules:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/firewall/access_rules/rules
|
||||||
|
POST /zones/{zone_id}/firewall/access_rules/rules
|
||||||
|
{
|
||||||
|
"mode": "block"|"challenge"|"whitelist",
|
||||||
|
"configuration": {"target": "ip", "value": "192.0.2.1"},
|
||||||
|
"notes": "Blocked malicious IP"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rate limiting:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/rate_limits
|
||||||
|
POST /zones/{zone_id}/rate_limits
|
||||||
|
```
|
||||||
|
|
||||||
|
### Analytics
|
||||||
|
|
||||||
|
**Get analytics:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/analytics/dashboard
|
||||||
|
```
|
||||||
|
|
||||||
|
**Traffic analytics:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/analytics/colos
|
||||||
|
```
|
||||||
|
|
||||||
|
**DNS analytics:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/dns_analytics/report
|
||||||
|
```
|
||||||
|
|
||||||
|
### Load Balancers
|
||||||
|
|
||||||
|
**List load balancers:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/load_balancers
|
||||||
|
```
|
||||||
|
|
||||||
|
**Get load balancer details:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/load_balancers/{lb_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
**List pools:**
|
||||||
|
```bash
|
||||||
|
GET /accounts/{account_id}/load_balancers/pools
|
||||||
|
```
|
||||||
|
|
||||||
|
**List monitors:**
|
||||||
|
```bash
|
||||||
|
GET /accounts/{account_id}/load_balancers/monitors
|
||||||
|
```
|
||||||
|
|
||||||
|
### Workers & Routes
|
||||||
|
|
||||||
|
**List worker routes:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/workers/routes
|
||||||
|
```
|
||||||
|
|
||||||
|
**List worker scripts:**
|
||||||
|
```bash
|
||||||
|
GET /accounts/{account_id}/workers/scripts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Settings (Other Common)
|
||||||
|
|
||||||
|
**Development mode:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/development_mode
|
||||||
|
PATCH /zones/{zone_id}/settings/development_mode
|
||||||
|
{"value": "on"|"off"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Security level:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/security_level
|
||||||
|
PATCH /zones/{zone_id}/settings/security_level
|
||||||
|
{"value": "off"|"essentially_off"|"low"|"medium"|"high"|"under_attack"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rocket Loader:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/rocket_loader
|
||||||
|
PATCH /zones/{zone_id}/settings/rocket_loader
|
||||||
|
{"value": "on"|"off"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Auto minify:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/minify
|
||||||
|
PATCH /zones/{zone_id}/settings/minify
|
||||||
|
{"value": {"css": "on", "html": "on", "js": "on"}}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Brotli compression:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/brotli
|
||||||
|
```
|
||||||
|
|
||||||
|
**HTTP/2:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/http2
|
||||||
|
```
|
||||||
|
|
||||||
|
**HTTP/3 (QUIC):**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/http3
|
||||||
|
```
|
||||||
|
|
||||||
|
**IPv6:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/ipv6
|
||||||
|
```
|
||||||
|
|
||||||
|
**Opportunistic Encryption:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/opportunistic_encryption
|
||||||
|
```
|
||||||
|
|
||||||
|
**Automatic HTTPS Rewrites:**
|
||||||
|
```bash
|
||||||
|
GET /zones/{zone_id}/settings/automatic_https_rewrites
|
||||||
|
PATCH /zones/{zone_id}/settings/automatic_https_rewrites
|
||||||
|
{"value": "on"|"off"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Learning New Endpoints
|
||||||
|
|
||||||
|
### Method 1: List All Settings
|
||||||
|
```bash
|
||||||
|
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/settings" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key" | jq '.result[] | {id, value}'
|
||||||
|
```
|
||||||
|
|
||||||
|
This returns all available settings with current values. Use setting `id` to construct endpoint:
|
||||||
|
`/zones/{zone_id}/settings/{id}`
|
||||||
|
|
||||||
|
### Method 2: Cloudflare API Docs
|
||||||
|
|
||||||
|
Browse official API reference: https://developers.cloudflare.com/api/
|
||||||
|
|
||||||
|
**Structure:**
|
||||||
|
- Operations organized by product/feature
|
||||||
|
- Each operation shows:
|
||||||
|
- HTTP method and endpoint
|
||||||
|
- Required/optional parameters
|
||||||
|
- Request body schema
|
||||||
|
- Response schema
|
||||||
|
- Example requests
|
||||||
|
|
||||||
|
**Search strategy:**
|
||||||
|
1. Identify feature/product (SSL, DNS, Cache, etc.)
|
||||||
|
2. Find relevant operations (List, Get, Create, Update, Delete)
|
||||||
|
3. Check request schema for required fields
|
||||||
|
4. Test with GET before making changes
|
||||||
|
|
||||||
|
### Method 3: Explore API Interactively
|
||||||
|
|
||||||
|
**Pattern:**
|
||||||
|
1. Start with zone info to understand structure
|
||||||
|
2. List resources: `GET /zones/{zone_id}/{resource_type}`
|
||||||
|
3. Get specific item: `GET /zones/{zone_id}/{resource_type}/{id}`
|
||||||
|
4. Check available operations in docs
|
||||||
|
5. Make changes: `PATCH/POST/DELETE`
|
||||||
|
|
||||||
|
**Example exploration for unknown feature:**
|
||||||
|
```bash
|
||||||
|
# 1. Check if endpoint exists
|
||||||
|
curl -I "https://api.cloudflare.com/client/v4/zones/{zone_id}/feature_name"
|
||||||
|
|
||||||
|
# 2. Try listing (if collection)
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/feature_name" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
|
||||||
|
# 3. Examine response structure
|
||||||
|
# 4. Consult docs for modification operations
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
Common error codes:
|
||||||
|
- 400: Bad request (check request format)
|
||||||
|
- 401: Unauthorized (check API credentials)
|
||||||
|
- 403: Forbidden (insufficient permissions)
|
||||||
|
- 404: Not found (check zone_id or resource_id)
|
||||||
|
- 429: Rate limit exceeded (wait before retrying)
|
||||||
|
- 500: Server error (Cloudflare issue, retry later)
|
||||||
|
|
||||||
|
**Error response structure:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": 1234,
|
||||||
|
"message": "Error description"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"messages": [],
|
||||||
|
"result": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rate Limits
|
||||||
|
|
||||||
|
- Free tier: ~1200 requests per 5 minutes
|
||||||
|
- Paid tiers: Higher limits based on plan
|
||||||
|
- If rate limited (429), back off exponentially
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Use jq for readability:**
|
||||||
|
```bash
|
||||||
|
curl ... | jq '.result'
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Extract specific fields:**
|
||||||
|
```bash
|
||||||
|
curl ... | jq '.result.value'
|
||||||
|
curl ... | jq '.result[] | {id, name, value}'
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Check success before processing:**
|
||||||
|
```bash
|
||||||
|
response=$(curl ...)
|
||||||
|
success=$(echo "$response" | jq -r '.success')
|
||||||
|
if [ "$success" = "true" ]; then
|
||||||
|
echo "$response" | jq '.result'
|
||||||
|
else
|
||||||
|
echo "$response" | jq '.errors'
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Store zone_id for reuse:**
|
||||||
|
```bash
|
||||||
|
zone_id=$(curl ... | jq -r '.result[0].id')
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Test with GET first:**
|
||||||
|
Before modifying configuration, always GET to see current state
|
||||||
|
|
||||||
|
## Common Investigation Patterns
|
||||||
|
|
||||||
|
### Pattern 1: Settings Investigation
|
||||||
|
```bash
|
||||||
|
# Get all settings
|
||||||
|
curl -X GET "/zones/{zone_id}/settings" | jq '.result[]'
|
||||||
|
|
||||||
|
# Filter specific settings
|
||||||
|
curl -X GET "/zones/{zone_id}/settings" | jq '.result[] | select(.id | contains("ssl"))'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 2: Resource Listing + Details
|
||||||
|
```bash
|
||||||
|
# List resources
|
||||||
|
curl -X GET "/zones/{zone_id}/dns_records" | jq '.result[] | {id, name, type}'
|
||||||
|
|
||||||
|
# Get specific resource
|
||||||
|
record_id="..."
|
||||||
|
curl -X GET "/zones/{zone_id}/dns_records/$record_id" | jq '.'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 3: Multi-Setting Check
|
||||||
|
```bash
|
||||||
|
# Check related settings in parallel
|
||||||
|
curl ... /settings/ssl &
|
||||||
|
curl ... /settings/always_use_https &
|
||||||
|
curl ... /pagerules &
|
||||||
|
wait
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 4: Change + Verify
|
||||||
|
```bash
|
||||||
|
# Make change
|
||||||
|
curl -X PATCH "/zones/{zone_id}/settings/ssl" -d '{"value":"full"}'
|
||||||
|
|
||||||
|
# Verify change applied
|
||||||
|
curl -X GET "/zones/{zone_id}/settings/ssl" | jq '.result.value'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Account-Level vs Zone-Level
|
||||||
|
|
||||||
|
Some resources are account-level, not zone-level:
|
||||||
|
|
||||||
|
**Account-level:**
|
||||||
|
- Load balancer pools/monitors: `/accounts/{account_id}/load_balancers/...`
|
||||||
|
- Workers scripts: `/accounts/{account_id}/workers/...`
|
||||||
|
- Access policies: `/accounts/{account_id}/access/...`
|
||||||
|
|
||||||
|
**Zone-level:**
|
||||||
|
- DNS records: `/zones/{zone_id}/dns_records`
|
||||||
|
- SSL settings: `/zones/{zone_id}/settings/ssl`
|
||||||
|
- Page rules: `/zones/{zone_id}/pagerules`
|
||||||
|
|
||||||
|
Get account_id from zone info:
|
||||||
|
```bash
|
||||||
|
curl -X GET "/zones?name=example.com" | jq '.result[0].account.id'
|
||||||
|
```
|
||||||
261
skills/cloudflare-troubleshooting/references/common_issues.md
Normal file
261
skills/cloudflare-troubleshooting/references/common_issues.md
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
# Common Cloudflare Issues and Solutions
|
||||||
|
|
||||||
|
## Redirect Loop Errors (ERR_TOO_MANY_REDIRECTS)
|
||||||
|
|
||||||
|
### Symptom
|
||||||
|
Browser displays "This page isn't working" or "ERR_TOO_MANY_REDIRECTS"
|
||||||
|
|
||||||
|
### Common Causes
|
||||||
|
|
||||||
|
#### 1. SSL Mode Mismatch (Most Common)
|
||||||
|
**Scenario:** Origin server enforces HTTPS, but Cloudflare SSL mode is "Flexible"
|
||||||
|
|
||||||
|
**Explanation:**
|
||||||
|
- Browser → HTTPS → Cloudflare
|
||||||
|
- Cloudflare → HTTP → Origin Server (because of Flexible mode)
|
||||||
|
- Origin Server → Redirects to HTTPS (because it enforces HTTPS)
|
||||||
|
- Infinite loop
|
||||||
|
|
||||||
|
**Affected Platforms:**
|
||||||
|
- GitHub Pages
|
||||||
|
- Netlify
|
||||||
|
- Vercel
|
||||||
|
- Heroku
|
||||||
|
- Most modern hosting platforms
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
Change SSL mode from "Flexible" to "Full" or "Full (strict)"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Diagnose
|
||||||
|
python scripts/check_cloudflare_config.py example.com user@example.com API_KEY
|
||||||
|
|
||||||
|
# Fix
|
||||||
|
python scripts/fix_ssl_mode.py example.com user@example.com API_KEY full --purge-cache
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Conflicting Page Rules
|
||||||
|
**Scenario:** Multiple redirect rules that conflict with each other
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
- Review Page Rules in Cloudflare Dashboard
|
||||||
|
- Remove conflicting "Always Use HTTPS" or "Forwarding URL" rules
|
||||||
|
- Ensure redirect rules don't create loops
|
||||||
|
|
||||||
|
#### 3. Origin Server Misconfiguration
|
||||||
|
**Scenario:** Origin server has incorrect redirect rules in .htaccess or nginx config
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
- Check origin server configuration
|
||||||
|
- Verify redirects don't conflict with Cloudflare settings
|
||||||
|
- Test direct origin access (bypass Cloudflare)
|
||||||
|
|
||||||
|
### Resolution Steps
|
||||||
|
|
||||||
|
1. **Check SSL mode:**
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/ssl" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Fix SSL mode if needed:**
|
||||||
|
```bash
|
||||||
|
python scripts/fix_ssl_mode.py domain.com email API_KEY full
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Purge cache:**
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/purge_cache" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key" \
|
||||||
|
-d '{"purge_everything":true}'
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Clear browser cache or use incognito mode**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DNS Resolution Issues
|
||||||
|
|
||||||
|
### Symptom
|
||||||
|
Website not accessible or showing old content
|
||||||
|
|
||||||
|
### Common Causes
|
||||||
|
|
||||||
|
#### 1. DNS Not Propagated
|
||||||
|
**Solution:** Wait 24-48 hours for full DNS propagation
|
||||||
|
|
||||||
|
Check propagation:
|
||||||
|
```bash
|
||||||
|
dig domain.com
|
||||||
|
nslookup domain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Incorrect DNS Records
|
||||||
|
**Solution:**
|
||||||
|
- Verify A/AAAA/CNAME records point to correct IPs
|
||||||
|
- For GitHub Pages: Use A records to GitHub IPs or CNAME to username.github.io
|
||||||
|
- Ensure "Proxied" status matches requirements
|
||||||
|
|
||||||
|
#### 3. DNSSEC Issues
|
||||||
|
**Solution:**
|
||||||
|
- Check DNSSEC status in Cloudflare Dashboard
|
||||||
|
- Verify DS records at registrar match Cloudflare's DNSSEC settings
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## SSL/TLS Certificate Errors
|
||||||
|
|
||||||
|
### Symptom
|
||||||
|
"Your connection is not private" or "NET::ERR_CERT_COMMON_NAME_INVALID"
|
||||||
|
|
||||||
|
### Common Causes
|
||||||
|
|
||||||
|
#### 1. Universal SSL Certificate Provisioning Delay
|
||||||
|
**Solution:** Wait 15-30 minutes for Cloudflare to provision certificate
|
||||||
|
|
||||||
|
#### 2. CAA Records Blocking Certificate Issuance
|
||||||
|
**Solution:**
|
||||||
|
- Check CAA records
|
||||||
|
- Ensure CAA allows Let's Encrypt: `letsencrypt.org` or Cloudflare CAs
|
||||||
|
|
||||||
|
#### 3. Full (Strict) Mode with Invalid Origin Certificate
|
||||||
|
**Solution:**
|
||||||
|
- Use "Full" mode instead of "Full (strict)" if origin cert is self-signed
|
||||||
|
- Or install valid certificate on origin server
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Issues
|
||||||
|
|
||||||
|
### Symptom
|
||||||
|
Slow page load times despite using Cloudflare
|
||||||
|
|
||||||
|
### Common Causes
|
||||||
|
|
||||||
|
#### 1. Cache Not Configured
|
||||||
|
**Solution:**
|
||||||
|
- Enable Auto Minify (JS, CSS, HTML)
|
||||||
|
- Set up Page Rules for cache levels
|
||||||
|
- Configure Browser Cache TTL
|
||||||
|
|
||||||
|
#### 2. Large Assets Not Optimized
|
||||||
|
**Solution:**
|
||||||
|
- Enable Cloudflare Image Optimization
|
||||||
|
- Use WebP format
|
||||||
|
- Implement lazy loading
|
||||||
|
|
||||||
|
#### 3. Too Many Uncached Requests
|
||||||
|
**Solution:**
|
||||||
|
- Review cache analytics
|
||||||
|
- Add cache rules for static assets
|
||||||
|
- Use Cloudflare Workers for dynamic caching
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Access Denied / 403 Errors
|
||||||
|
|
||||||
|
### Symptom
|
||||||
|
"Error 1020: Access Denied" or generic 403
|
||||||
|
|
||||||
|
### Common Causes
|
||||||
|
|
||||||
|
#### 1. Firewall Rules Blocking Traffic
|
||||||
|
**Solution:**
|
||||||
|
- Review Firewall Rules in Security → WAF
|
||||||
|
- Check IP Access Rules
|
||||||
|
- Verify Managed Rulesets aren't too strict
|
||||||
|
|
||||||
|
#### 2. Rate Limiting
|
||||||
|
**Solution:**
|
||||||
|
- Check Rate Limiting rules
|
||||||
|
- Adjust thresholds if legitimate traffic is blocked
|
||||||
|
|
||||||
|
#### 3. Browser Integrity Check
|
||||||
|
**Solution:**
|
||||||
|
- Disable "Browser Integrity Check" if needed
|
||||||
|
- Found in: Security → Settings
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Origin Server Errors (502/503/504)
|
||||||
|
|
||||||
|
### Symptom
|
||||||
|
"502 Bad Gateway" or "504 Gateway Timeout"
|
||||||
|
|
||||||
|
### Common Causes
|
||||||
|
|
||||||
|
#### 1. Origin Server Down
|
||||||
|
**Solution:**
|
||||||
|
- Verify origin server is running
|
||||||
|
- Check origin server logs
|
||||||
|
- Test direct IP access
|
||||||
|
|
||||||
|
#### 2. Origin SSL Certificate Invalid (Full Strict mode)
|
||||||
|
**Solution:**
|
||||||
|
- Switch to "Full" mode temporarily
|
||||||
|
- Fix origin certificate
|
||||||
|
- Or use Cloudflare Origin Certificate
|
||||||
|
|
||||||
|
#### 3. Timeout Issues
|
||||||
|
**Solution:**
|
||||||
|
- Increase origin server timeout settings
|
||||||
|
- Optimize slow queries/code
|
||||||
|
- Consider using Cloudflare Workers for timeouts
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Page Rules Not Working
|
||||||
|
|
||||||
|
### Symptom
|
||||||
|
Page Rules don't seem to apply
|
||||||
|
|
||||||
|
### Common Causes
|
||||||
|
|
||||||
|
#### 1. Rule Order
|
||||||
|
**Solution:** Page Rules are executed top-to-bottom; reorder if needed
|
||||||
|
|
||||||
|
#### 2. Pattern Matching Issues
|
||||||
|
**Solution:**
|
||||||
|
- Use `*` for wildcards correctly
|
||||||
|
- Test patterns: `example.com/*` vs `*example.com/*`
|
||||||
|
|
||||||
|
#### 3. Cache Already Set
|
||||||
|
**Solution:** Purge cache after creating/modifying Page Rules
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting Workflow
|
||||||
|
|
||||||
|
### Step 1: Identify the Issue
|
||||||
|
- Collect error messages and codes
|
||||||
|
- Note when issue started
|
||||||
|
- Check if issue is intermittent or consistent
|
||||||
|
|
||||||
|
### Step 2: Check Cloudflare Status
|
||||||
|
- Visit https://www.cloudflarestatus.com
|
||||||
|
- Verify no ongoing incidents
|
||||||
|
|
||||||
|
### Step 3: Run Diagnostics
|
||||||
|
```bash
|
||||||
|
python scripts/check_cloudflare_config.py domain.com email API_KEY
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Review Recent Changes
|
||||||
|
- Check Cloudflare Audit Log
|
||||||
|
- Review recent DNS/SSL/Page Rule changes
|
||||||
|
|
||||||
|
### Step 5: Test Bypass
|
||||||
|
- Temporarily set DNS to "DNS Only" (grey cloud)
|
||||||
|
- Test if issue persists without Cloudflare
|
||||||
|
|
||||||
|
### Step 6: Apply Fixes
|
||||||
|
- Implement specific solutions based on diagnosis
|
||||||
|
- Purge cache after changes
|
||||||
|
- Test in incognito/private mode
|
||||||
|
|
||||||
|
### Step 7: Monitor
|
||||||
|
- Verify fix works consistently
|
||||||
|
- Check analytics for any anomalies
|
||||||
|
- Document solution for future reference
|
||||||
246
skills/cloudflare-troubleshooting/references/ssl_modes.md
Normal file
246
skills/cloudflare-troubleshooting/references/ssl_modes.md
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
# Cloudflare SSL/TLS Modes Explained
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Cloudflare offers four SSL/TLS encryption modes that determine how traffic is encrypted between visitors, Cloudflare, and your origin server.
|
||||||
|
|
||||||
|
```
|
||||||
|
Visitor ←→ Cloudflare ←→ Origin Server
|
||||||
|
[A] [B] [C]
|
||||||
|
|
||||||
|
[A] Visitor to Cloudflare: Always HTTPS (handled by Cloudflare Universal SSL)
|
||||||
|
[B] Cloudflare to Origin: Depends on SSL mode setting
|
||||||
|
```
|
||||||
|
|
||||||
|
## The Four SSL Modes
|
||||||
|
|
||||||
|
### 1. Off (Not Recommended)
|
||||||
|
|
||||||
|
**Encryption:**
|
||||||
|
- Visitor → Cloudflare: HTTP (unencrypted)
|
||||||
|
- Cloudflare → Origin: HTTP (unencrypted)
|
||||||
|
|
||||||
|
**When to use:** Never. This disables HTTPS entirely.
|
||||||
|
|
||||||
|
**Issues:**
|
||||||
|
- Browser shows "Not Secure" warning
|
||||||
|
- No encryption between visitor and Cloudflare
|
||||||
|
- Vulnerable to man-in-the-middle attacks
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Flexible
|
||||||
|
|
||||||
|
**Encryption:**
|
||||||
|
- Visitor → Cloudflare: HTTPS (encrypted)
|
||||||
|
- Cloudflare → Origin: HTTP (unencrypted)
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Origin server doesn't support HTTPS
|
||||||
|
- Legacy systems without SSL certificates
|
||||||
|
- Temporary solution during certificate setup
|
||||||
|
|
||||||
|
**Issues:**
|
||||||
|
- ⚠️ **CAUSES REDIRECT LOOPS** with origins that enforce HTTPS
|
||||||
|
- Traffic between Cloudflare and origin is unencrypted
|
||||||
|
- Not recommended for sensitive data
|
||||||
|
|
||||||
|
**Common redirect loop scenario:**
|
||||||
|
```
|
||||||
|
1. Browser requests https://example.com
|
||||||
|
2. Cloudflare receives HTTPS request
|
||||||
|
3. Cloudflare forwards HTTP request to origin (because mode is Flexible)
|
||||||
|
4. Origin server enforces HTTPS → redirects to https://example.com
|
||||||
|
5. Back to step 1 → INFINITE LOOP
|
||||||
|
```
|
||||||
|
|
||||||
|
**Affected platforms:**
|
||||||
|
- GitHub Pages
|
||||||
|
- Netlify
|
||||||
|
- Vercel
|
||||||
|
- Heroku
|
||||||
|
- Any platform that enforces HTTPS
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Full (Recommended for Most Cases)
|
||||||
|
|
||||||
|
**Encryption:**
|
||||||
|
- Visitor → Cloudflare: HTTPS (encrypted)
|
||||||
|
- Cloudflare → Origin: HTTPS (encrypted)
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Origin server supports HTTPS (most modern hosting)
|
||||||
|
- Self-signed certificates on origin
|
||||||
|
- Default choice for GitHub Pages, Netlify, Vercel, etc.
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- End-to-end encryption
|
||||||
|
- No redirect loops with HTTPS-enforcing origins
|
||||||
|
- Compatible with self-signed certificates
|
||||||
|
|
||||||
|
**Important:**
|
||||||
|
- Cloudflare does NOT validate origin certificate
|
||||||
|
- Origin can use self-signed or expired certificates
|
||||||
|
- Still provides encryption, just doesn't verify origin identity
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Full (Strict) (Most Secure)
|
||||||
|
|
||||||
|
**Encryption:**
|
||||||
|
- Visitor → Cloudflare: HTTPS (encrypted)
|
||||||
|
- Cloudflare → Origin: HTTPS (encrypted + validated)
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Origin has valid SSL certificate from trusted CA
|
||||||
|
- Maximum security requirements
|
||||||
|
- Production environments with proper certificates
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
- Origin must have valid certificate from trusted CA
|
||||||
|
- Certificate must not be expired
|
||||||
|
- Certificate must match the domain
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- Maximum security
|
||||||
|
- Validates origin server identity
|
||||||
|
- Prevents man-in-the-middle attacks between Cloudflare and origin
|
||||||
|
|
||||||
|
**Issues if misconfigured:**
|
||||||
|
- 526 error if origin certificate is invalid
|
||||||
|
- 525 error if SSL handshake fails
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Decision Matrix
|
||||||
|
|
||||||
|
| Origin Supports HTTPS? | Origin Certificate Valid? | Recommended Mode | Why |
|
||||||
|
|------------------------|---------------------------|------------------|-----|
|
||||||
|
| No | N/A | Flexible | Only option (but upgrade origin ASAP) |
|
||||||
|
| Yes | Self-signed/Invalid | Full | Encrypts traffic, doesn't validate cert |
|
||||||
|
| Yes | Valid from trusted CA | Full (Strict) | Maximum security |
|
||||||
|
| Yes (enforced) | Any | Full or Full (Strict) | Prevents redirect loops |
|
||||||
|
|
||||||
|
## Common Platforms and Recommended Modes
|
||||||
|
|
||||||
|
| Platform | Enforces HTTPS? | Recommended Mode | Notes |
|
||||||
|
|----------|-----------------|------------------|-------|
|
||||||
|
| GitHub Pages | Yes | Full or Full (Strict) | Full (Strict) preferred |
|
||||||
|
| Netlify | Yes | Full or Full (Strict) | Has valid certificates |
|
||||||
|
| Vercel | Yes | Full or Full (Strict) | Has valid certificates |
|
||||||
|
| Heroku | Yes | Full or Full (Strict) | Has valid certificates |
|
||||||
|
| Custom VPS | Depends | Full (Strict) if possible | Install Let's Encrypt cert |
|
||||||
|
| Shared Hosting | Varies | Check with host | Usually Full |
|
||||||
|
| AWS CloudFront | Configurable | Full (Strict) | Use ACM certificates |
|
||||||
|
|
||||||
|
## Troubleshooting SSL Mode Issues
|
||||||
|
|
||||||
|
### Redirect Loop (ERR_TOO_MANY_REDIRECTS)
|
||||||
|
|
||||||
|
**Cause:** SSL mode is "Flexible" but origin enforces HTTPS
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
```bash
|
||||||
|
# Check current mode
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/settings/ssl" \
|
||||||
|
-H "X-Auth-Email: email" \
|
||||||
|
-H "X-Auth-Key: key"
|
||||||
|
|
||||||
|
# Change to Full
|
||||||
|
python scripts/fix_ssl_mode.py domain.com email API_KEY full --purge-cache
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error 526 (Invalid SSL Certificate)
|
||||||
|
|
||||||
|
**Cause:** Mode is "Full (Strict)" but origin certificate is invalid
|
||||||
|
|
||||||
|
**Solutions:**
|
||||||
|
1. Install valid certificate on origin (recommended)
|
||||||
|
2. Switch to "Full" mode temporarily:
|
||||||
|
```bash
|
||||||
|
python scripts/fix_ssl_mode.py domain.com email API_KEY full
|
||||||
|
```
|
||||||
|
3. Use Cloudflare Origin Certificate (free, only trusted by Cloudflare)
|
||||||
|
|
||||||
|
### Error 525 (SSL Handshake Failed)
|
||||||
|
|
||||||
|
**Cause:** Origin server SSL/TLS configuration issue
|
||||||
|
|
||||||
|
**Solutions:**
|
||||||
|
1. Check origin server SSL logs
|
||||||
|
2. Verify origin supports TLS 1.2 or higher
|
||||||
|
3. Ensure origin port 443 is open
|
||||||
|
4. Check cipher suite compatibility
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### 1. Start with Full Mode
|
||||||
|
When in doubt, use "Full" mode for origins that support HTTPS
|
||||||
|
|
||||||
|
### 2. Upgrade to Full (Strict) When Possible
|
||||||
|
Install proper certificates and use Full (Strict) for production
|
||||||
|
|
||||||
|
### 3. Never Use Flexible for New Sites
|
||||||
|
Flexible should only be used for legacy systems during migration
|
||||||
|
|
||||||
|
### 4. Use Cloudflare Origin Certificates
|
||||||
|
For custom origin servers, install Cloudflare Origin Certificates:
|
||||||
|
- Free
|
||||||
|
- Valid for 15 years
|
||||||
|
- Trusted by Cloudflare (enables Full Strict mode)
|
||||||
|
- Generate at: SSL/TLS → Origin Server → Create Certificate
|
||||||
|
|
||||||
|
### 5. Monitor SSL Errors
|
||||||
|
Set up alerts for SSL-related errors (525, 526) in Cloudflare Analytics
|
||||||
|
|
||||||
|
### 6. Test After Changes
|
||||||
|
- Clear browser cache
|
||||||
|
- Test in incognito mode
|
||||||
|
- Purge Cloudflare cache
|
||||||
|
- Wait 30-60 seconds for edge server updates
|
||||||
|
|
||||||
|
## Additional Security Settings
|
||||||
|
|
||||||
|
### Always Use HTTPS
|
||||||
|
- Redirects all HTTP requests to HTTPS
|
||||||
|
- Located: SSL/TLS → Edge Certificates
|
||||||
|
- Usually enabled by default
|
||||||
|
- Can cause loops if misconfigured with Page Rules
|
||||||
|
|
||||||
|
### HTTP Strict Transport Security (HSTS)
|
||||||
|
- Forces browsers to always use HTTPS
|
||||||
|
- Can't easily revert (browsers cache for months)
|
||||||
|
- Enable only when HTTPS is stable
|
||||||
|
- Located: SSL/TLS → Edge Certificates
|
||||||
|
|
||||||
|
### Minimum TLS Version
|
||||||
|
- Set to TLS 1.2 minimum (recommended)
|
||||||
|
- TLS 1.3 for maximum security
|
||||||
|
- Located: SSL/TLS → Edge Certificates
|
||||||
|
|
||||||
|
### Opportunistic Encryption
|
||||||
|
- Encrypts traffic when possible
|
||||||
|
- Good for mixed content
|
||||||
|
- Located: SSL/TLS → Edge Certificates
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### Get SSL Mode
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/ssl" \
|
||||||
|
-H "X-Auth-Email: user@example.com" \
|
||||||
|
-H "X-Auth-Key: api_key" \
|
||||||
|
-H "Content-Type: application/json"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Change SSL Mode
|
||||||
|
```bash
|
||||||
|
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/ssl" \
|
||||||
|
-H "X-Auth-Email: user@example.com" \
|
||||||
|
-H "X-Auth-Key: api_key" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data '{"value":"full"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Valid values: `off`, `flexible`, `full`, `strict`
|
||||||
@@ -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()
|
||||||
186
skills/cloudflare-troubleshooting/scripts/fix_ssl_mode.py
Normal file
186
skills/cloudflare-troubleshooting/scripts/fix_ssl_mode.py
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Fix Cloudflare SSL/TLS mode to resolve redirect loops.
|
||||||
|
|
||||||
|
This script changes the SSL mode to resolve common redirect loop issues
|
||||||
|
caused by SSL mode mismatches between Cloudflare and origin servers.
|
||||||
|
|
||||||
|
Common scenarios:
|
||||||
|
- GitHub Pages + Flexible mode → Change to Full
|
||||||
|
- Netlify/Vercel + Flexible mode → Change to Full
|
||||||
|
- Any HTTPS-enforcing origin + Flexible mode → Change to Full
|
||||||
|
|
||||||
|
Requires:
|
||||||
|
- requests library
|
||||||
|
- Cloudflare API credentials
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def fix_ssl_mode(zone_id: str, target_mode: str, email: str, api_key: str) -> bool:
|
||||||
|
"""
|
||||||
|
Change SSL mode for a zone.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
zone_id: Cloudflare zone ID
|
||||||
|
target_mode: Target SSL mode ('flexible', 'full', 'full_strict', 'off')
|
||||||
|
email: Cloudflare account email
|
||||||
|
api_key: Cloudflare Global API Key
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if successful, False otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
except ImportError:
|
||||||
|
print("Error: 'requests' library not installed")
|
||||||
|
print("Install with: pip install requests")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Validate mode
|
||||||
|
valid_modes = ["flexible", "full", "strict", "off"]
|
||||||
|
if target_mode not in valid_modes:
|
||||||
|
print(f"Error: Invalid SSL mode '{target_mode}'")
|
||||||
|
print(f"Valid modes: {', '.join(valid_modes)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Note: API uses 'strict' but documentation calls it 'full (strict)'
|
||||||
|
api_mode = target_mode
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.patch(
|
||||||
|
f"https://api.cloudflare.com/client/v4/zones/{zone_id}/settings/ssl",
|
||||||
|
headers={
|
||||||
|
"X-Auth-Email": email,
|
||||||
|
"X-Auth-Key": api_key,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
json={"value": api_mode},
|
||||||
|
timeout=30
|
||||||
|
)
|
||||||
|
|
||||||
|
if not response.ok:
|
||||||
|
print(f"❌ API Error: {response.status_code}")
|
||||||
|
print(f"Response: {response.text}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
if not data.get("success"):
|
||||||
|
print(f"❌ Failed to update SSL mode")
|
||||||
|
print(f"Errors: {data.get('errors', 'Unknown error')}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
new_mode = data["result"]["value"]
|
||||||
|
print(f"✅ SSL mode successfully changed to: {new_mode}")
|
||||||
|
print(f"\n⏳ Cloudflare is updating edge servers (typically takes 10-30 seconds)")
|
||||||
|
print(f"💡 Recommendation: Clear your browser cache or use incognito mode to test")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def purge_cache(zone_id: str, email: str, api_key: str) -> bool:
|
||||||
|
"""Purge all Cloudflare cache for the zone."""
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
except ImportError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.post(
|
||||||
|
f"https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache",
|
||||||
|
headers={
|
||||||
|
"X-Auth-Email": email,
|
||||||
|
"X-Auth-Key": api_key,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
json={"purge_everything": True},
|
||||||
|
timeout=30
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.ok and response.json().get("success"):
|
||||||
|
print("✅ Cache purged successfully")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function."""
|
||||||
|
if len(sys.argv) < 5:
|
||||||
|
print("Usage: python fix_ssl_mode.py <domain> <email> <api_key> <mode> [--purge-cache]")
|
||||||
|
print("\nSSL Modes:")
|
||||||
|
print(" flexible - Cloudflare → Origin uses HTTP (can cause loops with HTTPS origins)")
|
||||||
|
print(" full - Cloudflare → Origin uses HTTPS (recommended for most origins)")
|
||||||
|
print(" strict - Full + validates origin certificate (most secure)")
|
||||||
|
print(" off - No encryption (not recommended)")
|
||||||
|
print("\nExamples:")
|
||||||
|
print(" # Fix redirect loop for GitHub Pages")
|
||||||
|
print(" python fix_ssl_mode.py typeof.tech user@example.com abc123... full --purge-cache")
|
||||||
|
print("\n # Switch to strict mode")
|
||||||
|
print(" python fix_ssl_mode.py example.com user@example.com abc123... strict")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
domain = sys.argv[1]
|
||||||
|
email = sys.argv[2]
|
||||||
|
api_key = sys.argv[3]
|
||||||
|
target_mode = sys.argv[4]
|
||||||
|
should_purge = "--purge-cache" in sys.argv
|
||||||
|
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
except ImportError:
|
||||||
|
print("Error: 'requests' library not found")
|
||||||
|
print("Install with: pip install requests")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print(f"\n🔧 Fixing SSL configuration for: {domain}")
|
||||||
|
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}\n")
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"❌ Network error: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Fix SSL mode
|
||||||
|
if not fix_ssl_mode(zone_id, target_mode, email, api_key):
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Optionally purge cache
|
||||||
|
if should_purge:
|
||||||
|
print(f"\n🗑️ Purging cache...")
|
||||||
|
purge_cache(zone_id, email, api_key)
|
||||||
|
|
||||||
|
print("\n✅ Done! Test your site after 30 seconds.")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user