HTTP attempts to get client IP

Time:2022-7-7

Most of the policy requirements related to client IP obtained from HTTP can only provide suggestions in the current network environment More importantly

Explore more potential value through other unique identification

 

This article is mainly about how to try to obtain the client IP in the HTTP request as much as possible

 

First of all, we need to understand some prior knowledge

 

1. HTTP header key is not case sensitive

https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2

 

2. X-forwarded-for is the factual standard of HTTP proxy

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/X-Forwarded-For

X-Forwarded-For: , ,

 

3. Most gateways use nginx

http {
    #The following three behavior points can be added to obtain the real IP address of the client
    set_real_ip_from 0.0.0.0/0;
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;

    #The following three lines are the configuration of common reverse proxy to deliver real client IP
    #If it is configured in http{}, it will be globally applied to all servers below
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

https://amos-x.com/index.php/amos/archives/nginx-realip/

https://cloud.tencent.com/developer/article/1521273

 

Based on the above information, we begin to build scaffolding methods in the project

import (
    "fmt"
    "net"
    "net/http"
    "strings"
)

//If x-forwarded-for (XFF) needs to pass through HTTP proxy or load balancing server in the process of client accessing the server,
//It can be used to obtain the IP address of the client that originally initiated the request. This message header becomes the de facto standard
var xForwardedForKeys = [...]string{"X-Forwarded-For", "x-forwarded-for", "X-FORWARDED-FOR"}

//Xrealip nginx reverse proxy service IP
var xRealIPKeys = [...]string{"X-Real-IP", "X-Real-Ip", "x-real-ip", "X-REAL-IP"}

//Getclientip get client IP
func GetClientIP(r *http.Request) (ip string) {
    // X-Forwarded-For: , , 
    for _, xForwardedForKey := range xForwardedForKeys {
        xForwardedFor := strings.TrimSpace(r.Header.Get(xForwardedForKey))
        if len(xForwardedFor) > 0 {
            xForwardedFors := strings.Split(xForwardedFor, ",")
            ip = strings.TrimSpace(xForwardedFors[0])
            if len(ip) > 0 {
                return
            }
            break
        }
    }

    for _, xRealIPKey := range xRealIPKeys {
        ip = strings.TrimSpace(r.Header.Get(xRealIPKey))
        if len(ip) > 0 {
            return
        }
    }

    //Directly use the IP address requested by the client
    ip, _, _ = net.SplitHostPort(r.RemoteAddr)
    return
}