@@ -759,7 +759,7 @@ func (c *Context) ClientIP() string {
759
759
760
760
if trusted && c .engine .ForwardedByClientIP && c .engine .RemoteIPHeaders != nil {
761
761
for _ , headerName := range c .engine .RemoteIPHeaders {
762
- ip , valid := validateHeader (c .requestHeader (headerName ))
762
+ ip , valid := c . engine . validateHeader (c .requestHeader (headerName ))
763
763
if valid {
764
764
return ip
765
765
}
@@ -768,6 +768,17 @@ func (c *Context) ClientIP() string {
768
768
return remoteIP .String ()
769
769
}
770
770
771
+ func (e * Engine ) isTrustedProxy (ip net.IP ) bool {
772
+ if e .trustedCIDRs != nil {
773
+ for _ , cidr := range e .trustedCIDRs {
774
+ if cidr .Contains (ip ) {
775
+ return true
776
+ }
777
+ }
778
+ }
779
+ return false
780
+ }
781
+
771
782
// RemoteIP parses the IP from Request.RemoteAddr, normalizes and returns the IP (without the port).
772
783
// It also checks if the remoteIP is a trusted proxy or not.
773
784
// In order to perform this validation, it will see if the IP is contained within at least one of the CIDR blocks
@@ -782,35 +793,25 @@ func (c *Context) RemoteIP() (net.IP, bool) {
782
793
return nil , false
783
794
}
784
795
785
- if c .engine .trustedCIDRs != nil {
786
- for _ , cidr := range c .engine .trustedCIDRs {
787
- if cidr .Contains (remoteIP ) {
788
- return remoteIP , true
789
- }
790
- }
791
- }
792
-
793
- return remoteIP , false
796
+ return remoteIP , c .engine .isTrustedProxy (remoteIP )
794
797
}
795
798
796
- func validateHeader (header string ) (clientIP string , valid bool ) {
799
+ func ( e * Engine ) validateHeader (header string ) (clientIP string , valid bool ) {
797
800
if header == "" {
798
801
return "" , false
799
802
}
800
803
items := strings .Split (header , "," )
801
- for i , ipStr := range items {
802
- ipStr = strings .TrimSpace (ipStr )
804
+ for i := len ( items ) - 1 ; i >= 0 ; i -- {
805
+ ipStr : = strings .TrimSpace (items [ i ] )
803
806
ip := net .ParseIP (ipStr )
804
807
if ip == nil {
805
808
return "" , false
806
809
}
807
810
808
- // We need to return the first IP in the list, but,
809
- // we should not early return since we need to validate that
810
- // the rest of the header is syntactically valid
811
- if i == 0 {
812
- clientIP = ipStr
813
- valid = true
811
+ // X-Forwarded-For is appended by proxy
812
+ // Check IPs in reverse order and stop when find untrusted proxy
813
+ if (i == 0 ) || (! e .isTrustedProxy (ip )) {
814
+ return ipStr , true
814
815
}
815
816
}
816
817
return
0 commit comments