This commit is contained in:
Manu Mtz.-Almeida 2021-02-08 14:19:09 +01:00
parent 55ad88a12b
commit 6f562eafa8

View File

@ -725,9 +725,11 @@ func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (e
return bb.BindBody(body, obj) return bb.BindBody(body, obj)
} }
// ClientIP implements a best effort algorithm to return the real client IP, it parses // ClientIP implements a best effort algorithm to return the real client IP.
// X-Real-IP and X-Forwarded-For in order to work properly with reverse-proxies such us: nginx or haproxy. // It called c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not.
// Use X-Forwarded-For before X-Real-Ip as nginx uses X-Real-Ip with the proxy's IP. // If it's it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]).
// If the headers are nots syntactically valid OR the remote IP does not correspong to a trusted proxy,
// the remote IP (coming form Request.RemoteAddr) is returned.
func (c *Context) ClientIP() string { func (c *Context) ClientIP() string {
if c.engine.AppEngine { if c.engine.AppEngine {
if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" { if addr := c.requestHeader("X-Appengine-Remote-Addr"); addr != "" {
@ -739,7 +741,7 @@ func (c *Context) ClientIP() string {
if remoteIP == nil { if remoteIP == nil {
return "" return ""
} }
if trusted { if trusted && c.engine.ForwardedByClientIP && c.engine.RemoteIPHeaders != nil {
for _, headerName := range c.engine.RemoteIPHeaders { for _, headerName := range c.engine.RemoteIPHeaders {
ip, valid := validateHeader(c.requestHeader(headerName)) ip, valid := validateHeader(c.requestHeader(headerName))
if valid { if valid {
@ -750,6 +752,10 @@ func (c *Context) ClientIP() string {
return remoteIP.String() return remoteIP.String()
} }
// RemoteIP parses the IP from Request.RemoteAddr, normalizes and returns the IP (without the port).
// It also checks if the remoteIP is a trusted proxy or not.
// In order to perform this validation, it will see if the IP is contained within at least one of the CIDR blocks
// defined in Engine.TrustedProxies
func (c *Context) RemoteIP() (net.IP, bool) { func (c *Context) RemoteIP() (net.IP, bool) {
ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr)) ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr))
if err != nil { if err != nil {
@ -759,13 +765,7 @@ func (c *Context) RemoteIP() (net.IP, bool) {
if remoteIP == nil { if remoteIP == nil {
return nil, false return nil, false
} }
if c.engine.trustedCIDRs != nil {
shouldCheckTrustedIP := c.engine.ForwardedByClientIP &&
c.engine.RemoteIPHeaders != nil &&
len(c.engine.RemoteIPHeaders) > 0 &&
c.engine.trustedCIDRs != nil
if shouldCheckTrustedIP {
for _, cidr := range c.engine.trustedCIDRs { for _, cidr := range c.engine.trustedCIDRs {
if cidr.Contains(remoteIP) { if cidr.Contains(remoteIP) {
return remoteIP, true return remoteIP, true