NEW: spf flattener can make first record extra short (#781)

* NEW: spf flattener can make first record extra short

* fixup!
This commit is contained in:
Tom Limoncelli 2020-07-09 12:52:49 -04:00 committed by GitHub
parent f7d39b578a
commit 530bf10bfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 204 additions and 106 deletions

View file

@ -82,6 +82,7 @@ D("example.tld", REG, DSP, ...
SPF_BUILDER({
label: "@",
overflow: "_spf%d", // Delete this line if you don't want big strings split.
overhead1: "20", // There are 20 bytes of other TXT records on this domain. Compensate for this.
raw: "_rawspf", // Delete this line if the default is sufficient.
parts: [
"v=spf1",
@ -101,6 +102,7 @@ The parameters are:
* `label:` The label of the first TXT record. (Optional. Default: `"@"`)
* `overflow:` If set, SPF strings longer than 255 chars will be split into multiple TXT records. The value of this setting determines the template for what the additional labels will be named. If not set, no splitting will occur and dnscontrol may generate TXT strings that are too long.
* `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. (Optional. Default: `"_rawspf"`)
* `ttl:` This allows setting a specific TTL on this SPF record. (Optional. Default: using default record TTL)
* `parts:` The individual parts of the SPF settings.
@ -123,8 +125,50 @@ flattening required to reduce the number of lookups to 10 or less.
To count the number of lookups, you can use our interactive SPF
debugger at [https://stackexchange.github.io/dnscontrol/flattener/index.html](https://stackexchange.github.io/dnscontrol/flattener/index.html)
# The first in a chain is special
## Notes about the DNS Cache
When generating the chain of SPF
records, each one is max length 255. For the first item in
the chain, the max is 255 - "overhead1". Setting this to 255 or
higher has undefined behavior.
Why is this useful?
Some sites desire having all DNS queries fit in a single packet so
that UDP, not TCP, can be used to satisfy all requests. That means all
responses have to be relatively small.
When an SPF system does a "TXT" lookup, it gets SPF and non-SPF
records. This makes the first link in the chain extra large.
The bottom line is that if you want the TXT records to fit in a UDP
packet, keep increasing the value of `overhead1` until the packet
is no longer truncated.
Example:
```
$ dig +short whatexit.org txt | wc -c
118
```
Setting `overhead1` to 118 should be sufficient.
```
$ dig +short stackoverflow.com txt | wc -c
582
```
Since 582 is bigger than 255, it might not be possible to achieve the
goal. Any value larger than 255 will disable all flattening. Try
170, then 180, 190 until you get the desired results.
A validator such as
[https://www.kitterman.com/spf/validate.html](https://www.kitterman.com/spf/validate.html)
will tell you if the queries are being truncated and TCP was required
to get the entire record. (Sadly it caches heavily.)
## Notes about the `spfcache.json`
dnscontrol keeps a cache of the DNS lookups performed during
optimization. The cache is maintained so that the optimizer does

View file

@ -1,5 +1,12 @@
'use strict';
// If you edit this file, you must run `go generate` to embed this
// file in the source code.
// If you are heavily debugging this code, the "-dev" flag will
// read this file directly instead of using the output of
// `go generate`. You'll still need to run `go generate` before
// you commit the changes.
var conf = {
registrars: [],
dns_providers: [],
@ -725,6 +732,7 @@ var FRAME = recordBuilder('FRAME');
// ttl: The time for TTL, integer or string. (default: not defined, using DefaultTTL)
// 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.
function SPF_BUILDER(value) {
if (!value.parts || value.parts.length < 2) {
@ -756,6 +764,10 @@ function SPF_BUILDER(value) {
p.split = value.overflow;
}
if (value.overhead1) {
p.overhead1 = value.overhead1;
}
// Generate a TXT record with the metaparameters.
if (value.ttl) {
r.push(TXT(value.label, rawspf, p, TTL(value.ttl)));

View file

@ -212,106 +212,108 @@ var _escData = map[string]*_escFile{
"/helpers.js": {
name: "helpers.js",
local: "pkg/js/helpers.js",
size: 23384,
size: 23595,
modtime: 0,
compressed: `
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
uekrXAAA
`,
},
}

View file

@ -2,6 +2,7 @@ package normalize
import (
"fmt"
"strconv"
"strings"
"github.com/StackExchange/dnscontrol/v3/models"
@ -41,11 +42,27 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
}
// now split if needed
if split, ok := txt.Metadata["split"]; ok {
overhead1 := 0
// overhead1: The first segment of the SPF record
// needs to be shorter than the others due to the overhead of
// other (non-SPF) txt records. If there are (for example) 50
// bytes of txt records also on this domain record, setting
// overhead1=50 reduces the maxLen by 50. It only affects the
// first part of the split.
if oh, ok := txt.Metadata["overhead1"]; ok {
i, err := strconv.Atoi(oh)
if err != nil {
errs = append(errs, Warning{fmt.Errorf("split overhead1 %q is not an int", oh)})
}
overhead1 = 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)
recs := rec.TXTSplit(split+"."+domain.Name, overhead1)
for k, v := range recs {
if k == "@" {
txt.SetTargetTXT(v)

View file

@ -14,7 +14,7 @@ func (s *SPFRecord) TXT() string {
return text
}
const maxLen = 255
const maxLenDefault = 255
// TXTSplit returns a set of txt records to use for SPF.
// pattern given is used to name all chained spf records.
@ -22,14 +22,20 @@ const maxLen = 255
// should result in fqdn after replacement
// returned map will have keys with fqdn of resulting records.
// root record will be under key "@"
func (s *SPFRecord) TXTSplit(pattern string) map[string]string {
// overhead specifies that the first split part should assume an
// 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)
s.split("@", pattern, 1, m, overhead)
return m
}
func (s *SPFRecord) split(thisfqdn string, pattern string, nextIdx int, m map[string]string) {
func (s *SPFRecord) split(thisfqdn string, pattern string, nextIdx int, m map[string]string, overhead int) {
maxLen := maxLenDefault - overhead
base := s.TXT()
// simple case. it fits
if len(base) <= maxLen {
@ -66,7 +72,7 @@ func (s *SPFRecord) split(thisfqdn string, pattern string, nextIdx int, m map[st
}
}
m[thisfqdn] = thisText + tail
newRec.split(nextFQDN, pattern, nextIdx+1, m)
newRec.split(nextFQDN, pattern, nextIdx+1, m, 0)
}
// Flatten optimizes s.

View file

@ -1,6 +1,7 @@
package spflib
import (
"strconv"
"strings"
"testing"
)
@ -63,6 +64,13 @@ var splitTests = [][]string{
"_spf1.stackex.com",
"v=spf1 include:X12345678901234567890123456789000000000000000123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.com ~all",
},
{
"overhead-200",
"v=spf1 include:a.com include:b.com include:X12345678901234567890123456789000000000000000123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.com ~all",
"v=spf1 include:a.com include:_spf1.stackex.com ~all",
"_spf1.stackex.com",
"v=spf1 include:b.com include:X12345678901234567890123456789000000000000000123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789.com ~all",
},
{
"really big",
"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" +
@ -85,12 +93,21 @@ var splitTests = [][]string{
func TestSplit(t *testing.T) {
for _, tst := range splitTests {
overhead := 0
v := strings.Split(tst[0], "-")
if len(v) > 1 {
if i, err := strconv.Atoi(v[1]); err == nil {
overhead = i
}
}
t.Run(tst[0], func(t *testing.T) {
rec, err := Parse(tst[1], nil)
if err != nil {
t.Fatal(err)
}
res := rec.TXTSplit("_spf%d.stackex.com")
res := rec.TXTSplit("_spf%d.stackex.com", overhead)
if res["@"] != tst[2] {
t.Fatalf("Root record wrong. \nExp %s\ngot %s", tst[2], res["@"])
}