如何从将 x-real-ip 和 x-forward-for 添加到 header 的负载均衡器获取 gRPC 中的客户端 IP 地址?

How can I get the client IP address in gRPC from a load balancer that adds x-real-ip and x-forward-for to the header?

如何从将 x-real-ip 和 x-forward-for 添加到 header 的负载均衡器中获取 Go gRPC 中的客户端 IP 地址?

“对等”库为我提供了唯一的负载平衡器 ip。 (来自这个答案:Get client's IP address from load balance server by X-Forwarded-For

澄清一下:我需要获取此信息的上下文在 GRPC 服务器处理程序中。它可能在拦截器中或在请求处理程序中:

示例:

func (s *myservice) MethodName(ctx context.Context, request *pb.MethodRequest) (*pb.MethodResponse, error) {

    // How to get ip from ctx ? 
    // I have tryied peer but it gives me the loadbalancer ip
    peer, ok := peer.FromContext(ctx)

    return &pb.MethodResponse{Pong: "ok"}, nil
}

如果我也能从拦截器中得到这个就没问题了……无论哪种方式都适合我。

func (a *MyInterceptor) Unary() grpc.UnaryServerInterceptor {
    return func(
        ctx context.Context,
        req interface{},
        info *grpc.UnaryServerInfo,
        handler grpc.UnaryHandler,
    ) (interface{}, error) {
        log.Debug("--> My interceptor: " + info.FullMethod)

        
        // How to get ip from ctx ? 
        
        return handler(ctx, req)
    }
}

PS:我正在使用 Kong 作为负载均衡器。 https://docs.konghq.com/0.14.x/loadbalancing/

您可以从请求 object 中读取 headers。

func handler(w http.ResponseWriter, r *http.Request) {
    realIP := r.Header.Get("x-real-ip")
    forwardFor := r.Header.Get("x-forward-for");

    // ...
}

查看负载均衡器文档,您可以看到有 header 组 X-Real-IP https://docs.konghq.com/0.14.x/configuration/#real_ip_header

这应该在 ctx 的元数据中返回。不幸的是,我无法对此进行测试,但请告诉我它是否有效

func (a *MyInterceptor) Unary() grpc.UnaryServerInterceptor {
    return func(
        ctx context.Context,
        req interface{},
        info *grpc.UnaryServerInfo,
        handler grpc.UnaryHandler,
    ) (interface{}, error) {
        log.Debug("--> My interceptor: " + info.FullMethod)

        
        // How to get ip from ctx ?
        var realIP string
        m, ok := metadata.FromIncomingContext(ctx)
        if ok {
            realIP := md.Get("X-Real-IP") 
        }
        // do what you need with realIP
        return handler(ctx, req)
    }
}