Golang中如何获取客户端的真实IP地址?
Golang中如何获取客户端的真实IP地址? 我有些犹豫不决,我想识别客户端的请求,有什么比使用IP地址更好的方法呢?但查看我的选项后,我不知道哪个更可靠:
使用 net 包的原生选项:
func PrintIP(l net.Listener) {
fmt.Println(fmt.Sprintf("<%s> %s", l.Addr().Network(), l.Addr().String()))
}
使用 github.com/tomasen/realip 包的外部选项:
func PrintIP(r *http.Request) {
fmt.Println(realip.FromRequest(r))
}
net.Listener 会保留客户端的真实IP吗?因为如果是这样,我倾向于使用那个选项;但如果不是,那么我想最好使用 realip.FromRequest,或者有更好的建议吗?
更多关于Golang中如何获取客户端的真实IP地址?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
net.Listener 适用于获取任意连接的 IP 地址,而 realip.FromRequest 适用于 HTTP 请求,但它很可能会返回真实客户端的 IP,而不是其使用的代理的 IP。不过,理论上这个 IP 也可能来自私有网络,而且并非所有代理都会设置能告知原始 IP 的头部信息。
最终,这取决于您的具体使用场景。
更多关于Golang中如何获取客户端的真实IP地址?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Golang中获取客户端真实IP地址需要考虑代理和负载均衡的情况。net.Listener只能获取到直接连接的客户端IP,而无法处理经过代理的X-Forwarded-For等头部信息。
以下是更完整的解决方案:
package main
import (
"fmt"
"net"
"net/http"
"strings"
)
// 获取客户端真实IP
func GetClientIP(r *http.Request) string {
// 检查X-Forwarded-For头部(代理服务器传递)
xForwardedFor := r.Header.Get("X-Forwarded-For")
if xForwardedFor != "" {
// 可能有多个IP,取第一个
ips := strings.Split(xForwardedFor, ",")
return strings.TrimSpace(ips[0])
}
// 检查X-Real-IP头部(Nginx等代理)
xRealIP := r.Header.Get("X-Real-IP")
if xRealIP != "" {
return xRealIP
}
// 检查CF-Connecting-IP(Cloudflare代理)
cfConnectingIP := r.Header.Get("CF-Connecting-IP")
if cfConnectingIP != "" {
return cfConnectingIP
}
// 最后使用RemoteAddr
ip, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
return r.RemoteAddr
}
return ip
}
// 处理HTTP请求的示例
func handler(w http.ResponseWriter, r *http.Request) {
clientIP := GetClientIP(r)
fmt.Fprintf(w, "客户端真实IP: %s\n", clientIP)
// 如果需要获取监听器信息
if server := r.Context().Value(http.ServerContextKey).(*http.Server); server != nil {
fmt.Fprintf(w, "服务器地址: %s\n", server.Addr)
}
}
func main() {
http.HandleFunc("/", handler)
// 创建监听器
listener, err := net.Listen("tcp", ":8080")
if err != nil {
panic(err)
}
// 显示监听器信息(这只是服务器绑定的地址)
fmt.Printf("服务器监听在: %s\n", listener.Addr().String())
// 启动服务器
http.Serve(listener, nil)
}
对于更复杂的情况,可以使用realip包的增强版本:
package main
import (
"fmt"
"net/http"
"github.com/tomasen/realip"
)
func handler(w http.ResponseWriter, r *http.Request) {
// 使用realip包
clientIP := realip.FromRequest(r)
fmt.Fprintf(w, "客户端IP (realip包): %s\n", clientIP)
// 也可以自定义可信代理
realip.SetTrustedProxies([]string{"10.0.0.0/8", "192.168.0.0/16"})
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
关键点:
net.Listener.Addr()返回的是服务器自身的绑定地址,不是客户端IP- 直接连接的客户端IP可以通过
r.RemoteAddr获取 - 经过代理时需要检查
X-Forwarded-For、X-Real-IP等头部 realip.FromRequest已经处理了这些逻辑,是更可靠的选择
在生产环境中,推荐使用realip包或实现类似的逻辑,因为它能正确处理代理链中的IP地址。

