1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

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
6 changed files with 204 additions and 106 deletions

View File

@@ -82,6 +82,7 @@ D("example.tld", REG, DSP, ...
SPF_BUILDER({ SPF_BUILDER({
label: "@", label: "@",
overflow: "_spf%d", // Delete this line if you don't want big strings split. 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. raw: "_rawspf", // Delete this line if the default is sufficient.
parts: [ parts: [
"v=spf1", "v=spf1",
@@ -101,6 +102,7 @@ The parameters are:
* `label:` The label of the first TXT record. (Optional. Default: `"@"`) * `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. * `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"`) * `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) * `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. * `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 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) 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 dnscontrol keeps a cache of the DNS lookups performed during
optimization. The cache is maintained so that the optimizer does optimization. The cache is maintained so that the optimizer does

View File

@@ -1,5 +1,12 @@
'use strict'; '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 = { var conf = {
registrars: [], registrars: [],
dns_providers: [], dns_providers: [],
@@ -725,6 +732,7 @@ var FRAME = recordBuilder('FRAME');
// ttl: The time for TTL, integer or string. (default: not defined, using DefaultTTL) // 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') // split: The template for additional records to be created (default: '_spf%d')
// flatten: A list of domains to be flattened. // 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) { function SPF_BUILDER(value) {
if (!value.parts || value.parts.length < 2) { if (!value.parts || value.parts.length < 2) {
@@ -756,6 +764,10 @@ function SPF_BUILDER(value) {
p.split = value.overflow; p.split = value.overflow;
} }
if (value.overhead1) {
p.overhead1 = value.overhead1;
}
// Generate a TXT record with the metaparameters. // Generate a TXT record with the metaparameters.
if (value.ttl) { if (value.ttl) {
r.push(TXT(value.label, rawspf, p, TTL(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": { "/helpers.js": {
name: "helpers.js", name: "helpers.js",
local: "pkg/js/helpers.js", local: "pkg/js/helpers.js",
size: 23384, size: 23595,
modtime: 0, modtime: 0,
compressed: ` compressed: `
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
uekrXAAA
`, `,
}, },
} }

View File

@@ -2,6 +2,7 @@ package normalize
import ( import (
"fmt" "fmt"
"strconv"
"strings" "strings"
"github.com/StackExchange/dnscontrol/v3/models" "github.com/StackExchange/dnscontrol/v3/models"
@@ -41,11 +42,27 @@ func flattenSPFs(cfg *models.DNSConfig) []error {
} }
// now split if needed // now split if needed
if split, ok := txt.Metadata["split"]; ok { 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") { 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())}) errs = append(errs, Warning{fmt.Errorf("Split format `%s` in `%s` is not proper format (should have %%d in it)", split, txt.GetLabelFQDN())})
continue continue
} }
recs := rec.TXTSplit(split + "." + domain.Name) recs := rec.TXTSplit(split+"."+domain.Name, overhead1)
for k, v := range recs { for k, v := range recs {
if k == "@" { if k == "@" {
txt.SetTargetTXT(v) txt.SetTargetTXT(v)

View File

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

View File

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