Skip to content

Instantly share code, notes, and snippets.

@skyzyx
Last active May 12, 2022 20:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skyzyx/ae8328a224f0b5c6388660eb11bb6a08 to your computer and use it in GitHub Desktop.
Save skyzyx/ae8328a224f0b5c6388660eb11bb6a08 to your computer and use it in GitHub Desktop.
SPF records

Instructions

Expectations

  • Verbalize your thoughts as you solve the problem. How you arrived at the solution is just as important as the solution itself.

  • Ask questions if you're not sure about something, rather than guessing.

  • Read the instructions, which consist of this entire page.

The Problem

Starting with a first piece of data, we're going to query a remote service for results which we will then parse into more data that we will make requests about. But instead of HTTP requests to an API, we're going to make DNS requests for DNS records.

  1. Starting with a first/entry domain, fetch the TXT record for the domain spf.ryanparman.dev.

    dig spf.ryanparman.dev +noall +answer -t TXT
    
  2. Results will include a blend of include:, ip4:, or ip6: statements and possibly others.

  3. We want to collect all IP statements (CIDR ranges) as a unique, flattened list.

  4. For any include: statements (domain names), follow them down the rabbit-hole by repeating steps 1–4.

Helper

(For lower-level candidates…)

If you don't know how to make DNS requests in your preferred language, or can't find a package for it, you can reference a pretend function in your code that knows how to take a domain name and return the DNS TXT record. You can use this pretend function without writing its contents yourself.

The (pseudo) function signature looks something like this:

function spf(domain string): string

Example Responses to Parse

$ dig TXT spf.ryanparman.dev

"v=spf1 a mx include:_spf.google.com include:sendgrid.net ip4:216.58.192.0/19 ip6:2607:f8b0:4000::/36 include:mailgun.org -all"
$ dig TXT _spf.google.com

"v=spf1 ip4:216.58.192.0/19 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"
$ dig TXT _netblocks.google.com

"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"
$ dig TXT _netblocks2.google.com

"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"

Bounds of the Problem

  1. This is your program, and your solution. You can solve the problem however you want.

  2. People search the web to look stuff up all the time. Feel free to search the web if you need to.

  3. The lookups will be n levels deep. Could be 3. Could be 300. Could be 3000. Your code shouldn’t care.

  4. v=spf1 is always the preamble, and ~all or -all is always the postamble. We can ignore these.

  5. We only care about the include: statements, and the ip4: and ip6: statements.

  6. Aside from the preamble and postable, statements can be in any order.

  7. There can be zero or more include:, ip4:, and ip6: statements. Don't expect that all records will have all types of statements.

  8. Statements are in the format key:value, for example, include:_spf.google.com or ip4:64.18.0.0/20.

  9. We can generally assume that a company will always implement working SPF records, so excessive error handling is not necessary for this solution. Focus first on the "happy path", then we can go back and do error handling as there's time.

  10. DNS records are always strings, and statements are always space-delimited.

  11. You can use any language you are comfortable with.

  12. Please resist the urge to complicate the solution. Focus first on the simplest solution, then we can go through and adapt the solution to additional use-cases later.

  13. If you have any questions, ask.

@skyzyx
Copy link
Author

skyzyx commented May 12, 2022

spf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment