github.com/influx6/npkg@v0.8.8/nip/nip.go (about) 1 package nip 2 3 import ( 4 "bytes" 5 "net" 6 "net/http" 7 "strings" 8 9 "github.com/influx6/npkg/nerror" 10 ) 11 12 var DefaultSubnet = PrivateSubnets{ 13 IpRange{ 14 Start: net.ParseIP("10.0.0.0"), 15 End: net.ParseIP("10.255.255.255"), 16 }, 17 IpRange{ 18 Start: net.ParseIP("100.64.0.0"), 19 End: net.ParseIP("100.127.255.255"), 20 }, 21 IpRange{ 22 Start: net.ParseIP("172.16.0.0"), 23 End: net.ParseIP("172.31.255.255"), 24 }, 25 IpRange{ 26 Start: net.ParseIP("192.0.0.0"), 27 End: net.ParseIP("192.0.0.255"), 28 }, 29 IpRange{ 30 Start: net.ParseIP("192.168.0.0"), 31 End: net.ParseIP("192.168.255.255"), 32 }, 33 IpRange{ 34 Start: net.ParseIP("198.18.0.0"), 35 End: net.ParseIP("198.19.255.255"), 36 }, 37 } 38 39 //IpRange - a structure that holds the Start and End of a range of ip addresses 40 type IpRange struct { 41 Start net.IP 42 End net.IP 43 } 44 45 // InRange - check to see if a given ip address is within a range given 46 func InRange(r IpRange, ipAddress net.IP) bool { 47 // strcmp type byte comparison 48 if bytes.Compare(ipAddress, r.Start) >= 0 && bytes.Compare(ipAddress, r.End) < 0 { 49 return true 50 } 51 return false 52 } 53 54 type PrivateSubnets []IpRange 55 56 func (subnet *PrivateSubnets) ParseRequestIP(r *http.Request) (net.Addr, error) { 57 for _, h := range []string{"X-Forwarded-For", "X-Real-Ip"} { 58 addresses := strings.Split(r.Header.Get(h), ",") 59 // march from right to left until we get a public address 60 // that will be the address right before our proxy. 61 for i := len(addresses) - 1; i >= 0; i-- { 62 ip := strings.TrimSpace(addresses[i]) 63 // header can contain spaces too, strip those out. 64 realIP := net.ParseIP(ip) 65 if !realIP.IsGlobalUnicast() || IsPrivateSubnet(*subnet, realIP) { 66 // bad address, go to next 67 continue 68 } 69 70 var parsedIP, parseErr = net.ResolveIPAddr("tcp", realIP.String()) 71 if parseErr != nil { 72 return nil, nerror.WrapOnly(parseErr) 73 } 74 return parsedIP, nil 75 } 76 } 77 78 var ip, _, err = net.SplitHostPort(r.RemoteAddr) 79 if err != nil { 80 return nil, nerror.WrapOnly(err) 81 } 82 83 var parsedIP, parseErr = net.ResolveIPAddr("tcp", ip) 84 if parseErr != nil { 85 return nil, nerror.WrapOnly(parseErr) 86 } 87 88 return parsedIP, nil 89 } 90 91 // IsPrivateSubnet - check to see if this ip is in a private subnet 92 func IsPrivateSubnet(subnet PrivateSubnets, ipAddress net.IP) bool { 93 // my use case is only concerned with ipv4 atm 94 if ipCheck := ipAddress.To4(); ipCheck != nil { 95 // iterate over all our ranges 96 for _, r := range subnet { 97 // check if this ip is in a private range 98 if InRange(r, ipAddress) { 99 return true 100 } 101 } 102 } 103 return false 104 }