mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
SPF Optimizer: Enable the use of TXTMulti records to support longer SPF records (#794)
* Add multiple string support to SPF optimizer Notes: * This implements [RFC 4408][rfc] for the SPF optimizer. Allowing for more SPF records to fit within the 10 lookups by using multiple strings. * By default the max size of the TXT remains at 255. Meaning users will still only get a single 255 length string unless they modify `txtMaxSize` and opt into this feature. * The general recommendation when using multiple strings for TXT records is to keep the size within a single UDP packet. It seems like the maximum size for this depends on a bunch of factors that are sometimes outside of your control. A similar tool has a [formula for estimating the maximum allowed size][formula]. However I felt giving a user configurable size would fit with the current configuration style that dnscontrol has. Similar to how dnscontrol recommends only flattening a record if absolutely needed, I can see this length being increased by only enough to get you within 10 lookups. [rfc]: https://tools.ietf.org/html/rfc4408#section-3.1.3 [formula]: https://github.com/oasys/mkspf/blob/master/Overhead.md * Add a nice comment for the Chunks function
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
package spflib
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -94,6 +95,7 @@ var splitTests = [][]string{
|
||||
func TestSplit(t *testing.T) {
|
||||
for _, tst := range splitTests {
|
||||
overhead := 0
|
||||
txtMaxSize := 255
|
||||
|
||||
v := strings.Split(tst[0], "-")
|
||||
if len(v) > 1 {
|
||||
@ -107,17 +109,91 @@ func TestSplit(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
res := rec.TXTSplit("_spf%d.stackex.com", overhead)
|
||||
if res["@"] != tst[2] {
|
||||
t.Fatalf("Root record wrong. \nExp %s\ngot %s", tst[2], res["@"])
|
||||
res := rec.TXTSplit("_spf%d.stackex.com", overhead, txtMaxSize)
|
||||
if res["@"][0] != tst[2] {
|
||||
t.Fatalf("Root record wrong. \nExp %s\ngot %s", tst[2], res["@"][0])
|
||||
}
|
||||
for i := 3; i < len(tst); i += 2 {
|
||||
fqdn := tst[i]
|
||||
exp := tst[i+1]
|
||||
if res[fqdn] != exp {
|
||||
if res[fqdn][0] != exp {
|
||||
t.Fatalf("Record %s.\nExp %s\ngot %s", fqdn, exp, res[fqdn])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultiStringSplit(t *testing.T) {
|
||||
var tests = []struct {
|
||||
description string
|
||||
unsplitInput string
|
||||
txtMaxSize int
|
||||
want map[string][]string
|
||||
}{
|
||||
{
|
||||
description: "basic multiple strings",
|
||||
unsplitInput: "v=spf1 -all",
|
||||
txtMaxSize: 255,
|
||||
want: map[string][]string{
|
||||
"@": {
|
||||
"v=spf1 -all",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "too long to split, not enough txtMaxSize for a multi string",
|
||||
unsplitInput: "v=spf1 include:a0123456789012345678901234567890123456789012345sssss6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.com -all",
|
||||
txtMaxSize: 255,
|
||||
want: map[string][]string{
|
||||
"@": {
|
||||
"v=spf1 include:a0123456789012345678901234567890123456789012345sssss6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.com -all",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "can actually be split with multiple txt strings",
|
||||
unsplitInput: "v=spf1 include:a0123456789012345678901234567890123456789012345sssss6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.com -all",
|
||||
txtMaxSize: 450,
|
||||
want: map[string][]string{
|
||||
"@": {
|
||||
// First string
|
||||
"v=spf1 include:a0123456789012345678901234567890123456789012345sssss6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.com",
|
||||
// Second string
|
||||
" -all",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "really big with multiple txt strings",
|
||||
unsplitInput: "v=spf1 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178" +
|
||||
" ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178" +
|
||||
" ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 -all",
|
||||
txtMaxSize: 450,
|
||||
want: map[string][]string{
|
||||
"@": {
|
||||
"v=spf1 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.",
|
||||
"192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 include:_spf1.stackex.com -all",
|
||||
},
|
||||
"_spf1.stackex.com": {
|
||||
"v=spf1 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.",
|
||||
"192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 ip4:200.192.169.178 -all",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
rec, err := Parse(test.unsplitInput, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := rec.TXTSplit("_spf%d.stackex.com", 0, test.txtMaxSize)
|
||||
|
||||
if !reflect.DeepEqual(got, test.want) {
|
||||
t.Errorf("got %v want %v", got, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user