fix(http): set TrustedPlatform=Cloudflare so c.ClientIP reads CF-Connecting-IP
Previous SetTrustedProxies commit (407dbb7) was necessary but
insufficient. In production Manager sits behind Cloudflare in
proxy mode, which:
- strips the inbound X-Forwarded-For header
- sets CF-Connecting-IP with the real client IP
Gin's default ClientIP() only knows about X-Forwarded-For + X-Real-IP
— it does NOT recognize CF-Connecting-IP. So every request showed the
docker bridge peer (10.2.3.4) in audit fields and rate-limit buckets
even after we added private ranges to TrustedProxies.
Setting TrustedPlatform = gin.PlatformCloudflare instructs Gin to
read CF-Connecting-IP as ground truth, bypassing the XFF parser.
When the header is absent (health checks, direct non-CF probes)
Gin falls back through TrustedProxies → XFF → RemoteAddr as before.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -188,6 +188,21 @@ func main() {
|
||||
common.FatalLog(fmt.Sprintf("SetTrustedProxies: %v", err))
|
||||
}
|
||||
|
||||
// Cloudflare-aware ClientIP resolution. In production Manager runs
|
||||
// behind Cloudflare's proxy mode, which strips the inbound
|
||||
// X-Forwarded-For and replaces it with CF-Connecting-IP carrying
|
||||
// the real client IP. Setting TrustedPlatform short-circuits Gin's
|
||||
// default XFF parsing and reads CF-Connecting-IP as ground truth —
|
||||
// without this, every request shows the docker bridge peer
|
||||
// (10.2.3.x) regardless of how many CIDRs we add to TrustedProxies.
|
||||
//
|
||||
// Honoured globally: c.ClientIP() returns the real IP for all
|
||||
// downstream consumers (token IP allowlist, rate-limit, device
|
||||
// last-seen IP, gin access log, audit logs). When the header is
|
||||
// absent (e.g. health checks from the VM itself, or direct
|
||||
// non-CF hits) Gin falls back to TrustedProxies → XFF → RemoteAddr.
|
||||
server.TrustedPlatform = gin.PlatformCloudflare
|
||||
|
||||
server.Use(gin.CustomRecovery(func(c *gin.Context, err any) {
|
||||
common.SysLog(fmt.Sprintf("panic detected: %v", err))
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
|
||||
Reference in New Issue
Block a user