@@ -38,13 +38,13 @@ server {
|
|||||||
# En el bloque http {}
|
# En el bloque http {}
|
||||||
http {
|
http {
|
||||||
# Zona de rate limiting para API general
|
# Zona de rate limiting para API general
|
||||||
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
|
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/h;
|
||||||
|
|
||||||
# Zona específica para ping (más restrictiva)
|
# Zona específica para ping (más restrictiva)
|
||||||
limit_req_zone $binary_remote_addr zone=ping:10m rate=10r/m;
|
limit_req_zone $binary_remote_addr zone=ping:10m rate=5r/10m;
|
||||||
|
|
||||||
# Rate limiting por IP real (después del proxy)
|
# Rate limiting por IP real (después del proxy)
|
||||||
limit_req_zone $realip_remote_addr zone=real_ip:10m rate=10r/m;
|
limit_req_zone $realip_remote_addr zone=real_ip:10m rate=5r/10m;
|
||||||
}
|
}
|
||||||
|
|
||||||
# En el bloque server {}
|
# En el bloque server {}
|
||||||
@@ -144,7 +144,7 @@ curl -H "X-Forwarded-For: 203.0.113.1" http://your-domain.com/api/status
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Script para probar rate limiting
|
# Script para probar rate limiting
|
||||||
for i in {1..15}; do
|
for i in {1..8}; do
|
||||||
echo "Request $i:"
|
echo "Request $i:"
|
||||||
curl -s http://your-domain.com/api/ping \
|
curl -s http://your-domain.com/api/ping \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
|
|||||||
16
EXAMPLES.md
16
EXAMPLES.md
@@ -76,7 +76,7 @@ curl -X GET http://localhost:3000/api/status
|
|||||||
### Rate Limit Excedido
|
### Rate Limit Excedido
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Después de 10 requests en 1 minuto
|
# Después de 5 requests en 10 minutos
|
||||||
curl -X POST http://localhost:3000/api/ping \
|
curl -X POST http://localhost:3000/api/ping \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"target": "8.8.8.8"}'
|
-d '{"target": "8.8.8.8"}'
|
||||||
@@ -87,8 +87,8 @@ curl -X POST http://localhost:3000/api/ping \
|
|||||||
{
|
{
|
||||||
"error": "Rate limit exceeded",
|
"error": "Rate limit exceeded",
|
||||||
"message": "Too many requests. Please try again later.",
|
"message": "Too many requests. Please try again later.",
|
||||||
"resetTime": 1692180660000,
|
"resetTime": 1692181260000,
|
||||||
"limit": 10,
|
"limit": 5,
|
||||||
"remaining": 0
|
"remaining": 0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -211,7 +211,7 @@ async function checkRateLimit() {
|
|||||||
const rateLimit = data.clientInfo.rateLimit;
|
const rateLimit = data.clientInfo.rateLimit;
|
||||||
console.log(`Rate Limit: ${rateLimit.remaining}/${rateLimit.limit} remaining`);
|
console.log(`Rate Limit: ${rateLimit.remaining}/${rateLimit.limit} remaining`);
|
||||||
|
|
||||||
if (rateLimit.remaining < 3) {
|
if (rateLimit.remaining < 2) {
|
||||||
console.warn('⚠️ Approaching rate limit!');
|
console.warn('⚠️ Approaching rate limit!');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ if result:
|
|||||||
status = client.get_status()
|
status = client.get_status()
|
||||||
if status:
|
if status:
|
||||||
print(f"Service: {status['service']}")
|
print(f"Service: {status['service']}")
|
||||||
print(f"Rate limit: {status['clientInfo']['rateLimit']['remaining']}/10")
|
print(f"Rate limit: {status['clientInfo']['rateLimit']['remaining']}/5")
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Monitor Continuo
|
### 2. Monitor Continuo
|
||||||
@@ -349,9 +349,9 @@ curl -I -X POST http://localhost:3000/api/ping \
|
|||||||
|
|
||||||
**Headers de respuesta:**
|
**Headers de respuesta:**
|
||||||
```
|
```
|
||||||
X-RateLimit-Limit: 10
|
X-RateLimit-Limit: 5
|
||||||
X-RateLimit-Remaining: 9
|
X-RateLimit-Remaining: 4
|
||||||
X-RateLimit-Reset: 1692180660000
|
X-RateLimit-Reset: 1692181260000
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🚀 Casos de Uso Avanzados
|
## 🚀 Casos de Uso Avanzados
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Un servicio moderno de ping construido con Next.js 15 que permite realizar prueb
|
|||||||
|
|
||||||
## 🚀 Características
|
## 🚀 Características
|
||||||
|
|
||||||
- **Rate Limiting**: Máximo 10 peticiones por minuto por IP para prevenir abuso
|
- **Rate Limiting**: Máximo 5 peticiones cada 10 minutos por IP para prevenir abuso
|
||||||
- **Validación de seguridad**: Bloquea IPs privadas, localhost y rangos reservados
|
- **Validación de seguridad**: Bloquea IPs privadas, localhost y rangos reservados
|
||||||
- **Interfaz moderna**: UI responsiva con Tailwind CSS
|
- **Interfaz moderna**: UI responsiva con Tailwind CSS
|
||||||
- **Tiempo real**: Resultados en tiempo real con indicadores de progreso
|
- **Tiempo real**: Resultados en tiempo real con indicadores de progreso
|
||||||
@@ -45,7 +45,7 @@ Obtiene información del estado del servicio y estadísticas del cliente.
|
|||||||
## 🛡️ Seguridad
|
## 🛡️ Seguridad
|
||||||
|
|
||||||
### Rate Limiting
|
### Rate Limiting
|
||||||
- **Límite**: 10 peticiones por minuto por IP
|
- **Límite**: 5 peticiones cada 10 minutos por IP
|
||||||
- **Ventana deslizante**: Se renueva automáticamente
|
- **Ventana deslizante**: Se renueva automáticamente
|
||||||
|
|
||||||
### Validaciones
|
### Validaciones
|
||||||
|
|||||||
@@ -141,13 +141,13 @@ server {
|
|||||||
#
|
#
|
||||||
# http {
|
# http {
|
||||||
# # Rate limiting para API general
|
# # Rate limiting para API general
|
||||||
# limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
|
# limit_req_zone $binary_remote_addr zone=api:10m rate=30r/h;
|
||||||
#
|
#
|
||||||
# # Rate limiting específico para ping (más restrictivo)
|
# # Rate limiting específico para ping (más restrictivo)
|
||||||
# limit_req_zone $binary_remote_addr zone=ping:10m rate=10r/m;
|
# limit_req_zone $binary_remote_addr zone=ping:10m rate=5r/10m;
|
||||||
#
|
#
|
||||||
# # Rate limiting por IP real (considerando proxy)
|
# # Rate limiting por IP real (considerando proxy)
|
||||||
# limit_req_zone $realip_remote_addr zone=real_ip:10m rate=10r/m;
|
# limit_req_zone $realip_remote_addr zone=real_ip:10m rate=5r/10m;
|
||||||
# }
|
# }
|
||||||
|
|
||||||
# Configuración adicional para development/testing
|
# Configuración adicional para development/testing
|
||||||
|
|||||||
@@ -169,6 +169,6 @@ export async function GET() {
|
|||||||
timeout: 'Timeout in milliseconds (1000-10000, default: 5000)'
|
timeout: 'Timeout in milliseconds (1000-10000, default: 5000)'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rateLimit: 'Maximum 10 requests per minute per IP address'
|
rateLimit: 'Maximum 5 requests per 10 minutes per IP address'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export async function GET(request) {
|
|||||||
'No private IP addresses',
|
'No private IP addresses',
|
||||||
'No localhost addresses',
|
'No localhost addresses',
|
||||||
'No reserved IP ranges',
|
'No reserved IP ranges',
|
||||||
'Rate limited to 10 requests per minute'
|
'Rate limited to 5 requests per 10 minutes'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
endpoints: {
|
endpoints: {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export default function PingInterface() {
|
|||||||
Usage Guidelines
|
Usage Guidelines
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="text-blue-700 dark:text-blue-300 space-y-1">
|
<ul className="text-blue-700 dark:text-blue-300 space-y-1">
|
||||||
<li>• Maximum 10 requests per minute per IP address</li>
|
<li>• Maximum 5 requests per 10 minutes per IP address</li>
|
||||||
<li>• Maximum 10 pings per request</li>
|
<li>• Maximum 10 pings per request</li>
|
||||||
<li>• Timeout range: 1-10 seconds</li>
|
<li>• Timeout range: 1-10 seconds</li>
|
||||||
<li>• Private IPs and localhost are blocked for security</li>
|
<li>• Private IPs and localhost are blocked for security</li>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export default function RateLimitInfo({ rateLimitInfo }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{remaining <= 2 && (
|
{remaining <= 1 && (
|
||||||
<div className="mt-3 text-xs text-red-600 dark:text-red-400">
|
<div className="mt-3 text-xs text-red-600 dark:text-red-400">
|
||||||
⚠️ You're approaching the rate limit. Please wait before making more requests.
|
⚠️ You're approaching the rate limit. Please wait before making more requests.
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default function Home() {
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer className="text-center mt-12 text-sm text-gray-500 dark:text-gray-400">
|
<footer className="text-center mt-12 text-sm text-gray-500 dark:text-gray-400">
|
||||||
<p>Built with Next.js 15 • Rate limited to 10 requests per minute</p>
|
<p>Built with Next.js 15 • Rate limited to 5 requests per 10 minutes</p>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
export const PING_CONFIG = {
|
export const PING_CONFIG = {
|
||||||
// Rate limiting
|
// Rate limiting
|
||||||
RATE_LIMIT: {
|
RATE_LIMIT: {
|
||||||
MAX_REQUESTS: parseInt(process.env.RATE_LIMIT_MAX) || 10,
|
MAX_REQUESTS: parseInt(process.env.RATE_LIMIT_MAX) || 5,
|
||||||
WINDOW_MS: parseInt(process.env.RATE_LIMIT_WINDOW_MS) || 60 * 1000, // 1 minuto
|
WINDOW_MS: parseInt(process.env.RATE_LIMIT_WINDOW_MS) || 10 * 60 * 1000, // 10 minutos
|
||||||
},
|
},
|
||||||
|
|
||||||
// Límites de ping
|
// Límites de ping
|
||||||
@@ -77,8 +77,8 @@ export function getEnvironmentConfig() {
|
|||||||
const envConfigs = {
|
const envConfigs = {
|
||||||
development: {
|
development: {
|
||||||
RATE_LIMIT: {
|
RATE_LIMIT: {
|
||||||
MAX_REQUESTS: 20, // Más permisivo en desarrollo
|
MAX_REQUESTS: 10, // Más permisivo en desarrollo
|
||||||
WINDOW_MS: 60 * 1000,
|
WINDOW_MS: 10 * 60 * 1000, // 10 minutos
|
||||||
},
|
},
|
||||||
DEBUG: {
|
DEBUG: {
|
||||||
LOG_REQUESTS: true,
|
LOG_REQUESTS: true,
|
||||||
@@ -89,8 +89,8 @@ export function getEnvironmentConfig() {
|
|||||||
|
|
||||||
production: {
|
production: {
|
||||||
RATE_LIMIT: {
|
RATE_LIMIT: {
|
||||||
MAX_REQUESTS: 10, // Más restrictivo en producción
|
MAX_REQUESTS: 5, // Más restrictivo en producción
|
||||||
WINDOW_MS: 60 * 1000,
|
WINDOW_MS: 10 * 60 * 1000, // 10 minutos
|
||||||
},
|
},
|
||||||
DEBUG: {
|
DEBUG: {
|
||||||
LOG_REQUESTS: false,
|
LOG_REQUESTS: false,
|
||||||
@@ -101,8 +101,8 @@ export function getEnvironmentConfig() {
|
|||||||
|
|
||||||
test: {
|
test: {
|
||||||
RATE_LIMIT: {
|
RATE_LIMIT: {
|
||||||
MAX_REQUESTS: 100, // Sin límites en tests
|
MAX_REQUESTS: 50, // Sin límites en tests
|
||||||
WINDOW_MS: 60 * 1000,
|
WINDOW_MS: 10 * 60 * 1000, // 10 minutos
|
||||||
},
|
},
|
||||||
DEBUG: {
|
DEBUG: {
|
||||||
LOG_REQUESTS: false,
|
LOG_REQUESTS: false,
|
||||||
|
|||||||
Referencia en una nueva incidencia
Block a user