Skip to content

Instantly share code, notes, and snippets.

@chantra
Last active February 3, 2021 00:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chantra/d7b49d5b38b07c20d9fc7772b624e794 to your computer and use it in GitHub Desktop.
Save chantra/d7b49d5b38b07c20d9fc7772b624e794 to your computer and use it in GitHub Desktop.
package main
import (
"context"
"flag"
"fmt"
"log"
"math/rand"
"net"
"os"
"os/signal"
"syscall"
"time"
"github.com/miekg/dns"
)
var rfc1918_10 = net.IPNet{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)}
var rfc1918_192 = net.IPNet{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)}
var rfc1918_172 = net.IPNet{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)}
// RFC1918 returns True when an IP is within RFC1918 range.
func RFC1918(ip net.IP) bool {
return rfc1918_10.Contains(ip) ||
rfc1918_192.Contains(ip) ||
rfc1918_172.Contains(ip)
}
// ReproConfig config for the repro
type ReproConfig struct {
workers int
port int
addr string
}
var privateRand *rand.Rand
func init() {
privateRand = rand.New(rand.NewSource(time.Now().UnixNano()))
}
// IPV4Address returns a valid IPv4 address as string
func IPV4Address() net.IP {
var ip = net.IPv4(uint8(privateRand.Intn(255)), uint8(privateRand.Intn(255)), uint8(privateRand.Intn(255)), uint8(privateRand.Intn(255)))
return ip
}
// IPV6Address returns a valid IPv6 address as net.IP
func IPV6Address() net.IP {
var ip net.IP
for i := 0; i < net.IPv6len; i++ {
number := uint8(privateRand.Intn(255))
ip = append(ip, number)
}
return ip
}
func worker(ctx context.Context, config ReproConfig, jobs <-chan net.IP) {
server := fmt.Sprintf("%s:%d", config.addr, config.port)
api := dns.Fqdn("bar.example.com.")
latest := dns.Fqdn("intcode.example.com.")
for {
select {
case <-ctx.Done():
return
case ip := <-jobs:
m := new(dns.Msg)
m.SetQuestion("foo.example.com.", dns.TypeA)
o := new(dns.OPT)
o.Hdr.Name = "."
o.Hdr.Rrtype = dns.TypeOPT
o.SetUDPSize(2048)
e := new(dns.EDNS0_SUBNET)
e.Code = dns.EDNS0SUBNET
e.Family = 1
e.Address = ip.To4()
e.SourceNetmask = uint8(32)
o.Option = append(o.Option, e)
m.Extra = append([]dns.RR{o}, m.Extra...)
c := new(dns.Client)
c.Net = "udp"
//log.Printf("Sending %s", m)
r, _, err := c.Exchange(m, server)
//log.Printf("Received %s: %s", r, err)
if err == nil && r != nil && r.Response {
for _, a := range r.Answer {
if record, ok := a.(*dns.CNAME); ok {
if record.Hdr.Name == api {
if RFC1918(ip) { //record.Target == latest && !RFC1918(ip) {
if record.Target == latest {
log.Printf("OK")
} else {
log.Printf("%d NOK", int32(time.Now().Unix()))
}
}
}
}
}
}
}
}
}
func main() {
var config ReproConfig
flag.IntVar(&config.workers, "workers", 4096, "Number of workers")
flag.StringVar(&config.addr, "addr", "[::1]", "Address of DNS server")
flag.IntVar(&config.port, "port", 53, "Port of DNS server")
flag.Parse()
ctx, cancel := context.WithCancel(context.Background())
jobs := make(chan net.IP, 100)
for w := 0; w < config.workers; w++ {
go worker(ctx, config, jobs)
}
go func() {
for {
jobs <- IPV4Address()
}
}()
//close(jobs)
sig := make(chan os.Signal)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig
cancel()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment