gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

network.go (4351B)


      1 package limiter
      2 
      3 import (
      4 	"net"
      5 	"net/http"
      6 	"strings"
      7 )
      8 
      9 var (
     10 	// DefaultIPv4Mask defines the default IPv4 mask used to obtain user IP.
     11 	DefaultIPv4Mask = net.CIDRMask(32, 32)
     12 	// DefaultIPv6Mask defines the default IPv6 mask used to obtain user IP.
     13 	DefaultIPv6Mask = net.CIDRMask(128, 128)
     14 )
     15 
     16 // GetIP returns IP address from request.
     17 // If options is defined and either TrustForwardHeader is true or ClientIPHeader is defined,
     18 // it will lookup IP in HTTP headers.
     19 // Please be advised that using this option could be insecure (ie: spoofed) if your reverse
     20 // proxy is not configured properly to forward a trustworthy client IP.
     21 // Please read the section "Limiter behind a reverse proxy" in the README for further information.
     22 func (limiter *Limiter) GetIP(r *http.Request) net.IP {
     23 	return GetIP(r, limiter.Options)
     24 }
     25 
     26 // GetIPWithMask returns IP address from request by applying a mask.
     27 // If options is defined and either TrustForwardHeader is true or ClientIPHeader is defined,
     28 // it will lookup IP in HTTP headers.
     29 // Please be advised that using this option could be insecure (ie: spoofed) if your reverse
     30 // proxy is not configured properly to forward a trustworthy client IP.
     31 // Please read the section "Limiter behind a reverse proxy" in the README for further information.
     32 func (limiter *Limiter) GetIPWithMask(r *http.Request) net.IP {
     33 	return GetIPWithMask(r, limiter.Options)
     34 }
     35 
     36 // GetIPKey extracts IP from request and returns hashed IP to use as store key.
     37 // If options is defined and either TrustForwardHeader is true or ClientIPHeader is defined,
     38 // it will lookup IP in HTTP headers.
     39 // Please be advised that using this option could be insecure (ie: spoofed) if your reverse
     40 // proxy is not configured properly to forward a trustworthy client IP.
     41 // Please read the section "Limiter behind a reverse proxy" in the README for further information.
     42 func (limiter *Limiter) GetIPKey(r *http.Request) string {
     43 	return limiter.GetIPWithMask(r).String()
     44 }
     45 
     46 // GetIP returns IP address from request.
     47 // If options is defined and either TrustForwardHeader is true or ClientIPHeader is defined,
     48 // it will lookup IP in HTTP headers.
     49 // Please be advised that using this option could be insecure (ie: spoofed) if your reverse
     50 // proxy is not configured properly to forward a trustworthy client IP.
     51 // Please read the section "Limiter behind a reverse proxy" in the README for further information.
     52 func GetIP(r *http.Request, options ...Options) net.IP {
     53 	if len(options) >= 1 {
     54 		if options[0].ClientIPHeader != "" {
     55 			ip := getIPFromHeader(r, options[0].ClientIPHeader)
     56 			if ip != nil {
     57 				return ip
     58 			}
     59 		}
     60 		if options[0].TrustForwardHeader {
     61 			ip := getIPFromXFFHeader(r)
     62 			if ip != nil {
     63 				return ip
     64 			}
     65 
     66 			ip = getIPFromHeader(r, "X-Real-IP")
     67 			if ip != nil {
     68 				return ip
     69 			}
     70 		}
     71 	}
     72 
     73 	remoteAddr := strings.TrimSpace(r.RemoteAddr)
     74 	host, _, err := net.SplitHostPort(remoteAddr)
     75 	if err != nil {
     76 		return net.ParseIP(remoteAddr)
     77 	}
     78 
     79 	return net.ParseIP(host)
     80 }
     81 
     82 // GetIPWithMask returns IP address from request by applying a mask.
     83 // If options is defined and either TrustForwardHeader is true or ClientIPHeader is defined,
     84 // it will lookup IP in HTTP headers.
     85 // Please be advised that using this option could be insecure (ie: spoofed) if your reverse
     86 // proxy is not configured properly to forward a trustworthy client IP.
     87 // Please read the section "Limiter behind a reverse proxy" in the README for further information.
     88 func GetIPWithMask(r *http.Request, options ...Options) net.IP {
     89 	if len(options) == 0 {
     90 		return GetIP(r)
     91 	}
     92 
     93 	ip := GetIP(r, options[0])
     94 	if ip.To4() != nil {
     95 		return ip.Mask(options[0].IPv4Mask)
     96 	}
     97 	if ip.To16() != nil {
     98 		return ip.Mask(options[0].IPv6Mask)
     99 	}
    100 	return ip
    101 }
    102 
    103 func getIPFromXFFHeader(r *http.Request) net.IP {
    104 	headers := r.Header.Values("X-Forwarded-For")
    105 	if len(headers) == 0 {
    106 		return nil
    107 	}
    108 
    109 	parts := []string{}
    110 	for _, header := range headers {
    111 		parts = append(parts, strings.Split(header, ",")...)
    112 	}
    113 
    114 	for i := range parts {
    115 		part := strings.TrimSpace(parts[i])
    116 		ip := net.ParseIP(part)
    117 		if ip != nil {
    118 			return ip
    119 		}
    120 	}
    121 
    122 	return nil
    123 }
    124 
    125 func getIPFromHeader(r *http.Request, name string) net.IP {
    126 	header := strings.TrimSpace(r.Header.Get(name))
    127 	if header == "" {
    128 		return nil
    129 	}
    130 
    131 	ip := net.ParseIP(header)
    132 	if ip != nil {
    133 		return ip
    134 	}
    135 
    136 	return nil
    137 }