golang grpc 获取 remote-ip 和 real-ip
前言:
grpc-go 提供了 peer 库可以获取客户端地址,如果无网关及代理的情况下,通过 peer 是可以直接拿到对端的 ip 地址,反之有网关代理,那么拿到的地址非真实客户端,而是对端的直连地址。
该文章原文地址 http://xiaorui.cc/archives/6892
实现:
无网关代理时,可使用 GetPeerAddr() 获取。如有代理需要在代理转发时把代理对端的 ip 给塞到 header 的 x-real-ip 头里,这个过程其实跟 nginx 操作 X-Real-IP 和 X-Forwarded-For 一样的。可做 grpc 网关的服务有很多,比如 nginx、traefik、envoy。下面拿 nginx grpc 配置为例。
// xiaorui.ccserver {listen 9099 http2;access_log /var/log/nginx/xiaorui.cc.log;location / {grpc_pass grpc://127.0.0.1:9091;grpc_set_header X-Real-IP $remote_addr;}}
Go
Copy
使用 metadata 从 header 里获取 x-real-ip。
// xiaorui.cc// GetRealAddr get real client ipfunc GetRealAddr(ctx context.Context) string {md, ok := metadata.FromIncomingContext(ctx)if !ok {return ""}rips := md.Get("x-real-ip")if len(rips) == 0 {return ""}return rips[0]}// GetPeerAddr get peer addrfunc GetPeerAddr(ctx context.Context) string {var addr stringif pr, ok := peer.FromContext(ctx); ok {if tcpAddr, ok := pr.Addr.(*net.TCPAddr); ok {addr = tcpAddr.IP.String()} else {addr = pr.Addr.String()}}return addr}
Go
Copy
总结:
x-forwared-for 在 web 场景下很常见,grpc 下想不到场景。 😅 通常为了优化 web 服务,加入多级缓存及负载均衡,这些节点都有可能追加 x-forwared-for 头。
http://xiaorui.cc/archives/6892
