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