Search code examples
gogrpckongamazon-elb

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?


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

The "peer" lib is giving me the only load balancer ip. (from this answer: Get client's IP address from load balance server by X-Forwarded-For)

Just to make it clear: The context where I need to grab this information is inside the GRPC server handler. It may be in an interceptor or inside the request handler:

example:

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
}

It would be ok if I could get this from the interceptor as well... either way works for me.

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: I'm using Kong as load balancer. https://docs.konghq.com/0.14.x/loadbalancing/


Solution

  • Looking at the loadbalancer docs you can see that there is a header set of X-Real-IP https://docs.konghq.com/0.14.x/configuration/#real_ip_header

    This should be returned in the metadata of the ctx. I can't test this unfortunately, but let me know if it works

    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)
        }
    }