How can I get the client IP address and user-agent in Golang gRPC?
Asked Answered
D

3

8

I set up a series of gRPC requests and responses which all work fine, but I'm stuck when I try to get the client IP address and user-agent who is calling my gRPC APIs.

I read the Go gRPC documentation and other sources, but didn't find much valuable information. Few of them are talking about gRPC in Golang.

Should I set up a key-value to store the IP address in the context when setting up the gRPC APIs?

Dannica answered 8/8, 2018 at 18:31 Comment(3)
godoc.org/google.golang.org/grpc/peer#FromContextSpermato
The user agent is part of the metadata if I recall correctly.Spermato
Thank you Peter. That's correct. I'm testing it.Dannica
E
26

In Golang GRPC, you can use

func (UserServicesServer) Login(ctx context.Context, request *sso.LoginRequest) (*sso.LoginResponse, error) {
  p, _ := peer.FromContext(ctx)
  request.Frontendip = p.Addr.String()
  .
  .
}

But, do not forget import "google.golang.org/grpc/peer"

Egidius answered 11/10, 2019 at 9:5 Comment(2)
Great answer. Is it always an IP address?Prud
Yes, it is @PrudEgidius
N
2

There is one gRPC middleware realip

Package realip is a middleware that extracts the real IP of requests based on header values

import  "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip"

// Simple example of a unary server initialization code.
func ExampleUnaryServerInterceptor() {
    // Define list of trusted peers from which we accept forwarded-for and
    // real-ip headers.
    trustedPeers := []netip.Prefix{
        netip.MustParsePrefix("127.0.0.1/32"),
    }
    // Define headers to look for in the incoming request.
    headers := []string{realip.XForwardedFor, realip.XRealIp}
    _ = grpc.NewServer(
        grpc.ChainUnaryInterceptor(
            realip.UnaryServerInterceptor(trustedPeers, headers),
        ),
    )
}

For grpc-gateway is used, the client IP address may be retrieved through x-forwarded-for like this:

// Get IP from GRPC context
func GetIP(ctx context.Context) string {
    if headers, ok := metadata.FromIncomingContext(ctx); ok {
        xForwardFor := headers.Get("x-forwarded-for")
        if len(xForwardFor) > 0 && xForwardFor[0] != "" {
            ips := strings.Split(xForwardFor[0], ",")
            if len(ips) > 0 {
                clientIp := ips[0]
                return clientIp
            }
        }
    }
    return ""
}
Ninurta answered 4/2, 2021 at 12:20 Comment(0)
T
1

In Golang GRPC, context has 3 values

  1. authority

  2. content-type

  3. user-agent

    md,ok:=metadata.FromIncomingContext(ctx)
    fmt.Printf("%+v%+v",md,ok)
    
Trephine answered 4/2, 2021 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.