Giter Site home page Giter Site logo

spf-tools / spf-tools Goto Github PK

View Code? Open in Web Editor NEW
174.0 27.0 64.0 312 KB

Shell scripts for taming the SPF (Sender Policy Framework) records in order to fight 10-maximum-DNS-look-ups limit.

License: Apache License 2.0

Shell 99.52% Ruby 0.48%
spf sender-policy-framework spf-records dns shell continuous-integration posix-sh

spf-tools's Introduction

             _|       |               |      
  __| __ \  |         __|  _ \   _ \  |  __| 
\__ \ |   | __|_____| |   (   | (   | |\__ \ 
____/ .__/ _|        \__|\___/ \___/ _|____/ 
     _|

SPF-tools

Join the chat at https://gitter.im/jsarenik/spf-tools

Simple tools for keeping the SPF TXT records tidy in order to fight 10 maximum DNS look-ups.

Release notes

2019/10 - new domain spf-tools.eu.org

Domain name spf-tools.eu.org is used for testing now.

2016/11 - new records on output

spf-tools since version spf-tools/spf-tools@f4f51f7 do not output merely ip4 and ip6 records, but also keep original ptr and exists ones.

General Usage

Your original TXT record which causes more than 10 DNS look-ups should be saved as an otherwise unused subdomain TXT record (e.g. spf-orig.spf-tools.eu.org).

Create a configuration file:

cat > ~/.spf-toolsrc <<EOF
DOMAIN=spf-tools.eu.org
ORIG_SPF=spf-orig.spf-tools.eu.org
DESPF_SKIP_DOMAINS=_spf.domain1.com:spf.domain2.org
DNS_TIMEOUT=5
DNS_SERVER=
EOF

Now just call any of the scripts described below.

Tools Description

despf.sh

Usage: despf.sh [OPTION]... [DOMAIN]...
Decompose SPF records of a DOMAIN. Optionaly can
sort and unique them.
DOMAIN may be specified in an environment variable.

Available options:
  -s DOMAIN[:DOMAIN...]      skip domains, i.e. leave include
                             without decomposition
  -t N                       set DNS timeout to N seconds
  -h                         display this help and exit

despf.sh is a tool that resolves all ip4 and ip6 blocks found in any included SPF subdomain. It prints all these blocks sort(1)ed and uniq(1)ed to stdout, one per line. Other output (Getting ...) is on stderr.

Example:

./despf.sh google.com
Getting _spf.google.com
Getting _netblocks.google.com
Getting _netblocks2.google.com
Getting _netblocks3.google.com
ip4:173.194.0.0/16
ip4:74.125.0.0/16
...
ip6:2a00:1450:4000::/36
ip6:2c0f:fb50:4000::/36

The DNS_TIMEOUT configuration variable sets number of seconds for the host -W SECS command (the same as option -t, see help).

mkblocks.sh

mkblocks.sh tool is meant to parse a list of blocks produced by despf.sh and prepare content of TXT records that all fit into one UDP packet, splitting into more TXT records if needed.

One TXT record per line of standard output.

./despf.sh | ./normalize.sh | ./simplify.sh | ./mkblocks.sh

compare.sh

Current SPF records can be verified by running compare.sh. If the TXT records need an update, it will automatically run the other tools to print out or copy into pastebuffer the new TXT records in reverse order.

Best practice is to put those lines into DNS starting with the last one. That's why xsel.sh reverses the input gathered from mkblocks.sh.

The last record to update is root domain's record which just contains an include. It should be always updated as the last one and the prefix alternated between spf and _spf prefixes when changing records, so the records are all consistent until the root one is changed.

xsel.sh

In order to semi-automate the task of updating the records, pipe the output of mkblocks.sh to xsel.sh.

normalize.sh

This script takes care of correct CIDR ranges. At the moment only IPv4.

Example:

$ ./normalize.sh <<EOF
> ip4:207.68.169.173/30
> ip4:207.68.169.175/30
> ip4:65.55.238.129/26
> EOF
ip4:207.68.169.172/30
ip4:207.68.169.172/30
ip4:65.55.238.128/26

simplify.sh

This script takes out individual IPv4 addresses which are already contained in CIDR ranges.

$ ./simplify.sh <<EOF
> ip4:192.168.0.1
> ip4:192.168.0.0/24
> EOF
ip4:192.168.0.0/24

cloudflare.sh

Dependencies: jq, awk, sed, grep

Script to update pre-existing TXT SPF records for a domain according to the input in DNS zone format using CloudFlare's API.

To use this script, file .spf-toolsrc in $HOME directory should contain TOKEN variable definition which is then used to connect to CloudFlare API. The file should also contain DOMAIN and ORIG_SPF variables which stand for the target SPF domain (e.g. spf-tools.eu.org) and original SPF record with includes (e.g. spf-orig.spf-tools.eu.org) in order to use runspftools.sh without modifying the script.

The script is written against v4 of https://api.cloudflare.com/

The only needed permissions for a custom API token are:

  • Zone.Zone: Read
  • Zone.DNS: Edit

Usage:

./despf.sh | ./normalize.sh | ./simplify.sh | ./iprange.sh | ./cloudflare.sh

route53.sh

Dependencies: jq, aws, awk, sed, grep

 Usage: route53.sh [OPTION]... [HOSTED_ZONE_ID]
  Script to update pre-existing TXT SPF records for
  a domain according to the input in DNS zone format.

  Available options:
    -t TTL                     set Time To Live for DNS records
    -a TXT RECORD              set aditional TXT record to domain (can be used multiple times)

  Default values:
    TTL = 300

Script to update pre-existing TXT SPF records for a domain according to the input in DNS zone format.

The AWS CLI can be configured using ~/.aws/credentials or using environment variables: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (find more details in Configuring the AWS CLI documentation.

Example:

./despf.sh | ./simplify.sh | ./mkblocks.sh | \
  ./route53.sh -a "google-site-verification=deadbeef" DEADBEEF

iprange.sh

Extra dependencies: iprange

This script optimizes the IPv4 address block output (similar to, but more than simplify.sh because it can join multiple networks into one bigger).

Usage:

./despf.sh | ./iprange.sh

Example:

$ ./despf.sh cont.spf-tools.eu.org
ip4:13.111.0.0/24
ip4:13.111.1.0/24
ip4:13.111.2.0/24
ip4:13.111.3.0/24
$ ./despf.sh cont.spf-tools.eu.org | ./iprange.sh
ip4:13.111.0.0/22

Putting it all together

./despf.sh | ./normalize.sh | ./simplify.sh | ./iprange.sh \
  | ./mkblocks.sh | ./xsel.sh

Free Ad

As we are successfully using a free eu.org domain, we are proud to spread the word: Free domains: http://www.eu.org/

Links

License

Copyright 2015-2019 spf-tools team (see AUTHORS)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

spf-tools's People

Contributors

alexclinebb avatar danielweigl avatar epf avatar gglockner avatar gitter-badger avatar ilude avatar jcbf avatar jsarenik avatar materemias avatar phavekes avatar regnauld avatar vhex avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spf-tools's Issues

Have a list of domains that don't get despf'ed

When using example.com with the following record:

"v=spf1 include:_spf.google.com include:spf.mailjet.com include:salesforce.com mx a ip4:203.174.167.178/32 ip4:203.174.179.50/32 ~all"

And optimize records with

./despf.sh example.com | ./normalize.sh | ./simplify.sh | ./mkblocks.sh example.com

I may want to leave one ( or more) includes in the final records.

Any way to handle ptr: results, like with Yahoo?

Yahoo has always chosen to go their own way (e.g. they really held onto DomainKeys while everyone else evolved to DKIM), and it's no different with SPF records, it seems.

# despf.sh yahoo.com
Getting _spf.mail.yahoo.com
ptr:yahoo.com
ptr:yahoo.net

Is the issue solely with their SPF record being purposely difficult, or can anyone think of a way to get valid despf.sh output from Yahoo some other way?

Allow for cloudflare Automatic TTL

The TTL is hardcoded at 1800 (which is certainly reasonable), but many Cloudflare users prefer the 'Automatic' setting so Cloudflare can choose the right value. According to the CF API docs, a TTL value of 1 will set it to 'Automatic'

""ttl"
TTL of record in seconds. 1 = Automatic, otherwise, value must in between 120 and 86400 seconds.

I guess you could do it in two ways - have some type of setting in the rc file indicating CloudFlare and then use 1 instead of 1800 or allow a TTL to be set in the RC file the same way.

Or have the cloudflare.sh script replace 1800 with 1, since it's use implies the availability of the Cloudflare Automatic TTL setting.

isincidrange.sh /32 Check - Integer Expression Expected Warning

Hello, been using spf-tools for a while to update our records. have recently added an include for aspmx.pardot.com and noted some errors/warnings.

If you run the command I use to generate my spf's, directly on aspmx.pardot.com it will reproduce the warnings eg.

./despf.sh aspmx.pardot.com | ./normalize.sh | ./simplify.sh | ./mkblocks.sh | ./xsel.sh

will show following warnings, for every IP that goes through the 'isincidrange.sh' check when it gets checked against any IP listed as in a /32:

  • read cidr
  • mask=32
  • ciaddr=199.122.123.192
  • isincidrange.sh 74.86.241.250 199.122.123.192 32
    /spf-tools/include/isincidrange.sh: line 55: test: 74.86.241.250: integer expression expected

From what I can tell it's due to the lookup finding an IP specified with the /32 range of which there is one in the above lookup:

ip4:13.111.0.1/24
ip4:13.111.1.0/24
ip4:136.147.135.1/24
ip4:136.147.176.1/24
ip4:136.147.182.1/24
ip4:174.36.84.12
ip4:174.36.84.14/31
ip4:174.36.84.245
ip4:174.36.84.32
ip4:198.245.81.1/24
ip4:199.122.123.188/30
** ip4:199.122.123.192/32
ip4:208.43.21.28
ip4:208.43.21.66
ip4:208.43.21.70
ip4:67.228.21.188
ip4:74.86.113.29
ip4:74.86.207.39
ip4:74.86.236.242
ip4:74.86.241.250

I guess it being superfluous/unnecessary to check against a /32, the isincidrange script doesn't handle this?

This seems to break the output and no SPF records will hit stdout when pressing enter. Could be wrong about the cause as incidrange.sh does seem to check against /32, but thats what I'm seeing with the above run.

Make test scripts executable

For simplicity test scripts should be executable.

-rw-r--r--  1 jcbf  staff   207 Apr 14 13:41 test-real.sh
-rwxr-xr-x  1 jcbf  staff   673 Apr 14 13:41 test-shell.sh
-rw-r--r--  1 jcbf  staff  1472 Apr 14 13:41 test-unit.sh

Detect Too Many SPF records

While trying to setup spf-tools, I was getting a weird SPF entry out of mkzoneent.sh:

Too. 1800 IN TXT Too many DNS lookups!

This was an error out of mkblocks.sh when there are more than 10 SPF includes. But the error propagates through to cloudflare.sh and tries to create a DNS record with that (and breaks SPF since spf9 will try to include SPF10, which rightly does not exist.

This is, of course, an artifact of the horrific Go Daddy/Media Temple/secureserver.net SPF setup, which includes half the Internet. I have a domain on Google Apps, that also uses Mailchimp and Zendesk that hosts web apps on media temple. Needless to say - that SPF record will cause this error:

v=spf1 include:_spf.google.com include:servers.mcsv.net include:mail.zendesk.com include:spf.mail01.mtsvc.net ~all

Anyway - seems like there needs to be a way to gracefully exit out of mkblocks or have mkzoneent catch the > 10 issue before trying to invoke cloudflare.sh

Check for valid ip records

While reporting #28 , @stevejenkins mentioned the possibility of having invalid ips in record may result in "strange" blocks in the normalisation script.

ip4/ip6 should be validated before printing.

In https://tools.ietf.org/html/rfc7208#section-5.6 the format is well define and SPF validators will ignore invalid one.

Should be this be check in normalize.sh or should be in despf.sh ?

Pros and Cons

  • In despf.sh:
    • No real side effect since SPF validators will ignore those records
    • If despf.shis targeted for optimisation os SPF records, having invalid record beats the purpose.
    • Really sucks for automated process that rely on valid data
  • In normalize.sh:
    • This is only an issue in CIDR normalisation
    • No real side effect since SPF validators will ignore those records

Comments, please!

Relevant part of RFC 7208

5.6.  "ip4" and "ip6"

   These mechanisms test whether <ip> is contained within a given
   IP network.

   ip4              = "ip4"      ":" ip4-network   [ ip4-cidr-length ]
   ip6              = "ip6"      ":" ip6-network   [ ip6-cidr-length ]

   ip4-cidr-length  = "/" ("0" / %x31-39 0*1DIGIT) ; value range 0-32
   ip6-cidr-length  = "/" ("0" / %x31-39 0*2DIGIT) ; value range 0-128
   dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]

   ip4-network      = qnum "." qnum "." qnum "." qnum
   qnum             = DIGIT                 ; 0-9
                      / %x31-39 DIGIT       ; 10-99
                      / "1" 2DIGIT          ; 100-199
                      / "2" %x30-34 DIGIT   ; 200-249
                      / "25" %x30-35        ; 250-255
            ; as per conventional dotted-quad notation, e.g., 192.0.2.0

   ip6-network      = <as per Section 2.2 of [RFC4291]>
            ; e.g., 2001:db8::cd30

   The <ip> is compared to the given network.  If CIDR prefix length
   high-order bits match, the mechanism matches.

   If ip4-cidr-length is omitted, it is taken to be "/32".  If
   ip6-cidr-length is omitted, it is taken to be "/128".  It is not
   permitted to omit parts of the IP address instead of using CIDR
   notations.  That is, use 192.0.2.0/24 instead of 192.0.2.

despf.sh google.com gives no output

Hello,
I just have installed a server using modoboa and following the problem, I passed to postwhite that gived me to spf-tools. I found that /usr/local/bin/spf-tools/despf.sh google.com gives no output. Also I tried to use the cloned version of this repo and continues showing any output.

root@mail-2022:/usr/local/bin/spf-tools# ./despf.sh google.com
root@mail-2022:/usr/local/bin/spf-tools# ping -c 1 google.com
PING google.com(par21s05-in-x0e.1e100.net (2a00:1450:4007:812::200e)) 56 data bytes
64 bytes from par21s05-in-x0e.1e100.net (2a00:1450:4007:812::200e): icmp_seq=1 ttl=114 time=6.07 ms

--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 6.071/6.071/6.071/0.000 ms

I'm using debian 11.3 inside an ovh cloud server. I have an other lxc server inside proxmox with debian 10.11 and despf.sh gives output.

I checked that a ping resolves to google, also I tried to change de DNS nameserver.

Any clue about what could happen?

Thanks you much

SFP Qualifiers are removed

Usually the + qualifier is used and it's the default anyway, But when other qualifier is defined then may have the reverse effect.
Example:

$ ./despf.sh encryption.it.
ip4:88.149.188.40/29
ip4:88.149.188.41
$ host -t TXT encryption.it.
encryption.it descriptive text "v=spf1 -ip4:88.149.188.41 +ip4:88.149.188.40/29 ~all"

and

$ host -t TXT rambler.ru.
rambler.ru descriptive text "v=spf1 ip4:81.19.78.96/27 ip4:81.19.66.0/23 ip4:81.19.88.0/24 ip4:81.19.92.32/27 -exists:%{ir}.spf.rambler.ru -exists:%{l}.u.spf.rambler.ru ~all"
$ ./despf.sh rambler.ru.
exists:%{ir}.spf.rambler.ru
exists:%{l}.u.spf.rambler.ru
ip4:81.19.66.0/23
ip4:81.19.78.96/27
ip4:81.19.88.0/24
ip4:81.19.92.32/27

Update docs to help with jq dependency

Was trying to setup spf-tools on a shared host setup that did not provide jq. I'm not a shell guru by any means, but was able to just download jq to my script directory and updated cloudflare.sh with

alias jq="$PWD/jq"

to get things running. But you might want to update the readme section for cloudflare.sh to indicate the error:

./cloudflare.sh: line 14: type: jq: not found

Means you need to download jq locally and setup an alias to it (or there may be a more graceful way to do it - again not a shell guru by any stretch). Maybe a test within the local directory (or incldues) for a jq binary if one isn't found on the system.

BSD no longer supports dig

Per:

https://www.freebsd.org/releases/10.0R/relnotes.html

'dig' is no longer in BSD-based operating systems. BIND (which provides dig) was removed and replaced with unbound.

This change was made a couple years ago, but is starting to affect more systems as they upgrade to systems that rely on unbound instead of BIND.

The replacement tool in unbound is 'drill.' But the 'host' command exists in both BIND and unbound. There's no rush on this, but it might be interesting/useful to see if host could be used in place of dig. And if not, perhaps explore whether drill support could be provided in despf.sh on systems running unbound instead of BIND.

FWIW, I run unbound on a few systems... and find it superior to BIND.

If primary DNS server fails, secondaries servers are not used

./despf.sh hotmail.comwill trigger this query

 dig +time=2 +short -t TXT hotmail.com @ns4.msft.net. ns2.msft.net. ns1.msft.net. ns3.msft.net.

Ideas:

  • Parse SOA record for primary and then query for NS records - badly configured "hidden primary" architectures
  • simple iterate by all NS servers and break on success.

New release ?

There are 232 commits to master since release 1.0. Looking at the closed issues I think is worth a new release , let's say v1.1.
What do you think ?

Just as reference, this is a generated ChangeLog

Change Log

Unreleased

Full Changelog

Implemented enhancements:

  • Check for valid ip records #48
  • Update docs to help with jq dependency #38
  • despf.sh fails to follow "redirect" in SPF records #27

Fixed bugs:

  • Truncated DNS results cause issues #53
  • If primary DNS server fails, secondaries servers are not used #50
  • Records like a/24 or mx/24 ignores net mask #49
  • Detect Too Many SPF records #37
  • despf.sh fails silently #33
  • despf.sh fails to retrieve IP addresses from some domains #29

Closed issues:

  • Make test scripts executable #84
  • Allowing for multiple MX records #70
  • isincidrange.sh /32 Check - Integer Expression Expected Warning #64

Merged pull requests:

* This Change Log was automatically generated by github_changelog_generator

Missing CIDR Notation, no Recursion

Checkout the SPF record for ticketmaster.com:

  1. The raw record cuts on a quotation mark for 208.66.204.0/22 at 208.66.204.0 and wraps to the next line, which begins with a quotation mark. You're script doesn't catch that. You're missing the /22 at the end, so output for ./despf.sh ticketmaster.com is ip4:208.66.204.0. This is likely the case for any such instance. Something like this fixes it:

cat $rawdatafile | tr '\n' '\f' | sed -e 's/"\f"//g' | tr '\f' '\n'

  1. You're not recursing: The SPF record for ticketmaster.com includes spf-95.jangomail.com and the latter lists ip4:208.75.253.59. On the other hand, ./despf.sh ticketmaster.com doesn't list that ip address. Is that desired behavior?

despf.sh allows invalid CIDR ranges as output

This isn't technically a "bug" in despf.sh, in that it's doing what it's supposed to do: query the DNS and spit out the IP addresses and CIDR ranges.

This is an enhancement request to do some sort of validation checking on the CIDR range before outputting it. For example, when I run despf.sh against outlook.com (or even just against _spf-ssg-b.microsoft.com, which is one of the include: statements that gets evaluated), two of the CIDRs published by Microsoft (207.68.169.173/30 and 65.55.238.129/26) are invalid.

It would be wonderful if despf.sh ignored invalid CIDRs, and simply didn't output them. Thanks! :)

Still keeping invalid IPv6 CIDR ranges

Just wondering if any progress has been made on only keeping valid IPv6 CIDR ranges in the output of despf.sh. LinkedIn is still publishing an invalid address, and despf.sh still outputs it:

# despf.sh linkedin.com
ip4:108.174.3.0/24
ip4:108.174.3.215
ip4:108.174.6.0/24
ip4:162.248.185.121
ip4:162.248.186.121
...
ip6:2620:109:c003:104::/64
ip6:2620:109:c006:104::/64
ip6:2620:109:c006:104::215
ip6:2620:109:c00d:104::/64

The one ending in "215" is invalid.

allow the possibility to keep untouched includes in the first SPF

In order to authorize us, one of our mailing service provider (MailXXmp) insists on having their include as part of our first SPF, and won't search for it in the included sub-sections. So we need to keep it first.

Since 19ed7d5 the simplify.sh script arbitrarily keep includes at the end.

So I've disabled the use of simplify.sh. Not sure if it could be modified to have a different default order, or at least configured to do so.

despf does not consolidate cidrs

./despf.sh et._spf.pardot.com | ./normalize.sh | ./simplify.sh gives

ip4:13.111.0.0/24
ip4:13.111.1.0/24
ip4:13.111.2.0/24
ip4:13.111.3.0/24
ip4:136.147.135.0/24
ip4:136.147.176.0/24
ip4:136.147.182.0/24
ip4:198.245.81.0/24
ip4:199.122.123.188/30
ip4:199.122.123.192

This correct but not consolidated. It should be merged properly as follows:

13.111.0.0/22
136.147.135.0/24
136.147.176.0/24
136.147.182.0/24
198.245.81.0/24
199.122.123.188/30
199.122.123.192

Allow custom prefix from config file

Simple mod to allow PREFIX to come from config file..

@@ -35,7 +35,7 @@

 # Default values
 domain=${DOMAIN:-"spf-tools.eu.org"}
-prefix="spf"
+prefix=${PREFIX:-"spf"}
 suffix=""
 policy="~all"
 delim="^"

License

Dear contributors. I think it's time to set the direction and make others less shy. What about license? @jcbf @urg @stevejenkins

  • Public domain?
  • MIT?
  • GNU GPL?

No flames please, but feel free to explain your opinion. Just a pragmatic question before there are more people on the list :-)

Feel free to send those ideas to my email address so we do not influence each other before we state our own opinions. Then I will write a summary and we can vote. Thanks for consideration!

Handle macros in spf entries

Although there isn't a wide spread usage , entries with macros shouldn't be processed.
For instance, gentoo.org has some.

gentoo.org. 60 IN TXT "v=spf1 include:_netblocks.spf.gentoo.org a:mail.gentoo.org mx include:%{l}.%{o}.spf.gentoo.org ?all"

despf.sh fails silently

If despf.sh is run against an invalid domain or a domain with no SPF records (such as example.com) it "fails" silently.

Something in the way it exits after not returning any values (I'm presuming it's by virtual of the line trap "cleanup $loopfile; exit 1;" INT QUIT) causes a script that relies on despf.sh (such as https://github.com/stevejenkins/postwhite/) to exit in that case, rather than continue on in the same manner as it would if despf.sh finished a valid query.

Let me know if you'd like to see an example (you can test by editing my postwhite script and putting in an invalid $host).

Allowing for multiple MX records

The grep -m1 is restricting me to only having 1 MX record resolved. I bumped it up to 5 (arbitrary). I'm not sure what would be the best generic case.

--- a/include/despf.inc.sh
+++ b/include/despf.inc.sh
@@ -81,7 +81,7 @@ dea() {
 # demx <domain>
 # Get MX record for a domain
 demx() {
-  mymx=$(mydig -t MX $1 | awk '{print $2}' | grep -m1 .)
+  mymx=$(mydig -t MX $1 | awk '{print $2}' | grep -m5 .)
   for name in $mymx; do dea $name $2; done
 }

despf.sh fails to retrieve IP addresses from some domains

I'm not sure of the cause, but some domains's SPF records seem to cause despf.sh to not recursively search the include: hosts.

For example:

# dig txt ebay.com | grep spf1
ebay.com.         600   IN      TXT     "v=spf1 include:s._spf.ebay.com include:c._spf.ebay.com include:p._spf.ebay.com include:p2._spf.ebay.com include:_spf.google.com ~all"

However:

# /usr/local/bin/spf-tools/despf.sh ebay.com
Getting s._spf.ebay.com
Getting c._spf.ebay.com
Getting p._spf.ebay.com
Getting emarsys.net
Getting _spf.salesforce.com
Getting _mtablock1.salesforce.com
Getting _mtablock2.salesforce.com
Getting p2._spf.ebay.com
Getting sendgrid.net
Getting sendgrid.biz
Getting mktomail.com
#

but if you query one of the hosts listed in the SPF record:

# /usr/local/bin/spf-tools/despf.sh s._spf.ebay.com
ip4:205.201.137.229
ip4:66.135.213.241
ip4:66.135.215.0/24
ip4:66.211.161.0/25
ip4:66.211.184.0/23
#

It should display those same IP addresses (and many more) when ebay.com is queried.

Truncated DNS results cause issues

I was experiencing the following issue:

./compare.sh dragonbox.com origspf.dragonbox.com
Getting spf1.dragonbox.com
Getting spf2.dragonbox.com
Getting spf3.dragonbox.com
Getting spf4.dragonbox.com
Getting spf5.dragonbox.com
dig: couldn't get address for ';;': not found
DNS lookup error!
Getting _spf.google.com

which caused compare to fail. (maybe 1 / 3 times).

To troubleshoot, I've modified despf.inc to do

diff --git a/include/despf.inc.sh b/include/despf.inc.sh
index 888c2a3..862741e 100644
--- a/include/despf.inc.sh
+++ b/include/despf.inc.sh
@@ -1,8 +1,9 @@
 DNS_TIMEOUT=${DNS_TIMEOUT:-"2"}

 mydg() {
-  dig +time=$DNS_TIMEOUT "$@" \
-      || { echo "DNS lookup error!" >&2; cleanup; false; }
+  AR=$@
+  dig +time=$DNS_TIMEOUT $AR \
+      || { echo "DNS lookup error! <$AR>" >&2; cleanup; false; exit -1; }
 }

 mydig() {`

and the error becomes.
DNS lookup error! <+short -t TXT origspf.dragonbox.com @;; Truncated, retrying in TCP mode. ns14.ovh.net. dns14.ovh.net.>

so this seems related to https://forums.opensuse.org/showthread.php/398114-DNS-UDP-response-truncated.

I modifed the code to do dig +tcp and all is fine now. I don't send a PR as I am not sure what you would consider the proper fix to be. E.g.

  1. work-around by parsing out everything after ";;"
  2. force tcp argument
  3. use a bigger buffer
  4. optionally add a dig argument option to the .spftoolsrc so that we can tune it as we wish.
  5. etc.

Problem with missing domain in example from README

./despf.sh | ./normalize.sh | ./simplify.sh | ./mkblocks.sh
./normalize.sh: line 56: [: too many arguments
./normalize.sh: line 56: [: =: unary operator expected
./normalize.sh: line 56: [: too many arguments
./normalize.sh: line 56: [: too many arguments
./normalize.sh: line 56: [: too many arguments
./normalize.sh: line 56: [: too many arguments
./normalize.sh: line 56: [: too many arguments
energystan.com^"v=spf1 Usage: despf.sh [OPTION]... [DOMAIN]... Decompose SPF records of a DOMAIN, sort and unique them. Available options: -s DOMAIN[:DOMAIN...] skip domains, i.e. leave include without decomposition include:spf1.energystan.com ~all"
spf1.energystan.com^"v=spf1 -t N set DNS timeout to N seconds -h display this help and exit ~all"

fixed by:

 ./despf.sh google.com | ./normalize.sh | ./simplify.sh | ./mkblocks.sh
Getting _spf.google.com
Getting _netblocks.google.com
Getting _netblocks2.google.com
Getting _netblocks3.google.com
energystan.com^"v=spf1 ip4:108.177.8.0/21 ip4:172.217.0.0/19 ip4:173.194.0.0/16 ip4:207.126.144.0/20 ip4:209.85.128.0/17 ip4:216.239.32.0/19 ip4:216.58.192.0/19 ip4:64.18.0.0/20 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 include:spf1.energystan.com ~all"
spf1.energystan.com^"v=spf1 ip4:72.14.192.0/18 ip4:74.125.0.0/16 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"

but I'm not sure if domain missing in all examples or just in this. I have ~/.spf-toolsrc and this not used in despf.sh automatically.

jq error

Thank you for creating this tool, it's exactly what I need. The only problem is I'm getting an error when using it to create/update cloudflare records.

When using ./runspftools.sh I get the error:

jq: error (at :1): Cannot index string with string "id"
parse error: Invalid numeric literal at line 1, column 1760

Then later I get:

parse error: Invalid numeric literal at line 1, column 143

Have you come across this before?

Which OS has this been developed/tested on ?

I've had some trouble getting any output from the tools on an older Ubuntu LTS and FreeBSD 10.1.
Obviously it's not your scope to support older/unsupported OSes, but it would be good to indicate somewhere on which platform spf-tools have been tested/developed, and which tools are expected to be available (dependencies) to the spf-tools suite.

The README.md references tac(1) - this isn't a standard command on BSDs, for instance.

Prevent overwrite of other TXT records

We're on AWS and we're using route53 for our DNS. We have an SPF and a Google Site Verification TXT record.

When we run ./despf.sh | ./simplify.sh | ./mkblocks.sh | ./route53.sh <our zone id> we find the google-site-verification TXT record is removed.

Unfortunately, Google requires it to be in place - it seems to check it regularly.

I've fudged it manually in the short term by adding the following to route53.sh, but it's definitely a hack! Can anyone think of a better way of achieving this?

CHANGES=$(echo $CHANGES | jq -r '.Changes[0].ResourceRecordSet.ResourceRecords += [{"Value": "\"google-site-verification=the-code-from-google\""}]')

Thanks for building this tool - it's been helpful for us.

Fix string comparisons

Similar to @jcbf 's fix in #107 fix also following ones (or at least the latter of them):

$ git grep -E '\$[^"]+ ='
include/despf.inc.sh:  test $# = 2 && echo $2 | grep -wq $1
tests/test-unit.sh:  test $1 = "-n" && { shift; > $tmp-out; } || cat > $tmp-out

No record for sportssystems.com

Using latest files from Jan 18, ./despf.sh sportssystems.com gives nothing, but

dig TXT sportssystems.com +short gives
"GOOGLE-SITE-VERIFICATION=KA6GOR_NXZNHOXANLL7PQSDIPZVJ21ZOQQBWZOHVIKU"
"V=SPF1 include:_spf.google.com IP4:166.78.205.64 IP4:166.78.205.65 IP4:166.78.205.66 IP4:216.73.93.70/31 IP4:216.73.93.72/31 MX PTR A ~ALL"

Wondering if the presence of the MX, PTR and A records have anything to do with it and also if they're handled properly, i.e. are lookups done for those records or is it just the ip addresses and include statements that are processed?

(I wouldn't bother with looking up PTR records myself, their use is strongly discouraged by RFC 7208 with SPF records)

.spf-toolsrc ignored?

Hello

I created a file /root/.spf-toolsrc:

DOMAIN=our-domain.eu
ORIG_SPF=spf-orig.our-domain.eu
DESPF_SKIP_DOMAINS=
DNS_TIMEOUT=5
DNS_SERVER=1.1.1.1
TOKEN=cloudflare_token_here
[email protected]

If I run this from /opt/spf-tools, where I checked out your repository:
./despf.sh | ./normalize.sh | ./simplify.sh | ./iprange.sh | ./mkblocks.sh | ./cloudflare.sh
Absolutely nothing happens our appears.

It only works a bit if I specify it like this:
./despf.sh spf-orig.our-domain.eu | ./normalize.sh | ./simplify.sh | ./iprange.sh | ./mkblocks.sh our-domain.eu

I get the idea that the config file isn't loaded or ignored or something. If I add | ./cloudflare.sh at the end, it also results in just nothing.

How to make a test for iprange ?

How do you think is the beste way to test iprange.sh , assuming that iprange may not exists and , depending on that, may have diferent results ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.