grs.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. package grs
  2. import (
  3. "errors"
  4. "fmt"
  5. "log"
  6. "net"
  7. "net/url"
  8. "regexp"
  9. "strings"
  10. "time"
  11. napping "gopkg.in/jmcvetta/napping.v3"
  12. )
  13. const (
  14. // GrsURL contains the RIPE REST API URL
  15. GrsURL = "http://rest.db.ripe.net/search.json"
  16. )
  17. // GRS contains whois data from the ripe API
  18. type GRS struct {
  19. //ID bson.ObjectId `bson:"_id,omitempty" json:"id"`
  20. ID string `bson:"_id" json:"_id"`
  21. Source string `bson:"source" json:"source"`
  22. IpFrom string `bson:"ip_from" json:"ip_from"`
  23. IpTo string `bson:"ip_to" json:"ip_to"`
  24. IpFromRaw []byte `bson:"ip_from_raw" json:"ip_from_raw"`
  25. IpToRaw []byte `bson:"ip_to_raw" json:"ip_to_raw"`
  26. Description string `bson:"description" json:"description"`
  27. Country string `bson:"country" json:"country"`
  28. Status string `bson:"status" json:"status"`
  29. Cidr string `bson:"cidr" json:"cidr"`
  30. NetMaskBits int `bson:"netmask_bits" json:"netmask_bits"`
  31. Name string `bson:"name" json:"name"`
  32. Org string `bson:"org" json:"org"`
  33. ASN string `bson:"asn" json:"asn"`
  34. CreatedAt time.Time `bson:"created_at" json:"created_at"`
  35. ModifiedAt time.Time `bson:"modified_at" json:"modified_at"`
  36. Organization Organization `bson:"organization" json:"organization"`
  37. }
  38. // GRSRaw contains the raw GRS response from the ripe API server
  39. type GRSRaw struct {
  40. Service Name `json:"service"`
  41. Parameters Parameters `json:"parameters"`
  42. Objects Objects `json:"objects"`
  43. Terms Terms `json:"terms-and-conditions"`
  44. ErrorMessages ErrorMessages `json:"errormessages"`
  45. }
  46. // Name contains the GRS name
  47. type Name struct {
  48. Name string `json:"name"`
  49. }
  50. // Parameters contains all API query parameters
  51. type Parameters struct {
  52. InverseLookup map[string]interface{} `json:"inverse-lookup"`
  53. TypeFilters map[string]interface{} `json:"type-filters"`
  54. Flags map[string]interface{} `json:"flags"`
  55. QueryStrings QueryString `json:"query-strings"`
  56. Sources Sources `json:"sources"`
  57. }
  58. // QueryString contains a list of query-strings for API requests
  59. type QueryString struct {
  60. QueryString []Value `json:"query-string"`
  61. }
  62. // Value contains a GRS value
  63. type Value struct {
  64. Value string `json:"value"`
  65. }
  66. type Sources struct {
  67. Ids []Id `json:"source"`
  68. }
  69. type AutNum struct {
  70. Source string
  71. ID string
  72. Name string
  73. Org string
  74. AdminContact string
  75. TechContact string
  76. Status string
  77. Notify []string
  78. Maintainer []string
  79. Created time.Time
  80. Modified time.Time
  81. Organization Organization
  82. }
  83. type Organization struct {
  84. // ID string
  85. Name string
  86. Type string
  87. Address []string
  88. Phone string
  89. Fax string
  90. Email string
  91. Organization string
  92. AbuseEmail string
  93. Source string
  94. }
  95. type Id struct {
  96. ID string `json:"id"`
  97. }
  98. type Objects struct {
  99. Objects []Object `json:"object"`
  100. }
  101. type Object struct {
  102. Type string `json:"type"`
  103. Link Link `json:"link"`
  104. Source Id `json:"source"`
  105. PrimaryKey Attributes `json:"primary-key"`
  106. Attributes Attributes `json:"attributes"`
  107. Tags Tags `json:"tags"`
  108. }
  109. type Link struct {
  110. Type string `json:"type"`
  111. Href string `json:"href"`
  112. }
  113. type Attributes struct {
  114. Attributes []Attribute `json:"attribute"`
  115. }
  116. type Attribute struct {
  117. Link Link `json:"link"`
  118. Name string `json:"name"`
  119. Value string `json:"value"`
  120. ReferencedType string `json:"referenced-type"`
  121. }
  122. type Tags struct {
  123. Tags []Tag `json:"tag"`
  124. }
  125. type Tag struct {
  126. ID string `json:"id"`
  127. Data string `json:"data"`
  128. }
  129. type Terms struct {
  130. Type string `json:"type"`
  131. Href string `json:"href"`
  132. }
  133. type ErrorMessages struct {
  134. ErrorMessage []ErrorMessage `json:"errormessage"`
  135. }
  136. type ErrorMessage struct {
  137. Severity string `json:"severity"`
  138. Text string `json:"text"`
  139. }
  140. // LookupAutNum looks up the Autonomous System Number (ASN) using the RIPE API and returns an AutNum object
  141. func LookupAutNum(id string) (AutNum, error) {
  142. asID := id
  143. asID = strings.TrimPrefix(asID, "MNT-")
  144. asID = strings.TrimPrefix(asID, "AS")
  145. asID = fmt.Sprintf("AS%s", id)
  146. args := url.Values{}
  147. args.Set("query-string", id)
  148. args.Add("type-filter", "aut-num")
  149. args.Add("source", "ripe-grs")
  150. args.Add("source", "arin-grs")
  151. args.Add("source", "apnic-grs")
  152. args.Add("source", "lacnic-grs")
  153. args.Add("source", "afrinic-grs")
  154. var data GRSRaw
  155. resp, err := napping.Get(GrsURL, &args, &data, nil)
  156. if err != nil {
  157. return AutNum{}, errors.New(fmt.Sprint("Failed to load data from ", resp.Url, ": ", err))
  158. }
  159. if resp.Status() != 200 {
  160. return AutNum{}, errors.New(fmt.Sprint("Failed to load data from GRS server: ", resp.Status()))
  161. }
  162. if len(data.ErrorMessages.ErrorMessage) > 0 {
  163. return AutNum{}, errors.New(fmt.Sprint("No GRS data for ", id, ": ", data.ErrorMessages.ErrorMessage[0].Text))
  164. }
  165. if err != nil {
  166. return AutNum{}, err
  167. }
  168. var aut AutNum
  169. var autnum *Object
  170. var org *Object
  171. ymdRegexp := regexp.MustCompile(`^\d+$`)
  172. for i, e := range data.Objects.Objects {
  173. switch e.Type {
  174. case "aut-num":
  175. autnum = &data.Objects.Objects[i]
  176. case "organisation":
  177. org = &data.Objects.Objects[i]
  178. }
  179. }
  180. if autnum != nil {
  181. for _, e := range autnum.Attributes.Attributes {
  182. switch e.Name {
  183. case "aut-num":
  184. aut.ID = e.Value
  185. case "as-name":
  186. aut.Name = e.Value
  187. case "org":
  188. aut.Org = e.Value
  189. case "admin-c":
  190. aut.AdminContact = e.Value
  191. case "tech-c":
  192. aut.TechContact = e.Value
  193. case "status":
  194. aut.Status = e.Value
  195. case "mnt-by":
  196. aut.Maintainer = append(aut.Maintainer, e.Value)
  197. case "source":
  198. aut.Source = e.Value
  199. case "created":
  200. if ymdRegexp.MatchString(e.Value) {
  201. t, err := time.Parse("20060102", e.Value)
  202. if err != nil {
  203. log.Printf("%s: %s\n", e.Value, err)
  204. break
  205. }
  206. aut.Created = t
  207. break
  208. }
  209. t, err := time.Parse(time.RFC3339, e.Value)
  210. if err != nil {
  211. log.Printf("%s: %s\n", e.Value, err)
  212. break
  213. }
  214. aut.Created = t
  215. case "last-modified":
  216. if ymdRegexp.MatchString(e.Value) {
  217. t, err := time.Parse("20060102", e.Value)
  218. if err != nil {
  219. log.Printf("%s: %s\n", e.Value, err)
  220. break
  221. }
  222. aut.Modified = t
  223. break
  224. }
  225. t, err := time.Parse(time.RFC3339, e.Value)
  226. if err != nil {
  227. log.Printf("%s: %s\n", e.Value, err)
  228. break
  229. }
  230. aut.Modified = t
  231. }
  232. }
  233. }
  234. if org != nil {
  235. o := Organization{}
  236. for _, e := range org.Attributes.Attributes {
  237. switch e.Name {
  238. case "organisation":
  239. o.Organization = e.Value
  240. case "org-name":
  241. o.Name = e.Value
  242. case "org-type":
  243. o.Type = e.Value
  244. case "address":
  245. o.Address = append(o.Address, e.Value)
  246. case "phone":
  247. o.Phone = e.Value
  248. case "abuse-mailbox":
  249. o.AbuseEmail = e.Value
  250. case "e-mail":
  251. o.Email = e.Value
  252. }
  253. }
  254. aut.Organization = o
  255. }
  256. return aut, nil
  257. }
  258. // Lookup loads GRS data from the RIPE REST API and returns a GRS object
  259. func Lookup(ip string) (GRS, error) {
  260. // var data map[string]interface{}
  261. var data GRSRaw
  262. args := url.Values{}
  263. args.Set("query-string", ip)
  264. args.Add("source", "ripe-grs")
  265. args.Add("source", "arin-grs")
  266. args.Add("source", "apnic-grs")
  267. args.Add("source", "lacnic-grs")
  268. args.Add("source", "afrinic-grs")
  269. resp, err := napping.Get(GrsURL, &args, &data, nil)
  270. if err != nil {
  271. return GRS{}, errors.New(fmt.Sprint("Failed to load data from ", resp.Url, ": ", err))
  272. }
  273. if resp.Status() != 200 {
  274. return GRS{}, errors.New(fmt.Sprint("Failed to load data from GRS server: ", resp.Status()))
  275. }
  276. if len(data.ErrorMessages.ErrorMessage) > 0 {
  277. return GRS{}, errors.New(fmt.Sprint("No GRS data for ", ip, ": ", data.ErrorMessages.ErrorMessage[0].Text))
  278. }
  279. grs := GRS{}
  280. var grs_inetnum *Object
  281. var grs_route *Object
  282. var grs_org *Object
  283. var inetnum string
  284. ymdRegexp := regexp.MustCompile(`^\d+$`)
  285. for i, e := range data.Objects.Objects {
  286. switch e.Type {
  287. case "inetnum":
  288. grs_inetnum = &data.Objects.Objects[i]
  289. case "inet6num":
  290. grs_inetnum = &data.Objects.Objects[i]
  291. case "route":
  292. grs_route = &data.Objects.Objects[i]
  293. case "organisation":
  294. grs_org = &data.Objects.Objects[i]
  295. }
  296. }
  297. // Inetnum fields
  298. //
  299. if grs_inetnum != nil {
  300. for _, e := range grs_inetnum.Attributes.Attributes {
  301. switch e.Name {
  302. case "inetnum":
  303. inetnum = e.Value
  304. case "inet6num":
  305. inetnum = e.Value
  306. case "netname":
  307. grs.Name = e.Value
  308. case "descr":
  309. grs.Description = e.Value
  310. case "country":
  311. grs.Country = e.Value
  312. case "status":
  313. grs.Status = e.Value
  314. case "org":
  315. grs.Org = e.Value
  316. case "source":
  317. grs.Source = e.Value
  318. case "created":
  319. if ymdRegexp.MatchString(e.Value) {
  320. t, err := time.Parse("20060102", e.Value)
  321. if err != nil {
  322. log.Printf("%s: %s\n", e.Value, err)
  323. break
  324. }
  325. grs.CreatedAt = t
  326. break
  327. }
  328. t, err := time.Parse(time.RFC3339, e.Value)
  329. if err != nil {
  330. log.Printf("%s: %s\n", e.Value, err)
  331. break
  332. }
  333. grs.CreatedAt = t
  334. case "last-modified":
  335. if ymdRegexp.MatchString(e.Value) {
  336. t, err := time.Parse("20060102", e.Value)
  337. if err != nil {
  338. log.Printf("%s: %s\n", e.Value, err)
  339. break
  340. }
  341. grs.ModifiedAt = t
  342. break
  343. }
  344. t, err := time.Parse(time.RFC3339, e.Value)
  345. if err != nil {
  346. log.Printf("%s: %s\n", e.Value, err)
  347. break
  348. }
  349. grs.ModifiedAt = t
  350. }
  351. }
  352. }
  353. // Route fields
  354. //
  355. if grs_route != nil {
  356. for _, e := range grs_route.Attributes.Attributes {
  357. switch e.Name {
  358. //case "route":
  359. // grs.Cidr = e.Value
  360. case "descr":
  361. grs.Description = e.Value
  362. case "origin":
  363. grs.ASN = e.Value
  364. }
  365. }
  366. }
  367. var ipFrom net.IP
  368. var ipTo net.IP
  369. if inetnum != "" {
  370. _, network, err := net.ParseCIDR(inetnum)
  371. if err == nil {
  372. ipFrom, ipTo = networkRange(network)
  373. grs.IpFrom = ipFrom.String()
  374. grs.IpTo = ipTo.String()
  375. if grs.Cidr == "" {
  376. grs.Cidr = network.String()
  377. _, numBits := network.Mask.Size()
  378. grs.NetMaskBits = numBits
  379. }
  380. } else {
  381. reg := regexp.MustCompile(`^\s*(\d+\.\d+\.\d+\.\d+)\s*-\s*(\d+\.\d+\.\d+\.\d+)\s*$`)
  382. matches := reg.FindAllStringSubmatch(inetnum, -1)
  383. if matches != nil && matches[0] != nil && matches[0][1] != "" && matches[0][2] != "" {
  384. grs.IpFrom = matches[0][1]
  385. grs.IpTo = matches[0][2]
  386. ipFrom = net.ParseIP(grs.IpFrom)
  387. ipTo = net.ParseIP(grs.IpTo)
  388. _, masklen := cidr(ipFrom, ipTo)
  389. grs.NetMaskBits = masklen
  390. grs.Cidr = fmt.Sprintf("%s/%d", grs.IpFrom, masklen)
  391. }
  392. }
  393. grs.IpFromRaw = ipFrom.To16()
  394. grs.IpToRaw = ipTo.To16()
  395. }
  396. if grs_org != nil {
  397. org := Organization{}
  398. for _, e := range grs_org.Attributes.Attributes {
  399. switch e.Name {
  400. case "organisation":
  401. org.Organization = e.Value
  402. case "org-name":
  403. org.Name = e.Value
  404. case "org-type":
  405. org.Type = e.Value
  406. case "address":
  407. org.Address = append(org.Address, e.Value)
  408. case "e-mail":
  409. org.Email = e.Value
  410. case "abuse-mailbox":
  411. org.AbuseEmail = e.Value
  412. case "phone":
  413. org.Phone = e.Value
  414. case "fax":
  415. org.Fax = e.Value
  416. case "source":
  417. org.Source = e.Value
  418. }
  419. }
  420. grs.Organization = org
  421. }
  422. return grs, nil
  423. }
  424. // Calculates the first and last IP addresses in an IPNet
  425. func networkRange(network *net.IPNet) (net.IP, net.IP) {
  426. netIP := network.IP.To16()
  427. firstIP := netIP.Mask(network.Mask)
  428. lastIP := net.ParseIP("::").To16()
  429. for i := 0; i < len(lastIP); i++ {
  430. lastIP[i] = netIP[i] | ^network.Mask[i]
  431. }
  432. return firstIP, lastIP
  433. }
  434. func cidr(first, last net.IP) (net.IPMask, int) {
  435. // Is the address IPv4?
  436. a := first.To4()
  437. b := last.To4()
  438. if a == nil || b == nil {
  439. a = first
  440. b = last
  441. }
  442. l := len(a)
  443. m := make([]byte, l)
  444. for i := 0; i < l; i++ {
  445. msk := a[i] ^ b[i]
  446. m[i] = ^msk
  447. }
  448. ipmask := net.IPMask(m)
  449. masklen, _ := ipmask.Size()
  450. return ipmask, masklen
  451. }