使用Gin框架时如何仅获取客户端的IPv4地址?
嘿,这个问题我碰到过好几次——明明服务只监听IPv4,gin却偶尔返回IPv6地址,对吧?别慌,咱们一步步解决:
为什么会出现这种情况?
虽然你明确用net.Listen("tcp4", ...)监听IPv4端口,但还是可能拿到IPv6地址,主要原因有两个:
- 客户端通过IPv6过渡技术(比如NAT64、IPv6隧道)访问,请求会被转换成IPv6格式转发到你的IPv4服务;
- 如果你的服务前端有反向代理/负载均衡,代理可能会把客户端的IPv6地址通过
X-Forwarded-For这类请求头传递过来,而gin的ClientIP()会优先读取这些头的内容。
解决方案
根据你的场景,分两种情况处理:
情况1:无反向代理(直接监听IPv4)
直接对c.ClientIP()返回的地址做解析过滤,提取纯IPv4地址,尤其是处理常见的IPv4映射的IPv6地址(格式如::ffff:192.168.1.1):
web.POST("/path", func(c *gin.Context) { ipStr := c.ClientIP() // 解析IP地址 ip := net.ParseIP(ipStr) if ip == nil { // 处理无效IP的场景,比如返回错误 c.String(http.StatusBadRequest, "invalid IP address") return } // 提取IPv4地址:To4()会返回对应的IPv4(如果是IPv4或IPv4映射的IPv6),否则返回nil ipv4Addr := ip.To4() if ipv4Addr != nil { // 拿到了合法的IPv4地址 c.String(http.StatusOK, "Client IPv4: %s", ipv4Addr.String()) } else { // 纯IPv6地址,根据你的业务需求处理:比如记录日志、返回空或拒绝请求 // 因为你的服务只监听IPv4,这种情况大概率是异常请求 c.String(http.StatusBadRequest, "only IPv4 requests are allowed") } })
情况2:有反向代理/负载均衡
如果你的服务前面有代理(比如Nginx、Cloudflare),需要先配置gin的信任代理列表,让ClientIP()正确识别真实客户端的IPv4地址,而不是代理的IPv6地址:
router := gin.Default() // 设置信任的代理IP段(替换成你的代理服务器IPv4地址/段) router.SetTrustedProxies([]string{"192.168.1.0/24", "10.0.0.0/8"}) // 然后处理请求 web.POST("/path", func(c *gin.Context) { ipStr := c.ClientIP() ip := net.ParseIP(ipStr) if ipv4Addr := ip.To4(); ipv4Addr != nil { // 使用提取的IPv4地址 } })
额外说明
你收到的那些纯IPv6地址(比如2402:800:xxxx:xxxx),大概率是客户端通过IPv6网络访问,但你的服务监听的是IPv4,这可能是因为你的服务器所在的网络支持IPv6过渡,或者客户端开启了IPv6优先。这种情况下,用上面的代码就能过滤掉纯IPv6,只保留合法的IPv4地址。
内容的提问来源于stack exchange,提问作者majidarif
相关产品推荐
相关产品推荐

