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

moving a bunch of packages under pkg (#124)

* moving a bunch of packages under pkg

* fix gen

* fix tst

* oops

* fix test fo real

* parse mx/a
This commit is contained in:
Craig Peterson
2017-05-25 14:25:39 -04:00
committed by GitHub
parent 01a242480c
commit 42ef9f4b9e
49 changed files with 140 additions and 49 deletions

71
cmd/convertzone/README.md Normal file
View File

@@ -0,0 +1,71 @@
# convertzone -- Converts a standard DNS zonefile into tsv, pretty, or DSL
## Building the software
Build the software and install in your personal bin:
```cmd
$ cd misc/convertzone/
$ go build
$ cp convertzone ~/bin/.
```
## Usage Overview
convertzone converts an old-style DNS zone file into one of three formats:
convertzone [-mode=MODE] zonename [filename]
-mode=tsv Output the zone recoreds as tab-separated values
-mode=pretty Output the zone pretty-printed.
-mode=dsl Output the zone records as the DNSControl DSL language.
zonename The FQDN of the zone name.
filename File to read (optional. Defaults to stdin)
Output is sent to stdout.
The zonename is required as it can not be guessed automatically from the input.
Example:
convertzone stackoverflow.com zone.stackoverflow.com >new/stackoverflow.com
### -mode=tsv:
This is useful for `awk` and other systems that expect a very
uniform set of input.
Example: Print all CNAMEs:
convertzone -mode=tsv foo.com <zone.foo.com | awk '$4 == "CNAME" { print $1 " -> " $5 }'
### -mode=pretty:
This is useful for cleaning up a zonefile. It sorts the records,
moving SOA and NS records to the top of the zone; all other records
are alphabetically sorted; if a label has mutiple records, they are
listed in a logical (not numeric) order, multiple A records are
listed sorted by IP address, MX records are sorted by priority,
etc. Use `-ttl` to set a default TTL.
Example: Clean up a zone file:
convertzone -mode=pretty foo.com <old/zone.foo.com >new/zone.foo.com
### -mode=dsl:
This is useful for generating your draft `dnsconfig.js` configuration.
The output can be appended to the `dnsconfig.js` file as a good first draft.
Example: Generate statements for a dnsconfig.js file:
convertzone -mode=dsl foo.com <old/zone.foo.com >first-draft.js
Note: The conversion is not perfect. You'll need to manually clean
it up and insert it into `dnsconfig.js`. More instructions in the
DNSControl [migration doc]({site.github.url}}/migration).

156
cmd/convertzone/main.go Normal file
View File

@@ -0,0 +1,156 @@
package main
/*
convertzone: Read BIND-style zonefile and output.
convertzone [-mode=MODE] zonename [filename]
-mode=tsv TAB-separated values (default)
-mode=dsl DNSControl DSL
-mode=pretty Sort and pretty-print records.
zonename The FQDN of the zone name.
filename File to read (default: stdin)
*/
import (
"bufio"
"flag"
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
"github.com/StackExchange/dnscontrol/providers/bind"
"github.com/miekg/dns"
"github.com/miekg/dns/dnsutil"
"github.com/pkg/errors"
)
var flagMode = flag.String("mode", "tsv", "tsv|dsl|pretty")
var flagDefaultTTL = flag.Uint("ttl", 300, "Default TTL")
var flagRegText = flag.String("registrar", "REG_FILL_IN", "registrar text")
var flagProviderText = flag.String("provider", "DNS_FILL_IN", "provider text")
// parseargs parses the non-flag arguments.
func parseargs(args []string) (zonename string, filename string, r io.Reader, err error) {
// 1 args: first arg is the zonename. Read stdin.
// 2 args: first arg is the zonename. 2nd is the filename.
// Anything else returns an error.
if len(args) < 1 {
return "", "", nil, fmt.Errorf("no command line parameters. Zone name required")
}
zonename = args[0]
if len(args) == 1 {
filename = "stdin"
r = bufio.NewReader(os.Stdin)
} else if len(args) == 2 {
filename = flag.Arg(1)
r, err = os.Open(filename)
if err != nil {
return "", "", nil, errors.Wrapf(err, "Could not open file: %s", filename)
}
} else {
return "", "", nil, fmt.Errorf("too many command line parameters")
}
return zonename, filename, r, nil
}
// pretty outputs the zonefile using the prettyprinter.
func pretty(zonename string, filename string, r io.Reader, defaultTTL uint32) {
var l []dns.RR
for x := range dns.ParseZone(r, zonename, filename) {
if x.Error == nil {
l = append(l, x.RR)
}
}
bind.WriteZoneFile(os.Stdout, l, zonename)
}
// rrFormat outputs the zonefile in either DSL or TSV format.
func rrFormat(zonename string, filename string, r io.Reader, defaultTTL uint32, dsl bool) {
zonenamedot := zonename + "."
for x := range dns.ParseZone(r, zonename, filename) {
if x.Error != nil {
continue
}
// Skip comments. Parse the formatted version.
line := x.String()
if line[0] == ';' {
continue
}
items := strings.SplitN(line, "\t", 5)
if len(items) < 5 {
log.Fatalf("Too few items in: %v", line)
}
target := items[4]
hdr := x.Header()
nameFqdn := hdr.Name
name := dnsutil.TrimDomainName(nameFqdn, zonenamedot)
ttl := strconv.FormatUint(uint64(hdr.Ttl), 10)
classStr := dns.ClassToString[hdr.Class]
typeStr := dns.TypeToString[hdr.Rrtype]
// MX records should split out the prio vs. target.
if hdr.Rrtype == dns.TypeMX {
target = strings.Replace(target, " ", "\t", 1)
}
if !dsl { // TSV format:
fmt.Printf("%s\t%s\t%s\t%s\t%s\n", name, ttl, classStr, typeStr, target)
} else { // DSL format:
switch hdr.Rrtype {
case dns.TypeMX:
m := strings.SplitN(target, "\t", 2)
target = m[0] + ", '" + m[1] + "'"
case dns.TypeSOA:
continue
case dns.TypeTXT:
// Leave target as-is.
default:
target = "'" + target + "'"
}
if hdr.Ttl == defaultTTL {
ttl = ""
} else {
ttl = fmt.Sprintf(", TTL(%d)", hdr.Ttl)
}
fmt.Printf(",\n\t%s('%s', %s%s)", typeStr, name, target, ttl)
}
}
}
func main() {
flag.Parse()
zonename, filename, reader, err := parseargs(flag.Args())
if err != nil {
flag.Usage()
}
defTTL := uint32(*flagDefaultTTL)
switch *flagMode {
case "pretty":
pretty(zonename, filename, reader, defTTL)
case "dsl":
fmt.Printf(`D("%s", %s, DnsProvider(%s)`, zonename, *flagRegText, *flagProviderText)
rrFormat(zonename, filename, reader, defTTL, true)
fmt.Println("\n)")
case "tsv":
rrFormat(zonename, filename, reader, defTTL, false)
default:
flag.Usage()
}
}

View File

@@ -4,8 +4,8 @@ import (
"fmt"
"strings"
"github.com/StackExchange/dnscontrol/dnsresolver"
"github.com/StackExchange/dnscontrol/spflib"
"github.com/StackExchange/dnscontrol/pkg/dnsresolver"
"github.com/StackExchange/dnscontrol/pkg/spflib"
)
func main() {
@@ -27,9 +27,11 @@ func main() {
fmt.Println("---------------------")
fmt.Println()
res := dnsresolver.NewResolverLive("preload-dns.json")
//res := dnsresolver.NewResolverPreloaded("preload-dns.json")
//res := dnsresolver.NewResolverLive("spf-store2.json")
res, err := dnsresolver.NewResolverPreloaded("spf-store2.json")
if err != nil {
panic(err)
}
rec, err := spflib.Parse(strings.Join([]string{"v=spf1",
"ip4:198.252.206.0/24",
"ip4:192.111.0.0/24",
@@ -50,15 +52,15 @@ func main() {
fmt.Println("---------------------")
fmt.Println()
var spfs []string
spfs, err = spflib.Lookup("stackex.com", res)
var spf string
spf, err = spflib.Lookup("whatexit.org", res)
if err != nil {
panic(err)
}
rec, err = spflib.Parse(strings.Join(spfs, " "), res)
rec, err = spflib.Parse(spf, res)
if err != nil {
panic(err)
}
spflib.DumpSPF(rec, "")
//res.Close()
}

View File

@@ -0,0 +1,12 @@
{
"_spf.google.com": {
"txt": [
"v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"
]
},
"spf-basic.fogcreek.com": {
"txt": [
"v=spf1 ip4:64.34.80.172 -all"
]
}
}

View File

@@ -0,0 +1,69 @@
{
"_netblocks.google.com": {
"txt": [
"v=spf1 ip4:64.18.0.0/20 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:74.125.0.0/16 ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:207.126.144.0/20 ip4:209.85.128.0/17 ip4:216.58.192.0/19 ip4:216.239.32.0/19 ~all"
]
},
"_netblocks2.google.com": {
"txt": [
"v=spf1 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all"
]
},
"_netblocks3.google.com": {
"txt": [
"v=spf1 ip4:172.217.0.0/19 ip4:108.177.96.0/19 ~all"
]
},
"_spf.google.com": {
"txt": [
"v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"
]
},
"mail.zendesk.com": {
"txt": [
"v=spf1 ip4:192.161.144.0/20 ip4:185.12.80.0/22 ip4:96.46.150.192/27 ip4:174.137.46.0/24 ip4:188.172.128.0/20 ip4:216.198.0.0/18 ~all"
]
},
"mailgun.org": {
"txt": [
"google-site-verification=FIGVOKZm6lQFDBJaiC2DdwvBy8TInunoGCt-1gnL4PA",
"v=spf1 include:spf1.mailgun.org include:spf2.mailgun.org ~all"
]
},
"sendgrid.net": {
"txt": [
"v=spf1 ip4:167.89.0.0/17 ip4:208.117.48.0/20 ip4:50.31.32.0/19 ip4:198.37.144.0/20 ip4:198.21.0.0/21 ip4:192.254.112.0/20 ip4:168.245.0.0/17 ~all",
"google-site-verification=NxyooVvVaIgddVa23KTlOEuVPuhffcDqJFV8RzWrAys"
]
},
"servers.mcsv.net": {
"txt": [
"v=spf1 ip4:205.201.128.0/20 ip4:198.2.128.0/18 ip4:148.105.8.0/21 ?all"
]
},
"spf-basic.fogcreek.com": {
"txt": [
"v=spf1 ip4:64.34.80.172 -all"
]
},
"spf.mtasv.net": {
"txt": [
"v=spf1 ip4:50.31.156.96/27 ip4:104.245.209.192/26 ~all"
]
},
"spf1.mailgun.org": {
"txt": [
"v=spf1 ip4:173.193.210.32/27 ip4:50.23.218.192/27 ip4:174.37.226.64/27 ip4:208.43.239.136/30 ip4:184.173.105.0/24 ip4:184.173.153.0/24 ip4:104.130.122.0/23 ip4:146.20.112.0/26 ~all"
]
},
"spf2.mailgun.org": {
"txt": [
"v=spf1 ip4:209.61.151.0/24 ip4:166.78.68.0/22 ip4:198.61.254.0/23 ip4:192.237.158.0/23 ip4:23.253.182.0/23 ip4:104.130.96.0/28 ip4:146.20.113.0/24 ip4:146.20.191.0/24 ~all"
]
},
"whatexit.org": {
"txt": [
"v=spf1 ip6:2607:f2f8:a9c0::3 ip4:174.136.107.195 include:servers.mcsv.net include:_spf.google.com mx:evite.com -all"
]
}
}