Browse Source

moar spf

tags/v0.3.1
Bob Rudis 8 years ago
parent
commit
2072f5245d
  1. 8
      DESCRIPTION
  2. 16
      NAMESPACE
  3. 8
      R/gdns-package.r
  4. 37
      R/gdns.r
  5. 108
      R/spf.r
  6. 27
      README.Rmd
  7. 245
      README.md
  8. 9
      man/bulk_query.Rd
  9. 4
      man/gdns.Rd
  10. 15
      man/has_spf.Rd
  11. 21
      man/is_soft_fail.Rd
  12. 15
      man/query.Rd
  13. 24
      man/spf_ipv4s.Rd
  14. 18
      man/split_spf.Rd
  15. 2
      tests/testthat/test-gdns.R

8
DESCRIPTION

@ -1,6 +1,6 @@
Package: gdns Package: gdns
Title: Tools to Work with Google DNS Over HTTPS API Title: Tools to Work with Google DNS Over HTTPS API
Version: 0.1.0.9000 Version: 0.2.0.9000
Authors@R: c(person("Bob", "Rudis", email = "bob@rudis.net", role = c("aut", "cre"))) Authors@R: c(person("Bob", "Rudis", email = "bob@rudis.net", role = c("aut", "cre")))
Maintainer: Bob Rudis <bob@rudis.net> Maintainer: Bob Rudis <bob@rudis.net>
Description: To address the problem of insecurity of UDP-based DNS requests, Description: To address the problem of insecurity of UDP-based DNS requests,
@ -9,7 +9,8 @@ Description: To address the problem of insecurity of UDP-based DNS requests,
between a client and a recursive resolver, and complements DNSSEC between a client and a recursive resolver, and complements DNSSEC
to provide end-to-end authenticated DNS lookups. Functions that enable to provide end-to-end authenticated DNS lookups. Functions that enable
querying individual requests that bulk requests that return detailed querying individual requests that bulk requests that return detailed
responses and bulk requests are both provided. responses and bulk requests are both provided. Support for reverse
lookups is also provided.
License: AGPL + file LICENSE License: AGPL + file LICENSE
LazyData: true LazyData: true
Encoding: UTF-8 Encoding: UTF-8
@ -20,5 +21,6 @@ Suggests:
Imports: Imports:
httr, httr,
jsonlite, jsonlite,
purrr purrr,
stringi
RoxygenNote: 5.0.1 RoxygenNote: 5.0.1

16
NAMESPACE

@ -1,9 +1,25 @@
# Generated by roxygen2: do not edit by hand # Generated by roxygen2: do not edit by hand
export(bulk_query) export(bulk_query)
export(has_spf)
export(is_hard_fail)
export(is_soft_fail)
export(passes_all)
export(query) export(query)
export(spf_exists)
export(spf_includes)
export(spf_ipv4s)
export(spf_ipv6s)
export(spf_ptrs)
export(split_spf)
import(httr) import(httr)
importFrom(jsonlite,fromJSON) importFrom(jsonlite,fromJSON)
importFrom(purrr,"%||%")
importFrom(purrr,map) importFrom(purrr,map)
importFrom(purrr,map_df) importFrom(purrr,map_df)
importFrom(purrr,safely) importFrom(purrr,safely)
importFrom(stringi,stri_enc_toutf8)
importFrom(stringi,stri_replace_all_regex)
importFrom(stringi,stri_split_fixed)
importFrom(stringi,stri_split_regex)
importFrom(stringi,stri_trim)

8
R/gdns-package.r

@ -10,12 +10,16 @@
#' To address this problem, Google Public DNS offers DNS resolution over an #' To address this problem, Google Public DNS offers DNS resolution over an
#' encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and #' encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and
#' security between a client and a recursive resolver, and complements DNSSEC #' security between a client and a recursive resolver, and complements DNSSEC
#' to provide end-to-end authenticated DNS lookups.#' #' to provide end-to-end authenticated DNS lookups.\cr
#' \cr
#' Support for reverse lookups is also provided.
#' #'
#' @name gdns #' @name gdns
#' @docType package #' @docType package
#' @author Bob Rudis (@@hrbrmstr) #' @author Bob Rudis (@@hrbrmstr)
#' @import httr #' @import httr
#' @importFrom stringi stri_split_fixed stri_split_regex stri_trim
#' stri_replace_all_regex stri_enc_toutf8
#' @importFrom jsonlite fromJSON #' @importFrom jsonlite fromJSON
#' @importFrom purrr safely map map_df #' @importFrom purrr safely map map_df %||%
NULL NULL

37
R/gdns.r

@ -1,3 +1,6 @@
ipv4_regex <-
"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
S_GET <- purrr::safely(GET) S_GET <- purrr::safely(GET)
#' Perform DNS over HTTPS queries using Google #' Perform DNS over HTTPS queries using Google
@ -20,9 +23,12 @@ S_GET <- purrr::safely(GET)
#' @param name item to lookup. Valid characters are numbers, letters, hyphen, and dot. Length #' @param name item to lookup. Valid characters are numbers, letters, hyphen, and dot. Length
#' must be between 1 and 255. Names with escaped or non-ASCII characters #' must be between 1 and 255. Names with escaped or non-ASCII characters
#' are not supported. Internationalized domain names must use the #' are not supported. Internationalized domain names must use the
#' punycode format (e.g. "\code{xn--qxam}"). #' punycode format (e.g. "\code{xn--qxam}").\cr
#' \cr If an IPv4 string is input, it will be transformed into
#' a proper format for reverse lookups.
#' @param type RR type can be represented as a number in [1, 65535] or canonical #' @param type RR type can be represented as a number in [1, 65535] or canonical
#' string (A, aaaa, etc.) #' string (A, aaaa, etc). More information on RR types can be
#' found \href{http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4}{here}.
#' @param edns_client_subnet The edns0-client-subnet option. Format is an IP #' @param edns_client_subnet The edns0-client-subnet option. Format is an IP
#' address with a subnet mask. Examples: \code{1.2.3.4/24}, #' address with a subnet mask. Examples: \code{1.2.3.4/24},
#' \code{2001:700:300::/48}.\cr #' \code{2001:700:300::/48}.\cr
@ -31,13 +37,23 @@ S_GET <- purrr::safely(GET)
#' nameservers for geographic location accuracy, use #' nameservers for geographic location accuracy, use
#' \code{edns_client_subnet=0.0.0.0/0}. Google Public DNS normally sends #' \code{edns_client_subnet=0.0.0.0/0}. Google Public DNS normally sends
#' approximate network information (usually replacing the last part of #' approximate network information (usually replacing the last part of
#' your IPv4 address with zeroes). #' your IPv4 address with zeroes). \code{0.0.0.0/0} is the default.
#' @return a \code{list} with the query result or \code{NULL} if an error occurred #' @return a \code{list} with the query result or \code{NULL} if an error occurred
#' @references \url{https://developers.google.com/speed/public-dns/docs/dns-over-https} #' @references \url{https://developers.google.com/speed/public-dns/docs/dns-over-https}
#' @export #' @export
#' @examples #' @examples
#' query("rud.is") #' query("rud.is")
query <- function(name, type="1", edns_client_subnet=NULL) { #' query("microsoft.com", "MX")
#' query("google-public-dns-a.google.com", "TXT")
#' query("apple.com")
#' query("17.142.160.59", "PTR")
query <- function(name, type="1", edns_client_subnet="0.0.0.0/0") {
if (grepl(ipv4_regex, name)) {
name <- paste0(c(rev(unlist(stringi::stri_split_fixed(name, ".", 4))),
"in-addr.arpa."),
sep="", collapse=".")
}
res <- S_GET("https://dns.google.com/resolve", res <- S_GET("https://dns.google.com/resolve",
query=list(name=name, query=list(name=name,
@ -46,7 +62,10 @@ query <- function(name, type="1", edns_client_subnet=NULL) {
if (!is.null(res$result)) { if (!is.null(res$result)) {
stop_for_status(res$result) stop_for_status(res$result)
jsonlite::fromJSON(httr::content(res$result, as="text")) txt <- httr::content(res$result, as="text")
txt <- stringi::stri_enc_toascii(txt)
txt <- stringi::stri_replace_all_regex(txt, "[[:cntrl:][:blank:]\\n ]+", " ")
jsonlite::fromJSON(txt)
} else { } else {
NULL NULL
} }
@ -56,13 +75,17 @@ query <- function(name, type="1", edns_client_subnet=NULL) {
#' Vectorized query, returning only answers in a data frame #' Vectorized query, returning only answers in a data frame
#' #'
#' @param hosts character vector of hosts to query #' @param hosts character vector of hosts to query
#' @param type RR type (see \code{type} in \code{query()}).
#' @return \code{data.frame} of only answers (use \code{query()} for detailed responses) #' @return \code{data.frame} of only answers (use \code{query()} for detailed responses)
#' @references \url{https://developers.google.com/speed/public-dns/docs/dns-over-https} #' @references \url{https://developers.google.com/speed/public-dns/docs/dns-over-https}
#' @export #' @export
#' @note this is a fairly naive function. It expects \code{Answer} to be one of the
#' return value list slots. The intent for it was to make it easier
#' to do bulk forward queries. It will get smarter in future versions.
#' @examples #' @examples
#' hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com") #' hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com")
#' gdns::bulk_query(hosts) #' gdns::bulk_query(hosts)
bulk_query <- function(hosts) { bulk_query <- function(hosts, type=1) {
results <- map(hosts, gdns::query) results <- map(hosts, gdns::query, type=type)
map_df(results, "Answer") map_df(results, "Answer")
} }

108
R/spf.r

@ -0,0 +1,108 @@
#' Split out all SPF records in a domain's TXT record
#'
#' Given a vector of TXT records, this function will return a list of vectors
#' of all the SPF records for each. If the given TXT record is not an SPF
#' record, \code{NULL} is returned (which makes it easy to skip with \code{purrr}
#' functions).
#'
#' @param spf_rec a character vector of DNS TXT records
#' @export
split_spf <- function(spf_rec) {
purrr::map(spf_rec, .split_spf)
}
.split_spf <- function(spf_rec) {
if (has_spf(spf_rec)) {
spf_rec <- stringi::stri_trim(stringi::stri_replace_all_regex(spf_rec, '"', ""))
recs <- stri_trim(unlist(stringi::stri_split_regex(spf_rec, "\ +")))
grep("v=spf1", recs, invert=TRUE, value=TRUE)
} else {
NA_character_
}
}
#' Test for whether a DNS TXT record is an SPF record
#'
#' @param spf_rec a character vector of DNS TXT records
#' @export
has_spf <- function(spf_rec) {
grepl("v=spf1", spf_rec)
}
#' SPF "all" type test
#'
#' @param spf_rec a character vector of DNS TXT records
#' @export
is_soft_fail <- function(spf_rec) {
ret <- vector("logical", length(spf_rec))
spf_rec <- stringi::stri_trim(stringi::stri_replace_all_regex(spf_rec, '"', ""))
SPF <- which(has_spf(spf_rec))
ret[SPF] <- grepl("~all$", stringi::stri_trim(spf_rec[SPF]))
ret[!SPF] <- NA
ret
}
#' @rdname is_soft_fail
#' @export
is_hard_fail <- function(spf_rec) {
ret <- vector("logical", length(spf_rec))
spf_rec <- stringi::stri_trim(stringi::stri_replace_all_regex(spf_rec, '"', ""))
SPF <- which(has_spf(spf_rec))
ret[SPF] <- grepl("\\-all$", stringi::stri_trim(spf_rec[SPF]))
ret[!SPF] <- NA
ret
}
#' @rdname is_soft_fail
#' @export
passes_all <- function(spf_rec) {
ret <- vector("logical", length(spf_rec))
spf_rec <- stringi::stri_trim(stringi::stri_replace_all_regex(spf_rec, '"', ""))
SPF <- which(has_spf(spf_rec))
ret[SPF] <- grepl("\\+all$", stringi::stri_trim(spf_rec[SPF]))
ret[!SPF] <- NA
ret
}
#' SPF field extraction functions
#'
#' @export
spf_ipv4s <- function(spf_rec) {
purrr::map(split_spf(spf_rec), function(x) {
stringi::stri_replace_all_regex(grep("ip4", x, value=TRUE), "^ip4:", "")
})
}
#' @rdname spf_ipv4s
#' @export
spf_ipv6s <- function(spf_rec) {
purrr::map(split_spf(spf_rec), function(x) {
stringi::stri_replace_all_regex(grep("ip6", x, value=TRUE), "^ip6:", "")
})
}
#' @rdname spf_ipv4s
#' @export
spf_includes <- function(spf_rec) {
purrr::map(split_spf(spf_rec), function(x) {
stringi::stri_replace_all_regex(grep("include", x, value=TRUE), "^include:", "")
})
}
#' @rdname spf_ipv4s
#' @export
spf_ptrs <- function(spf_rec) {
purrr::map(split_spf(spf_rec), function(x) {
stringi::stri_replace_all_regex(grep("ptr", x, value=TRUE), "^ptr[:]", "")
})
}
#' @rdname spf_ipv4s
#' @export
spf_exists <- function(spf_rec) {
purrr::map(split_spf(spf_rec), function(x) {
stringi::stri_replace_all_regex(grep("exists", x, value=TRUE), "^exists:", "")
})
}

27
README.Rmd

@ -23,11 +23,22 @@ More info at <https://developers.google.com/speed/public-dns/docs/dns-over-https
The following functions are implemented: The following functions are implemented:
- `query` : perform Google DNS query for a single host (retreives metadata & answer) - `bulk_query`: Vectorized query, returning only answers in a data frame
- `bulk_query` : perform bulk host queries, returning a \code{data.frame} of only answers (no metadata) - `has_spf`: Test for whether a DNS TXT record is an SPF record
- `is_hard_fail`: SPF "all" type test
- `is_soft_fail`: SPF "all" type test
- `passes_all`: SPF "all" type test
- `query`: Perform DNS over HTTPS queries using Google
- `spf_exists`: SPF field extraction functions
- `spf_includes`: SPF field extraction functions
- `spf_ipv4s`: SPF field extraction functions
- `spf_ipv6s`: SPF field extraction functions
- `spf_ptrs`: SPF field extraction functions
- `split_spf`: Split out all SPF records in a domain's TXT record
### News ### News
- Version 0.2.0.9000 SPF stuff
- Version 0.1.0.9000 released - Version 0.1.0.9000 released
### Installation ### Installation
@ -60,9 +71,19 @@ date()
test_dir("tests/") test_dir("tests/")
hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com") query("rud.is")
query("microsoft.com", "MX")
query("google-public-dns-a.google.com", "TXT")
query("apple.com")
query("17.142.160.59", "PTR")
hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com")
gdns::bulk_query(hosts) gdns::bulk_query(hosts)
``` ```
### Code of Conduct ### Code of Conduct

245
README.md

@ -12,11 +12,22 @@ More info at <https://developers.google.com/speed/public-dns/docs/dns-over-https
The following functions are implemented: The following functions are implemented:
- `query` : perform Google DNS query for a single host (retreives metadata & answer) - `bulk_query`: Vectorized query, returning only answers in a data frame
- `bulk_query` : perform bulk host queries, returning a of only answers (no metadata) - `has_spf`: Test for whether a DNS TXT record is an SPF record
- `is_hard_fail`: SPF "all" type test
- `is_soft_fail`: SPF "all" type test
- `passes_all`: SPF "all" type test
- `query`: Perform DNS over HTTPS queries using Google
- `spf_exists`: SPF field extraction functions
- `spf_includes`: SPF field extraction functions
- `spf_ipv4s`: SPF field extraction functions
- `spf_ipv6s`: SPF field extraction functions
- `spf_ptrs`: SPF field extraction functions
- `split_spf`: Split out all SPF records in a domain's TXT record
### News ### News
- Version 0.2.0.9000 SPF stuff
- Version 0.1.0.9000 released - Version 0.1.0.9000 released
### Installation ### Installation
@ -32,7 +43,7 @@ library(gdns)
# current verison # current verison
packageVersion("gdns") packageVersion("gdns")
#> [1] '0.1.0.9000' #> [1] '0.2.0.9000'
``` ```
### Test Results ### Test Results
@ -42,26 +53,236 @@ library(gdns)
library(testthat) library(testthat)
date() date()
#> [1] "Sat Apr 9 21:17:02 2016" #> [1] "Sun Apr 10 14:51:46 2016"
test_dir("tests/") test_dir("tests/")
#> testthat results ======================================================================================================== #> testthat results ========================================================================================================
#> OK: 2 SKIPPED: 0 FAILED: 0 #> OK: 2 SKIPPED: 0 FAILED: 0
hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com") query("rud.is")
#> $Status
#> [1] 0
#>
#> $TC
#> [1] FALSE
#>
#> $RD
#> [1] TRUE
#>
#> $RA
#> [1] TRUE
#>
#> $AD
#> [1] FALSE
#>
#> $CD
#> [1] FALSE
#>
#> $Question
#> name type
#> 1 rud.is. 1
#>
#> $Answer
#> name type TTL data
#> 1 rud.is. 1 3599 104.236.112.222
#>
#> $Additional
#> list()
#>
#> $edns_client_subnet
#> [1] "0.0.0.0/0"
#>
#> $Comment
#> [1] "Response from dns.mwebdns.net.(84.246.121.10)"
query("microsoft.com", "MX")
#> $Status
#> [1] 0
#>
#> $TC
#> [1] FALSE
#>
#> $RD
#> [1] TRUE
#>
#> $RA
#> [1] TRUE
#>
#> $AD
#> [1] FALSE
#>
#> $CD
#> [1] FALSE
#>
#> $Question
#> name type
#> 1 microsoft.com. 15
#>
#> $Answer
#> name type TTL data
#> 1 microsoft.com. 15 2054 10 microsoft-com.mail.protection.outlook.com.
#>
#> $Additional
#> list()
#>
#> $edns_client_subnet
#> [1] "0.0.0.0/0"
query("google-public-dns-a.google.com", "TXT")
#> $Status
#> [1] 0
#>
#> $TC
#> [1] FALSE
#>
#> $RD
#> [1] TRUE
#>
#> $RA
#> [1] TRUE
#>
#> $AD
#> [1] FALSE
#>
#> $CD
#> [1] FALSE
#>
#> $Question
#> name type
#> 1 google-public-dns-a.google.com. 16
#>
#> $Answer
#> name type TTL data
#> 1 google-public-dns-a.google.com. 16 21599 "http://xkcd.com/1361/"
#>
#> $Additional
#> list()
#>
#> $edns_client_subnet
#> [1] "0.0.0.0/0"
#>
#> $Comment
#> [1] "Response from 216.239.38.10"
query("apple.com")
#> $Status
#> [1] 0
#>
#> $TC
#> [1] FALSE
#>
#> $RD
#> [1] TRUE
#>
#> $RA
#> [1] TRUE
#>
#> $AD
#> [1] FALSE
#>
#> $CD
#> [1] FALSE
#>
#> $Question
#> name type
#> 1 apple.com. 1
#>
#> $Answer
#> name type TTL data
#> 1 apple.com. 1 1119 17.172.224.47
#> 2 apple.com. 1 1119 17.178.96.59
#> 3 apple.com. 1 1119 17.142.160.59
#>
#> $Additional
#> list()
#>
#> $edns_client_subnet
#> [1] "0.0.0.0/0"
query("17.142.160.59", "PTR")
#> $Status
#> [1] 0
#>
#> $TC
#> [1] FALSE
#>
#> $RD
#> [1] TRUE
#>
#> $RA
#> [1] TRUE
#>
#> $AD
#> [1] FALSE
#>
#> $CD
#> [1] FALSE
#>
#> $Question
#> name type
#> 1 59.160.142.17.in-addr.arpa. 12
#>
#> $Answer
#> name type TTL data
#> 1 59.160.142.17.in-addr.arpa. 12 1134 alchemysynth.com.
#> 2 59.160.142.17.in-addr.arpa. 12 1134 openni.org.
#> 3 59.160.142.17.in-addr.arpa. 12 1134 swell.am.
#> 4 59.160.142.17.in-addr.arpa. 12 1134 appleweb.net.
#> 5 59.160.142.17.in-addr.arpa. 12 1134 apple.com.
#> 6 59.160.142.17.in-addr.arpa. 12 1134 pv-apple-com.apple.com.
#> 7 59.160.142.17.in-addr.arpa. 12 1134 apple.by.
#> 8 59.160.142.17.in-addr.arpa. 12 1134 airtunes.info.
#> 9 59.160.142.17.in-addr.arpa. 12 1134 applecentre.info.
#> 10 59.160.142.17.in-addr.arpa. 12 1134 applecomputerinc.info.
#> 11 59.160.142.17.in-addr.arpa. 12 1134 appleexpo.info.
#> 12 59.160.142.17.in-addr.arpa. 12 1134 applemasters.info.
#> 13 59.160.142.17.in-addr.arpa. 12 1134 applepay.info.
#> 14 59.160.142.17.in-addr.arpa. 12 1134 applepaymerchantsupplies.info.
#> 15 59.160.142.17.in-addr.arpa. 12 1134 applepaysupplies.info.
#> 16 59.160.142.17.in-addr.arpa. 12 1134 applescript.info.
#> 17 59.160.142.17.in-addr.arpa. 12 1134 appleshare.info.
#> 18 59.160.142.17.in-addr.arpa. 12 1134 macosx.info.
#> 19 59.160.142.17.in-addr.arpa. 12 1134 powerbook.info.
#> 20 59.160.142.17.in-addr.arpa. 12 1134 powermac.info.
#> 21 59.160.142.17.in-addr.arpa. 12 1134 quicktimelive.info.
#> 22 59.160.142.17.in-addr.arpa. 12 1134 quicktimetv.info.
#> 23 59.160.142.17.in-addr.arpa. 12 1134 sherlock.info.
#> 24 59.160.142.17.in-addr.arpa. 12 1134 shopdifferent.info.
#> 25 59.160.142.17.in-addr.arpa. 12 1134 skyvines.info.
#> 26 59.160.142.17.in-addr.arpa. 12 1134 ubnw.info.
#> 27 59.160.142.17.in-addr.arpa. 12 1134 webobjects.info.
#> 28 59.160.142.17.in-addr.arpa. 12 1134 yessql.info.
#> 29 59.160.142.17.in-addr.arpa. 12 1134 ripmixburn.com.
#> 30 59.160.142.17.in-addr.arpa. 12 1134 apples-msk.ru.
#> 31 59.160.142.17.in-addr.arpa. 12 1134 icloud.se.
#> 32 59.160.142.17.in-addr.arpa. 12 1134 icloud.es.
#> 33 59.160.142.17.in-addr.arpa. 12 1134 icloud.om.
#> 34 59.160.142.17.in-addr.arpa. 12 1134 icloudo.com.
#> 35 59.160.142.17.in-addr.arpa. 12 1134 icloud.ch.
#> 36 59.160.142.17.in-addr.arpa. 12 1134 icloud.fr.
#> 37 59.160.142.17.in-addr.arpa. 12 1134 icloude.com.
#> 38 59.160.142.17.in-addr.arpa. 12 1134 camelspaceeffect.com.
#> 39 59.160.142.17.in-addr.arpa. 12 1134 camelphat.com.
#>
#> $Additional
#> list()
#>
#> $edns_client_subnet
#> [1] "0.0.0.0/0"
hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com")
gdns::bulk_query(hosts) gdns::bulk_query(hosts)
#> Source: local data frame [7 x 4] #> Source: local data frame [7 x 4]
#> #>
#> name type TTL data #> name type TTL data
#> (chr) (int) (int) (chr) #> (chr) (int) (int) (chr)
#> 1 rud.is. 1 710 104.236.112.222 #> 1 rud.is. 1 3598 104.236.112.222
#> 2 dds.ec. 1 280 162.243.111.4 #> 2 dds.ec. 1 299 162.243.111.4
#> 3 r-project.org. 1 6410 137.208.57.37 #> 3 r-project.org. 1 7177 137.208.57.37
#> 4 rstudio.com. 1 71 45.79.156.36 #> 4 rstudio.com. 1 3599 45.79.156.36
#> 5 apple.com. 1 3290 17.172.224.47 #> 5 apple.com. 1 1102 17.172.224.47
#> 6 apple.com. 1 3290 17.178.96.59 #> 6 apple.com. 1 1102 17.178.96.59
#> 7 apple.com. 1 3290 17.142.160.59 #> 7 apple.com. 1 1102 17.142.160.59
``` ```
### Code of Conduct ### Code of Conduct

9
man/bulk_query.Rd

@ -4,10 +4,12 @@
\alias{bulk_query} \alias{bulk_query}
\title{Vectorized query, returning only answers in a data frame} \title{Vectorized query, returning only answers in a data frame}
\usage{ \usage{
bulk_query(hosts) bulk_query(hosts, type = 1)
} }
\arguments{ \arguments{
\item{hosts}{character vector of hosts to query} \item{hosts}{character vector of hosts to query}
\item{type}{RR type (see \code{type} in \code{query()}).}
} }
\value{ \value{
\code{data.frame} of only answers (use \code{query()} for detailed responses) \code{data.frame} of only answers (use \code{query()} for detailed responses)
@ -15,6 +17,11 @@ bulk_query(hosts)
\description{ \description{
Vectorized query, returning only answers in a data frame Vectorized query, returning only answers in a data frame
} }
\note{
this is a fairly naive function. It expects \code{Answer} to be one of the
return value list slots. The intent for it was to make it easier
to do bulk forward queries. It will get smarter in future versions.
}
\examples{ \examples{
hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com") hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com")
gdns::bulk_query(hosts) gdns::bulk_query(hosts)

4
man/gdns.Rd

@ -16,7 +16,9 @@ often incorporate additional protection.\cr
To address this problem, Google Public DNS offers DNS resolution over an To address this problem, Google Public DNS offers DNS resolution over an
encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and
security between a client and a recursive resolver, and complements DNSSEC security between a client and a recursive resolver, and complements DNSSEC
to provide end-to-end authenticated DNS lookups.#' to provide end-to-end authenticated DNS lookups.\cr
\cr
Support for reverse lookups is also provided.
} }
\author{ \author{
Bob Rudis (@hrbrmstr) Bob Rudis (@hrbrmstr)

15
man/has_spf.Rd

@ -0,0 +1,15 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/spf.r
\name{has_spf}
\alias{has_spf}
\title{Test for whether a DNS TXT record is an SPF record}
\usage{
has_spf(spf_rec)
}
\arguments{
\item{spf_rec}{a character vector of DNS TXT records}
}
\description{
Test for whether a DNS TXT record is an SPF record
}

21
man/is_soft_fail.Rd

@ -0,0 +1,21 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/spf.r
\name{is_soft_fail}
\alias{is_hard_fail}
\alias{is_soft_fail}
\alias{passes_all}
\title{SPF "all" type test}
\usage{
is_soft_fail(spf_rec)
is_hard_fail(spf_rec)
passes_all(spf_rec)
}
\arguments{
\item{spf_rec}{a character vector of DNS TXT records}
}
\description{
SPF "all" type test
}

15
man/query.Rd

@ -4,16 +4,19 @@
\alias{query} \alias{query}
\title{Perform DNS over HTTPS queries using Google} \title{Perform DNS over HTTPS queries using Google}
\usage{ \usage{
query(name, type = "1", edns_client_subnet = NULL) query(name, type = "1", edns_client_subnet = "0.0.0.0/0")
} }
\arguments{ \arguments{
\item{name}{item to lookup. Valid characters are numbers, letters, hyphen, and dot. Length \item{name}{item to lookup. Valid characters are numbers, letters, hyphen, and dot. Length
must be between 1 and 255. Names with escaped or non-ASCII characters must be between 1 and 255. Names with escaped or non-ASCII characters
are not supported. Internationalized domain names must use the are not supported. Internationalized domain names must use the
punycode format (e.g. "\code{xn--qxam}").} punycode format (e.g. "\code{xn--qxam}").\cr
\cr If an IPv4 string is input, it will be transformed into
a proper format for reverse lookups.}
\item{type}{RR type can be represented as a number in [1, 65535] or canonical \item{type}{RR type can be represented as a number in [1, 65535] or canonical
string (A, aaaa, etc.)} string (A, aaaa, etc). More information on RR types can be
found \href{http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4}{here}.}
\item{edns_client_subnet}{The edns0-client-subnet option. Format is an IP \item{edns_client_subnet}{The edns0-client-subnet option. Format is an IP
address with a subnet mask. Examples: \code{1.2.3.4/24}, address with a subnet mask. Examples: \code{1.2.3.4/24},
@ -23,7 +26,7 @@ not want any part of your IP address to be sent to authoritative
nameservers for geographic location accuracy, use nameservers for geographic location accuracy, use
\code{edns_client_subnet=0.0.0.0/0}. Google Public DNS normally sends \code{edns_client_subnet=0.0.0.0/0}. Google Public DNS normally sends
approximate network information (usually replacing the last part of approximate network information (usually replacing the last part of
your IPv4 address with zeroes).} your IPv4 address with zeroes). \code{0.0.0.0/0} is the default.}
} }
\value{ \value{
a \code{list} with the query result or \code{NULL} if an error occurred a \code{list} with the query result or \code{NULL} if an error occurred
@ -47,6 +50,10 @@ To perform vectorized queries with only answers (and no metadata) use
} }
\examples{ \examples{
query("rud.is") query("rud.is")
query("microsoft.com", "MX")
query("google-public-dns-a.google.com", "TXT")
query("apple.com")
query("17.142.160.59", "PTR")
} }
\references{ \references{
\url{https://developers.google.com/speed/public-dns/docs/dns-over-https} \url{https://developers.google.com/speed/public-dns/docs/dns-over-https}

24
man/spf_ipv4s.Rd

@ -0,0 +1,24 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/spf.r
\name{spf_ipv4s}
\alias{spf_exists}
\alias{spf_includes}
\alias{spf_ipv4s}
\alias{spf_ipv6s}
\alias{spf_ptrs}
\title{SPF field extraction functions}
\usage{
spf_ipv4s(spf_rec)
spf_ipv6s(spf_rec)
spf_includes(spf_rec)
spf_ptrs(spf_rec)
spf_exists(spf_rec)
}
\description{
SPF field extraction functions
}

18
man/split_spf.Rd

@ -0,0 +1,18 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/spf.r
\name{split_spf}
\alias{split_spf}
\title{Split out all SPF records in a domain's TXT record}
\usage{
split_spf(spf_rec)
}
\arguments{
\item{spf_rec}{a character vector of DNS TXT records}
}
\description{
Given a vector of TXT records, this function will return a list of vectors
of all the SPF records for each. If the given TXT record is not an SPF
record, \code{NULL} is returned (which makes it easy to skip with \code{purrr}
functions).
}

2
tests/testthat/test-gdns.R

@ -1,7 +1,7 @@
context("basic functionality") context("basic functionality")
test_that("we can do something", { test_that("we can do something", {
expect_that(length(gdns::query("example.com")), equals(8)) expect_that(length(gdns::query("example.com")), equals(10))
doms <- c("example.com", "example.org", "example.net") doms <- c("example.com", "example.org", "example.net")
qry <- gdns::bulk_query(doms) qry <- gdns::bulk_query(doms)

Loading…
Cancel
Save