Golang中如何从net.Conn获取真实的客户端IP

Golang中如何从net.Conn获取真实的客户端IP

func main() {
    fmt.Println("hello world")
}

我在使用已连接客户端的 conn.RemoteAddr() 时注意到,客户端的地址与我的电脑地址相同,但端口不同。谷歌搜索显示了 net/http 包的解决方案,但我没有使用 http。所以我想知道如何获取客户端的真实 IP 地址?

3 回复

嗨克里斯托弗 🙂 你说得对。我刚发布这个主题后就豁然开朗,想到要检查外部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-ForX-Real-IP)。但既然你没有使用HTTP协议,而是原始TCP连接,获取真实IP的可行性取决于你的网络架构:

  1. 直接连接:如果客户端直接连接到服务器,RemoteAddr()就是客户端的真实IP。
  2. 通过代理或负载均衡器:如果连接经过代理,代理需要在协议中嵌入客户端的真实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,这通常需要自定义协议设计。

回到顶部