que paso?
This commit is contained in:
291
CLOUDFLARE.md
Normal file
291
CLOUDFLARE.md
Normal file
@@ -0,0 +1,291 @@
|
||||
# Traefik + Cloudflare Tunnel - Configuración
|
||||
|
||||
Esta guía explica cómo funciona Traefik detrás de Cloudflare Tunnel y cómo obtener las IPs reales de los visitantes.
|
||||
|
||||
## 🌐 Arquitectura
|
||||
|
||||
```
|
||||
Internet → Cloudflare (SSL/DDoS) → Cloudflare Tunnel → Traefik (443) → Contenedores
|
||||
```
|
||||
|
||||
## 📍 IPs Reales de Visitantes
|
||||
|
||||
### ¿Cómo funciona?
|
||||
|
||||
Cuando un usuario visita tu sitio:
|
||||
|
||||
1. **Cloudflare recibe la conexión** y conoce la IP real del visitante
|
||||
2. **Cloudflare envía la IP real en headers HTTP:**
|
||||
- `CF-Connecting-IP`: IP real del cliente ✅ (más confiable)
|
||||
- `X-Forwarded-For`: Cadena de proxies
|
||||
- `X-Real-IP`: IP real (alternativa)
|
||||
3. **Traefik lee estos headers** y los pasa a tus aplicaciones
|
||||
|
||||
### Configuración aplicada
|
||||
|
||||
Ya está configurado en `traefik/traefik.yml`:
|
||||
|
||||
```yaml
|
||||
entryPoints:
|
||||
websecure:
|
||||
forwardedHeaders:
|
||||
trustedIPs:
|
||||
- "173.245.48.0/20" # Rangos de IPs de Cloudflare
|
||||
- "103.21.244.0/22"
|
||||
# ... etc (23 rangos en total)
|
||||
```
|
||||
|
||||
Esto le dice a Traefik: **"Confía en los headers de IPs que vienen de Cloudflare"**
|
||||
|
||||
### ✅ Verificar que funciona
|
||||
|
||||
1. **Inicia Traefik:**
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
2. **Verifica los logs de acceso:**
|
||||
```bash
|
||||
docker compose logs traefik | grep "CF-Connecting-IP"
|
||||
```
|
||||
|
||||
3. **Deberías ver la IP real en los logs:**
|
||||
```json
|
||||
{
|
||||
"ClientAddr": "173.245.48.5:12345", // IP de Cloudflare
|
||||
"headers": {
|
||||
"CF-Connecting-IP": "187.123.45.67" // ← IP REAL del visitante
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔍 Leer IP real desde tus aplicaciones
|
||||
|
||||
### Node.js / Express
|
||||
|
||||
```javascript
|
||||
app.get('/', (req, res) => {
|
||||
const realIP = req.headers['cf-connecting-ip']
|
||||
|| req.headers['x-forwarded-for']?.split(',')[0]
|
||||
|| req.connection.remoteAddress;
|
||||
|
||||
console.log('IP real del visitante:', realIP);
|
||||
});
|
||||
```
|
||||
|
||||
### Python / Flask
|
||||
|
||||
```python
|
||||
from flask import Flask, request
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
real_ip = request.headers.get('CF-Connecting-IP') \
|
||||
or request.headers.get('X-Forwarded-For', '').split(',')[0] \
|
||||
or request.remote_addr
|
||||
|
||||
print(f'IP real del visitante: {real_ip}')
|
||||
```
|
||||
|
||||
### Go / Gin
|
||||
|
||||
```go
|
||||
func handler(c *gin.Context) {
|
||||
realIP := c.GetHeader("CF-Connecting-IP")
|
||||
if realIP == "" {
|
||||
realIP = c.ClientIP()
|
||||
}
|
||||
|
||||
fmt.Printf("IP real del visitante: %s\n", realIP)
|
||||
}
|
||||
```
|
||||
|
||||
### PHP
|
||||
|
||||
```php
|
||||
<?php
|
||||
$real_ip = $_SERVER['HTTP_CF_CONNECTING_IP']
|
||||
?? explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0]
|
||||
?? $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
echo "IP real del visitante: $real_ip";
|
||||
```
|
||||
|
||||
### Nginx (dentro de contenedor)
|
||||
|
||||
Si tienes nginx dentro de un contenedor detrás de Traefik:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
location / {
|
||||
# Traefik ya pasó los headers, solo léelos
|
||||
set $real_ip $http_cf_connecting_ip;
|
||||
|
||||
# O usa el módulo real_ip
|
||||
real_ip_header CF-Connecting-IP;
|
||||
|
||||
# Loguea la IP real
|
||||
access_log /var/log/nginx/access.log combined;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🛡️ Seguridad
|
||||
|
||||
### ¿Por qué confiar solo en IPs de Cloudflare?
|
||||
|
||||
La configuración `trustedIPs` es crucial para **evitar IP spoofing**:
|
||||
|
||||
❌ **Sin trustedIPs:**
|
||||
```
|
||||
Atacante envía: X-Forwarded-For: 1.1.1.1
|
||||
Traefik cree que la IP real es 1.1.1.1 (FALSO)
|
||||
```
|
||||
|
||||
✅ **Con trustedIPs (configurado):**
|
||||
```
|
||||
Si la petición viene de 192.168.1.1 (no es IP de Cloudflare):
|
||||
→ Traefik IGNORA el header X-Forwarded-For
|
||||
→ Usa la IP de conexión real
|
||||
|
||||
Si viene de 173.245.48.5 (IP de Cloudflare):
|
||||
→ Traefik CONFÍA en CF-Connecting-IP ✅
|
||||
```
|
||||
|
||||
### Actualizar rangos de IPs de Cloudflare
|
||||
|
||||
Cloudflare publica sus IPs oficiales:
|
||||
|
||||
```bash
|
||||
# IPv4
|
||||
curl https://www.cloudflare.com/ips-v4
|
||||
|
||||
# IPv6
|
||||
curl https://www.cloudflare.com/ips-v6
|
||||
```
|
||||
|
||||
Si Cloudflare agrega nuevos rangos, actualiza `traefik/traefik.yml`.
|
||||
|
||||
## 🔐 SSL/TLS con Cloudflare
|
||||
|
||||
### Opciones de SSL en Cloudflare
|
||||
|
||||
En el dashboard de Cloudflare → SSL/TLS, tienes 3 opciones:
|
||||
|
||||
1. **Flexible** (❌ No recomendado)
|
||||
- Cloudflare ↔ Cliente: HTTPS ✅
|
||||
- Cloudflare ↔ Traefik: HTTP ❌
|
||||
- Vulnerable a ataques man-in-the-middle
|
||||
|
||||
2. **Full** (⚠️ Aceptable)
|
||||
- Cloudflare ↔ Cliente: HTTPS ✅
|
||||
- Cloudflare ↔ Traefik: HTTPS ✅ (autofirmado OK)
|
||||
- Más seguro
|
||||
|
||||
3. **Full (Strict)** (✅ Recomendado)
|
||||
- Cloudflare ↔ Cliente: HTTPS ✅
|
||||
- Cloudflare ↔ Traefik: HTTPS con certificado válido ✅
|
||||
- Máxima seguridad
|
||||
|
||||
### Tu configuración actual
|
||||
|
||||
Con Cloudflare Tunnel apuntando a puerto **443**:
|
||||
|
||||
- Cloudflare → Tunnel → Traefik:443 (HTTPS)
|
||||
- Traefik puede usar:
|
||||
- **Certificados Let's Encrypt** (ya configurado en `traefik.yml`)
|
||||
- O certificados autofirmados para el túnel
|
||||
|
||||
**Recomendación**: Usar **Full** o **Full (Strict)** en Cloudflare.
|
||||
|
||||
## 📊 Monitoreo de IPs
|
||||
|
||||
### Ver IPs en logs de Traefik
|
||||
|
||||
```bash
|
||||
# Ver logs en tiempo real con IPs
|
||||
docker compose logs -f traefik
|
||||
|
||||
# Filtrar solo IPs de Cloudflare
|
||||
docker compose logs traefik | grep "CF-Connecting-IP"
|
||||
|
||||
# Ver estadísticas de IPs únicas
|
||||
docker exec traefik cat /var/log/traefik/access.log | \
|
||||
jq -r '.headers["CF-Connecting-IP"]' | \
|
||||
sort | uniq -c | sort -rn
|
||||
```
|
||||
|
||||
### Dashboard de Traefik
|
||||
|
||||
El dashboard muestra:
|
||||
- ❌ IP de Cloudflare (173.245.x.x) en "Client Address"
|
||||
- ✅ IP real disponible en logs JSON
|
||||
|
||||
## 🧪 Prueba rápida
|
||||
|
||||
Después de iniciar Traefik:
|
||||
|
||||
```bash
|
||||
# 1. Simular petición desde "fuera" (pasando por Cloudflare)
|
||||
curl -H "CF-Connecting-IP: 187.123.45.67" \
|
||||
-H "Host: whoami.nucleoriofrio.com" \
|
||||
http://localhost
|
||||
|
||||
# 2. Ver los logs y buscar la IP
|
||||
docker compose logs traefik | tail -20
|
||||
```
|
||||
|
||||
## ❓ FAQ
|
||||
|
||||
### ¿Necesito certificados SSL si uso Cloudflare?
|
||||
|
||||
**Para el tunnel NO** (Cloudflare maneja SSL público), **pero sí es recomendable** para:
|
||||
- Seguridad adicional Cloudflare ↔ Traefik
|
||||
- Servicios internos
|
||||
- Modo Full (Strict) de Cloudflare
|
||||
|
||||
### ¿Puedo bloquear acceso directo al puerto 443?
|
||||
|
||||
**SÍ, deberías hacerlo**:
|
||||
|
||||
```bash
|
||||
# Firewall: permitir solo Cloudflare IPs en 443
|
||||
sudo ufw allow from 173.245.48.0/20 to any port 443
|
||||
sudo ufw allow from 103.21.244.0/22 to any port 443
|
||||
# ... agregar todos los rangos
|
||||
|
||||
# O usar iptables
|
||||
sudo iptables -A INPUT -p tcp --dport 443 -s 173.245.48.0/20 -j ACCEPT
|
||||
sudo iptables -A INPUT -p tcp --dport 443 -j DROP
|
||||
```
|
||||
|
||||
Esto asegura que **solo Cloudflare** pueda llegar a Traefik.
|
||||
|
||||
### ¿Qué pasa si la IP en logs es de Cloudflare?
|
||||
|
||||
Verifica:
|
||||
|
||||
1. **Headers en logs:** `grep "CF-Connecting-IP" access.log`
|
||||
2. **trustedIPs configurado:** Revisa `traefik.yml`
|
||||
3. **Cloudflare enviando headers:** Verifica en Cloudflare dashboard
|
||||
|
||||
### ¿Los rangos de IP de Cloudflare cambian?
|
||||
|
||||
Sí, ocasionalmente. Verifica periódicamente:
|
||||
|
||||
```bash
|
||||
curl https://www.cloudflare.com/ips-v4
|
||||
```
|
||||
|
||||
Y actualiza `traefik.yml` si hay cambios.
|
||||
|
||||
## 📚 Referencias
|
||||
|
||||
- [Cloudflare IP Ranges](https://www.cloudflare.com/ips/)
|
||||
- [Traefik ForwardedHeaders](https://doc.traefik.io/traefik/routing/entrypoints/#forwarded-headers)
|
||||
- [Cloudflare Headers](https://developers.cloudflare.com/fundamentals/reference/http-request-headers/)
|
||||
|
||||
---
|
||||
|
||||
**Última actualización**: Octubre 2025
|
||||
**Rangos de IP Cloudflare verificados**: Octubre 2025
|
||||
Reference in New Issue
Block a user