Skip to content

Commit e0bd8ad

Browse files
committed
Merged PR #42
2 parents f02069f + 305be41 commit e0bd8ad

10 files changed

Lines changed: 99 additions & 11 deletions

File tree

internal/dns/dns.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,12 @@ func writeDomain(buffer *bytes.Buffer, domain string) error {
295295
return nil
296296
}
297297

298-
func readDomain(data []byte, buffer *bytes.Buffer) (string, error) {
298+
func readDomain(data []byte, buffer *bytes.Buffer, exitEarlyOnError bool) (string, error) {
299299
currentBuffer := buffer
300300
parts := make([]string, 0)
301301
visitedOffsets := make(map[uint16]struct{})
302302

303+
containsIllegalCharacters := false
303304
pointerJustVisited := false
304305
totalLength := 0
305306
for {
@@ -360,7 +361,11 @@ func readDomain(data []byte, buffer *bytes.Buffer) (string, error) {
360361

361362
label := string(section)
362363
if !labelRegex.MatchString(label) {
363-
return "", fmt.Errorf("illegal characters in label")
364+
containsIllegalCharacters = true
365+
366+
if exitEarlyOnError {
367+
return "", fmt.Errorf("illegal characters in label")
368+
}
364369
}
365370

366371
parts = append(parts, label)
@@ -376,6 +381,10 @@ func readDomain(data []byte, buffer *bytes.Buffer) (string, error) {
376381
name = strings.Join(parts, ".")
377382
}
378383

384+
if containsIllegalCharacters {
385+
return "", FormatError{Domain: name}
386+
}
387+
379388
return name, nil
380389
}
381390

@@ -544,7 +553,7 @@ func readClass(buffer *bytes.Buffer) (ClassType, error) {
544553
}
545554

546555
func readEDNS(data []byte, buffer *bytes.Buffer) (uint16, error) {
547-
name, err := readDomain(data, buffer)
556+
name, err := readDomain(data, buffer, true)
548557
if err != nil {
549558
return 0, err
550559
}
@@ -575,6 +584,11 @@ func readEDNS(data []byte, buffer *bytes.Buffer) (uint16, error) {
575584
return 0, err
576585
}
577586

587+
version := (extendedRCODEAndFlags >> 16) & 0xFF
588+
if version != 0 {
589+
return 0, fmt.Errorf("EDNS version must be 0")
590+
}
591+
578592
// According to RFC 6891 section 6.1.2 any option codes not understood must be ignored.
579593
// None are currently implemented.
580594
_, err = readArray16(buffer)

internal/dns/dns_https.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,11 @@ func readIPv4(data []byte) ([]net.IP, error) {
336336

337337
r := make([]net.IP, 0)
338338
for i := 0; i < count; i++ {
339+
// TODO consider alternatives to just dropping
340+
if i == maxNumberOfIPv4Hints {
341+
break
342+
}
343+
339344
index := 4 * i
340345
ip := net.IPv4(data[index+0], data[index+1], data[index+2], data[index+3])
341346

@@ -354,6 +359,11 @@ func readIPv6(data []byte) ([]net.IP, error) {
354359

355360
r := make([]net.IP, 0)
356361
for i := 0; i < count; i++ {
362+
// TODO consider alternatives to just dropping
363+
if i == maxNumberOfIPv6Hints {
364+
break
365+
}
366+
357367
index := 16 * i
358368
var ip net.IP = data[index : index+16]
359369

internal/dns/dns_proxy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func Server(conn *net.UDPConn, tcpListener *net.TCPListener, config *Config, pol
116116
go func() {
117117
for result := range resultsChannel {
118118
if result.err != nil {
119-
fmt.Printf("error: worker failed to process: %s\n", result.err.Error())
119+
fmt.Printf("error: %s\n", result.err.Error())
120120
} else {
121121
logResult(config, result)
122122
}

internal/dns/dns_request.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func UnmarshalRequest(data []byte) (*Request, error) {
7474
return nil, fmt.Errorf("unexpected non-zero RCODE %d", flags.RCODE)
7575
}
7676

77-
name, err := readDomain(data, buffer)
77+
name, err := readDomain(data, buffer, false)
7878
if err != nil {
7979
return nil, err
8080
}

internal/dns/dns_response.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ const (
1212
maxNumberOfIPv4Records = 10
1313
maxNumberOfIPv6Records = 10
1414
maxNumberOfHTTPSRecords = 10
15+
maxNumberOfIPv4Hints = 10
16+
maxNumberOfIPv6Hints = 10
17+
maxNumberOfECH = 10
1518
headerLength = 12
1619
tcpMaxPayloadSize = 65535
1720
)
@@ -247,7 +250,7 @@ func UnmarshalResponse(data []byte) (*Response, error) {
247250
// https://datatracker.ietf.org/doc/html/rfc1035#section-4.1.2
248251
questions := make([]Question, 0)
249252
for i := 0; i < int(header.NumberOfQuestions); i++ {
250-
name, err := readDomain(data, p)
253+
name, err := readDomain(data, p, true)
251254
if err != nil {
252255
return nil, err
253256
}
@@ -278,7 +281,7 @@ func UnmarshalResponse(data []byte) (*Response, error) {
278281
IPv6Count := 0
279282
HTTPSCount := 0
280283
for i := 0; i < int(header.NumberOfAnswers); i++ {
281-
name, err := readDomain(data, p)
284+
name, err := readDomain(data, p, true)
282285
if err != nil {
283286
return nil, err
284287
}
@@ -351,7 +354,7 @@ func UnmarshalResponse(data []byte) (*Response, error) {
351354
}
352355
case RecordTypeCNAME:
353356
pb := bytes.NewBuffer(rawData)
354-
domain, err := readDomain(data, pb)
357+
domain, err := readDomain(data, pb, true)
355358
if err != nil {
356359
return nil, err
357360
}

internal/dns/dns_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func TestName(t *testing.T) {
115115
t.Fatal(err)
116116
}
117117

118-
domain, err := readDomain(buffer.Bytes(), buffer)
118+
domain, err := readDomain(buffer.Bytes(), buffer, true)
119119
if err != nil {
120120
t.Fatal(err)
121121
}
@@ -142,7 +142,7 @@ func TestTooLongName(t *testing.T) {
142142
t.Fatal(err)
143143
}
144144

145-
_, err = readDomain(buffer.Bytes(), buffer)
145+
_, err = readDomain(buffer.Bytes(), buffer, true)
146146
if err == nil {
147147
t.Fatal("expected error, got none")
148148
}
@@ -169,7 +169,7 @@ func TestAlmostTooLongName(t *testing.T) {
169169
t.Fatal(err)
170170
}
171171

172-
_, err = readDomain(buffer.Bytes(), buffer)
172+
_, err = readDomain(buffer.Bytes(), buffer, true)
173173
if err != nil {
174174
t.Fatal(err)
175175
}

internal/dns/ech.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ func UnmarshalECHConfig(data []byte) ([]ECHConfig, error) {
6969
}
7070
result = append(result, *echConfig)
7171

72+
// TODO consider alternatives to dropping the rest
73+
if len(result) == maxNumberOfECH {
74+
break
75+
}
76+
7277
if buffer.Len() == 0 {
7378
break
7479
}

internal/dns/filter.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const (
2525
)
2626

2727
var labelRegex = regexp.MustCompile("^[a-z0-9]([a-z0-9-]*[a-z0-9])?$")
28+
var standardRegex = regexp.MustCompile("^[a-zA-Z0-9-_.]$")
2829

2930
type Policy struct {
3031
exactSearchAllow *suffixtrie.Node

internal/dns/logging.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,31 @@
11
package dns
22

3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
38
type LogEvent string
49
type FilterReason string
10+
11+
type FormatError struct {
12+
Domain string
13+
}
14+
15+
func (e FormatError) Error() string {
16+
return fmt.Sprintf("%s: %s", ResponseCodeFormatError.Name(), escapeNonStandard(e.Domain))
17+
}
18+
19+
func escapeNonStandard(domain string) string {
20+
sb := strings.Builder{}
21+
22+
for i := range domain {
23+
if standardRegex.Match([]byte{domain[i]}) {
24+
sb.WriteByte(domain[i])
25+
} else {
26+
sb.WriteString(fmt.Sprintf("\\%.3d", domain[i]))
27+
}
28+
}
29+
30+
return sb.String()
31+
}

internal/dns/logging_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package dns
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestEscapeNonStandard(t *testing.T) {
8+
t1 := "-_a.b.YZ.10"
9+
r1 := escapeNonStandard(t1)
10+
expected := "-_a.b.YZ.10"
11+
if r1 != expected {
12+
t.Errorf("expected %s, got %s", expected, r1)
13+
}
14+
15+
t2 := "a\nb"
16+
r2 := escapeNonStandard(t2)
17+
expected = "a\\010b"
18+
if r2 != expected {
19+
t.Errorf("expected %s, got %s", expected, r2)
20+
}
21+
22+
t3 := "\n#$"
23+
r3 := escapeNonStandard(t3)
24+
expected = "\\010\\035\\036"
25+
if r3 != expected {
26+
t.Errorf("expected %s, got %s", expected, r3)
27+
}
28+
}

0 commit comments

Comments
 (0)