如何在golang中获取传入HTTP请求的NATed IP地址?

huangapple go评论72阅读模式
英文:

How do you retrieve the NATed IP address of an incoming HTTP request in golang?

问题

我有一个在GCP云运行的服务,它会将数据发布到外部URL。这些外部请求通过NAT路由,以确保请求源自静态IP地址。当我将数据发布到https://curlmyip.org时,CurlmyIP能够正确识别静态IP地址。

我有另一个Cloud Run服务可以接收相同的数据。然而,该服务无法获取静态IP地址。我正在使用以下代码尝试获取传入请求的静态IP地址:

func getIP(r *http.Request) (string, error) {
	// 从X-REAL-IP头部获取IP
	ip := r.Header.Get("X-REAL-IP")
	log.Printf("X-REAL-IP: %s", ip)
	netIP := net.ParseIP(ip)
	if netIP != nil {
		return ip, nil
	}

	// 从X-FORWARDED-FOR头部获取IP
	ips := r.Header.Get("X-FORWARDED-FOR")
	log.Printf("X-FORWARDED-FOR: %s", ips)
	splitIps := strings.Split(ips, ",")
	for _, ip := range splitIps {
		netIP := net.ParseIP(ip)
		if netIP != nil {
			return ip, nil
		}
	}

	// 从RemoteAddr获取IP
	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		return "", err
	}
	log.Printf("r.RemoteAddr: %s", ip)
	netIP = net.ParseIP(ip)
	if netIP != nil {
		return ip, nil
	}
	return "", fmt.Errorf("未找到有效的IP")
}

上述代码总是返回0.0.0.0,而不是配置的静态IP地址。我添加了日志以打印传入请求中的所有头部信息,但配置的IP地址无处可寻。

英文:

I have a GCP cloud run service that posts data to external URLs. These outgoing requests are routed thru a NAT to ensure requests originate from a static IP address. When I post the data to https://curlmyip.org, CurlmyIP correctly identifies the static IP address.

I have another Cloud Run service that can receive the same data. However, this service is unable to retrieve the static IP address. I am using this code to try and retrieve the static IP address of the incoming request

func getIP(r *http.Request) (string, error) {
	//Get IP from the X-REAL-IP header
	ip := r.Header.Get("X-REAL-IP")
	log.Printf("X-REAL-IP: %s", ip)
	netIP := net.ParseIP(ip)
	if netIP != nil {
		return ip, nil
	}

	//Get IP from X-FORWARDED-FOR header
	ips := r.Header.Get("X-FORWARDED-FOR")
	log.Printf("X-FORWARDED-FOR: %s", ips)
	splitIps := strings.Split(ips, ",")
	for _, ip := range splitIps {
		netIP := net.ParseIP(ip)
		if netIP != nil {
			return ip, nil
		}
	}

	//Get IP from RemoteAddr
	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		return "", err
	}
	log.Printf("r.RemoteAddr: %s", ip)
	netIP = net.ParseIP(ip)
	if netIP != nil {
		return ip, nil
	}
	return "", fmt.Errorf("no valid ip found")
}

The above always returns 0.0.0.0 which is in r.RemoteAddr and not the configured static IP address. I added logs to print all the headers in the incoming request and the configured IP address is nowhere to be found.

答案1

得分: 1

根据请求在到达您之前经过的路由器/代理服务器/负载均衡器/内容分发网络等(以及这些设备的配置),该标头可能出现在以下任何一个中:

  • True-Client-IP
  • X-Forwarded-For
  • X-Real-IP
  • 其他?

或者它可能根本不存在。

英文:

Depending on what routers/proxies/load balancers/content delivery networks/etc. the request passes through before it gets to you (and how those boxen are configured), the header could be found in any of

  • True-Client-IP
  • X-Forwarded-For
  • X-Real-IP
  • Others?

Or it could simply not be there at all.

答案2

得分: 1

过去我们使用的是x-forwarded-for头部,但是我们通过nginx模块跳过了GCP IP范围。

在网络上我们找到了一些IP块,但是你必须包括负载均衡器的IP。然后从头部提取第一个非私有IP。

你可以使用纯Go来完成。只需要找到要跳过的IP范围。

英文:

In the past we use the header x-forwarded-for but we skip the gcp ip ranges via nginx module.

There are some ip blocks that we found in the web but you must include the load balancer ip too. Then extract the first non-private ip from header.

You can do with pure go. Just need to find the ip ranges to skip

huangapple
  • 本文由 发表于 2022年6月3日 01:31:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/72480164.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定