c.IP() detrás del proxy del hosting devuelve la IP interna del contenedor que reenvía (10.x.x.x). Contra eso, ninguna IP pública cargada en una llave podía coincidir: toda API key con restricción de IP daba 403, que es exactamente lo que le pasó a la integración de vCard. Ahora se lee X-Forwarded-For, y se toma la ÚLTIMA entrada, no la primera: con un proxy adelante esa es la que escribió el proxy. Si quien llama manda su propio X-Forwarded-For, el proxy le agrega la IP real al final — quedarse con la primera sería dejar que cada uno declare su IP y la restricción no valdría nada. El test fija ese caso. Mismo arreglo en la autenticación de Pagos Externos, que comparaba igual. El 403 ahora dice qué IP se vio y cuál está permitida: sin eso, del otro lado se prueba a ciegas. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
31 lines
1007 B
Go
31 lines
1007 B
Go
package middlewares
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
// IPDelCliente devuelve la IP pública desde la que se hizo la petición.
|
|
//
|
|
// c.IP() no sirve para esto en producción: detrás del proxy del hosting
|
|
// devuelve la IP interna del proxy (10.x.x.x), así que ninguna IP pública
|
|
// autorizada coincidía nunca y toda llave con restricción de IP daba 403.
|
|
//
|
|
// Se toma la ÚLTIMA entrada de X-Forwarded-For, no la primera: con un solo
|
|
// proxy adelante, esa es la que escribió el proxy y no la puede falsear quien
|
|
// llama. Si el cliente manda su propio X-Forwarded-For, el proxy le agrega la
|
|
// IP real al final — quedarse con la primera sería creerle al que llama.
|
|
func IPDelCliente(c *fiber.Ctx) string {
|
|
if xff := c.Get("X-Forwarded-For"); xff != "" {
|
|
partes := strings.Split(xff, ",")
|
|
if ip := strings.TrimSpace(partes[len(partes)-1]); ip != "" {
|
|
return ip
|
|
}
|
|
}
|
|
if real := strings.TrimSpace(c.Get("X-Real-Ip")); real != "" {
|
|
return real
|
|
}
|
|
return c.IP()
|
|
}
|