-
Notifications
You must be signed in to change notification settings - Fork 65
/
dotlistener_test.go
147 lines (122 loc) · 4.45 KB
/
dotlistener_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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package rdns
import (
"net"
"testing"
"time"
"github.com/miekg/dns"
"github.com/stretchr/testify/require"
)
func TestDoTListenerSimple(t *testing.T) {
upstream := new(TestResolver)
// Find a free port for the listener
addr, err := getLnAddress()
require.NoError(t, err)
// Create the listener
tlsServerConfig, err := TLSServerConfig("", "testdata/server.crt", "testdata/server.key", false)
require.NoError(t, err)
s := NewDoTListener("test-ln", addr, DoTListenerOptions{TLSConfig: tlsServerConfig}, upstream)
go func() {
err := s.Start()
require.NoError(t, err)
}()
defer s.Stop()
time.Sleep(time.Second)
// Make a client talking to the listener. Need to trust the issue of the server certificate.
tlsConfig, err := TLSClientConfig("testdata/ca.crt", "", "", "")
require.NoError(t, err)
c, _ := NewDoTClient("test-dot", addr, DoTClientOptions{TLSConfig: tlsConfig})
// Send a query to the client. This should be proxied through the listener and hit the test resolver.
q := new(dns.Msg)
q.SetQuestion("cloudflare.com.", dns.TypeA)
_, err = c.Resolve(q, ClientInfo{})
require.NoError(t, err)
// The upstream resolver should have seen the query
require.Equal(t, 1, upstream.HitCount())
}
func TestDoTListenerMutual(t *testing.T) {
upstream := new(TestResolver)
// Find a free port for the listener
addr, err := getLnAddress()
require.NoError(t, err)
// Create the listener, expecting client certs to be presented.
tlsServerConfig, err := TLSServerConfig("testdata/ca.crt", "testdata/server.crt", "testdata/server.key", true)
require.NoError(t, err)
s := NewDoTListener("test-ln", addr, DoTListenerOptions{TLSConfig: tlsServerConfig}, upstream)
go func() {
err := s.Start()
require.NoError(t, err)
}()
defer s.Stop()
time.Sleep(time.Second)
// Make a client talking to the listener. Need to trust the issue of the server certificate and
// present a client certificate.
tlsClientConfig, err := TLSClientConfig("testdata/ca.crt", "testdata/client.crt", "testdata/client.key", "")
require.NoError(t, err)
c, _ := NewDoTClient("test-dot", addr, DoTClientOptions{TLSConfig: tlsClientConfig})
// Send a query to the client. This should be proxied through the listener and hit the test resolver.
q := new(dns.Msg)
q.SetQuestion("cloudflare.com.", dns.TypeA)
_, err = c.Resolve(q, ClientInfo{})
require.NoError(t, err)
// The upstream resolver should have seen the query
require.Equal(t, 1, upstream.HitCount())
}
func TestDoTListenerPadding(t *testing.T) {
// Define a listener that does not respond with padding
upstream, _ := NewDNSClient("test-dns", "8.8.8.8:53", "udp", DNSClientOptions{})
// Find a free port for the listener
addr, err := getLnAddress()
require.NoError(t, err)
// Create the listener
tlsServerConfig, err := TLSServerConfig("", "testdata/server.crt", "testdata/server.key", false)
require.NoError(t, err)
s := NewDoTListener("test-ln", addr, DoTListenerOptions{TLSConfig: tlsServerConfig}, upstream)
go func() {
err := s.Start()
require.NoError(t, err)
}()
defer s.Stop()
time.Sleep(time.Second)
// Make a client talking to the listener. Need to trust the issue of the server certificate.
tlsConfig, err := TLSClientConfig("testdata/ca.crt", "", "", "")
require.NoError(t, err)
c, _ := NewDoTClient("test-dot", addr, DoTClientOptions{TLSConfig: tlsConfig})
// Send a query with the EDNS0 option set. This should cause the listener to add padding in the response.
q := new(dns.Msg)
q.SetQuestion("google.com.", dns.TypeA)
q.SetEdns0(4096, false)
a, err := c.Resolve(q, ClientInfo{})
require.NoError(t, err)
edns0 := a.IsEdns0()
require.NotNil(t, edns0, "expected EDNS0 option in response")
var foundPadding bool
for _, opt := range edns0.Option {
if opt.Option() == dns.EDNS0PADDING {
foundPadding = true
}
}
require.True(t, foundPadding, "expected padding in response")
// Send a query without the EDNS0 option. The response should not have an EDNS0 record.
q = new(dns.Msg)
q.SetQuestion("google.com.", dns.TypeA)
a, err = c.Resolve(q, ClientInfo{})
require.NoError(t, err)
edns0 = a.IsEdns0()
require.Nil(t, edns0, "unexpected EDNS0 option in response")
}
func getLnAddress() (string, error) {
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return "", nil
}
defer l.Close()
return l.Addr().String(), nil
}
func getUDPLnAddress() (string, error) {
l, err := net.ListenPacket("udp", "127.0.0.1:0")
if err != nil {
return "", err
}
defer l.Close()
return l.LocalAddr().String(), nil
}