ip.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. package ip
  2. import (
  3. "bufio"
  4. "io"
  5. "net"
  6. "os"
  7. "strconv"
  8. "strings"
  9. )
  10. // IP ip struct info.
  11. type IP struct {
  12. Begin uint32
  13. End uint32
  14. ISPCode int
  15. ISP string
  16. CountryCode int
  17. Country string
  18. ProvinceCode int
  19. Province string
  20. CityCode int
  21. City string
  22. DistrictCode int
  23. District string
  24. Latitude float64
  25. Longitude float64
  26. }
  27. // Zone ip struct info.
  28. type Zone struct {
  29. ID int64 `json:"id"`
  30. Addr string `json:"addr"`
  31. ISP string `json:"isp"`
  32. Country string `json:"country"`
  33. Province string `json:"province"`
  34. City string `json:"city"`
  35. Latitude float64 `json:"latitude"`
  36. Longitude float64 `json:"longitude"`
  37. CountryCode int `json:"country_code,omitempty"`
  38. }
  39. // List struct info list.
  40. type List struct {
  41. IPs []*IP
  42. }
  43. // New create Xip instance and return.
  44. func New(path string) (list *List, err error) {
  45. var (
  46. ip *IP
  47. file *os.File
  48. line []byte
  49. )
  50. list = new(List)
  51. if file, err = os.Open(path); err != nil {
  52. return
  53. }
  54. defer file.Close()
  55. reader := bufio.NewReader(file)
  56. for {
  57. if line, _, err = reader.ReadLine(); err != nil {
  58. if err == io.EOF {
  59. err = nil
  60. break
  61. }
  62. continue
  63. }
  64. lines := strings.Fields(string(line))
  65. if len(lines) < 13 {
  66. continue
  67. }
  68. // lines[2]:country lines[3]:province lines[4]:city lines[5]:unit
  69. if lines[3] == "香港" || lines[3] == "澳门" || lines[3] == "台湾" {
  70. lines[2] = lines[3]
  71. lines[3] = lines[4]
  72. lines[4] = "*"
  73. }
  74. // ex.: from 中国 中国 * to 中国 ”“ ”“
  75. if lines[2] == lines[3] || lines[3] == "*" {
  76. lines[3] = ""
  77. lines[4] = ""
  78. } else if lines[3] == lines[4] || lines[4] == "*" {
  79. // ex.: from 中国 北京 北京 to 中国 北京 ”“
  80. lines[4] = ""
  81. }
  82. ip = &IP{
  83. Begin: InetAtoN(lines[0]),
  84. End: InetAtoN(lines[1]),
  85. Country: lines[2],
  86. Province: lines[3],
  87. City: lines[4],
  88. ISP: lines[6],
  89. }
  90. ip.Latitude, _ = strconv.ParseFloat(lines[7], 64)
  91. ip.Longitude, _ = strconv.ParseFloat(lines[8], 64)
  92. ip.CountryCode, _ = strconv.Atoi(lines[12])
  93. list.IPs = append(list.IPs, ip)
  94. }
  95. return
  96. }
  97. // IP ip zone info by ip
  98. func (l *List) IP(ipStr string) (ip *IP) {
  99. addr := InetAtoN(ipStr)
  100. i, j := 0, len(l.IPs)
  101. for i < j {
  102. h := i + (j-i)/2 // avoid overflow when computing h
  103. ip = l.IPs[h]
  104. // i ≤ h < j
  105. if addr < ip.Begin {
  106. j = h
  107. } else if addr > ip.End {
  108. i = h + 1
  109. } else {
  110. break
  111. }
  112. }
  113. return
  114. }
  115. // Zone get ip info from ip
  116. func (l *List) Zone(addr string) (zone *Zone) {
  117. ip := l.IP(addr)
  118. if ip == nil {
  119. return
  120. }
  121. return &Zone{
  122. ID: ZoneID(ip.Country, ip.Province, ip.City),
  123. Addr: addr,
  124. ISP: ip.ISP,
  125. Country: ip.Country,
  126. Province: ip.Province,
  127. City: ip.City,
  128. Latitude: ip.Latitude,
  129. Longitude: ip.Longitude,
  130. CountryCode: ip.CountryCode,
  131. }
  132. }
  133. // All return ipInfos.
  134. func (l *List) All() []*IP {
  135. return l.IPs
  136. }
  137. // ExternalIP get external ip.
  138. func ExternalIP() (res []string) {
  139. inters, err := net.Interfaces()
  140. if err != nil {
  141. return
  142. }
  143. for _, inter := range inters {
  144. if !strings.HasPrefix(inter.Name, "lo") {
  145. addrs, err := inter.Addrs()
  146. if err != nil {
  147. continue
  148. }
  149. for _, addr := range addrs {
  150. if ipnet, ok := addr.(*net.IPNet); ok {
  151. if ipnet.IP.IsLoopback() || ipnet.IP.IsLinkLocalMulticast() || ipnet.IP.IsLinkLocalUnicast() {
  152. continue
  153. }
  154. if ip4 := ipnet.IP.To4(); ip4 != nil {
  155. switch true {
  156. case ip4[0] == 10:
  157. continue
  158. case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:
  159. continue
  160. case ip4[0] == 192 && ip4[1] == 168:
  161. continue
  162. default:
  163. res = append(res, ipnet.IP.String())
  164. }
  165. }
  166. }
  167. }
  168. }
  169. }
  170. return
  171. }
  172. // InternalIP get internal ip.
  173. func InternalIP() string {
  174. inters, err := net.Interfaces()
  175. if err != nil {
  176. return ""
  177. }
  178. for _, inter := range inters {
  179. if !strings.HasPrefix(inter.Name, "lo") {
  180. addrs, err := inter.Addrs()
  181. if err != nil {
  182. continue
  183. }
  184. for _, addr := range addrs {
  185. if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
  186. if ipnet.IP.To4() != nil {
  187. return ipnet.IP.String()
  188. }
  189. }
  190. }
  191. }
  192. }
  193. return ""
  194. }
  195. // InetAtoN conver ip addr to uint32.
  196. func InetAtoN(s string) (sum uint32) {
  197. ip := net.ParseIP(s)
  198. if ip == nil {
  199. return
  200. }
  201. ip = ip.To4()
  202. if ip == nil {
  203. return
  204. }
  205. sum += uint32(ip[0]) << 24
  206. sum += uint32(ip[1]) << 16
  207. sum += uint32(ip[2]) << 8
  208. sum += uint32(ip[3])
  209. return sum
  210. }
  211. // InetNtoA conver uint32 to ip addr.
  212. func InetNtoA(sum uint32) string {
  213. ip := make(net.IP, net.IPv4len)
  214. ip[0] = byte((sum >> 24) & 0xFF)
  215. ip[1] = byte((sum >> 16) & 0xFF)
  216. ip[2] = byte((sum >> 8) & 0xFF)
  217. ip[3] = byte(sum & 0xFF)
  218. return ip.String()
  219. }