gitlab.com/ignitionrobotics/web/ign-go@v1.0.0-rc4/ip_finder.go (about) 1 package ign 2 3 // Code originally taken from 4 // https://husobee.github.io/golang/ip-address/2015/12/17/remote-ip-go.html 5 6 import ( 7 "bytes" 8 "net" 9 "net/http" 10 "strings" 11 ) 12 13 // ipRange is a structure that holds the start and end of a range of 14 // ip addresses 15 type ipRange struct { 16 start net.IP 17 end net.IP 18 } 19 20 // private ranges lists IP ranges that are considered private or local 21 // addresses 22 var privateRanges = []ipRange{ 23 { 24 start: net.ParseIP("10.0.0.0"), 25 end: net.ParseIP("10.255.255.255"), 26 }, 27 { 28 start: net.ParseIP("100.64.0.0"), 29 end: net.ParseIP("100.127.255.255"), 30 }, 31 { 32 start: net.ParseIP("172.16.0.0"), 33 end: net.ParseIP("172.31.255.255"), 34 }, 35 { 36 start: net.ParseIP("192.0.0.0"), 37 end: net.ParseIP("192.0.0.255"), 38 }, 39 { 40 start: net.ParseIP("192.168.0.0"), 41 end: net.ParseIP("192.168.255.255"), 42 }, 43 { 44 start: net.ParseIP("198.18.0.0"), 45 end: net.ParseIP("198.19.255.255"), 46 }, 47 } 48 49 // inRange checks to see if a given ip address is within a range given 50 func inRange(r ipRange, ipAddress net.IP) bool { 51 // strcmp type byte comparison 52 if bytes.Compare(ipAddress, r.start) >= 0 && 53 bytes.Compare(ipAddress, r.end) < 0 { 54 return true 55 } 56 return false 57 } 58 59 // isPrivateSubnet checks to see if this ip is in a private subnet 60 func isPrivateSubnet(ipAddress net.IP) bool { 61 // my use case is only concerned with ipv4 atm 62 if ipCheck := ipAddress.To4(); ipCheck != nil { 63 // iterate over all our ranges 64 for _, r := range privateRanges { 65 // check if this ip is in a private range 66 if inRange(r, ipAddress) { 67 return true 68 } 69 } 70 } 71 return false 72 } 73 74 ///////////////////////////////////////////////// 75 /// getIPAddress searches, from right to left, for a valid IP address in a 76 /// request. 77 func getIPAddress(r *http.Request) string { 78 79 // Search over possible headers. 80 for _, h := range []string{"X-Forwarded-For", "X-Real-Ip"} { 81 82 // Number of addresses in the header 83 addresses := strings.Split(r.Header.Get(h), ",") 84 85 // March from right to left until we get a public address 86 // that will be the address right before our proxy. 87 for i := len(addresses) - 1; i >= 0; i-- { 88 ip := strings.TrimSpace(addresses[i]) 89 90 // header can contain spaces too, strip those out. 91 realIP := net.ParseIP(ip) 92 93 if !realIP.IsGlobalUnicast() || isPrivateSubnet(realIP) { 94 // bad address, go to next 95 continue 96 } 97 return ip 98 } 99 } 100 return "" 101 }