Golang中如何从net.Conn获取真实的客户端IP
Golang中如何从net.Conn获取真实的客户端IP
func main() {
fmt.Println("hello world")
}
我在使用已连接客户端的 conn.RemoteAddr() 时注意到,客户端的地址与我的电脑地址相同,但端口不同。谷歌搜索显示了 net/http 包的解决方案,但我没有使用 http。所以我想知道如何获取客户端的真实 IP 地址?
嗨克里斯托弗 🙂 你说得对。我刚发布这个主题后就豁然开朗,想到要检查外部IP连接,结果看到了我预期的情况 🙂 感谢你的帮助 🙂
更多关于Golang中如何从net.Conn获取真实的客户端IP的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你好!你可能获取到的是本地主机IP,也就是127.0.0.1,这始终是你计算机的本地IP。conn.RemoteAddr() 在本地环境中总是返回该IP,但如果你从网络上的其他位置进行测试,就会看到不同的结果。
你可能已经想明白了这一点,但这确实是个容易犯的错误,没什么好尴尬的 😊 我只是想给你一个答复,这样如果将来有人遇到同样的问题,他们就能知道原因了。
在Go语言中,当使用net.Conn处理TCP连接时,RemoteAddr()方法返回的是与服务器直接通信的对端地址。如果客户端通过代理或负载均衡器连接,RemoteAddr()可能返回的是代理的地址,而不是客户端的真实IP。
要获取客户端的真实IP,通常需要依赖代理服务器在连接时传递的额外信息,例如HTTP头(如X-Forwarded-For或X-Real-IP)。但既然你没有使用HTTP协议,而是原始TCP连接,获取真实IP的可行性取决于你的网络架构:
- 直接连接:如果客户端直接连接到服务器,
RemoteAddr()就是客户端的真实IP。 - 通过代理或负载均衡器:如果连接经过代理,代理需要在协议中嵌入客户端的真实IP(例如,在自定义数据包格式中包含IP信息)。你需要解析这些数据。
以下是一个示例,假设代理在连接建立后发送客户端的真实IP作为初始数据的一部分。代码演示了如何从连接中读取IP信息:
package main
import (
"encoding/binary"
"fmt"
"net"
)
func main() {
ln, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println("Error listening:", err)
return
}
defer ln.Close()
fmt.Println("Listening on :8080")
for {
conn, err := ln.Accept()
if err != nil {
fmt.Println("Error accepting connection:", err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
// 假设代理发送了4字节的IPv4地址作为前缀
var ipBytes [4]byte
_, err := conn.Read(ipBytes[:])
if err != nil {
fmt.Println("Error reading IP from connection:", err)
return
}
// 将字节转换为IP地址
ip := net.IP(ipBytes[:])
fmt.Printf("Client real IP: %s\n", ip.String())
// 处理后续数据...
// 例如:读取和响应客户端消息
buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
fmt.Println("Error reading data:", err)
return
}
fmt.Printf("Received: %s\n", string(buf[:n]))
conn.Write([]byte("Message received"))
}
在这个示例中:
- 服务器监听TCP端口8080。
- 当客户端连接时,假设代理首先发送4字节的IPv4地址。
- 服务器读取这些字节并解析为IP地址,然后处理后续数据。
如果代理没有发送此类信息,你无法获取真实IP。在这种情况下,你需要配置代理(如Nginx或HAProxy)来传递真实IP,或在客户端协议中明确包含IP地址。对于原始TCP,这通常需要自定义协议设计。

