1
0
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:
Michael Russell
2020-07-31 19:28:13 +02:00
committed by GitHub
parent 237c573c2a
commit f21c8fc400
6 changed files with 245 additions and 119 deletions

View File

@ -105,9 +105,13 @@ The parameters are:
* `overhead1:` "Overhead for the 1st TXT record". When calculating the max length of each TXT record, reduce the maximum for the first TXT record in the chain by this amount.
* `raw:` The label of the unaltered SPF settings. Setting to an empty string `''` will disable this. (Optional. Default: `"_rawspf"`)
* `ttl:` This allows setting a specific TTL on this SPF record. (Optional. Default: using default record TTL)
* `txtMaxSize` The maximum size for each TXT record. Values over 255 will result in [multiple strings][multi-string]. General recommendation is to [not go higher than 450][record-size] so that DNS responses will still fit in a UDP packet. (Optional. Default: `"255"`)
* `parts:` The individual parts of the SPF settings.
* `flatten:` Which includes should be inlined. For safety purposes the flattening is done on an opt-in basis. If `"*"` is listed, all includes will be flattened... this might create more problems than is solves due to length limitations.
[multi-string]: https://tools.ietf.org/html/rfc4408#section-3.1.3
[record-size]: https://tools.ietf.org/html/rfc4408#section-3.1.4
`SPR_BUILDER()` returns multiple `TXT()` records:
* `TXT("@", "v=spf1 .... ~all")`

View File

@ -733,6 +733,7 @@ var FRAME = recordBuilder('FRAME');
// split: The template for additional records to be created (default: '_spf%d')
// flatten: A list of domains to be flattened.
// overhead1: Amout of "buffer room" to reserve on the first item in the spf chain.
// txtMaxSize: The maximum size for each TXT string. Values over 255 will result in multiple strings (default: '255')
function SPF_BUILDER(value) {
if (!value.parts || value.parts.length < 2) {
@ -771,6 +772,10 @@ function SPF_BUILDER(value) {
p.overhead1 = value.overhead1;
}
if (value.txtMaxSize) {
p.txtMaxSize = value.txtMaxSize;
}
// Generate a TXT record with the metaparameters.
if (value.ttl) {
r.push(TXT(value.label, rawspf, p, TTL(value.ttl)));

View File

@ -212,110 +212,112 @@ var _escData = map[string]*_escFile{
"/helpers.js": {
name: "helpers.js",
local: "pkg/js/helpers.js",
size: 23999,
size: 24193,
modtime: 0,
compressed: `
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
NmaBXgAA
`,
},
}

View File

@ -58,17 +58,27 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
overhead1 = i
}
// Default txtMaxSize will not result in multiple TXT strings
txtMaxSize := 255
if oh, ok := txt.Metadata["txtMaxSize"]; ok {
i, err := strconv.Atoi(oh)
if err != nil {
errs = append(errs, Warning{fmt.Errorf("split txtMaxSize %q is not an int", oh)})
}
txtMaxSize = i
}
if !strings.Contains(split, "%d") {
errs = append(errs, Warning{fmt.Errorf("Split format `%s` in `%s` is not proper format (should have %%d in it)", split, txt.GetLabelFQDN())})
continue
}
recs := rec.TXTSplit(split+"."+domain.Name, overhead1)
recs := rec.TXTSplit(split+"."+domain.Name, overhead1, txtMaxSize)
for k, v := range recs {
if k == "@" {
txt.SetTargetTXT(v)
txt.SetTargetTXTs(v)
} else {
cp, _ := txt.Copy()
cp.SetTargetTXT(v)
cp.SetTargetTXTs(v)
cp.SetLabelFromFQDN(k, domain.Name)
domain.Records = append(domain.Records, cp)
}

View File

@ -5,6 +5,31 @@ import (
"strings"
)
// Chunks splits strings into arrays of a certain chunk size. We
// use this to split TXT records into 255 sized chunks for RFC 4408
// https://tools.ietf.org/html/rfc4408#section-3.1.3
// Borrowed from https://stackoverflow.com/a/61469854/11477663
func Chunks(s string, chunkSize int) []string {
if chunkSize >= len(s) {
return []string{s}
}
var chunks []string
chunk := make([]rune, chunkSize)
len := 0
for _, r := range s {
chunk[len] = r
len++
if len == chunkSize {
chunks = append(chunks, string(chunk))
len = 0
}
}
if len > 0 {
chunks = append(chunks, string(chunk[:len]))
}
return chunks
}
// TXT outputs s as a TXT record.
func (s *SPFRecord) TXT() string {
text := "v=spf1"
@ -14,7 +39,10 @@ func (s *SPFRecord) TXT() string {
return text
}
const maxLenDefault = 255
// Maximum length of a single TXT string. Anything
// bigger than this will be split into multiple strings
// if the user has set a txtMaxSize length greater than 255
const txtStringLength = 255
// TXTSplit returns a set of txt records to use for SPF.
// pattern given is used to name all chained spf records.
@ -26,20 +54,20 @@ const maxLenDefault = 255
// overhead of that many bytes. For example, if there are other txt
// records and you wish to reduce the first SPF record size to prevent
// DNS over TCP.
func (s *SPFRecord) TXTSplit(pattern string, overhead int) map[string]string {
m := map[string]string{}
s.split("@", pattern, 1, m, overhead)
func (s *SPFRecord) TXTSplit(pattern string, overhead int, txtMaxSize int) map[string][]string {
m := map[string][]string{}
s.split("@", pattern, 1, m, overhead, txtMaxSize)
return m
}
func (s *SPFRecord) split(thisfqdn string, pattern string, nextIdx int, m map[string]string, overhead int) {
maxLen := maxLenDefault - overhead
func (s *SPFRecord) split(thisfqdn string, pattern string, nextIdx int, m map[string][]string, overhead int, txtMaxSize int) {
maxLen := txtMaxSize - overhead
base := s.TXT()
// simple case. it fits
if len(base) <= maxLen {
m[thisfqdn] = base
m[thisfqdn] = Chunks(base, txtStringLength)
return
}
@ -62,7 +90,7 @@ func (s *SPFRecord) split(thisfqdn string, pattern string, nextIdx int, m map[st
over = true
if addedCount == 0 {
// the first part is too big to include. We kinda have to give up here.
m[thisfqdn] = base
m[thisfqdn] = []string{base}
return
}
}
@ -71,8 +99,9 @@ func (s *SPFRecord) split(thisfqdn string, pattern string, nextIdx int, m map[st
newRec.Parts = append(newRec.Parts, part)
}
}
m[thisfqdn] = thisText + tail
newRec.split(nextFQDN, pattern, nextIdx+1, m, 0)
m[thisfqdn] = Chunks(thisText+tail, txtStringLength)
newRec.split(nextFQDN, pattern, nextIdx+1, m, 0, txtMaxSize)
}
// Flatten optimizes s.

View File

@ -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)
}
})
}
}