Gin允许您指定保存真实客户端IP的头文件(如果有的话),以及指定您信任的代理(或直接客户端)来指定这些头文件之一。

在gin.engine上使用函数setTrustedProxies(),以指定网络地址或网络CIDR,客户端的请求体头包含与之相关的IP的时候才能够被信任。它们可以是IPv4地址,IPv4 CIDR,IPv6地址或IPv6 CIDR。

Note

默认情况下,不使用上面的函数设置信任的代理,那么默认信任所有的代理,但是这是不安全的。同时,如果您不使用任何代理,则可以使用Engine.settrustedproxies(NIL)禁用此功能,然后Contect.ClientIP()将直接返回远程地址以避免进行一些不必要的计算。

import (
	"fmt"
 
	"github.com/gin-gonic/gin"
)
 
func main() {
 
	router := gin.Default()
	router.SetTrustedProxies([]string{"192.168.1.2"})
 
	router.GET("/", func(c *gin.Context) {
		// 来源于信任的客户ip,会从X-Forwarded-For头中来推断出原始的客户端IP
		// 否则简单返回直接交互的ip
		fmt.Printf("ClientIP: %s\n", c.ClientIP())
	})
	router.Run()
}

也就是说,如果客户端的IP是可信任的代理中的IP,那么可以通过其获取到最原始的客户端IP。否则,就直接将与其通信的IP当作客户端IP。

如果使用的是CDN服务,则可以设置Engine.trustedplatform以跳过可信赖的检查,它的优先级高于TrustedProxies。查看下面的示例:

import (
	"fmt"
	"github.com/gin-gonic/gin"
)
 
func main() {
 
	router := gin.Default()
	// 使用预定义的头 gin.PlatformXXX
	router.TrustedPlatform = gin.PlatformGoogleAppEngine
	// 为你信任的代理服务设置你自己的信任请求头
	// 不要将其设置为任何怀疑请求头,是不安全的
	router.TrustedPlatform = "X-CDN-IP"
 
	router.GET("/", func(c *gin.Context) {
		// 如果设置了TrustedPlatform,ClientIP会解析对应的头并直接返回IP。
		fmt.Printf("ClientIP: %s\n", c.ClientIP())
	})
	router.Run()
}

tags: gin