diff --git a/ex/fks-shield/cache.go b/ex/fks-shield/cache.go index c6d313bd..d7829bd0 100644 --- a/ex/fks-shield/cache.go +++ b/ex/fks-shield/cache.go @@ -4,11 +4,13 @@ import ( "dns" "fmt" "log" - "radix" + "github.com/miekg/radix" "strings" "time" ) +const TTL time.Duration = 30 * 1e9 // 30 seconds + // Cache elements, we using to key (toRadixKey) to distinguish between dns and dnssec type Packet struct { ttl time.Time // insertion time @@ -43,11 +45,28 @@ func NewCache() *Cache { return &Cache{Radix: radix.New()} } +func (c *Cache) Evict() { + // A bit tedious, keys() -> find() -> remove() + for _, key := range c.Radix.Keys() { + log.Printf("look for key %s\n", key) + node := c.Radix.Find(key) + if node == nil { + continue + } + if time.Since(node.Value.(*Packet).ttl) > TTL { + c.Radix.Remove(key) + if *flaglog { + log.Printf("fsk-shield: evicting %s\n", key) + } + } + } +} + func (c *Cache) Find(d *dns.Msg) []byte { p := c.Radix.Find(toRadixKey(d)) if p == nil { - if *verbose { - log.Printf("Cache miss for " + toRadixKey(d)) + if *flaglog { + log.Printf("fsk-shield: cache miss for " + toRadixKey(d)) } return nil } @@ -55,10 +74,10 @@ func (c *Cache) Find(d *dns.Msg) []byte { } func (c *Cache) Insert(d *dns.Msg) { - if *verbose { - log.Printf("Inserting " + toRadixKey(d)) + if *flaglog { + log.Printf("fsk-shield: inserting " + toRadixKey(d)) } - buf, _ := d.Pack() // Should always work + buf, _ := d.Pack() // Should always work c.Radix.Insert(toRadixKey(d), &Packet{d: buf, ttl: time.Now().UTC()}) } diff --git a/ex/fks-shield/shield.go b/ex/fks-shield/shield.go index f931c6be..0366535a 100644 --- a/ex/fks-shield/shield.go +++ b/ex/fks-shield/shield.go @@ -1,22 +1,19 @@ -/* - * Funkensturm, a versatile DNS proxy - * Miek Gieben (c) 2011 - * GPLv2 - */ - package main +// TODO: locking + import ( "dns" "flag" "log" "os" + "time" ) var ( listen = flag.String("listen", "127.0.0.1:8053", "set the listener address") - server = flag.String("server", "127.0.0.1:53", "remote server address(es), seperate with commas") - verbose = flag.Bool("verbose", false, "be more verbose") + server = flag.String("server", "127.0.0.1:53", "remote server address") + flaglog = flag.Bool("log", false, "be more verbose") ) func serve(w dns.ResponseWriter, r *dns.Msg, c *Cache) { @@ -29,7 +26,7 @@ func serve(w dns.ResponseWriter, r *dns.Msg, c *Cache) { // Cache miss client := new(dns.Client) if p, e := client.Exchange(r, *server); e == nil { - if *verbose { + if *flaglog { log.Printf("fks-shield: cache miss") } // TODO(mg): If r has edns0 and p has not we create a mismatch here @@ -38,7 +35,9 @@ func serve(w dns.ResponseWriter, r *dns.Msg, c *Cache) { return } else { log.Printf("fks-shield: failed to get answer " + e.Error()) - // w.Write(SERFVAIL) + m := new(dns.Msg) + m.SetRcode(r, dns.RcodeServerFailure) + w.Write(m) } } @@ -54,9 +53,16 @@ func main() { // Only listen on UDP go func() { if err := dns.ListenAndServe(*listen, "udp", nil); err != nil { - log.Fatal("fks-shield: failed to setup %s %s", net, add) + log.Fatal("fks-shield: failed to setup %s %s", *listen, "udp") } - } + }() + go func() { + for { + // Every 10 sec run the cache cleaner + time.Sleep(10 * 1e9) + cache.Evict() + } + }() sig := make(chan os.Signal) forever: