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.cc
server {
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 ip
func 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 addr
func GetPeerAddr(ctx context.Context) string {
var addr string
if 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