-
Notifications
You must be signed in to change notification settings - Fork 0
/
dnsgrab_test.go
133 lines (109 loc) · 4.01 KB
/
dnsgrab_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package dnsgrab
import (
"io/ioutil"
"net"
"os"
"path/filepath"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/getlantern/dns"
"github.com/getlantern/dnsgrab/internal"
"github.com/getlantern/dnsgrab/persistentcache"
)
const (
maxAge = 2 * time.Second
)
func TestInMemory(t *testing.T) {
doTest(t, NewInMemoryCache(2), internal.MinIP)
}
func TestPersistent(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "dnsgrab")
require.NoError(t, err)
defer os.RemoveAll(tmpDir)
filename := filepath.Join(tmpDir, "dnsgrab.db")
cache, err := persistentcache.New(filename, maxAge)
require.NoError(t, err)
doTest(t, cache, internal.MinIP)
cache.Close()
// Reopen cache and test again to make sure that initialization of already saved DB is handled correctly
time.Sleep(maxAge)
reopenedCache, err := persistentcache.New(filename, maxAge)
require.NoError(t, err)
doTest(t, reopenedCache, internal.IPStringToInt("240.0.0.5"))
cache.Close()
}
func doTest(t *testing.T, cache Cache, startingIP uint32) {
s, err := ListenWithCache(":0", func() string { return "8.8.8.8" }, cache)
require.NoError(t, err)
defer s.Close()
go s.Serve()
addr := s.LocalAddr().String()
test := func(name string, expectedIPInt uint32, condition string) {
expectedIP := internal.IntToIP(expectedIPInt).String()
q := &dns.Msg{}
q.SetQuestion(name+".", dns.TypeA)
a, err := dns.Exchange(q, addr)
require.NoError(t, err)
fakeIP := a.Answer[0].(*dns.A).A
require.Equal(t, expectedIP, fakeIP.String(), "Wrong IP from query for '%v'", condition)
q = makeSRPQuery(fakeIP.String())
parts := strings.Split(fakeIP.String(), ".")
parts[0], parts[1], parts[2], parts[3] = parts[3], parts[2], parts[1], parts[0]
ipQuery := strings.Join(parts, ".") + ".in-addr.arpa."
q.SetQuestion(ipQuery, dns.TypePTR)
a, err = dns.Exchange(q, addr)
require.NoError(t, err)
require.Len(t, a.Answer, 1)
require.Equal(t, name+".", a.Answer[0].(*dns.PTR).Ptr, "Wrong name from reverse lookup for '%v'", condition)
reversed, ok := s.ReverseLookup(fakeIP)
require.True(t, ok, "Reverse lookup failed for '%v'", condition)
require.Equal(t, name, reversed, "Wrong reverse lookup for '%v'", condition)
}
testError := func(name string) {
q := &dns.Msg{}
q.SetQuestion(name+".", dns.TypeA)
_, err := dns.Exchange(q, addr)
require.Error(t, err)
}
testUnknown := func(name string, succeed bool, ip string, condition string) {
reversed, ok := s.ReverseLookup(net.ParseIP(ip))
require.Equal(t, succeed, ok, "Unexpected reverse lookup status for '%v'", condition)
require.Equal(t, name, reversed, "Wrong reverse lookup for '%v'", condition)
}
test("domain1", startingIP, "first query, new IP")
test("domain2", startingIP+1, "second query, new IP")
test("domain1", startingIP, "repeated query, same IP")
test("domain3", startingIP+2, "third query, new IP")
time.Sleep(maxAge)
test("domain2", startingIP+3, "repeated expired query, new IP")
testError("")
testUnknown("172.155.98.32", true, "172.155.98.32", "regular IP address")
testUnknown("", false, "240.0.10.10", "unknown fake IP address")
// Also test that SRP lookups for unknown IPs get passed through
host := "dfw28s05-in-f4.1e100.net"
ip, err := net.ResolveIPAddr("ip4", host)
require.NoError(t, err)
q := makeSRPQuery(ip.String())
a, err := dns.Exchange(q, addr)
require.NoError(t, err)
require.NotEmpty(t, a.Answer)
require.True(t, strings.HasSuffix(a.Answer[0].(*dns.PTR).Ptr, "1e100.net."), "Wrong name from reverse lookup of %v", host)
// And test that SVCB and HTTPS lookups are ignored
for _, queryType := range []uint16{dns.TypeSVCB, dns.TypeHTTPS} {
q = &dns.Msg{}
q.SetQuestion(host+".", queryType)
a, err = dns.Exchange(q, addr)
require.Error(t, err)
require.Nil(t, a)
}
}
func makeSRPQuery(ip string) *dns.Msg {
q := &dns.Msg{}
parts := strings.Split(ip, ".")
parts[0], parts[1], parts[2], parts[3] = parts[3], parts[2], parts[1], parts[0]
ipQuery := strings.Join(parts, ".") + ".in-addr.arpa."
q.SetQuestion(ipQuery, dns.TypePTR)
return q
}