forked from coredns/coredns
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add bufsize plugin for preparing the DNS Flag Day and avoiding IP fra…
…gmentation (coredns#3401) * add bufsize plugin Signed-off-by: ykhr53 <yukihira.lab@gmail.com> * add docstring and comment Signed-off-by: ykhr53 <yukihira.lab@gmail.com> * delete stdout messages when get an error Signed-off-by: ykhr53 <yukihira.lab@gmail.com> * change to context.Background from TODO Signed-off-by: ykhr53 <yukihira.lab@gmail.com> * define default bufsize as defaultBufSize constant Signed-off-by: ykhr53 <yukihira.lab@gmail.com> * fix some comments Signed-off-by: ykhr53 <yukihira.lab@gmail.com> * function name change: parse Signed-off-by: ykhr53 <yukihira.lab@gmail.com> * function name change: parse Signed-off-by: ykhr53 <yukihira.lab@gmail.com>
- Loading branch information
Showing
8 changed files
with
234 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ var Directives = []string{ | |
"tls", | ||
"reload", | ||
"nsid", | ||
"bufsize", | ||
"root", | ||
"bind", | ||
"debug", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ cancel:cancel | |
tls:tls | ||
reload:reload | ||
nsid:nsid | ||
bufsize:bufsize | ||
root:root | ||
bind:bind | ||
debug:debug | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# bufsize | ||
## Name | ||
*bufsize* - sizes EDNS0 buffer size to prevent IP fragmentation. | ||
|
||
## Description | ||
*bufsize* limits a requester's UDP payload size. | ||
It prevents IP fragmentation so that to deal with DNS vulnerability. | ||
|
||
## Syntax | ||
```txt | ||
bufsize [SIZE] | ||
``` | ||
|
||
**[SIZE]** is an int value for setting the buffer size. | ||
The default value is 512, and the value must be within 512 - 4096. | ||
Only one argument is acceptable, and it covers both IPv4 and IPv6. | ||
|
||
## Examples | ||
```corefile | ||
. { | ||
bufsize 512 | ||
forward . 172.31.0.10 | ||
log | ||
} | ||
``` | ||
|
||
If you run a resolver on 172.31.0.10, the buffer size of incoming query on the resolver will be set to 512 bytes. | ||
|
||
## Considerations | ||
For now, if a client does not use EDNS, this plugin adds OPT RR. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Package bufsize implements a plugin that modifies EDNS0 buffer size. | ||
package bufsize | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/coredns/coredns/plugin" | ||
|
||
"github.com/miekg/dns" | ||
) | ||
|
||
// Bufsize implements bufsize plugin. | ||
type Bufsize struct { | ||
Next plugin.Handler | ||
Size int | ||
} | ||
|
||
// ServeDNS implements the plugin.Handler interface. | ||
func (buf Bufsize) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { | ||
if option := r.IsEdns0(); option != nil { | ||
option.SetUDPSize(uint16(buf.Size)) | ||
} else { | ||
// If a client does not use EDNS, add it | ||
r.SetEdns0(uint16(buf.Size), false) | ||
} | ||
|
||
return plugin.NextOrFailure(buf.Name(), buf.Next, ctx, w, r) | ||
} | ||
|
||
// Name implements the Handler interface. | ||
func (buf Bufsize) Name() string { return "bufsize" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package bufsize | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/coredns/coredns/plugin" | ||
"github.com/coredns/coredns/plugin/test" | ||
"github.com/coredns/coredns/plugin/whoami" | ||
|
||
"github.com/miekg/dns" | ||
) | ||
|
||
func TestBufsize(t *testing.T) { | ||
em := Bufsize{ | ||
Size: 512, | ||
} | ||
|
||
tests := []struct { | ||
next plugin.Handler | ||
qname string | ||
inputBufsize uint16 | ||
outgoingBufsize uint16 | ||
expectedErr error | ||
}{ | ||
// This plugin is responsible for limiting outgoing query's bufize | ||
{ | ||
next: whoami.Whoami{}, | ||
qname: ".", | ||
inputBufsize: 1200, | ||
outgoingBufsize: 512, | ||
expectedErr: nil, | ||
}, | ||
// If EDNS is not enabled, this plugin adds it | ||
{ | ||
next: whoami.Whoami{}, | ||
qname: ".", | ||
outgoingBufsize: 512, | ||
expectedErr: nil, | ||
}, | ||
} | ||
|
||
for i, tc := range tests { | ||
req := new(dns.Msg) | ||
req.SetQuestion(dns.Fqdn(tc.qname), dns.TypeA) | ||
req.Question[0].Qclass = dns.ClassINET | ||
em.Next = tc.next | ||
|
||
if tc.inputBufsize != 0 { | ||
req.SetEdns0(tc.inputBufsize, false) | ||
} | ||
|
||
_, err := em.ServeDNS(context.Background(), &test.ResponseWriter{}, req) | ||
|
||
if err != tc.expectedErr { | ||
t.Errorf("Test %d: Expected error is %v, but got %v", i, tc.expectedErr, err) | ||
} | ||
|
||
if tc.outgoingBufsize != 0 { | ||
for _, extra := range req.Extra { | ||
if option, ok := extra.(*dns.OPT); ok { | ||
b := option.UDPSize() | ||
if b != tc.outgoingBufsize { | ||
t.Errorf("Test %d: Expected outgoing bufsize is %d, but got %d", i, tc.outgoingBufsize, b) | ||
} | ||
} else { | ||
t.Errorf("Test %d: Not found OPT RR.", i) | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package bufsize | ||
|
||
import ( | ||
"strconv" | ||
|
||
"github.com/coredns/coredns/core/dnsserver" | ||
"github.com/coredns/coredns/plugin" | ||
|
||
"github.com/caddyserver/caddy" | ||
) | ||
|
||
func init() { plugin.Register("bufsize", setup) } | ||
|
||
func setup(c *caddy.Controller) error { | ||
bufsize, err := parse(c) | ||
if err != nil { | ||
return plugin.Error("bufsize", err) | ||
} | ||
|
||
dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { | ||
return Bufsize{Next: next, Size: bufsize} | ||
}) | ||
|
||
return nil | ||
} | ||
|
||
func parse(c *caddy.Controller) (int, error) { | ||
const defaultBufSize = 512 | ||
for c.Next() { | ||
args := c.RemainingArgs() | ||
switch len(args) { | ||
case 0: | ||
// Nothing specified; use 512 as default | ||
return defaultBufSize, nil | ||
case 1: | ||
// Specified value is needed to verify | ||
bufsize, err := strconv.Atoi(args[0]) | ||
if err != nil { | ||
return -1, plugin.Error("bufsize", c.ArgErr()) | ||
} | ||
// Follows RFC 6891 | ||
if bufsize < 512 || bufsize > 4096 { | ||
return -1, plugin.Error("bufsize", c.ArgErr()) | ||
} | ||
return bufsize, nil | ||
default: | ||
// Only 1 argument is acceptable | ||
return -1, plugin.Error("bufsize", c.ArgErr()) | ||
} | ||
} | ||
return -1, plugin.Error("bufsize", c.ArgErr()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package bufsize | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
|
||
"github.com/caddyserver/caddy" | ||
) | ||
|
||
func TestSetupBufsize(t *testing.T) { | ||
tests := []struct { | ||
input string | ||
shouldErr bool | ||
expectedData int | ||
expectedErrContent string // substring from the expected error. Empty for positive cases. | ||
}{ | ||
{`bufsize`, false, 512, ""}, | ||
{`bufsize "1232"`, false, 1232, ""}, | ||
{`bufsize "5000"`, true, -1, "plugin"}, | ||
{`bufsize "512 512"`, true, -1, "plugin"}, | ||
{`bufsize "abc123"`, true, -1, "plugin"}, | ||
} | ||
|
||
for i, test := range tests { | ||
c := caddy.NewTestController("dns", test.input) | ||
bufsize, err := parse(c) | ||
|
||
if test.shouldErr && err == nil { | ||
t.Errorf("Test %d: Expected error but found %s for input %s", i, err, test.input) | ||
} | ||
|
||
if err != nil { | ||
if !test.shouldErr { | ||
t.Errorf("Test %d: Error found for input %s. Error: %v", i, test.input, err) | ||
} | ||
|
||
if !strings.Contains(err.Error(), test.expectedErrContent) { | ||
t.Errorf("Test %d: Expected error to contain: %v, found error: %v, input: %s", i, test.expectedErrContent, err, test.input) | ||
} | ||
} | ||
|
||
if !test.shouldErr && bufsize != test.expectedData { | ||
t.Errorf("Test %d: Bufsize not correctly set for input %s. Expected: %d, actual: %d", i, test.input, test.expectedData, bufsize) | ||
} | ||
} | ||
} |