소스 검색

add resolver asn and ip targeting

Ewan Chou 11 년 전
부모
커밋
3c3cb3edcf
6개의 변경된 파일91개의 추가작업 그리고 23개의 파일을 삭제
  1. 3 1
      dns/test.example.com.json
  2. 38 1
      geoip.go
  3. 40 18
      targeting.go
  4. 6 2
      targeting_test.go
  5. 3 0
      zones.go
  6. 1 1
      zones_test.go

+ 3 - 1
dns/test.example.com.json

@@ -5,7 +5,7 @@
     "stathat": true,
     "stathat": true,
     "stathat_api": "abc-test"
     "stathat_api": "abc-test"
   },
   },
-  "targeting": "country continent @ regiongroup region",
+  "targeting": "country continent @ regiongroup region ip asn",
   "contact": "support.bitnames.com",
   "contact": "support.bitnames.com",
   "data" : {
   "data" : {
     "":  {
     "":  {
@@ -33,6 +33,8 @@
       "ttl": "601"
       "ttl": "601"
     },
     },
     "bar.no": { "a": [] },
     "bar.no": { "a": [] },
+    "bar.as15169": { "a": [ ["192.168.1.4" ] ] },
+    "bar.1.0.0.255": { "a": [ ["192.168.1.3" ] ] },
     "0": {
     "0": {
       "a": [ [ "192.168.0.1", 10 ] ]
       "a": [ [ "192.168.0.1", 10 ] ]
     },
     },

+ 38 - 1
geoip.go

@@ -17,6 +17,10 @@ type GeoIP struct {
 	city         *geoip.GeoIP
 	city         *geoip.GeoIP
 	cityLastLoad time.Time
 	cityLastLoad time.Time
 	hasCity      bool
 	hasCity      bool
+
+	asn          *geoip.GeoIP
+	hasAsn       bool
+	asnLastLoad  time.Time
 }
 }
 
 
 var geoIP = new(GeoIP)
 var geoIP = new(GeoIP)
@@ -61,6 +65,21 @@ func (g *GeoIP) GetCountryRegion(ip net.IP) (country, continent, regionGroup, re
 	return
 	return
 }
 }
 
 
+func (g *GeoIP) GetASN (ip net.IP) (asn string, netmask int) {
+	if g.asn == nil {
+		log.Println("No asn database available")
+		return
+	}
+	name, netmask := g.asn.GetName(ip.String())
+	if len(name) > 0 {
+		index := strings.Index(name, " ")
+		if index > 0 {
+			asn = strings.ToLower(name[:index])
+		}
+	}
+	return
+}
+
 func (g *GeoIP) setDirectory() {
 func (g *GeoIP) setDirectory() {
 	if len(Config.GeoIP.Directory) > 0 {
 	if len(Config.GeoIP.Directory) > 0 {
 		geoip.SetCustomDirectory(Config.GeoIP.Directory)
 		geoip.SetCustomDirectory(Config.GeoIP.Directory)
@@ -97,8 +116,26 @@ func (g *GeoIP) setupGeoIPCity() {
 		log.Printf("Could not open city GeoIP database: %s\n", err)
 		log.Printf("Could not open city GeoIP database: %s\n", err)
 		return
 		return
 	}
 	}
-	g.countryLastLoad = time.Now()
+	g.cityLastLoad = time.Now()
 	g.hasCity = true
 	g.hasCity = true
 	g.city = gi
 	g.city = gi
 
 
 }
 }
+
+func (g *GeoIP) setupGeoIPASN() {
+	if g.asn != nil {
+		return
+	}
+
+	g.setDirectory()
+
+	gi, err := geoip.OpenType(geoip.GEOIP_ASNUM_EDITION)
+	if gi == nil || err != nil {
+		log.Printf("Could not open ASN GeoIP database: %s\n", err)
+		return
+	}
+	g.asnLastLoad = time.Now()
+	g.hasAsn = true
+	g.asn = gi
+
+}

+ 40 - 18
targeting.go

@@ -14,37 +14,49 @@ const (
 	TargetCountry
 	TargetCountry
 	TargetRegionGroup
 	TargetRegionGroup
 	TargetRegion
 	TargetRegion
+	TargetASN
+	TargetIP
 )
 )
 
 
 func (t TargetOptions) GetTargets(ip net.IP) ([]string, int) {
 func (t TargetOptions) GetTargets(ip net.IP) ([]string, int) {
 
 
 	targets := make([]string, 0)
 	targets := make([]string, 0)
 
 
-	var country, continent string
+	var country, continent, region, regionGroup, asn string
 	var netmask int
 	var netmask int
 
 
-	switch {
-	case t >= TargetRegionGroup:
-		var region, regionGroup string
+	if t&TargetASN > 0 {
+		asn, netmask = geoIP.GetASN(ip)
+	}
+
+	if t&TargetRegion > 0 || t&TargetRegionGroup > 0 {
 		country, continent, regionGroup, region, netmask = geoIP.GetCountryRegion(ip)
 		country, continent, regionGroup, region, netmask = geoIP.GetCountryRegion(ip)
-		if t&TargetRegion > 0 && len(region) > 0 {
-			targets = append(targets, region)
-		}
-		if t&TargetRegionGroup > 0 && len(regionGroup) > 0 {
-			targets = append(targets, regionGroup)
-		}
 
 
-	case t >= TargetContinent:
+	}else if t&TargetCountry > 0 || t&TargetContinent > 0 {
 		country, continent, netmask = geoIP.GetCountry(ip)
 		country, continent, netmask = geoIP.GetCountry(ip)
 	}
 	}
 
 
-	if len(country) > 0 {
-		if t&TargetCountry > 0 {
-			targets = append(targets, country)
-		}
-		if t&TargetContinent > 0 && len(continent) > 0 {
-			targets = append(targets, continent)
-		}
+	if t&TargetIP > 0 {
+		targets = append(targets, ip.String())
+	}
+
+	if t&TargetASN > 0 && len(asn) > 0 {
+		targets = append(targets, asn)
+	}
+
+	if t&TargetRegion > 0 && len(region) > 0 {
+		targets = append(targets, region)
+	}
+	if t&TargetRegionGroup > 0 && len(regionGroup) > 0 {
+		targets = append(targets, regionGroup)
+	}
+
+	if t&TargetCountry > 0 && len(country) > 0 {
+		targets = append(targets, country)
+	}
+
+	if t&TargetContinent > 0 && len(continent) > 0 {
+		targets = append(targets, continent)
 	}
 	}
 
 
 	if t&TargetGlobal > 0 {
 	if t&TargetGlobal > 0 {
@@ -70,6 +82,12 @@ func (t TargetOptions) String() string {
 	if t&TargetRegion > 0 {
 	if t&TargetRegion > 0 {
 		targets = append(targets, "region")
 		targets = append(targets, "region")
 	}
 	}
+	if t&TargetASN > 0 {
+		targets = append(targets, "asn")
+	}
+	if t&TargetIP > 0 {
+		targets = append(targets, "ip")
+	}
 	return strings.Join(targets, " ")
 	return strings.Join(targets, " ")
 }
 }
 
 
@@ -88,6 +106,10 @@ func parseTargets(v string) (tgt TargetOptions, err error) {
 			x = TargetRegionGroup
 			x = TargetRegionGroup
 		case "region":
 		case "region":
 			x = TargetRegion
 			x = TargetRegion
+		case "asn":
+			x = TargetASN
+		case "ip":
+			x = TargetIP
 		default:
 		default:
 			err = fmt.Errorf("Unknown targeting option '%s'", t)
 			err = fmt.Errorf("Unknown targeting option '%s'", t)
 		}
 		}

+ 6 - 2
targeting_test.go

@@ -29,10 +29,10 @@ func (s *TargetingSuite) TestTargetParse(c *C) {
 	c.Check(str, Equals, "@ country")
 	c.Check(str, Equals, "@ country")
 	c.Check(err.Error(), Equals, "Unknown targeting option 'foo'")
 	c.Check(err.Error(), Equals, "Unknown targeting option 'foo'")
 
 
-	tgt, err = parseTargets("@ continent country")
+	tgt, err = parseTargets("@ continent country asn")
 	c.Assert(err, IsNil)
 	c.Assert(err, IsNil)
 	str = tgt.String()
 	str = tgt.String()
-	c.Check(str, Equals, "@ continent country")
+	c.Check(str, Equals, "@ continent country asn")
 }
 }
 func (s *TargetingSuite) TestGetTargets(c *C) {
 func (s *TargetingSuite) TestGetTargets(c *C) {
 
 
@@ -40,6 +40,7 @@ func (s *TargetingSuite) TestGetTargets(c *C) {
 
 
 	geoIP.setupGeoIPCity()
 	geoIP.setupGeoIPCity()
 	geoIP.setupGeoIPCountry()
 	geoIP.setupGeoIPCountry()
+	geoIP.setupGeoIPASN()
 
 
 	tgt, _ := parseTargets("@ continent country")
 	tgt, _ := parseTargets("@ continent country")
 	targets, _ := tgt.GetTargets(ip)
 	targets, _ := tgt.GetTargets(ip)
@@ -58,4 +59,7 @@ func (s *TargetingSuite) TestGetTargets(c *C) {
 	targets, _ = tgt.GetTargets(ip)
 	targets, _ = tgt.GetTargets(ip)
 	c.Check(targets, DeepEquals, []string{"us-ca", "us-west", "us", "north-america", "@"})
 	c.Check(targets, DeepEquals, []string{"us-ca", "us-west", "us", "north-america", "@"})
 
 
+	tgt, _ = parseTargets("@ continent regiongroup country region asn ip")
+	targets, _ = tgt.GetTargets(ip)
+	c.Check(targets, DeepEquals, []string{"207.171.7.51", "as53582", "us-ca", "us-west", "us", "north-america", "@"})
 }
 }

+ 3 - 0
zones.go

@@ -210,6 +210,9 @@ func readZoneFile(zoneName, fileName string) (zone *Zone, zerr error) {
 	case zone.Options.Targeting >= TargetContinent:
 	case zone.Options.Targeting >= TargetContinent:
 		geoIP.setupGeoIPCountry()
 		geoIP.setupGeoIPCountry()
 	}
 	}
+	if zone.Options.Targeting&TargetASN > 0 {
+		geoIP.setupGeoIPASN()
+	}
 
 
 	return zone, nil
 	return zone, nil
 }
 }

+ 1 - 1
zones_test.go

@@ -41,7 +41,7 @@ func (s *ConfigSuite) TestReadConfigs(c *C) {
 
 
 	c.Check(tz.Options.MaxHosts, Equals, 2)
 	c.Check(tz.Options.MaxHosts, Equals, 2)
 	c.Check(tz.Options.Contact, Equals, "support.bitnames.com")
 	c.Check(tz.Options.Contact, Equals, "support.bitnames.com")
-	c.Check(tz.Options.Targeting.String(), Equals, "@ continent country regiongroup region")
+	c.Check(tz.Options.Targeting.String(), Equals, "@ continent country regiongroup region asn ip")
 
 
 	// Got logging option
 	// Got logging option
 	c.Check(tz.Logging.StatHat, Equals, true)
 	c.Check(tz.Logging.StatHat, Equals, true)