diff --git a/README.md b/README.md index 9af45de..3c2ad09 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ > `dnsp` is a lightweight but powerful DNS server. Queries are blocked or > resolved based on a blacklist or a whitelist. Wildcard host patterns are > supported (e.g. `*.com`) as well as hosted, community-managed hosts files. -> Ideal for running on mobile devices or embedded systems. +> Ideal for running on mobile devices or embedded systems, given its [low +> memory footprint][1]. ### Installation @@ -137,5 +138,6 @@ Why, you ask, is a DNS proxy useful? ![dnsp](https://cloud.githubusercontent.com/assets/196617/5892473/cc29afe2-a4bf-11e4-9c6a-d1cc5169d62a.png) +[1]: https://github.com/gophergala/dnsp/pull/15#issue-55432972 [hosts-file.net]: http://hosts-file.net [AdBlock]: https://getadblock.com diff --git a/whitelist.go b/whitelist.go index 5c7b2d9..c44eb0d 100644 --- a/whitelist.go +++ b/whitelist.go @@ -1,6 +1,7 @@ package dnsp import ( + "crypto/md5" "log" "regexp" "strings" @@ -9,9 +10,11 @@ import ( "github.com/miekg/dns" ) -type hosts map[string]struct{} +type hosts map[checksum]struct{} -type hostsRX map[string]*regexp.Regexp +type hostsRX map[checksum]*regexp.Regexp + +type checksum [md5.Size / 2]byte // isAllowed returns whether we are allowed to resolve this host. // @@ -23,7 +26,7 @@ func (s *Server) isAllowed(host string) bool { s.m.RLock() defer s.m.RUnlock() - _, ok := s.hosts[host] + _, ok := s.hosts[hash(host)] if s.white { // whitelist mode if ok { @@ -75,10 +78,10 @@ func (s *Server) loadHostEntries() error { if !strings.ContainsRune(host, '*') { // Plain host string: - hosts[host] = struct{}{} + hosts[hash(host)] = struct{}{} } else if rx := compilePattern(host); rx != nil { // Host pattern (regex): - hostsRX[rx.String()] = rx + hostsRX[hash(rx.String())] = rx } }); err != nil { return err @@ -133,12 +136,12 @@ func (s *Server) addHostEntry(host string) { if !strings.ContainsRune(host, '*') { // Plain host string: s.m.Lock() - s.hosts[host] = struct{}{} + s.hosts[hash(host)] = struct{}{} s.m.Unlock() } else if rx := compilePattern(host); rx != nil { // Host pattern (regex): s.m.Lock() - s.hostsRX[rx.String()] = rx + s.hostsRX[hash(rx.String())] = rx s.m.Unlock() } } @@ -154,12 +157,12 @@ func (s *Server) removeHostEntry(host string) { if !strings.ContainsRune(host, '*') { // Plain host string: s.m.Lock() - delete(s.hosts, host) + delete(s.hosts, hash(host)) s.m.Unlock() } else if rx := compilePattern(host); rx != nil { // Host pattern (regex): s.m.Lock() - delete(s.hostsRX, rx.String()) + delete(s.hostsRX, hash(rx.String())) s.m.Unlock() } } @@ -175,3 +178,17 @@ func compilePattern(pat string) *regexp.Regexp { } return rx } + +func hash(s string) checksum { + sum := md5.Sum([]byte(s)) + return checksum{ + sum[0] ^ sum[1], + sum[2] ^ sum[3], + sum[4] ^ sum[5], + sum[6] ^ sum[7], + sum[8] ^ sum[9], + sum[10] ^ sum[11], + sum[12] ^ sum[13], + sum[14] ^ sum[15], + } +}