├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── CONDUCT.md ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── as-data-frame.R ├── datasets.R ├── dkim.r ├── gdns-package.r ├── spf.r ├── utils-mappers.R ├── utils-pipe.R ├── utils-safely.R ├── utils.R ├── zbulk-query.R └── zgdns.r ├── README.Rmd ├── README.md ├── appveyor.yml ├── cran-comments.md ├── data-raw └── rrtypes.R ├── data ├── dns_classes.rda ├── dns_glob_names.rda ├── dns_opcodes.rda ├── dns_rcodes.rda ├── edns0_option_codes.rda ├── resource_record_tbl.rda └── rrtypes.rda ├── docs ├── index.html ├── news │ └── index.html ├── pkgdown.css ├── pkgdown.js └── reference │ ├── bulk_query.html │ ├── gdns.html │ ├── has_spf.html │ ├── index.html │ ├── is_soft_fail.html │ ├── query.html │ ├── spf_ipv4s.html │ └── split_spf.html ├── gdns.Rproj ├── inst └── tinytest │ └── test_gdns.R ├── man ├── as.data.frame.gdns_response.Rd ├── bulk_query.Rd ├── dns_classes.Rd ├── dns_glob_names.Rd ├── dns_opcodes.Rd ├── dns_rcodes.Rd ├── edns0_option_codes.Rd ├── gdns.Rd ├── has_spf.Rd ├── is_soft_fail.Rd ├── pipe.Rd ├── query.Rd ├── resource_record_tbl.Rd ├── rrtypes.Rd ├── spf_ipv4s.Rd └── split_spf.Rd ├── tests └── tinytest.R └── tools └── mk-rsrc-rcrd-tbl.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^README\.Rmd$ 4 | ^README-.*\.png$ 5 | ^\.travis\.yml$ 6 | ^CONDUCT\.md$ 7 | ^cran-comments\.md$ 8 | ^docs$ 9 | ^tools$ 10 | ^data-raw$ 11 | ^LICENSE\.md$ 12 | ^appveyor\.yml$ 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: R 2 | 3 | sudo: false 4 | 5 | cache: packages 6 | 7 | os: 8 | - linux 9 | - osx 10 | 11 | r: 12 | - oldrel 13 | - release 14 | -------------------------------------------------------------------------------- /CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (http:contributor-covenant.org), version 1.0.0, available at 25 | http://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: gdns 2 | Title: Tools to Work with Google's 'DNS'-over-'HTTPS' ('DoH') API 3 | Version: 0.5.0 4 | Authors@R: c( 5 | person("Bob", "Rudis", email = "bob@rud.is", role = c("aut", "cre"), 6 | comment = c(ORCID = "0000-0001-5670-2640")) 7 | ) 8 | Maintainer: Bob Rudis 9 | Description: To address the problem of insecurity of 'UDP'-based 'DNS' requests, 10 | Google Public 'DNS' offers 'DNS' resolution over an encrypted 'HTTPS' 11 | connection. 'DNS'-over-'HTTPS' greatly enhances privacy and security 12 | between a client and a recursive resolver, and complements 'DNSSEC' 13 | to provide end-to-end authenticated DNS lookups. Functions that enable 14 | querying individual requests that bulk requests that return detailed 15 | responses and bulk requests are both provided. Support for reverse 16 | lookups is also provided. See 17 | 18 | for more information. 19 | License: MIT + file LICENSE 20 | LazyData: true 21 | Encoding: UTF-8 22 | Depends: 23 | R (>= 3.5.0) 24 | Imports: 25 | httr, 26 | stats, 27 | jsonlite, 28 | stringi, 29 | magrittr, 30 | tinytest 31 | RoxygenNote: 7.1.0 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2020 2 | COPYRIGHT HOLDER: Bob Rudis 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2020 Bob Rudis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(as.data.frame,gdns_response) 4 | export("%>%") 5 | export(bulk_query) 6 | export(dig) 7 | export(has_spf) 8 | export(is_hard_fail) 9 | export(is_soft_fail) 10 | export(passes_all) 11 | export(query) 12 | export(spf_exists) 13 | export(spf_includes) 14 | export(spf_ipv4s) 15 | export(spf_ipv6s) 16 | export(spf_ptrs) 17 | export(split_spf) 18 | import(httr) 19 | importFrom(jsonlite,fromJSON) 20 | importFrom(magrittr,"%>%") 21 | importFrom(stats,terms) 22 | importFrom(stringi,stri_detect_fixed) 23 | importFrom(stringi,stri_enc_toutf8) 24 | importFrom(stringi,stri_replace_all_regex) 25 | importFrom(stringi,stri_split_fixed) 26 | importFrom(stringi,stri_split_regex) 27 | importFrom(stringi,stri_trim) 28 | importFrom(tinytest,at_home) 29 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # gdns 0.5.0 2 | 3 | * Addressed CRAN check issues 4 | * Switched to tinytest 5 | * Switched to MIT license 6 | * Added support for 'dns-message' new content type 7 | 8 | # gdns 0.4.0 9 | 10 | * Updated the JSON API endpoint per Google notification 11 | * Added `dig()` alias for `query()` 12 | * Added an `as.data.frame()` coercer for query results 13 | * Added IANA DNS-related datasets 14 | 15 | # gdns 0.3.1 16 | 17 | * fixed bug in `bulk_query()` 18 | 19 | # gdns 0.3.0 20 | 21 | * removed purrr, dplyr and tibble dependencies 22 | * `bulk_query()` now returns the original query string in a `query` column 23 | * added `resource_record_tbl` data frame of DNS RR metadata 24 | 25 | # gdns 0.2.1 26 | 27 | * Fix CRAN checks due to purrr insanity 28 | 29 | # gdns 0.2.0 30 | 31 | * CRAN release 32 | * Added a `NEWS.md` file to track changes to the package. 33 | -------------------------------------------------------------------------------- /R/as-data-frame.R: -------------------------------------------------------------------------------- 1 | #' Coerce a gdns query response answer to a data frame 2 | #' 3 | #' Helper function to get to the `Answer` quickly 4 | #' @param x a `gdns_response` object 5 | #' @param ... unused 6 | #' @export 7 | as.data.frame.gdns_response <- function(x, ...) { 8 | 9 | if (length(x[["Answer"]]) == 0) { 10 | data.frame( 11 | name = NA_character_, 12 | type = NA_character_, 13 | ttl = NA_character_, 14 | data = NA_character_, 15 | stringsAsFactors = FALSE 16 | ) -> out 17 | } else { 18 | out <- x[["Answer"]] 19 | } 20 | 21 | if (length(x[["Question"]][["name"]])) { 22 | out[["query"]] <- x[["Question"]][["name"]][[1]] 23 | out[["qtype"]] <- x[["Question"]][["type"]][[1]] 24 | } else { 25 | out[["query"]] <- NA_character_ 26 | out[["qtype"]] <- NA_character_ 27 | } 28 | 29 | colnames(out) <- tolower(colnames(out)) 30 | out <- out[,c("query", "qtype", "name", "type", "ttl", "data")] 31 | 32 | class(out) <- c("tbl_df", "tbl", "data.frame") 33 | out 34 | 35 | } 36 | -------------------------------------------------------------------------------- /R/datasets.R: -------------------------------------------------------------------------------- 1 | # This file is autogenerated. Do not edit by hand. 2 | # Last refresh: 2019-06-27 11:16:48 3 | 4 | #' @md 5 | #' @title DNS CLASSes (dataset) 6 | #' @description DNS CLASSes 7 | #' @format data frame with columns: `decimal`, `hexadecimal`, `name`, `reference` 8 | #' @docType data 9 | #' @keywords datasets 10 | #' @name dns_classes 11 | #' @references 12 | #' @references 13 | #' @references rfc6895 14 | #' @note As noted in , Multicast DNS can only carry DNS records with classes in the range 0-32767. 15 | #' Classes in the range 32768 to 65535 are incompatible with Multicast DNS. 16 | #' @note Last updated 2019-06-27 11:16:48 17 | #' @usage data('dns_classes') 18 | NULL 19 | 20 | #' @md 21 | #' @title Resource Record (RR) TYPEs (dataset) 22 | #' @description Resource Record (RR) TYPEs 23 | #' @format data frame with columns: `type`, `value`, `meaning`, `reference`, `template`, `registration_date` 24 | #' @docType data 25 | #' @keywords datasets 26 | #' @name rrtypes 27 | #' @references 28 | #' @references 29 | #' @references rfc6895, rfc1035 30 | #' @note Last updated 2019-06-27 11:16:48 31 | #' @usage data('rrtypes') 32 | NULL 33 | 34 | #' @md 35 | #' @title DNS OpCodes (dataset) 36 | #' @description DNS OpCodes 37 | #' @format data frame with columns: `op_code`, `name`, `reference` 38 | #' @docType data 39 | #' @keywords datasets 40 | #' @name dns_opcodes 41 | #' @references 42 | #' @references 43 | #' @references rfc6895, rfc1035 44 | #' @note Last updated 2019-06-27 11:16:48 45 | #' @usage data('dns_opcodes') 46 | NULL 47 | 48 | #' @md 49 | #' @title DNS RCODEs (dataset) 50 | #' @description DNS RCODEs 51 | #' @format data frame with columns: `rcode`, `name`, `description`, `reference` 52 | #' @docType data 53 | #' @keywords datasets 54 | #' @name dns_rcodes 55 | #' @references 56 | #' @references 57 | #' @references rfc6895, rfc1035 58 | #' @note Last updated 2019-06-27 11:16:48 59 | #' @usage data('dns_rcodes') 60 | NULL 61 | 62 | #' @md 63 | #' @title DNS EDNS0 Option Codes (OPT) (dataset) 64 | #' @description DNS EDNS0 Option Codes (OPT) 65 | #' @format data frame with columns: `value`, `name`, `status`, `reference` 66 | #' @docType data 67 | #' @keywords datasets 68 | #' @name edns0_option_codes 69 | #' @references 70 | #' @references 71 | #' @references rfc6891, 3604 72 | #' @note Registrations made by standards-track documents are listed as "Standard," 73 | #' and by non-standards-track documents as "Optional." Registrations for 74 | #' which there are no final specifications are listed as "On-Hold." 75 | #' @note Last updated 2019-06-27 11:16:48 76 | #' @usage data('edns0_option_codes') 77 | NULL 78 | 79 | #' @md 80 | #' @title Underscored and Globally Scoped DNS Node Names (dataset) 81 | #' @description Underscored and Globally Scoped DNS Node Names 82 | #' @format data frame with columns: `rr_type`, `node_name`, `reference` 83 | #' @docType data 84 | #' @keywords datasets 85 | #' @name dns_glob_names 86 | #' @references 87 | #' @references 88 | #' @references rfc8552 89 | #' @note Last updated 2019-06-27 11:16:48 90 | #' @usage data('dns_glob_names') 91 | NULL 92 | 93 | -------------------------------------------------------------------------------- /R/dkim.r: -------------------------------------------------------------------------------- 1 | #' #' Split out all SPF records in a domain's TXT record 2 | #' #' 3 | #' #' Given a vector of TXT records, this function will return a list of vectors 4 | #' #' of all the SPF records for each. If the given TXT record is not an SPF 5 | #' #' record, \code{NA} is returned (which makes it easy to skip with \code{purrr} 6 | #' #' functions). 7 | #' #' 8 | #' #' @param dkim_rec a character vector of DNS TXT records 9 | #' #' @export 10 | #' parse_dkim <- function(dkim_rec) { 11 | #' purrr::map_df(dkim_rec, .parse_dkim) 12 | #' } 13 | #' 14 | #' .parse_dkim <- function(dkim_rec) { 15 | #' 16 | #' if (has_dkim(dkim_rec)) { 17 | #' spf_rec <- stringi::stri_trim(stringi::stri_replace_all_regex(dkim_rec, '"', "")) 18 | #' recs <- stri_trim(unlist(stringi::stri_split_regex(dkim_rec, ";"))) 19 | #' recs <- grep("v=DKIM1", recs, invert=TRUE, value=TRUE) 20 | #' purrr::keep(recs, stringi::stri_detect_fixed, "=") %>% 21 | #' purrr::map_df(~{ 22 | #' x <- stringi::stri_match_all_regex(.x, "(.*)=(.*)")[[1]] 23 | #' data_frame(key=x[,2], value=x[,3]) 24 | #' }) 25 | #' } else { 26 | #' NULL 27 | #' } 28 | #' 29 | #' } 30 | #' 31 | #' #' Test for whether a DNS TXT record is a DKIM record 32 | #' #' 33 | #' #' @param spf_rec a character vector of DNS TXT records 34 | #' #' @export 35 | #' has_dkim <- function(dkim_rec) { 36 | #' grepl("v=DKIM1", dkim_rec) 37 | #' } 38 | -------------------------------------------------------------------------------- /R/gdns-package.r: -------------------------------------------------------------------------------- 1 | #' Tools to Work with Google DNS Over HTTPS API 2 | #' 3 | #' Traditional DNS queries and responses are sent over UDP or TCP without 4 | #' encryption. This is vulnerable to eavesdropping and spoofing (including 5 | #' DNS-based Internet filtering). Responses from recursive resolvers to clients 6 | #' are the most vulnerable to undesired or malicious changes, while 7 | #' communications between recursive resolvers and authoritative nameservers 8 | #' often incorporate additional protection.\cr 9 | #' \cr 10 | #' To address this problem, Google Public DNS offers DNS resolution over an 11 | #' encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and 12 | #' security between a client and a recursive resolver, and complements DNSSEC 13 | #' to provide end-to-end authenticated DNS lookups.\cr 14 | #' \cr 15 | #' Support for reverse lookups is also provided.\cr 16 | #' \cr 17 | #' See \url{https://developers.google.com/speed/public-dns/docs/dns-over-https} 18 | #' for more information. 19 | #' 20 | #' @name gdns 21 | #' @docType package 22 | #' @author Bob Rudis (bob@@rud.is) 23 | #' @import httr 24 | #' @importFrom stringi stri_split_fixed stri_split_regex stri_trim 25 | #' stri_replace_all_regex stri_enc_toutf8 26 | #' stri_detect_fixed 27 | #' @importFrom jsonlite fromJSON 28 | #' @importFrom stats terms 29 | #' @importFrom tinytest at_home 30 | NULL 31 | 32 | 33 | #' An overview of resource records (RRs) permissible in zone files of the Domain Name System (DNS) 34 | #' 35 | #' A dataset containing the DNS resource record types, names, description and purpose 36 | #' 37 | #' @format A data frame with 39 rows and 4 variables: 38 | #' \describe{ 39 | #' \item{type}{numeric type of the resource record} 40 | #' \item{name}{short name of the resource record} 41 | #' \item{description}{short description of the resource record} 42 | #' \item{purpose}{long-form description of the resource record purpose/function/usage} 43 | #' } 44 | #' @source \url{https://en.wikipedia.org/wiki/List_of_DNS_record_types} 45 | "resource_record_tbl" 46 | -------------------------------------------------------------------------------- /R/spf.r: -------------------------------------------------------------------------------- 1 | #' Split out all SPF records in a domain's TXT record 2 | #' 3 | #' Given a vector of TXT records, this function will return a list of vectors 4 | #' of all the SPF records for each. If the given TXT record is not an SPF 5 | #' record, \code{NA} is returned (which makes it easy to skip with \code{purrr} 6 | #' functions). 7 | #' 8 | #' @param spf_rec a character vector of DNS TXT records 9 | #' @return list; each element is chr vector of spf components 10 | #' @export 11 | #' @examples 12 | #' split_spf("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all") 13 | split_spf <- function(spf_rec) { 14 | map(spf_rec, .split_spf) 15 | } 16 | 17 | .split_spf <- function(spf_rec) { 18 | 19 | if (has_spf(spf_rec)) { 20 | spf_rec <- stringi::stri_trim(stringi::stri_replace_all_regex(spf_rec, '"', "")) 21 | recs <- stri_trim(unlist(stringi::stri_split_regex(spf_rec, "\ +"))) 22 | grep("v=spf1", recs, invert=TRUE, value=TRUE) 23 | } else { 24 | NA_character_ 25 | } 26 | 27 | } 28 | 29 | #' Test for whether a DNS TXT record is an SPF record 30 | #' 31 | #' @param spf_rec a character vector of DNS TXT records 32 | #' @export 33 | #' @return character vector 34 | #' @examples 35 | #' has_spf("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all") 36 | has_spf <- function(spf_rec) { 37 | grepl("v=spf1", spf_rec) 38 | } 39 | 40 | #' SPF "all" type test 41 | #' 42 | #' @param spf_rec a character vector of DNS TXT records 43 | #' @export 44 | #' @return logical 45 | #' @examples 46 | #' is_soft_fail("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all") 47 | #' is_hard_fail("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all") 48 | #' passes_all("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all") 49 | is_soft_fail <- function(spf_rec) { 50 | ret <- vector("logical", length(spf_rec)) 51 | spf_rec <- stringi::stri_trim(stringi::stri_replace_all_regex(spf_rec, '"', "")) 52 | SPF <- which(has_spf(spf_rec)) 53 | ret[SPF] <- grepl("~all$", stringi::stri_trim(spf_rec[SPF])) 54 | ret[!SPF] <- NA 55 | ret 56 | } 57 | 58 | #' @rdname is_soft_fail 59 | #' @export 60 | is_hard_fail <- function(spf_rec) { 61 | ret <- vector("logical", length(spf_rec)) 62 | spf_rec <- stringi::stri_trim(stringi::stri_replace_all_regex(spf_rec, '"', "")) 63 | SPF <- which(has_spf(spf_rec)) 64 | ret[SPF] <- grepl("\\-all$", stringi::stri_trim(spf_rec[SPF])) 65 | ret[!SPF] <- NA 66 | ret 67 | } 68 | 69 | #' @rdname is_soft_fail 70 | #' @export 71 | passes_all <- function(spf_rec) { 72 | ret <- vector("logical", length(spf_rec)) 73 | spf_rec <- stringi::stri_trim(stringi::stri_replace_all_regex(spf_rec, '"', "")) 74 | SPF <- which(has_spf(spf_rec)) 75 | ret[SPF] <- grepl("[\\+ ]all$", stringi::stri_trim(spf_rec[SPF])) 76 | ret[!SPF] <- NA 77 | ret 78 | } 79 | 80 | #' SPF field extraction functions 81 | #' 82 | #' Various helper functions to extract SPF record components. 83 | #' 84 | #' @param spf_rec a character vector of DNS TXT records 85 | #' @export 86 | #' @return list; each element is a character vector of the specified component 87 | #' spf_ipv4s("v=spf1 +mx ip4:214.3.140.16/32 ip4:214.3.140.255/32 ip4:214.3.115.12/32") 88 | spf_ipv4s <- function(spf_rec) { 89 | map(split_spf(spf_rec), function(x) { 90 | stringi::stri_replace_all_regex(grep("ip4", x, value=TRUE), "^ip4:", "") 91 | }) 92 | } 93 | 94 | #' @rdname spf_ipv4s 95 | #' @export 96 | spf_ipv6s <- function(spf_rec) { 97 | map(split_spf(spf_rec), function(x) { 98 | stringi::stri_replace_all_regex(grep("ip6", x, value=TRUE), "^ip6:", "") 99 | }) 100 | } 101 | 102 | #' @rdname spf_ipv4s 103 | #' @export 104 | spf_includes <- function(spf_rec) { 105 | map(split_spf(spf_rec), function(x) { 106 | stringi::stri_replace_all_regex(grep("include", x, value=TRUE), "^include:", "") 107 | }) 108 | } 109 | 110 | #' @rdname spf_ipv4s 111 | #' @export 112 | spf_ptrs <- function(spf_rec) { 113 | map(split_spf(spf_rec), function(x) { 114 | stringi::stri_replace_all_regex(grep("ptr", x, value=TRUE), "^ptr[:]", "") 115 | }) 116 | } 117 | 118 | #' @rdname spf_ipv4s 119 | #' @export 120 | spf_exists <- function(spf_rec) { 121 | map(split_spf(spf_rec), function(x) { 122 | stringi::stri_replace_all_regex(grep("exists", x, value=TRUE), "^exists:", "") 123 | }) 124 | } 125 | -------------------------------------------------------------------------------- /R/utils-mappers.R: -------------------------------------------------------------------------------- 1 | # NOTE these aren't 100% equivalent to the purrr mappers but cover very common use-cases 2 | # 3 | # NOTE formula function (e.g. ~{}) are 100% supported 4 | 5 | map <- function(.x, .f, ...) { 6 | 7 | if (inherits(.f, "formula")) { 8 | .body <- dimnames(attr(terms(.f), "factors"))[[1]] 9 | .f <- function(.x, . = .x) {} 10 | body(.f) <- as.expression(parse(text=.body)) 11 | } 12 | 13 | if (inherits(.f, "function")) { 14 | lapply(.x, .f, ...) 15 | } else if (is.numeric(.f)) { 16 | lapply(.x, `[`, .f) 17 | } 18 | 19 | } 20 | 21 | map2 <- function(.x, .y, .f, ...) { 22 | 23 | if (inherits(.f, "formula")) { 24 | .body <- dimnames(attr(terms(.f), "factors"))[[1]] 25 | .f <- function(.x, .y, . = .x) {} 26 | body(.f) <- as.expression(parse(text=.body)) 27 | } 28 | 29 | if (inherits(.f, "function")) { 30 | mapply(.f, .x, .y, ..., SIMPLIFY=FALSE, USE.NAMES=FALSE) 31 | } 32 | 33 | } 34 | 35 | map_chr <- function(.x, .f, ...) { 36 | as.character(unlist(map(.x, .f, ...), use.names = FALSE)) 37 | } 38 | 39 | map2_chr <- function(.x, .y, .f, ...) { 40 | as.character(unlist(map2(.x, .y, .f, ...), use.names = FALSE)) 41 | } 42 | 43 | map_lgl <- function(.x, .f, ...) { 44 | as.logical(unlist(map(.x, .f, ...), use.names = FALSE)) 45 | } 46 | 47 | map2_lgl <- function(.x, .y, .f, ...) { 48 | as.logical(unlist(map2(.x, .y, .f, ...), use.names = FALSE)) 49 | } 50 | 51 | map_dbl <- function(.x, .f, ...) { 52 | as.double(unlist(map(.x, .f, ...), use.names = FALSE)) 53 | } 54 | 55 | map2_dbl <- function(.x, .y, .f, ...) { 56 | as.double(unlist(map2(.x, .y, .f, ...), use.names = FALSE)) 57 | } 58 | 59 | map_int <- function(.x, .f, ...) { 60 | as.integer(unlist(map(.x, .f, ...), use.names = FALSE)) 61 | } 62 | 63 | map2_int <- function(.x, .y, .f, ...) { 64 | as.integer(unlist(map2(.x, .y, .f, ...), use.names = FALSE)) 65 | } 66 | 67 | 68 | map_df <- function(.x, .f, ..., .id=NULL) { 69 | 70 | res <- map(.x, .f, ...) 71 | out <- bind_rows(res, .id=.id) 72 | out 73 | 74 | } 75 | 76 | map2_df <- function(.x, .y, .f, ..., .id=NULL) { 77 | 78 | res <- map(.x, .y, .f, ...) 79 | out <- bind_rows(res, .id = .id) 80 | out 81 | 82 | } 83 | 84 | # this has limitations and is more like 75% of dplyr::bind_rows() 85 | # this is also orders of magnitude slower than dplyr::bind_rows() 86 | bind_rows <- function(..., .id = NULL) { 87 | 88 | res <- list(...) 89 | 90 | if (length(res) == 1) res <- res[[1]] 91 | 92 | cols <- unique(unlist(lapply(res, names), use.names = FALSE)) 93 | 94 | if (!is.null(.id)) { 95 | inthere <- cols[.id %in% cols] 96 | if (length(inthere) > 0) { 97 | .id <- make.unique(c(inthere, .id))[2] 98 | } 99 | } 100 | 101 | id_vals <- if (is.null(names(res))) 1:length(res) else names(res) 102 | 103 | saf <- default.stringsAsFactors() 104 | options(stringsAsFactors = FALSE) 105 | on.exit(options(stringsAsFactors = saf)) 106 | 107 | idx <- 1 108 | do.call( 109 | rbind.data.frame, 110 | lapply(res, function(.x) { 111 | x_names <- names(.x) 112 | moar_names <- setdiff(cols, x_names) 113 | if (length(moar_names) > 0) { 114 | for (i in 1:length(moar_names)) { 115 | .x[[moar_names[i]]] <- rep(NA, length(.x[[1]])) 116 | } 117 | } 118 | if (!is.null(.id)) { 119 | .x[[.id]] <- id_vals[idx] 120 | idx <<- idx + 1 121 | } 122 | .x 123 | }) 124 | ) -> out 125 | 126 | rownames(out) <- NULL 127 | 128 | class(out) <- c("tbl_df", "tbl", "data.frame") 129 | 130 | out 131 | 132 | } 133 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | NULL 12 | -------------------------------------------------------------------------------- /R/utils-safely.R: -------------------------------------------------------------------------------- 1 | # Less cool counterparts to purrr's side-effect capture-rs 2 | # 3 | # Most of the helper functions are 100% from output.R in purrr repo 4 | # 5 | # @param quiet Hide errors (`TRUE`, the default), or display them 6 | # as they occur? 7 | # @param otherwise Default value to use when an error occurs. 8 | # 9 | # @return `safely`: wrapped function instead returns a list with 10 | # components `result` and `error`. One value is always `NULL`. 11 | # 12 | # `quietly`: wrapped function instead returns a list with components 13 | # `result`, `output`, `messages` and `warnings`. 14 | # 15 | # `possibly`: wrapped function uses a default value (`otherwise`) 16 | # whenever an error occurs. 17 | safely <- function(.f, otherwise = NULL, quiet = TRUE) { 18 | function(...) capture_error(.f(...), otherwise, quiet) 19 | } 20 | 21 | quietly <- function(.f) { 22 | function(...) capture_output(.f(...)) 23 | } 24 | 25 | possibly <- function(.f, otherwise, quiet = TRUE) { 26 | force(otherwise) 27 | function(...) { 28 | tryCatch(.f(...), 29 | error = function(e) { 30 | if (!quiet) 31 | message("Error: ", e$message) 32 | otherwise 33 | }, 34 | interrupt = function(e) { 35 | stop("Terminated by user", call. = FALSE) 36 | } 37 | ) 38 | } 39 | } 40 | 41 | capture_error <- function(code, otherwise = NULL, quiet = TRUE) { 42 | tryCatch( 43 | list(result = code, error = NULL), 44 | error = function(e) { 45 | if (!quiet) 46 | message("Error: ", e$message) 47 | 48 | list(result = otherwise, error = e) 49 | }, 50 | interrupt = function(e) { 51 | stop("Terminated by user", call. = FALSE) 52 | } 53 | ) 54 | } 55 | 56 | capture_output <- function(code) { 57 | warnings <- character() 58 | wHandler <- function(w) { 59 | warnings <<- c(warnings, w$message) 60 | invokeRestart("muffleWarning") 61 | } 62 | 63 | messages <- character() 64 | mHandler <- function(m) { 65 | messages <<- c(messages, m$message) 66 | invokeRestart("muffleMessage") 67 | } 68 | 69 | temp <- file() 70 | sink(temp) 71 | on.exit({ 72 | sink() 73 | close(temp) 74 | }) 75 | 76 | result <- withCallingHandlers( 77 | code, 78 | warning = wHandler, 79 | message = mHandler 80 | ) 81 | 82 | output <- paste0(readLines(temp, warn = FALSE), collapse = "\n") 83 | 84 | list( 85 | result = result, 86 | output = output, 87 | warnings = warnings, 88 | messages = messages 89 | ) 90 | } 91 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | set_names <- function (object = nm, nm) { 2 | names(object) <- nm 3 | object 4 | } 5 | -------------------------------------------------------------------------------- /R/zbulk-query.R: -------------------------------------------------------------------------------- 1 | #' Vectorized query, returning only answers in a data frame 2 | #' 3 | #' @param entities character vector of entities to query 4 | #' @param type RR type can be represented as a number in [1, 65535] or canonical 5 | #' string (A, aaaa, etc). More information on RR types can be 6 | #' found \href{http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4}{here}. 7 | #' @param cd (Checking Disabled) flag. Use `TRUE` to disable DNSSEC validation; 8 | #' Default: `FALSE`. 9 | #' @param do (DNSSEC OK) flag. Use `TRUE` include DNSSEC records (RRSIG, NSEC, NSEC3); 10 | #' Default: `FALSE`. 11 | #' @param edns_client_subnet The edns0-client-subnet option. Format is an IP 12 | #' address with a subnet mask. Examples: \code{1.2.3.4/24}, 13 | #' \code{2001:700:300::/48}.\cr 14 | #' If you are using DNS-over-HTTPS because of privacy concerns, and do 15 | #' not want any part of your IP address to be sent to authoritative 16 | #' nameservers for geographic location accuracy, use 17 | #' \code{edns_client_subnet=0.0.0.0/0}. Google Public DNS normally sends 18 | #' approximate network information (usually replacing the last part of 19 | #' your IPv4 address with zeroes). \code{0.0.0.0/0} is the default. 20 | #' @return \code{data.frame} of only answers (use \code{query()} for detailed responses) 21 | #' @references \url{https://developers.google.com/speed/public-dns/docs/dns-over-https} 22 | #' @export 23 | #' @note this is a fairly naive function. It expects \code{Answer} to be one of the 24 | #' return value list slots. The intent for it was to make it easier 25 | #' to do bulk forward queries. It will get smarter in future versions. 26 | #' @examples 27 | #' if (tinytest::at_home()) { 28 | #' hosts <- c("rud.is", "r-project.org", "rstudio.com", "apple.com") 29 | #' gdns::bulk_query(hosts) 30 | #' } 31 | bulk_query <- function(entities, type = 1, cd = FALSE, do = FALSE, 32 | edns_client_subnet = "0.0.0.0/0") { 33 | 34 | lapply( 35 | entities, 36 | query, type = type, cd = cd, 37 | edns_client_subnet = edns_client_subnet 38 | ) -> results 39 | 40 | lapply(seq_along(results), function(idx) { 41 | res <- as.data.frame(results[[idx]]) 42 | res$entity <- entities[[idx]] 43 | res 44 | }) -> xlst 45 | 46 | xdf <- do.call(rbind.data.frame, xlst) 47 | class(xdf) <- c("tbl_df", "tbl", "data.frame") 48 | xdf 49 | 50 | } 51 | -------------------------------------------------------------------------------- /R/zgdns.r: -------------------------------------------------------------------------------- 1 | ipv4_regex <- 2 | "^(?:(?: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]?)$" 3 | 4 | S_GET <- safely(httr::GET) 5 | 6 | #' Perform DNS over HTTPS queries using Google 7 | #' 8 | #' Traditional DNS queries and responses are sent over UDP or TCP without 9 | #' encryption. This is vulnerable to eavesdropping and spoofing (including 10 | #' DNS-based Internet filtering). Responses from recursive resolvers to clients 11 | #' are the most vulnerable to undesired or malicious changes, while 12 | #' communications between recursive resolvers and authoritative nameservers 13 | #' often incorporate additional protection.\cr 14 | #' \cr 15 | #' To address this problem, Google Public DNS offers DNS resolution over an 16 | #' encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and 17 | #' security between a client and a recursive resolver, and complements DNSSEC 18 | #' to provide end-to-end authenticated DNS lookups. 19 | #' 20 | #' To perform vectorized queries with only answers (and no metadata) use 21 | #' \code{bulk_query()}). 22 | #' 23 | #' @param name item to lookup. Valid characters are numbers, letters, hyphen, and dot. Length 24 | #' must be between 1 and 255. Names with escaped or non-ASCII characters 25 | #' are not supported. Internationalized domain names must use the 26 | #' punycode format (e.g. "\code{xn--qxam}").\cr 27 | #' \cr If an IPv4 string is input, it will be transformed into 28 | #' a proper format for reverse lookups. 29 | #' @param type RR type can be represented as a number in [1, 65535] or canonical 30 | #' string (A, aaaa, etc). More information on RR types can be 31 | #' found \href{http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4}{here}. 32 | #' You can use \code{255} for an \code{ANY} query. 33 | #' @param cd (Checking Disabled) flag. Use `TRUE` to disable DNSSEC validation; 34 | #' Default: `FALSE`. 35 | #' @param ct (Content Type) Desired content type option. Use `application/dns-message` 36 | #' to receive a binary DNS message in the response HTTP body instead of JSON text. 37 | #' Use `application/x-javascript` (the default) to explicitly request JSON text. 38 | #' Other content type values are ignored and default JSON content is returned. 39 | #' @param do (DNSSEC OK) flag. Use `TRUE` include DNSSEC records (RRSIG, NSEC, NSEC3); 40 | #' Default: `FALSE`. 41 | #' @param random_padding clients concerned about possible side-channel privacy 42 | #' attacks using the packet sizes of HTTPS GET requests can use this to 43 | #' make all requests exactly the same size by padding requests with random data. 44 | #' To prevent misinterpretation of the URL, restrict the padding characters to 45 | #' the unreserved URL characters: upper- and lower-case letters, digits, 46 | #' hyphen, period, underscore and tilde. 47 | #' @param edns_client_subnet The edns0-client-subnet option. Format is an IP 48 | #' address with a subnet mask. Examples: \code{1.2.3.4/24}, 49 | #' \code{2001:700:300::/48}.\cr 50 | #' If you are using DNS-over-HTTPS because of privacy concerns, and do 51 | #' not want any part of your IP address to be sent to authoritative 52 | #' nameservers for geographic location accuracy, use 53 | #' \code{edns_client_subnet=0.0.0.0/0}. Google Public DNS normally sends 54 | #' approximate network information (usually replacing the last part of 55 | #' your IPv4 address with zeroes). \code{0.0.0.0/0} is the default. 56 | #' @return a \code{list} with the query result or \code{NULL} if an error occurred 57 | #' @references 58 | #' @export 59 | #' @examples 60 | #' if (tinytest::at_home()) { 61 | #' query("rud.is") 62 | #' dig("example.com", "255") # ANY query 63 | #' query("microsoft.com", "MX") 64 | #' dig("google-public-dns-a.google.com", "TXT") 65 | #' query("apple.com") 66 | #' dig("17.142.160.59", "PTR") 67 | #' } 68 | query <- function(name, type = "1", cd = FALSE, 69 | ct = "application/x-javascript", 70 | do = FALSE, edns_client_subnet = "0.0.0.0/0", 71 | random_padding = NULL) { 72 | 73 | name <- name[1] 74 | cd <- cd[1] 75 | ct <- ct[1] 76 | do <- do[1] 77 | edns_client_subnet <- edns_client_subnet[1] 78 | random_padding <- random_padding[1] 79 | 80 | # helper to turn IPv4 addresses in to in-addr.arpa. 81 | 82 | if (grepl(ipv4_regex, name)) { 83 | name <- paste0(c(rev(unlist(stringi::stri_split_fixed(name, ".", 4))), 84 | "in-addr.arpa."), 85 | sep="", collapse=".") 86 | } 87 | 88 | res <- S_GET( 89 | url = "https://dns.google/resolve", 90 | query = list( 91 | name = name, 92 | type = type, 93 | cd = if (cd) 1 else 0, 94 | do = if (do) 1 else 0, 95 | ct = ct, 96 | edns_client_subnet = edns_client_subnet, 97 | random_padding = random_padding 98 | ) 99 | ) 100 | 101 | if (!is.null(res$result)) { 102 | 103 | stop_for_status(res$result) 104 | 105 | if (ct == "application/dns-message") { 106 | 107 | out <- httr::content(res$result, as="raw") 108 | 109 | class(out) <- c("gdns_raw_response", "list") 110 | 111 | out 112 | 113 | 114 | } else { 115 | 116 | txt <- httr::content(res$result, as="text") 117 | 118 | txt <- stringi::stri_enc_toascii(txt) 119 | txt <- stringi::stri_replace_all_regex(txt, "[[:cntrl:][:blank:]\\n ]+", " ") 120 | 121 | out <- jsonlite::fromJSON(txt) 122 | 123 | class(out) <- c("gdns_response", "list") 124 | 125 | } 126 | 127 | out 128 | 129 | } else { 130 | NULL 131 | } 132 | 133 | } 134 | 135 | #' @rdname query 136 | #' @export 137 | dig <- query 138 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: rmarkdown::github_document 3 | editor_options: 4 | chunk_output_type: console 5 | --- 6 | 7 | 8 | 9 | ```{r include=FALSE} 10 | knitr::opts_chunk$set( 11 | message = FALSE, 12 | warning = FALSE, 13 | fig.retina = 2 14 | ) 15 | options(width=120) 16 | ``` 17 | 18 | [![Travis-CI Build Status](https://travis-ci.org/hrbrmstr/gdns.svg?branch=master)](https://travis-ci.org/hrbrmstr/gdns) 19 | 20 | # gdns 21 | 22 | Tools to work with the Google DNS over HTTPS (DoH) API 23 | 24 | ## Description 25 | 26 | Traditional DNS queries and responses are sent over UDP or TCP without encryption. This is vulnerable to eavesdropping and spoofing (including DNS-based Internet filtering). Responses from recursive resolvers to clients are the most vulnerable to undesired or malicious changes, while communications between recursive resolvers and authoritative nameservers often incorporate additional protection. 27 | 28 | To address this problem, Google Public DNS offers DNS resolution over an encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and security between a client and a recursive resolver, and complements DNSSEC to provide end-to-end authenticated DNS lookups. 29 | 30 | More info at . 31 | 32 | The following functions are implemented: 33 | 34 | Core: 35 | 36 | - `query` / `dig`: Perform DNS over HTTPS queries using Google 37 | - `bulk_query`: Vectorized query, returning only answers in a data frame 38 | - `as.data.frame`: Coerce a gdns query response answer to a data frame 39 | 40 | Helpers: 41 | 42 | - `has_spf`: Test for whether a DNS TXT record is an SPF record 43 | - `is_hard_fail`: SPF "all" type test 44 | - `is_soft_fail`: SPF "all" type test 45 | - `passes_all`: SPF "all" type test 46 | - `spf_exists`: SPF field extraction functions 47 | - `spf_includes`: SPF field extraction functions 48 | - `spf_ipv4s`: SPF field extraction functions 49 | - `spf_ipv6s`: SPF field extraction functions 50 | - `spf_ptrs`: SPF field extraction functions 51 | - `split_spf`: Split out all SPF records in a domain's TXT record 52 | 53 | IANA Datasets: 54 | 55 | - `dns_classes`: DNS CLASSes (dataset) 56 | - `dns_glob_names`: Underscored and Globally Scoped DNS Node Names (dataset) 57 | - `dns_opcodes`: DNS OpCodes (dataset) 58 | - `dns_rcodes`: DNS RCODEs (dataset) 59 | - `edns0_option_codes`: DNS EDNS0 Option Codes (OPT) (dataset) 60 | - `rrtypes`: Resource Record (RR) TYPEs (dataset) 61 | 62 | ### Installation 63 | 64 | Any of the following: 65 | 66 | ```{r eval=FALSE} 67 | install.packages("gdns", repos = "https://cinc.rud.is") 68 | devtools::install_git("https://git.rud.is/hrbrmstr/gdns") 69 | devtools::install_git("https://git.sr.ht/~rbrmstr/gdns") 70 | devtools::install_bitbucket("hrbrmstr/gdns") 71 | devtools::install_gitlab("hrbrmstr/gdns") 72 | devtools::install_github("hrbrmstr/gdns") 73 | ``` 74 | 75 | ```{r echo=FALSE, message=FALSE, warning=FALSE, error=FALSE} 76 | options(width=120) 77 | ``` 78 | 79 | ### Usage 80 | 81 | ```{r} 82 | library(gdns) 83 | library(tibble) # for printing 84 | 85 | # current verison 86 | packageVersion("gdns") 87 | 88 | str(query("rud.is")) 89 | 90 | query("rud.is") %>% 91 | as.data.frame() 92 | 93 | str(dig("example.com", "255")) # "ANY" query 94 | 95 | query("microsoft.com", "MX") %>% 96 | as.data.frame() 97 | 98 | as.data.frame(query("apple.com")) 99 | 100 | as.data.frame(dig("17.142.160.59", "PTR")) 101 | 102 | hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com") 103 | 104 | gdns::bulk_query(hosts) 105 | ``` 106 | 107 | ## gdns Metrics 108 | 109 | ```{r cloc, echo=FALSE} 110 | cloc::cloc_pkg_md() 111 | ``` 112 | 113 | ## Code of Conduct 114 | 115 | Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | [![Travis-CI Build 5 | Status](https://travis-ci.org/hrbrmstr/gdns.svg?branch=master)](https://travis-ci.org/hrbrmstr/gdns) 6 | 7 | # gdns 8 | 9 | Tools to work with the Google DNS over HTTPS (DoH) API 10 | 11 | ## Description 12 | 13 | Traditional DNS queries and responses are sent over UDP or TCP without 14 | encryption. This is vulnerable to eavesdropping and spoofing (including 15 | DNS-based Internet filtering). Responses from recursive resolvers to 16 | clients are the most vulnerable to undesired or malicious changes, while 17 | communications between recursive resolvers and authoritative nameservers 18 | often incorporate additional protection. 19 | 20 | To address this problem, Google Public DNS offers DNS resolution over an 21 | encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and 22 | security between a client and a recursive resolver, and complements 23 | DNSSEC to provide end-to-end authenticated DNS lookups. 24 | 25 | More info at . 26 | 27 | The following functions are implemented: 28 | 29 | Core: 30 | 31 | - `query` / `dig`: Perform DNS over HTTPS queries using Google 32 | - `bulk_query`: Vectorized query, returning only answers in a data 33 | frame 34 | - `as.data.frame`: Coerce a gdns query response answer to a data frame 35 | 36 | Helpers: 37 | 38 | - `has_spf`: Test for whether a DNS TXT record is an SPF record 39 | - `is_hard_fail`: SPF “all” type test 40 | - `is_soft_fail`: SPF “all” type test 41 | - `passes_all`: SPF “all” type test 42 | - `spf_exists`: SPF field extraction functions 43 | - `spf_includes`: SPF field extraction functions 44 | - `spf_ipv4s`: SPF field extraction functions 45 | - `spf_ipv6s`: SPF field extraction functions 46 | - `spf_ptrs`: SPF field extraction functions 47 | - `split_spf`: Split out all SPF records in a domain’s TXT record 48 | 49 | IANA Datasets: 50 | 51 | - `dns_classes`: DNS CLASSes (dataset) 52 | - `dns_glob_names`: Underscored and Globally Scoped DNS Node Names 53 | (dataset) 54 | - `dns_opcodes`: DNS OpCodes (dataset) 55 | - `dns_rcodes`: DNS RCODEs (dataset) 56 | - `edns0_option_codes`: DNS EDNS0 Option Codes (OPT) (dataset) 57 | - `rrtypes`: Resource Record (RR) TYPEs (dataset) 58 | 59 | ### Installation 60 | 61 | Any of the following: 62 | 63 | ``` r 64 | install.packages("gdns", repos = "https://cinc.rud.is") 65 | devtools::install_git("https://git.rud.is/hrbrmstr/gdns") 66 | devtools::install_git("https://git.sr.ht/~rbrmstr/gdns") 67 | devtools::install_bitbucket("hrbrmstr/gdns") 68 | devtools::install_gitlab("hrbrmstr/gdns") 69 | devtools::install_github("hrbrmstr/gdns") 70 | ``` 71 | 72 | ### Usage 73 | 74 | ``` r 75 | library(gdns) 76 | library(tibble) # for printing 77 | 78 | # current verison 79 | packageVersion("gdns") 80 | ``` 81 | 82 | ## [1] '0.5.0' 83 | 84 | ``` r 85 | str(query("rud.is")) 86 | ``` 87 | 88 | ## List of 11 89 | ## $ Status : int 0 90 | ## $ TC : logi FALSE 91 | ## $ RD : logi TRUE 92 | ## $ RA : logi TRUE 93 | ## $ AD : logi FALSE 94 | ## $ CD : logi FALSE 95 | ## $ Question :'data.frame': 1 obs. of 2 variables: 96 | ## ..$ name: chr "rud.is." 97 | ## ..$ type: int 1 98 | ## $ Answer :'data.frame': 1 obs. of 4 variables: 99 | ## ..$ name: chr "rud.is." 100 | ## ..$ type: int 1 101 | ## ..$ TTL : int 3599 102 | ## ..$ data: chr "172.93.49.183" 103 | ## $ Additional : list() 104 | ## $ edns_client_subnet: chr "0.0.0.0/0" 105 | ## $ Comment : chr "Response from 84.246.121.10." 106 | ## - attr(*, "class")= chr [1:2] "gdns_response" "list" 107 | 108 | ``` r 109 | query("rud.is") %>% 110 | as.data.frame() 111 | ``` 112 | 113 | ## # A tibble: 1 x 6 114 | ## query qtype name type ttl data 115 | ## * 116 | ## 1 rud.is. 1 rud.is. 1 3599 172.93.49.183 117 | 118 | ``` r 119 | str(dig("example.com", "255")) # "ANY" query 120 | ``` 121 | 122 | ## List of 11 123 | ## $ Status : int 0 124 | ## $ TC : logi FALSE 125 | ## $ RD : logi TRUE 126 | ## $ RA : logi TRUE 127 | ## $ AD : logi TRUE 128 | ## $ CD : logi FALSE 129 | ## $ Question :'data.frame': 1 obs. of 2 variables: 130 | ## ..$ name: chr "example.com." 131 | ## ..$ type: int 255 132 | ## $ Answer :'data.frame': 2 obs. of 4 variables: 133 | ## ..$ name: chr [1:2] "example.com." "example.com." 134 | ## ..$ type: int [1:2] 47 46 135 | ## ..$ TTL : int [1:2] 3599 3599 136 | ## ..$ data: chr [1:2] "www.example.com. A NS SOA MX TXT AAAA RRSIG NSEC DNSKEY" "nsec 8 2 3600 1591086291 1589272385 21738 example.com. S9HOliGkjh8YEAU68DDrEtYmo2f1E8zeFKMqLMLrG8FzG9PSw1kG19Lk"| __truncated__ 137 | ## $ Additional : list() 138 | ## $ edns_client_subnet: chr "0.0.0.0/0" 139 | ## $ Comment : chr "Response from 2001:500:8d::53." 140 | ## - attr(*, "class")= chr [1:2] "gdns_response" "list" 141 | 142 | ``` r 143 | query("microsoft.com", "MX") %>% 144 | as.data.frame() 145 | ``` 146 | 147 | ## # A tibble: 1 x 6 148 | ## query qtype name type ttl data 149 | ## * 150 | ## 1 microsoft.com. 15 microsoft.com. 15 3599 10 microsoft-com.mail.protection.outlook.com. 151 | 152 | ``` r 153 | as.data.frame(query("apple.com")) 154 | ``` 155 | 156 | ## # A tibble: 3 x 6 157 | ## query qtype name type ttl data 158 | ## * 159 | ## 1 apple.com. 1 apple.com. 1 3441 17.172.224.47 160 | ## 2 apple.com. 1 apple.com. 1 3441 17.178.96.59 161 | ## 3 apple.com. 1 apple.com. 1 3441 17.142.160.59 162 | 163 | ``` r 164 | as.data.frame(dig("17.142.160.59", "PTR")) 165 | ``` 166 | 167 | ## # A tibble: 5 x 6 168 | ## query qtype name type ttl data 169 | ## * 170 | ## 1 59.160.142.17.in-addr.arpa. 12 59.160.142.17.in-addr.arpa. 12 3599 ipad.host. 171 | ## 2 59.160.142.17.in-addr.arpa. 12 59.160.142.17.in-addr.arpa. 12 3599 apple.by. 172 | ## 3 59.160.142.17.in-addr.arpa. 12 59.160.142.17.in-addr.arpa. 12 3599 apple.com. 173 | ## 4 59.160.142.17.in-addr.arpa. 12 59.160.142.17.in-addr.arpa. 12 3599 appleid.org. 174 | ## 5 59.160.142.17.in-addr.arpa. 12 59.160.142.17.in-addr.arpa. 12 3599 pv-apple-com.apple.com. 175 | 176 | ``` r 177 | hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com") 178 | 179 | gdns::bulk_query(hosts) 180 | ``` 181 | 182 | ## # A tibble: 7 x 7 183 | ## query qtype name type ttl data entity 184 | ## 185 | ## 1 rud.is. 1 rud.is. 1 3599 172.93.49.183 rud.is 186 | ## 2 dds.ec. 1 dds.ec. 1 599 104.247.81.52 dds.ec 187 | ## 3 r-project.org. 1 r-project.org. 1 7199 137.208.57.37 r-project.org 188 | ## 4 rstudio.com. 1 rstudio.com. 1 59 104.198.14.52 rstudio.com 189 | ## 5 apple.com. 1 apple.com. 1 3082 17.142.160.59 apple.com 190 | ## 6 apple.com. 1 apple.com. 1 3082 17.172.224.47 apple.com 191 | ## 7 apple.com. 1 apple.com. 1 3082 17.178.96.59 apple.com 192 | 193 | ## gdns Metrics 194 | 195 | | Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | 196 | | :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: | 197 | | R | 13 | 0.93 | 389 | 0.94 | 129 | 0.79 | 339 | 0.86 | 198 | | Rmd | 1 | 0.07 | 27 | 0.06 | 35 | 0.21 | 53 | 0.14 | 199 | 200 | ## Code of Conduct 201 | 202 | Please note that this project is released with a Contributor Code of 203 | Conduct. By participating in this project you agree to abide by its 204 | terms. 205 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE the "init" and "install" sections below 2 | 3 | # Download script file from GitHub 4 | init: 5 | ps: | 6 | $ErrorActionPreference = "Stop" 7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" 8 | Import-Module '..\appveyor-tool.ps1' 9 | 10 | install: 11 | ps: Bootstrap 12 | 13 | cache: 14 | - C:\RLibrary 15 | 16 | environment: 17 | NOT_CRAN: true 18 | # env vars that may need to be set, at least temporarily, from time to time 19 | # see https://github.com/krlmlr/r-appveyor#readme for details 20 | # USE_RTOOLS: true 21 | # R_REMOTES_STANDALONE: true 22 | 23 | # Adapt as necessary starting from here 24 | 25 | build_script: 26 | - travis-tool.sh install_deps 27 | 28 | test_script: 29 | - travis-tool.sh run_tests 30 | 31 | on_failure: 32 | - 7z a failure.zip *.Rcheck\* 33 | - appveyor PushArtifact failure.zip 34 | 35 | artifacts: 36 | - path: '*.Rcheck\**\*.log' 37 | name: Logs 38 | 39 | - path: '*.Rcheck\**\*.out' 40 | name: Logs 41 | 42 | - path: '*.Rcheck\**\*.fail' 43 | name: Logs 44 | 45 | - path: '*.Rcheck\**\*.Rout' 46 | name: Logs 47 | 48 | - path: '\*_*.tar.gz' 49 | name: Bits 50 | 51 | - path: '\*_*.zip' 52 | name: Bits 53 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Test environments 2 | * local OS X install, R 4.0.0 3 | * ubuntu 14.04 (on travis-ci), R 4.0.0 4 | * win-builder (devel and release) 5 | 6 | ## R CMD check results 7 | 8 | 0 errors | 0 warnings | 0 note 9 | 10 | * This is a new release. 11 | 12 | - Addressed CRAN check failures as per-CRAN email 13 | - Switched to MIT license 14 | - Added support for new google dns api params 15 | - Switched to tinytest 16 | - Added return types to all exported functions 17 | - Added examples to spf_ functions 18 | - Added tests for spf_functions 19 | -------------------------------------------------------------------------------- /data-raw/rrtypes.R: -------------------------------------------------------------------------------- 1 | ## code to prepare `rrtypes` dataset goes here 2 | 3 | library(tidyverse) 4 | library(xml2) 5 | 6 | xdf <- read_csv("https://www.iana.org/assignments/dns-parameters/dns-parameters-2.csv") 7 | dns_classes <- janitor::clean_names(xdf) 8 | usethis::use_data(dns_classes, overwrite = TRUE) 9 | 10 | xdf <- read_csv("https://www.iana.org/assignments/dns-parameters/dns-parameters-4.csv") 11 | rrtypes <- janitor::clean_names(xdf) 12 | usethis::use_data(rrtypes, overwrite = TRUE) 13 | 14 | xdf <- read_csv("https://www.iana.org/assignments/dns-parameters/dns-parameters-5.csv") 15 | dns_opcodes <- janitor::clean_names(xdf) 16 | usethis::use_data(dns_opcodes, overwrite = TRUE) 17 | 18 | xdf <- read_csv("https://www.iana.org/assignments/dns-parameters/dns-parameters-6.csv") 19 | dns_rcodes <- janitor::clean_names(xdf) 20 | usethis::use_data(dns_rcodes, overwrite = TRUE) 21 | 22 | xdf <- read_csv("https://www.iana.org/assignments/dns-parameters/dns-parameters-11.csv") 23 | edns0_option_codes <- janitor::clean_names(xdf) 24 | usethis::use_data(edns0_option_codes, overwrite = TRUE) 25 | 26 | xdf <- read_csv("https://www.iana.org/assignments/dns-parameters/underscored-globally-scoped-dns-node-names.csv") 27 | dns_glob_names <- janitor::clean_names(xdf) 28 | usethis::use_data(dns_glob_names, overwrite = TRUE) 29 | 30 | # https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml 31 | 32 | doc <- read_xml("https://www.iana.org/assignments/dns-parameters/dns-parameters.xml") 33 | doc <- xml_ns_strip(doc) 34 | 35 | fil <- here::here("R/datasets.R") 36 | 37 | upd <- as.character(Sys.time()) 38 | 39 | c( 40 | "dns_classes" = "dns-parameters-2", 41 | "rrtypes" = "dns-parameters-4", 42 | "dns_opcodes" = "dns-parameters-5", 43 | "dns_rcodes" = "dns-parameters-6", 44 | "edns0_option_codes" = "dns-parameters-11", 45 | "dns_glob_names" = "underscored-globally-scoped-dns-node-names" 46 | ) -> ids 47 | 48 | cat( 49 | "# This file is autogenerated. Do not edit by hand.\n", 50 | "# Last refresh: ", upd, "\n\n", sep = "", 51 | file = fil 52 | ) 53 | 54 | for (i in seq_along(ids)) { 55 | 56 | dat <- names(ids)[i] 57 | id <- unname(ids)[i] 58 | id <- glue::glue(".//registry[@id = '{id}']") 59 | 60 | node <- xml_find_first(doc, id) 61 | 62 | note <- "" 63 | if (!is.na(xml_text(xml_find_first(node, "note"))[[1]])) { 64 | note <- sprintf("#' @note %s\n", gsub("\n", "", paste0(xml_text(xml_find_first(node, "note")), collapse = " "))) 65 | } 66 | 67 | cat( 68 | "#' @md\n", 69 | "#' @title ", xml_text(xml_find_first(node, "title")), " (dataset)\n", 70 | "#' @description ", xml_text(xml_find_first(node, "title")), "\n", 71 | "#' @format data frame with columns: ", paste0(sprintf("`%s`", colnames(get(names(ids)[i]))), collapse = ", "), "\n", 72 | "#' @docType data\n", 73 | "#' @keywords datasets\n", 74 | "#' @name ", dat, "\n", 75 | "#' @references \n", 76 | "#' @references \n", 77 | "#' @references ", paste0(xml_attr(xml_find_all(node, "xref"), "data"), collapse = ", "), "\n", 78 | note, 79 | "#' @note Last updated ", upd, "\n", 80 | "#' @usage data('", dat, "')\n", 81 | "NULL\n\n", 82 | sep = "", file = fil, append = TRUE 83 | ) 84 | 85 | } 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /data/dns_classes.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/gdns/295f5d686a820a36438c62cdd4a86ac40a4c8f63/data/dns_classes.rda -------------------------------------------------------------------------------- /data/dns_glob_names.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/gdns/295f5d686a820a36438c62cdd4a86ac40a4c8f63/data/dns_glob_names.rda -------------------------------------------------------------------------------- /data/dns_opcodes.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/gdns/295f5d686a820a36438c62cdd4a86ac40a4c8f63/data/dns_opcodes.rda -------------------------------------------------------------------------------- /data/dns_rcodes.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/gdns/295f5d686a820a36438c62cdd4a86ac40a4c8f63/data/dns_rcodes.rda -------------------------------------------------------------------------------- /data/edns0_option_codes.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/gdns/295f5d686a820a36438c62cdd4a86ac40a4c8f63/data/edns0_option_codes.rda -------------------------------------------------------------------------------- /data/resource_record_tbl.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/gdns/295f5d686a820a36438c62cdd4a86ac40a4c8f63/data/resource_record_tbl.rda -------------------------------------------------------------------------------- /data/rrtypes.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrbrmstr/gdns/295f5d686a820a36438c62cdd4a86ac40a4c8f63/data/rrtypes.rda -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Home. gdns 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 68 | 69 |
70 | 71 |
72 |
73 | 74 |

Travis-CI Build Status

75 |

gdns : Tools to work with the Google DNS over HTTPS API

76 |

Traditional DNS queries and responses are sent over UDP or TCP without encryption. This is vulnerable to eavesdropping and spoofing (including DNS-based Internet filtering). Responses from recursive resolvers to clients are the most vulnerable to undesired or malicious changes, while communications between recursive resolvers and authoritative nameservers often incorporate additional protection.

77 |

To address this problem, Google Public DNS offers DNS resolution over an encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and security between a client and a recursive resolver, and complements DNSSEC to provide end-to-end authenticated DNS lookups.

78 |

More info at https://developers.google.com/speed/public-dns/docs/dns-over-https.

79 |

The following functions are implemented:

80 |
    81 |
  • 82 | bulk_query: Vectorized query, returning only answers in a data frame
  • 83 |
  • 84 | has_spf: Test for whether a DNS TXT record is an SPF record
  • 85 |
  • 86 | is_hard_fail: SPF “all” type test
  • 87 |
  • 88 | is_soft_fail: SPF “all” type test
  • 89 |
  • 90 | passes_all: SPF “all” type test
  • 91 |
  • 92 | query: Perform DNS over HTTPS queries using Google
  • 93 |
  • 94 | spf_exists: SPF field extraction functions
  • 95 |
  • 96 | spf_includes: SPF field extraction functions
  • 97 |
  • 98 | spf_ipv4s: SPF field extraction functions
  • 99 |
  • 100 | spf_ipv6s: SPF field extraction functions
  • 101 |
  • 102 | spf_ptrs: SPF field extraction functions
  • 103 |
  • 104 | split_spf: Split out all SPF records in a domain’s TXT record
  • 105 |
106 |

Installation

107 |
devtools::install_github("hrbrmstr/gdns")
108 |

Usage

109 |
library(gdns)
110 | 
111 | # current verison
112 | packageVersion("gdns")
113 | #> [1] '0.2.0.9000'
114 | 
115 | query("rud.is")
116 | #> $Status
117 | #> [1] 0
118 | #> 
119 | #> $TC
120 | #> [1] FALSE
121 | #> 
122 | #> $RD
123 | #> [1] TRUE
124 | #> 
125 | #> $RA
126 | #> [1] TRUE
127 | #> 
128 | #> $AD
129 | #> [1] FALSE
130 | #> 
131 | #> $CD
132 | #> [1] FALSE
133 | #> 
134 | #> $Question
135 | #>      name type
136 | #> 1 rud.is.    1
137 | #> 
138 | #> $Answer
139 | #>      name type  TTL            data
140 | #> 1 rud.is.    1 3599 104.236.112.222
141 | #> 
142 | #> $Additional
143 | #> list()
144 | #> 
145 | #> $edns_client_subnet
146 | #> [1] "0.0.0.0/0"
147 | #> 
148 | #> $Comment
149 | #> [1] "Response from dns.mwebdns.net.(84.246.124.75)"
150 | 
151 | query("example.com", "255") # "ANY" query
152 | #> $Status
153 | #> [1] 0
154 | #> 
155 | #> $TC
156 | #> [1] FALSE
157 | #> 
158 | #> $RD
159 | #> [1] TRUE
160 | #> 
161 | #> $RA
162 | #> [1] TRUE
163 | #> 
164 | #> $AD
165 | #> [1] TRUE
166 | #> 
167 | #> $CD
168 | #> [1] FALSE
169 | #> 
170 | #> $Question
171 | #>           name type
172 | #> 1 example.com.  255
173 | #> 
174 | #> $Answer
175 | #>            name type   TTL
176 | #> 1  example.com.    6  3599
177 | #> 2  example.com.   46 21599
178 | #> 3  example.com.   46 21599
179 | #> 4  example.com.   46  3599
180 | #> 5  example.com.   46    59
181 | #> 6  example.com.   46 21599
182 | #> 7  example.com.   46  3599
183 | #> 8  example.com.   46  3599
184 | #> 9  example.com.   46  3599
185 | #> 10 example.com.   47  3599
186 | #> 11 example.com.    2 21599
187 | #> 12 example.com.    2 21599
188 | #> 13 example.com.   28 21599
189 | #> 14 example.com.    1 21599
190 | #> 15 example.com.   16    59
191 | #> 16 example.com.   16    59
192 | #> 17 example.com.   48  3599
193 | #> 18 example.com.   48  3599
194 | #> 19 example.com.   48  3599
195 | #>                                                                                                                                                                                                                                                                                                                                                                                                                 data
196 | #> 1                                                                                                                                                                                                                                                                                                                                            sns.dns.icann.org. noc.dns.icann.org. 2015082662 7200 3600 1209600 3600
197 | #> 2                                                                                                                                                                               a 8 2 86400 1476095331 1474297785 1704 example.com. OnhJa3/aHkvePBvBME3nlZrkU/rdenyaquFgSYI/wKPq2/ZJVZGhv0TVBMJ5l6GZujqnyBfq9cvvb88//koi17oNjR5JEv2cv4rLT5pud3VhQdVrHD7fU8BV/YnCpP3ikXJMgjf6sAhgL7FZKLtpv7cFXnqznfRCTZ3HKkpBtAB0ZZw=
198 | #> 3                                                                                                                                                                              ns 8 2 86400 1476218628 1474362585 1704 example.com. dxPw4KtqLRMR/P1MB7umTClO/Tgf5X2ukJApKd133OMPhsy7c2N3QIxW4TLxZnCezUewDE1D86HBnGi1kGw4pN4W83lI37L6pTjIkDUtrc1acISOwg9Q9JM74On9/qKTGpTi7aSGVA5t4biLKqPm00a1Yu/VNPOxeLQPyYNjUYspNZ8=
199 | #> 4                                                                                                                                                                              soa 8 2 3600 1476508736 1474722585 1704 example.com. rHojLwiWn5xVU8noy1se7gRjiNI6GJdDcxwO1GU1qUs3Un4y7LyENjrK8qOv2z6EhblBOhPnrgnNMzEPPH3w+5azpU6xAH+jJHO4tExj4Pc3zzQ1sfFx1k8xWPfJjiWnUtUsk19y8vVqHvLXltvVItXlCClzljA0XyNUi1fvYjHbQxI=
200 | #> 5                                                                                                                                                                                txt 8 2 60 1476051975 1474218584 1704 example.com. FBZiE56Ux4VY5AMVtgitLIBWi+UteNSFh4BWwJksVRRt/7OoH7iD6h4UDqP8rNbk9qvXmRo4Ce2vROCbNkdTy/IDEoKo+Urfm69TuI2UTbl/nnQ2UtfMIEC83yywYRWdra5BPkt67SQhHSc4N7QHblABFbm2jPuu2+uOqaRCpfeoWYo=
201 | #> 6                                                                                                                                                                            aaaa 8 2 86400 1475967038 1474146584 1704 example.com. ZQgPaEBxSxHCPhOES76xksqOVYSRtNIieIwTwIo4Oceq0NGzjOyI+8wrgs79QHqs4e5SRe67hVX2rSaJ9Q167+TuQz57ZtyqeOZ+x+cgULyT1Q+8N0ZJlHpZS4i2VfR1xT+quG+0m9wtye8wA3Hl2mWPyTjtsH7mjoS7/U/ZQMJwi44=
202 | #> 7                                                                                                                                                                             nsec 8 2 3600 1475694918 1473887384 1704 example.com. XTCfotH8+cSDgNrFnCNWt4lx64yTnVzwOMZsFgynNSGS5LzY0VfRl7UvTH2WDVzdsIHgKpPBOUwv/DvjNhAMzUgHFlaK/A+U1aFa16/YQkqkIqqfnCA4EgBdhIK4FM3dSIVcpaj3PhGFKvMG4RBvoMAWLRXE3gKf3306CJzX1sfKdsA=
203 | #> 8  dnskey 8 2 3600 1476561735 1474722585 31406 example.com. Oup7snCR/5iUmTuGyHfCfFCisTeqaJ8RHD6aE9wZQR2CCkKZHXO9dzfUL1gA6T35p4T0XeM+TMlv1uZhX157RnanPwyZluancmm5cNz5ub0vG7G/O4DxnSoLmATYoBJ7Ub9Ul4iWFUE7nvyJ23X2MhX6XTiplXYPnztiem6rJLV84JiemoKtvapWchRhFi4w4Y+BdjHfY7IRERjQYNhVuaus5+EeppIoot9srsj2suXePGC7dE0R8z9K/BTYvQi76kBlJzzF9fNNy5JvyZPEUpXATuRD7KfxBsWHaFajOnYOb1eDAL/C0H3hhjVBov2Pexp7YDIsJzIa2g8850LruQ==
204 | #> 9  dnskey 8 2 3600 1476561735 1474722585 45620 example.com. f+aO6V+QKA4XgTC0Vqow59jBP/NlX6f7EEbaoXts0lp7Vaj/DBrhnS/sT4BbJb3VK1MvuPmNre5t0eyOeNCjbjrwIM2uf41GFuBI0AFxQx7o2PIdf1vrXsDnUGsZrMkYMv4gr802S7MXsvMdMN5cM0AA5Zol888sLP1yrHIcfNxG8hoUn3dS0L6nd/OxkL70+NjHBTjBQLqkLsK92ryJ0CWrzcJElszBRqfQfYGV/sJ84Ko4tjnBqRuki/rmTW5KQYdE7NI+MvERtGnep7RHb02Luk7BFPPD3uh353EYSAOVHrMH4fte6mJGcj3vxErfSWakRUXQpovLNcqYZNxoGQ==
205 | #> 10                                                                                                                                                                                                                                                                                                                                                              www.example.com. A NS SOA TXT AAAA RRSIG NSEC DNSKEY
206 | #> 11                                                                                                                                                                                                                                                                                                                                                                                               a.iana-servers.net.
207 | #> 12                                                                                                                                                                                                                                                                                                                                                                                               b.iana-servers.net.
208 | #> 13                                                                                                                                                                                                                                                                                                                                                                                2606:2800:220:1:248:1893:25c8:1946
209 | #> 14                                                                                                                                                                                                                                                                                                                                                                                                     93.184.216.34
210 | #> 15                                                                                                                                                                                                                                                                                                                                                                                                     "v=spf1 -all"
211 | #> 16                                                                                                                                                                                                                                                                                                                                                             "$Id: example.com 4415 2015-08-24 20:12:23Z davids $"
212 | #> 17                                                                                                                                                                                                                      256 3 8 AwEAAa3d68DfyIs03nGYpi3a9YX+f/wln3g6dhWWzjUUqp6CGXuaOdEHfS8zI/5JdGKi8Xoc4YmjPGfiCJIkCiQnMKn/QFygpZs41ANLdPp2jJlJhFA6IHE/xxTCxJfNhsdEAOGlMORN9Zu1XLUBo/IuCDUvUzZPgalivd/m9L+Jr4kxbg3v
213 | #> 18                                              257 3 8 AwEAAZ0aqu1rJ6orJynrRfNpPmayJZoAx9Ic2/Rl9VQWLMHyjxxem3VUSoNUIFXERQbj0A9Ogp0zDM9YIccKLRd6LmWiDCt7UJQxVdD+heb5Ec4qlqGmyX9MDabkvX2NvMwsUecbYBq8oXeTT9LRmCUt9KUt/WOi6DKECxoG/bWTykrXyBR8elD+SQY43OAVjlWrVltHxgp4/rhBCvRbmdflunaPIgu27eE2U4myDSLT8a4A0rB5uHG4PkOa9dIRs9y00M2mWf4lyPee7vi5few2dbayHXmieGcaAHrx76NGAABeY393xjlmDNcUkF1gpNWUla4fWZbbaYQzA93mLdrng+M=
214 | #> 19                                              257 3 8 AwEAAbOFAxl+Lkt0UMglZizKEC1AxUu8zlj65KYatR5wBWMrh18TYzK/ig6Y1t5YTWCO68bynorpNu9fqNFALX7bVl9/gybA0v0EhF+dgXmoUfRX7ksMGgBvtfa2/Y9a3klXNLqkTszIQ4PEMVCjtryl19Be9/PkFeC9ITjgMRQsQhmB39eyMYnal+f3bUxKk4fq7cuEU0dbRpue4H/N6jPucXWOwiMAkTJhghqgy+o9FfIp+tR/emKao94/wpVXDcPf5B18j7xz2SvTTxiuqCzCMtsxnikZHcoh1j4g+Y1B8zIMIvrEM+pZGhh/Yuf4RwCBgaYCi9hpiMWVvS4WBzx0/lU=
215 | #> 
216 | #> $Additional
217 | #> list()
218 | #> 
219 | #> $edns_client_subnet
220 | #> [1] "0.0.0.0/0"
221 | #> 
222 | #> $Comment
223 | #> [1] "Response from 199.43.135.53"
224 | 
225 | query("microsoft.com", "MX")
226 | #> $Status
227 | #> [1] 0
228 | #> 
229 | #> $TC
230 | #> [1] FALSE
231 | #> 
232 | #> $RD
233 | #> [1] TRUE
234 | #> 
235 | #> $RA
236 | #> [1] TRUE
237 | #> 
238 | #> $AD
239 | #> [1] FALSE
240 | #> 
241 | #> $CD
242 | #> [1] FALSE
243 | #> 
244 | #> $Question
245 | #>             name type
246 | #> 1 microsoft.com.   15
247 | #> 
248 | #> $Answer
249 | #>             name type  TTL                                          data
250 | #> 1 microsoft.com.   15 1509 10 microsoft-com.mail.protection.outlook.com.
251 | #> 
252 | #> $Additional
253 | #> list()
254 | #> 
255 | #> $edns_client_subnet
256 | #> [1] "0.0.0.0/0"
257 | 
258 | query("google-public-dns-a.google.com", "TXT")
259 | #> $Status
260 | #> [1] 0
261 | #> 
262 | #> $TC
263 | #> [1] FALSE
264 | #> 
265 | #> $RD
266 | #> [1] TRUE
267 | #> 
268 | #> $RA
269 | #> [1] TRUE
270 | #> 
271 | #> $AD
272 | #> [1] FALSE
273 | #> 
274 | #> $CD
275 | #> [1] FALSE
276 | #> 
277 | #> $Question
278 | #>                              name type
279 | #> 1 google-public-dns-a.google.com.   16
280 | #> 
281 | #> $Answer
282 | #>                              name type   TTL                    data
283 | #> 1 google-public-dns-a.google.com.   16 21599 "http://xkcd.com/1361/"
284 | #> 
285 | #> $Additional
286 | #> list()
287 | #> 
288 | #> $edns_client_subnet
289 | #> [1] "0.0.0.0/0"
290 | #> 
291 | #> $Comment
292 | #> [1] "Response from 216.239.36.10"
293 | 
294 | query("apple.com")
295 | #> $Status
296 | #> [1] 0
297 | #> 
298 | #> $TC
299 | #> [1] FALSE
300 | #> 
301 | #> $RD
302 | #> [1] TRUE
303 | #> 
304 | #> $RA
305 | #> [1] TRUE
306 | #> 
307 | #> $AD
308 | #> [1] FALSE
309 | #> 
310 | #> $CD
311 | #> [1] FALSE
312 | #> 
313 | #> $Question
314 | #>         name type
315 | #> 1 apple.com.    1
316 | #> 
317 | #> $Answer
318 | #>         name type  TTL          data
319 | #> 1 apple.com.    1 3413 17.172.224.47
320 | #> 2 apple.com.    1 3413  17.178.96.59
321 | #> 3 apple.com.    1 3413 17.142.160.59
322 | #> 
323 | #> $Additional
324 | #> list()
325 | #> 
326 | #> $edns_client_subnet
327 | #> [1] "0.0.0.0/0"
328 | 
329 | query("17.142.160.59", "PTR")
330 | #> $Status
331 | #> [1] 0
332 | #> 
333 | #> $TC
334 | #> [1] FALSE
335 | #> 
336 | #> $RD
337 | #> [1] TRUE
338 | #> 
339 | #> $RA
340 | #> [1] TRUE
341 | #> 
342 | #> $AD
343 | #> [1] FALSE
344 | #> 
345 | #> $CD
346 | #> [1] FALSE
347 | #> 
348 | #> $Question
349 | #>                          name type
350 | #> 1 59.160.142.17.in-addr.arpa.   12
351 | #> 
352 | #> $Answer
353 | #>                           name type  TTL                           data
354 | #> 1  59.160.142.17.in-addr.arpa.   12 3025                 apples-msk.ru.
355 | #> 2  59.160.142.17.in-addr.arpa.   12 3025                     icloud.se.
356 | #> 3  59.160.142.17.in-addr.arpa.   12 3025                     icloud.es.
357 | #> 4  59.160.142.17.in-addr.arpa.   12 3025                     icloud.om.
358 | #> 5  59.160.142.17.in-addr.arpa.   12 3025                   icloudo.com.
359 | #> 6  59.160.142.17.in-addr.arpa.   12 3025                     icloud.ch.
360 | #> 7  59.160.142.17.in-addr.arpa.   12 3025                     icloud.fr.
361 | #> 8  59.160.142.17.in-addr.arpa.   12 3025                   icloude.com.
362 | #> 9  59.160.142.17.in-addr.arpa.   12 3025          camelspaceeffect.com.
363 | #> 10 59.160.142.17.in-addr.arpa.   12 3025                 camelphat.com.
364 | #> 11 59.160.142.17.in-addr.arpa.   12 3025              alchemysynth.com.
365 | #> 12 59.160.142.17.in-addr.arpa.   12 3025                    openni.org.
366 | #> 13 59.160.142.17.in-addr.arpa.   12 3025                      swell.am.
367 | #> 14 59.160.142.17.in-addr.arpa.   12 3025                  appleweb.net.
368 | #> 15 59.160.142.17.in-addr.arpa.   12 3025                     apple.com.
369 | #> 16 59.160.142.17.in-addr.arpa.   12 3025        pv-apple-com.apple.com.
370 | #> 17 59.160.142.17.in-addr.arpa.   12 3025                ripmixburn.com.
371 | #> 18 59.160.142.17.in-addr.arpa.   12 3025                   yessql.info.
372 | #> 19 59.160.142.17.in-addr.arpa.   12 3025               webobjects.info.
373 | #> 20 59.160.142.17.in-addr.arpa.   12 3025                     ubnw.info.
374 | #> 21 59.160.142.17.in-addr.arpa.   12 3025                 skyvines.info.
375 | #> 22 59.160.142.17.in-addr.arpa.   12 3025            shopdifferent.info.
376 | #> 23 59.160.142.17.in-addr.arpa.   12 3025                 sherlock.info.
377 | #> 24 59.160.142.17.in-addr.arpa.   12 3025              quicktimetv.info.
378 | #> 25 59.160.142.17.in-addr.arpa.   12 3025            quicktimelive.info.
379 | #> 26 59.160.142.17.in-addr.arpa.   12 3025                 powermac.info.
380 | #> 27 59.160.142.17.in-addr.arpa.   12 3025                powerbook.info.
381 | #> 28 59.160.142.17.in-addr.arpa.   12 3025                   macosx.info.
382 | #> 29 59.160.142.17.in-addr.arpa.   12 3025               appleshare.info.
383 | #> 30 59.160.142.17.in-addr.arpa.   12 3025              applescript.info.
384 | #> 31 59.160.142.17.in-addr.arpa.   12 3025         applepaysupplies.info.
385 | #> 32 59.160.142.17.in-addr.arpa.   12 3025 applepaymerchantsupplies.info.
386 | #> 33 59.160.142.17.in-addr.arpa.   12 3025                 applepay.info.
387 | #> 34 59.160.142.17.in-addr.arpa.   12 3025             applemasters.info.
388 | #> 35 59.160.142.17.in-addr.arpa.   12 3025                appleexpo.info.
389 | #> 36 59.160.142.17.in-addr.arpa.   12 3025         applecomputerinc.info.
390 | #> 37 59.160.142.17.in-addr.arpa.   12 3025              applecentre.info.
391 | #> 38 59.160.142.17.in-addr.arpa.   12 3025                 airtunes.info.
392 | #> 39 59.160.142.17.in-addr.arpa.   12 3025                      apple.by.
393 | #> 
394 | #> $Additional
395 | #> list()
396 | #> 
397 | #> $edns_client_subnet
398 | #> [1] "0.0.0.0/0"
399 | 
400 | hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com")
401 | gdns::bulk_query(hosts)
402 | #>             name type  TTL            data
403 | #> 1        rud.is.    1 3598 104.236.112.222
404 | #> 2        dds.ec.    1  299   162.243.111.4
405 | #> 3 r-project.org.    1 3072   137.208.57.37
406 | #> 4   rstudio.com.    1 3599    45.79.156.36
407 | #> 5     apple.com.    1 3415   17.172.224.47
408 | #> 6     apple.com.    1 3415    17.178.96.59
409 | #> 7     apple.com.    1 3415   17.142.160.59
410 |

Test Results

411 |
library(gdns)
412 | library(testthat)
413 | 
414 | date()
415 | #> [1] "Thu Sep 29 09:44:11 2016"
416 | 
417 | test_dir("tests/")
418 | #> testthat results ========================================================================================================
419 | #> OK: 2 SKIPPED: 0 FAILED: 0
420 | #> 
421 | #> DONE ===================================================================================================================
422 |

Code of Conduct

423 |

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

424 | 425 |
426 |
427 | 428 | 431 |
432 | 433 | 434 | 435 | -------------------------------------------------------------------------------- /docs/news/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | All news. gdns 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 68 | 69 |
70 | 71 |
72 |
73 |
74 |

gdns 0.2.0

75 |
  • CRAN release
  • 76 |
  • Added a NEWS.md file to track changes to the package.
  • 77 |
78 |
79 | 80 | 88 | 89 |
90 | 91 | 94 |
95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | body { 2 | position: relative; 3 | } 4 | 5 | .icon img { 6 | float: right; 7 | border: 1px solid #ccc; 8 | } 9 | .index .internal {display: none;} 10 | ul.index li {margin-bottom: 0.5em; clear: both;} 11 | 12 | footer { 13 | margin-top: 45px; 14 | padding: 35px 0 36px; 15 | border-top: 1px solid #e5e5e5; 16 | } 17 | footer p { 18 | margin-bottom: 0; 19 | color: #555; 20 | } 21 | 22 | /* Fixes for fixed navbar --------------------------*/ 23 | 24 | body { 25 | position: relative; 26 | padding-top: 60px; 27 | } 28 | 29 | .section h1, .section h2, .section h3, .section h4 { 30 | padding-top: 60px; 31 | margin-top: -60px; 32 | } 33 | 34 | /* Table of contents --------------------------*/ 35 | 36 | #tocnav h2 { 37 | margin-top: 0; 38 | font-size: 1.5em; 39 | } 40 | 41 | 42 | /* Syntax highlighting ---------------------------------------------------- */ 43 | 44 | .fl,.number {color:rgb(21,20,181);} 45 | .fu,.functioncall {color:#264D66 ;} 46 | .ch,.st,.string {color:#375D81 ;} 47 | .kw,.keyword {font-weight:bolder ;color:black;} 48 | .argument {color:#264D66 ;} 49 | .co,.comment {color: #333;} 50 | .formalargs {color: #264D66;} 51 | .eqformalargs {color:#264D66;} 52 | .slot {font-style:italic;} 53 | .symbol {color:black ;} 54 | .prompt {color:black ;} 55 | 56 | pre img { 57 | background-color: #fff; 58 | display: block; 59 | } 60 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('#tocnav').affix({ 4 | offset: { 5 | top: $('#tocnav').offset().top - 80 6 | } 7 | }); 8 | $('body').scrollspy({ 9 | target: '#tocnav', 10 | offset: 80 11 | }); 12 | 13 | }); 14 | -------------------------------------------------------------------------------- /docs/reference/bulk_query.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | bulk_query. gdns 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 68 | 69 |
70 | 71 | 74 | 75 |
76 |
77 | 78 |

Vectorized query, returning only answers in a data frame

79 | 80 | 81 |
bulk_query(entities, type = 1, edns_client_subnet = "0.0.0.0/0")
82 | 83 |

Arguments

84 |
85 |
entities
86 |
character vector of entities to query
87 |
type
88 |
RR type can be represented as a number in [1, 65535] or canonical 89 | string (A, aaaa, etc). More information on RR types can be 90 | found http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4.
91 |
edns_client_subnet
92 |
The edns0-client-subnet option. Format is an IP 93 | address with a subnet mask. Examples: 1.2.3.4/24, 94 | 2001:700:300::/48. 95 | If you are using DNS-over-HTTPS because of privacy concerns, and do 96 | not want any part of your IP address to be sent to authoritative 97 | nameservers for geographic location accuracy, use 98 | edns_client_subnet=0.0.0.0/0. Google Public DNS normally sends 99 | approximate network information (usually replacing the last part of 100 | your IPv4 address with zeroes). 0.0.0.0/0 is the default.
101 |
102 | 103 |
104 |

Value

105 | 106 |

data.frame of only answers (use query() for detailed responses)

107 |
108 | 109 |
110 |

Note

111 | 112 |

this is a fairly naive function. It expects Answer to be one of the 113 | return value list slots. The intent for it was to make it easier 114 | to do bulk forward queries. It will get smarter in future versions.

115 |
116 | 117 | 122 | 123 |

Examples

124 |
hosts <- c("rud.is", "dds.ec", "r-project.org", "rstudio.com", "apple.com") 125 | gdns::bulk_query(hosts)
#> name type TTL data 126 | #> 1 rud.is. 1 3599 104.236.112.222 127 | #> 2 dds.ec. 1 299 162.243.111.4 128 | #> 3 r-project.org. 1 7199 137.208.57.37 129 | #> 4 rstudio.com. 1 3599 45.79.156.36 130 | #> 5 apple.com. 1 1006 17.172.224.47 131 | #> 6 apple.com. 1 1006 17.178.96.59 132 | #> 7 apple.com. 1 1006 17.142.160.59 133 | #>
134 |
135 |
136 |
137 |
138 | 139 | 142 |
143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /docs/reference/gdns.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | gdns. gdns 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 68 | 69 |
70 | 71 | 74 | 75 |
76 |
77 | 78 |

Traditional DNS queries and responses are sent over UDP or TCP without 79 | encryption. This is vulnerable to eavesdropping and spoofing (including 80 | DNS-based Internet filtering). Responses from recursive resolvers to clients 81 | are the most vulnerable to undesired or malicious changes, while 82 | communications between recursive resolvers and authoritative nameservers 83 | often incorporate additional protection.

84 | 85 |

To address this problem, Google Public DNS offers DNS resolution over an 86 | encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and 87 | security between a client and a recursive resolver, and complements DNSSEC 88 | to provide end-to-end authenticated DNS lookups.

89 | 90 |

Support for reverse lookups is also provided.

91 | 92 |

See https://developers.google.com/speed/public-dns/docs/dns-over-https 93 | for more information.

94 | 95 | 96 |
97 |
98 |

Author

99 | 100 | Bob Rudis (bob@rud.is) 101 | 102 |
103 |
104 | 105 | 108 |
109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /docs/reference/has_spf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | has_spf. gdns 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 68 | 69 |
70 | 71 | 74 | 75 |
76 |
77 | 78 |

Test for whether a DNS TXT record is an SPF record

79 | 80 | 81 |
has_spf(spf_rec)
82 | 83 |

Arguments

84 |
85 |
spf_rec
86 |
a character vector of DNS TXT records
87 |
88 |
89 |
90 |
91 |
92 | 93 | 96 |
97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /docs/reference/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Function reference. gdns 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 68 | 69 |
70 | 71 | 74 | 75 |
76 |
77 |
78 |

All functions

79 |

80 | 81 |
82 |
bulk_query
83 |
Vectorized query, returning only answers in a data frame
84 |
gdns
gdns-package
85 |
Tools to Work with Google DNS Over HTTPS API
86 |
has_spf
87 |
Test for whether a DNS TXT record is an SPF record
88 |
is_hard_fail
is_soft_fail
passes_all
89 |
SPF "all" type test
90 |
query
91 |
Perform DNS over HTTPS queries using Google
92 |
spf_exists
spf_includes
spf_ipv4s
spf_ipv6s
spf_ptrs
93 |
SPF field extraction functions
94 |
split_spf
95 |
Split out all SPF records in a domain's TXT record
96 |
97 |
98 |
99 |
100 | 101 | 104 |
105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /docs/reference/is_soft_fail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | is_soft_fail. gdns 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 68 | 69 |
70 | 71 | 74 | 75 |
76 |
77 | 78 |

SPF "all" type test

79 | 80 | 81 |
is_soft_fail(spf_rec)
 82 | 
 83 | is_hard_fail(spf_rec)
 84 | 
 85 | passes_all(spf_rec)
86 | 87 |

Arguments

88 |
89 |
spf_rec
90 |
a character vector of DNS TXT records
91 |
92 |
93 |
94 |
95 |
96 | 97 | 100 |
101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /docs/reference/query.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | query. gdns 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 68 | 69 |
70 | 71 | 74 | 75 |
76 |
77 | 78 |

Traditional DNS queries and responses are sent over UDP or TCP without 79 | encryption. This is vulnerable to eavesdropping and spoofing (including 80 | DNS-based Internet filtering). Responses from recursive resolvers to clients 81 | are the most vulnerable to undesired or malicious changes, while 82 | communications between recursive resolvers and authoritative nameservers 83 | often incorporate additional protection.

84 | 85 |

To address this problem, Google Public DNS offers DNS resolution over an 86 | encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and 87 | security between a client and a recursive resolver, and complements DNSSEC 88 | to provide end-to-end authenticated DNS lookups.

89 | 90 | 91 |
query(name, type = "1", edns_client_subnet = "0.0.0.0/0")
92 | 93 |

Arguments

94 |
95 |
name
96 |
item to lookup. Valid characters are numbers, letters, hyphen, and dot. Length 97 | must be between 1 and 255. Names with escaped or non-ASCII characters 98 | are not supported. Internationalized domain names must use the 99 | punycode format (e.g. "xn--qxam"). 100 | If an IPv4 string is input, it will be transformed into 101 | a proper format for reverse lookups.
102 |
type
103 |
RR type can be represented as a number in [1, 65535] or canonical 104 | string (A, aaaa, etc). More information on RR types can be 105 | found http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4. 106 | You can use 255 for an ANY query.
107 |
edns_client_subnet
108 |
The edns0-client-subnet option. Format is an IP 109 | address with a subnet mask. Examples: 1.2.3.4/24, 110 | 2001:700:300::/48. 111 | If you are using DNS-over-HTTPS because of privacy concerns, and do 112 | not want any part of your IP address to be sent to authoritative 113 | nameservers for geographic location accuracy, use 114 | edns_client_subnet=0.0.0.0/0. Google Public DNS normally sends 115 | approximate network information (usually replacing the last part of 116 | your IPv4 address with zeroes). 0.0.0.0/0 is the default.
117 |
118 | 119 |
120 |

Value

121 | 122 |

a list with the query result or NULL if an error occurred

123 |
124 | 125 |
126 |

Details

127 | 128 |

To perform vectorized queries with only answers (and no metadata) use 129 | bulk_query()).

130 |
131 | 132 | 137 | 138 |

Examples

139 |
query("rud.is")
#> $Status 140 | #> [1] 0 141 | #> 142 | #> $TC 143 | #> [1] FALSE 144 | #> 145 | #> $RD 146 | #> [1] TRUE 147 | #> 148 | #> $RA 149 | #> [1] TRUE 150 | #> 151 | #> $AD 152 | #> [1] FALSE 153 | #> 154 | #> $CD 155 | #> [1] FALSE 156 | #> 157 | #> $Question 158 | #> name type 159 | #> 1 rud.is. 1 160 | #> 161 | #> $Answer 162 | #> name type TTL data 163 | #> 1 rud.is. 1 3599 104.236.112.222 164 | #> 165 | #> $Additional 166 | #> list() 167 | #> 168 | #> $edns_client_subnet 169 | #> [1] "0.0.0.0/0" 170 | #> 171 | #> $Comment 172 | #> [1] "Response from dns.mwebdns.eu.(84.246.125.230)" 173 | #> 174 | #>
query("example.com", "255") # ANY query
#> $Status 175 | #> [1] 0 176 | #> 177 | #> $TC 178 | #> [1] FALSE 179 | #> 180 | #> $RD 181 | #> [1] TRUE 182 | #> 183 | #> $RA 184 | #> [1] TRUE 185 | #> 186 | #> $AD 187 | #> [1] TRUE 188 | #> 189 | #> $CD 190 | #> [1] FALSE 191 | #> 192 | #> $Question 193 | #> name type 194 | #> 1 example.com. 255 195 | #> 196 | #> $Answer 197 | #> name type TTL 198 | #> 1 example.com. 6 3599 199 | #> 2 example.com. 46 21599 200 | #> 3 example.com. 46 21599 201 | #> 4 example.com. 46 3599 202 | #> 5 example.com. 46 59 203 | #> 6 example.com. 46 21599 204 | #> 7 example.com. 46 3599 205 | #> 8 example.com. 46 3599 206 | #> 9 example.com. 46 3599 207 | #> 10 example.com. 47 3599 208 | #> 11 example.com. 2 21599 209 | #> 12 example.com. 2 21599 210 | #> 13 example.com. 28 21599 211 | #> 14 example.com. 1 21599 212 | #> 15 example.com. 16 59 213 | #> 16 example.com. 16 59 214 | #> 17 example.com. 48 3599 215 | #> 18 example.com. 48 3599 216 | #> 19 example.com. 48 3599 217 | #> data 218 | #> 1 sns.dns.icann.org. noc.dns.icann.org. 2015082669 7200 3600 1209600 3600 219 | #> 2 a 8 2 86400 1477364031 1475579385 1704 example.com. auGIKxU2oVxE9YE2ca9Xv5yuA2bP8uwIXW3t/d/wxGn6gnzuyVPefMHu5jT0z2ldwsqiB0+VGZpVguUeY7M22PCR0YwMGjB64/VQjsZQxAhaleVOLCRR2fya4EtOYvPRoWielQfDaS+4SBenCv0+nN8Gb3PMSsEe0ICjDSrzFRC0V7U= 220 | #> 3 ns 8 2 86400 1477484364 1475701785 1704 example.com. bY3Q/b0KCwv+fkMGpKABu3oT3y+u2xcCoykkPDJrkVGRM16Z4WojbemTYFR++pbsbuVHptz6uUtX3m94kbyvmaLvXTxy1bwY0b8F/0Rz9Se9jy5mIUiatTHftqlz434PC+UnQKNiWZBYsgQJegTJZJLlJ7/KaiIzjrhltRFWwqsOaUA= 221 | #> 4 soa 8 2 3600 1477543924 1475701785 1704 example.com. kWe1dnPv94cNlWhysZSKC3WC4/YlSTkG6/NZtFxxQcwPGlS7x+z4tRnNodhfLCpYw8D4loan0ybfWuRK/tzKminJsdt3lLqJxlXvcIzmEkI17xKUpcnD1jA0mhCfTptzLj4oCw4hhkC/d8JuD5jVmTskoiav36SV+cW1KngAY/UtPfw= 222 | #> 5 txt 8 2 60 1477325190 1475536185 1704 example.com. ZaMZnuA5mh+GSbmL3nJxDbVZEdAu0BC1I71FgOPojAgRT5i2pn4+obRCd+aUw3c/grt1xzciBdhyw9jMvzcyEwcxk2WDS+REkEwzBn1YKodoo1YCjcXVUZscugSXc+hq+eFaTcRlW/siqWq+cy77VVsjdKJTAJrcK12abkjOnRrqfww= 223 | #> 6 aaaa 8 2 86400 1477264070 1475449785 1704 example.com. M0ggDOmzYveQUd145aePLv19PwzYed7bDNsU74quoitB1nEZ8/r7ROdsT1m7VXi/BBimUVtezXBeVTc3/+2rEvhNsmX1WRrHN7seHzAiEt27TNogwn3e40YGCrwVIy+ypLRfZTi+Xlv/Ykd0H4Uvp0tW+69eel8MOlYRqSO5DMizMTc= 224 | #> 7 nsec 8 2 3600 1476958241 1475176185 1704 example.com. WnXb1Y/Qkn5CmiRir6a0KssPjiPbEq7Tko0rWsQQyFFPrT+JB/6YUKStJY5K+GN+M2tWGW3jrOSbTVei0GLxjE/3BBLoYtLqLURjEk3Ki3n5zP5c9FMyQPf3fCC0ac/kSxw5V3nTs3eSnu8p/quseV8BqkU/hYgm1qsvQOyXVUSFync= 225 | #> 8 dnskey 8 2 3600 1476561735 1474722585 31406 example.com. Oup7snCR/5iUmTuGyHfCfFCisTeqaJ8RHD6aE9wZQR2CCkKZHXO9dzfUL1gA6T35p4T0XeM+TMlv1uZhX157RnanPwyZluancmm5cNz5ub0vG7G/O4DxnSoLmATYoBJ7Ub9Ul4iWFUE7nvyJ23X2MhX6XTiplXYPnztiem6rJLV84JiemoKtvapWchRhFi4w4Y+BdjHfY7IRERjQYNhVuaus5+EeppIoot9srsj2suXePGC7dE0R8z9K/BTYvQi76kBlJzzF9fNNy5JvyZPEUpXATuRD7KfxBsWHaFajOnYOb1eDAL/C0H3hhjVBov2Pexp7YDIsJzIa2g8850LruQ== 226 | #> 9 dnskey 8 2 3600 1476561735 1474722585 45620 example.com. f+aO6V+QKA4XgTC0Vqow59jBP/NlX6f7EEbaoXts0lp7Vaj/DBrhnS/sT4BbJb3VK1MvuPmNre5t0eyOeNCjbjrwIM2uf41GFuBI0AFxQx7o2PIdf1vrXsDnUGsZrMkYMv4gr802S7MXsvMdMN5cM0AA5Zol888sLP1yrHIcfNxG8hoUn3dS0L6nd/OxkL70+NjHBTjBQLqkLsK92ryJ0CWrzcJElszBRqfQfYGV/sJ84Ko4tjnBqRuki/rmTW5KQYdE7NI+MvERtGnep7RHb02Luk7BFPPD3uh353EYSAOVHrMH4fte6mJGcj3vxErfSWakRUXQpovLNcqYZNxoGQ== 227 | #> 10 www.example.com. A NS SOA TXT AAAA RRSIG NSEC DNSKEY 228 | #> 11 a.iana-servers.net. 229 | #> 12 b.iana-servers.net. 230 | #> 13 2606:2800:220:1:248:1893:25c8:1946 231 | #> 14 93.184.216.34 232 | #> 15 "v=spf1 -all" 233 | #> 16 "$Id: example.com 4415 2015-08-24 20:12:23Z davids $" 234 | #> 17 256 3 8 AwEAAa3d68DfyIs03nGYpi3a9YX+f/wln3g6dhWWzjUUqp6CGXuaOdEHfS8zI/5JdGKi8Xoc4YmjPGfiCJIkCiQnMKn/QFygpZs41ANLdPp2jJlJhFA6IHE/xxTCxJfNhsdEAOGlMORN9Zu1XLUBo/IuCDUvUzZPgalivd/m9L+Jr4kxbg3v 235 | #> 18 257 3 8 AwEAAZ0aqu1rJ6orJynrRfNpPmayJZoAx9Ic2/Rl9VQWLMHyjxxem3VUSoNUIFXERQbj0A9Ogp0zDM9YIccKLRd6LmWiDCt7UJQxVdD+heb5Ec4qlqGmyX9MDabkvX2NvMwsUecbYBq8oXeTT9LRmCUt9KUt/WOi6DKECxoG/bWTykrXyBR8elD+SQY43OAVjlWrVltHxgp4/rhBCvRbmdflunaPIgu27eE2U4myDSLT8a4A0rB5uHG4PkOa9dIRs9y00M2mWf4lyPee7vi5few2dbayHXmieGcaAHrx76NGAABeY393xjlmDNcUkF1gpNWUla4fWZbbaYQzA93mLdrng+M= 236 | #> 19 257 3 8 AwEAAbOFAxl+Lkt0UMglZizKEC1AxUu8zlj65KYatR5wBWMrh18TYzK/ig6Y1t5YTWCO68bynorpNu9fqNFALX7bVl9/gybA0v0EhF+dgXmoUfRX7ksMGgBvtfa2/Y9a3klXNLqkTszIQ4PEMVCjtryl19Be9/PkFeC9ITjgMRQsQhmB39eyMYnal+f3bUxKk4fq7cuEU0dbRpue4H/N6jPucXWOwiMAkTJhghqgy+o9FfIp+tR/emKao94/wpVXDcPf5B18j7xz2SvTTxiuqCzCMtsxnikZHcoh1j4g+Y1B8zIMIvrEM+pZGhh/Yuf4RwCBgaYCi9hpiMWVvS4WBzx0/lU= 237 | #> 238 | #> $Additional 239 | #> list() 240 | #> 241 | #> $edns_client_subnet 242 | #> [1] "0.0.0.0/0" 243 | #> 244 | #> $Comment 245 | #> [1] "Response from 199.43.135.53" 246 | #> 247 | #>
query("microsoft.com", "MX")
#> $Status 248 | #> [1] 0 249 | #> 250 | #> $TC 251 | #> [1] FALSE 252 | #> 253 | #> $RD 254 | #> [1] TRUE 255 | #> 256 | #> $RA 257 | #> [1] TRUE 258 | #> 259 | #> $AD 260 | #> [1] FALSE 261 | #> 262 | #> $CD 263 | #> [1] FALSE 264 | #> 265 | #> $Question 266 | #> name type 267 | #> 1 microsoft.com. 15 268 | #> 269 | #> $Answer 270 | #> name type TTL data 271 | #> 1 microsoft.com. 15 74 10 microsoft-com.mail.protection.outlook.com. 272 | #> 273 | #> $Additional 274 | #> list() 275 | #> 276 | #> $edns_client_subnet 277 | #> [1] "0.0.0.0/0" 278 | #> 279 | #>
query("google-public-dns-a.google.com", "TXT")
#> $Status 280 | #> [1] 0 281 | #> 282 | #> $TC 283 | #> [1] FALSE 284 | #> 285 | #> $RD 286 | #> [1] TRUE 287 | #> 288 | #> $RA 289 | #> [1] TRUE 290 | #> 291 | #> $AD 292 | #> [1] FALSE 293 | #> 294 | #> $CD 295 | #> [1] FALSE 296 | #> 297 | #> $Question 298 | #> name type 299 | #> 1 google-public-dns-a.google.com. 16 300 | #> 301 | #> $Answer 302 | #> name type TTL data 303 | #> 1 google-public-dns-a.google.com. 16 21599 "http://xkcd.com/1361/" 304 | #> 305 | #> $Additional 306 | #> list() 307 | #> 308 | #> $edns_client_subnet 309 | #> [1] "0.0.0.0/0" 310 | #> 311 | #> $Comment 312 | #> [1] "Response from 216.239.38.10" 313 | #> 314 | #>
query("apple.com")
#> $Status 315 | #> [1] 0 316 | #> 317 | #> $TC 318 | #> [1] FALSE 319 | #> 320 | #> $RD 321 | #> [1] TRUE 322 | #> 323 | #> $RA 324 | #> [1] TRUE 325 | #> 326 | #> $AD 327 | #> [1] FALSE 328 | #> 329 | #> $CD 330 | #> [1] FALSE 331 | #> 332 | #> $Question 333 | #> name type 334 | #> 1 apple.com. 1 335 | #> 336 | #> $Answer 337 | #> name type TTL data 338 | #> 1 apple.com. 1 1002 17.172.224.47 339 | #> 2 apple.com. 1 1002 17.178.96.59 340 | #> 3 apple.com. 1 1002 17.142.160.59 341 | #> 342 | #> $Additional 343 | #> list() 344 | #> 345 | #> $edns_client_subnet 346 | #> [1] "0.0.0.0/0" 347 | #> 348 | #>
query("17.142.160.59", "PTR")
#> $Status 349 | #> [1] 0 350 | #> 351 | #> $TC 352 | #> [1] FALSE 353 | #> 354 | #> $RD 355 | #> [1] TRUE 356 | #> 357 | #> $RA 358 | #> [1] TRUE 359 | #> 360 | #> $AD 361 | #> [1] FALSE 362 | #> 363 | #> $CD 364 | #> [1] FALSE 365 | #> 366 | #> $Question 367 | #> name type 368 | #> 1 59.160.142.17.in-addr.arpa. 12 369 | #> 370 | #> $Answer 371 | #> name type TTL data 372 | #> 1 59.160.142.17.in-addr.arpa. 12 2587 icloud.se. 373 | #> 2 59.160.142.17.in-addr.arpa. 12 2587 icloud.es. 374 | #> 3 59.160.142.17.in-addr.arpa. 12 2587 icloud.om. 375 | #> 4 59.160.142.17.in-addr.arpa. 12 2587 icloudo.com. 376 | #> 5 59.160.142.17.in-addr.arpa. 12 2587 icloud.ch. 377 | #> 6 59.160.142.17.in-addr.arpa. 12 2587 icloud.fr. 378 | #> 7 59.160.142.17.in-addr.arpa. 12 2587 icloude.com. 379 | #> 8 59.160.142.17.in-addr.arpa. 12 2587 camelspaceeffect.com. 380 | #> 9 59.160.142.17.in-addr.arpa. 12 2587 camelphat.com. 381 | #> 10 59.160.142.17.in-addr.arpa. 12 2587 alchemysynth.com. 382 | #> 11 59.160.142.17.in-addr.arpa. 12 2587 openni.org. 383 | #> 12 59.160.142.17.in-addr.arpa. 12 2587 swell.am. 384 | #> 13 59.160.142.17.in-addr.arpa. 12 2587 appleweb.net. 385 | #> 14 59.160.142.17.in-addr.arpa. 12 2587 apple.com. 386 | #> 15 59.160.142.17.in-addr.arpa. 12 2587 pv-apple-com.apple.com. 387 | #> 16 59.160.142.17.in-addr.arpa. 12 2587 ripmixburn.com. 388 | #> 17 59.160.142.17.in-addr.arpa. 12 2587 yessql.info. 389 | #> 18 59.160.142.17.in-addr.arpa. 12 2587 webobjects.info. 390 | #> 19 59.160.142.17.in-addr.arpa. 12 2587 ubnw.info. 391 | #> 20 59.160.142.17.in-addr.arpa. 12 2587 skyvines.info. 392 | #> 21 59.160.142.17.in-addr.arpa. 12 2587 shopdifferent.info. 393 | #> 22 59.160.142.17.in-addr.arpa. 12 2587 sherlock.info. 394 | #> 23 59.160.142.17.in-addr.arpa. 12 2587 quicktimetv.info. 395 | #> 24 59.160.142.17.in-addr.arpa. 12 2587 quicktimelive.info. 396 | #> 25 59.160.142.17.in-addr.arpa. 12 2587 powermac.info. 397 | #> 26 59.160.142.17.in-addr.arpa. 12 2587 powerbook.info. 398 | #> 27 59.160.142.17.in-addr.arpa. 12 2587 macosx.info. 399 | #> 28 59.160.142.17.in-addr.arpa. 12 2587 appleshare.info. 400 | #> 29 59.160.142.17.in-addr.arpa. 12 2587 applescript.info. 401 | #> 30 59.160.142.17.in-addr.arpa. 12 2587 applepaysupplies.info. 402 | #> 31 59.160.142.17.in-addr.arpa. 12 2587 applepaymerchantsupplies.info. 403 | #> 32 59.160.142.17.in-addr.arpa. 12 2587 applepay.info. 404 | #> 33 59.160.142.17.in-addr.arpa. 12 2587 applemasters.info. 405 | #> 34 59.160.142.17.in-addr.arpa. 12 2587 appleexpo.info. 406 | #> 35 59.160.142.17.in-addr.arpa. 12 2587 applecomputerinc.info. 407 | #> 36 59.160.142.17.in-addr.arpa. 12 2587 applecentre.info. 408 | #> 37 59.160.142.17.in-addr.arpa. 12 2587 airtunes.info. 409 | #> 38 59.160.142.17.in-addr.arpa. 12 2587 apple.by. 410 | #> 39 59.160.142.17.in-addr.arpa. 12 2587 apples-msk.ru. 411 | #> 412 | #> $Additional 413 | #> list() 414 | #> 415 | #> $edns_client_subnet 416 | #> [1] "0.0.0.0/0" 417 | #> 418 | #>
419 |
420 |
421 |
422 |
423 | 424 | 427 |
428 | 429 | 430 | 431 | -------------------------------------------------------------------------------- /docs/reference/spf_ipv4s.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | spf_ipv4s. gdns 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 68 | 69 |
70 | 71 | 74 | 75 |
76 |
77 | 78 |

Various helper functions to extract SPF record components.

79 | 80 | 81 |
spf_ipv4s(spf_rec)
 82 | 
 83 | spf_ipv6s(spf_rec)
 84 | 
 85 | spf_includes(spf_rec)
 86 | 
 87 | spf_ptrs(spf_rec)
 88 | 
 89 | spf_exists(spf_rec)
90 | 91 |

Arguments

92 |
93 |
spf_rec
94 |
a character vector of DNS TXT records
95 |
96 |
97 |
98 |
99 |
100 | 101 | 104 |
105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /docs/reference/split_spf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | split_spf. gdns 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 68 | 69 |
70 | 71 | 74 | 75 |
76 |
77 | 78 |

Given a vector of TXT records, this function will return a list of vectors 79 | of all the SPF records for each. If the given TXT record is not an SPF 80 | record, NULL is returned (which makes it easy to skip with purrr 81 | functions).

82 | 83 | 84 |
split_spf(spf_rec)
85 | 86 |

Arguments

87 |
88 |
spf_rec
89 |
a character vector of DNS TXT records
90 |
91 |
92 |
93 |
94 |
95 | 96 | 99 |
100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /gdns.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageBuildArgs: --resave-data 22 | PackageCheckArgs: --as-cran 23 | PackageRoxygenize: rd,collate,namespace 24 | -------------------------------------------------------------------------------- /inst/tinytest/test_gdns.R: -------------------------------------------------------------------------------- 1 | library(gdns) 2 | 3 | if (at_home()) { 4 | 5 | expect_true(length(gdns::query("example.com")) > 0) 6 | 7 | doms <- c("example.com", "example.org", "example.net") 8 | 9 | qry <- gdns::bulk_query(doms) 10 | 11 | expect_true(nrow(qry) > 0) 12 | 13 | } 14 | 15 | expect_true(is_soft_fail("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all")) 16 | expect_false(is_hard_fail("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all")) 17 | expect_false(passes_all("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all")) 18 | 19 | -------------------------------------------------------------------------------- /man/as.data.frame.gdns_response.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/as-data-frame.R 3 | \name{as.data.frame.gdns_response} 4 | \alias{as.data.frame.gdns_response} 5 | \title{Coerce a gdns query response answer to a data frame} 6 | \usage{ 7 | \method{as.data.frame}{gdns_response}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{a `gdns_response` object} 11 | 12 | \item{...}{unused} 13 | } 14 | \description{ 15 | Helper function to get to the `Answer` quickly 16 | } 17 | -------------------------------------------------------------------------------- /man/bulk_query.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/zbulk-query.R 3 | \name{bulk_query} 4 | \alias{bulk_query} 5 | \title{Vectorized query, returning only answers in a data frame} 6 | \usage{ 7 | bulk_query( 8 | entities, 9 | type = 1, 10 | cd = FALSE, 11 | do = FALSE, 12 | edns_client_subnet = "0.0.0.0/0" 13 | ) 14 | } 15 | \arguments{ 16 | \item{entities}{character vector of entities to query} 17 | 18 | \item{type}{RR type can be represented as a number in [1, 65535] or canonical 19 | string (A, aaaa, etc). More information on RR types can be 20 | found \href{http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4}{here}.} 21 | 22 | \item{cd}{(Checking Disabled) flag. Use `TRUE` to disable DNSSEC validation; 23 | Default: `FALSE`.} 24 | 25 | \item{do}{(DNSSEC OK) flag. Use `TRUE` include DNSSEC records (RRSIG, NSEC, NSEC3); 26 | Default: `FALSE`.} 27 | 28 | \item{edns_client_subnet}{The edns0-client-subnet option. Format is an IP 29 | address with a subnet mask. Examples: \code{1.2.3.4/24}, 30 | \code{2001:700:300::/48}.\cr 31 | If you are using DNS-over-HTTPS because of privacy concerns, and do 32 | not want any part of your IP address to be sent to authoritative 33 | nameservers for geographic location accuracy, use 34 | \code{edns_client_subnet=0.0.0.0/0}. Google Public DNS normally sends 35 | approximate network information (usually replacing the last part of 36 | your IPv4 address with zeroes). \code{0.0.0.0/0} is the default.} 37 | } 38 | \value{ 39 | \code{data.frame} of only answers (use \code{query()} for detailed responses) 40 | } 41 | \description{ 42 | Vectorized query, returning only answers in a data frame 43 | } 44 | \note{ 45 | this is a fairly naive function. It expects \code{Answer} to be one of the 46 | return value list slots. The intent for it was to make it easier 47 | to do bulk forward queries. It will get smarter in future versions. 48 | } 49 | \examples{ 50 | if (tinytest::at_home()) { 51 | hosts <- c("rud.is", "r-project.org", "rstudio.com", "apple.com") 52 | gdns::bulk_query(hosts) 53 | } 54 | } 55 | \references{ 56 | \url{https://developers.google.com/speed/public-dns/docs/dns-over-https} 57 | } 58 | -------------------------------------------------------------------------------- /man/dns_classes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/datasets.R 3 | \docType{data} 4 | \name{dns_classes} 5 | \alias{dns_classes} 6 | \title{DNS CLASSes (dataset)} 7 | \format{ 8 | data frame with columns: \code{decimal}, \code{hexadecimal}, \code{name}, \code{reference} 9 | } 10 | \usage{ 11 | data('dns_classes') 12 | } 13 | \description{ 14 | DNS CLASSes 15 | } 16 | \note{ 17 | As noted in , Multicast DNS can only carry DNS records with classes in the range 0-32767. 18 | Classes in the range 32768 to 65535 are incompatible with Multicast DNS. 19 | 20 | Last updated 2019-06-27 11:16:48 21 | } 22 | \references{ 23 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2} 24 | 25 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml} 26 | 27 | rfc6895 28 | } 29 | \keyword{datasets} 30 | -------------------------------------------------------------------------------- /man/dns_glob_names.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/datasets.R 3 | \docType{data} 4 | \name{dns_glob_names} 5 | \alias{dns_glob_names} 6 | \title{Underscored and Globally Scoped DNS Node Names (dataset)} 7 | \format{ 8 | data frame with columns: \code{rr_type}, \code{node_name}, \code{reference} 9 | } 10 | \usage{ 11 | data('dns_glob_names') 12 | } 13 | \description{ 14 | Underscored and Globally Scoped DNS Node Names 15 | } 16 | \note{ 17 | Last updated 2019-06-27 11:16:48 18 | } 19 | \references{ 20 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#underscored-globally-scoped-dns-node-names} 21 | 22 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml} 23 | 24 | rfc8552 25 | } 26 | \keyword{datasets} 27 | -------------------------------------------------------------------------------- /man/dns_opcodes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/datasets.R 3 | \docType{data} 4 | \name{dns_opcodes} 5 | \alias{dns_opcodes} 6 | \title{DNS OpCodes (dataset)} 7 | \format{ 8 | data frame with columns: \code{op_code}, \code{name}, \code{reference} 9 | } 10 | \usage{ 11 | data('dns_opcodes') 12 | } 13 | \description{ 14 | DNS OpCodes 15 | } 16 | \note{ 17 | Last updated 2019-06-27 11:16:48 18 | } 19 | \references{ 20 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5} 21 | 22 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml} 23 | 24 | rfc6895, rfc1035 25 | } 26 | \keyword{datasets} 27 | -------------------------------------------------------------------------------- /man/dns_rcodes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/datasets.R 3 | \docType{data} 4 | \name{dns_rcodes} 5 | \alias{dns_rcodes} 6 | \title{DNS RCODEs (dataset)} 7 | \format{ 8 | data frame with columns: \code{rcode}, \code{name}, \code{description}, \code{reference} 9 | } 10 | \usage{ 11 | data('dns_rcodes') 12 | } 13 | \description{ 14 | DNS RCODEs 15 | } 16 | \note{ 17 | Last updated 2019-06-27 11:16:48 18 | } 19 | \references{ 20 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6} 21 | 22 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml} 23 | 24 | rfc6895, rfc1035 25 | } 26 | \keyword{datasets} 27 | -------------------------------------------------------------------------------- /man/edns0_option_codes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/datasets.R 3 | \docType{data} 4 | \name{edns0_option_codes} 5 | \alias{edns0_option_codes} 6 | \title{DNS EDNS0 Option Codes (OPT) (dataset)} 7 | \format{ 8 | data frame with columns: \code{value}, \code{name}, \code{status}, \code{reference} 9 | } 10 | \usage{ 11 | data('edns0_option_codes') 12 | } 13 | \description{ 14 | DNS EDNS0 Option Codes (OPT) 15 | } 16 | \note{ 17 | Registrations made by standards-track documents are listed as "Standard," 18 | and by non-standards-track documents as "Optional." Registrations for 19 | which there are no final specifications are listed as "On-Hold." 20 | 21 | Last updated 2019-06-27 11:16:48 22 | } 23 | \references{ 24 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-11} 25 | 26 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml} 27 | 28 | rfc6891, 3604 29 | } 30 | \keyword{datasets} 31 | -------------------------------------------------------------------------------- /man/gdns.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gdns-package.r 3 | \docType{package} 4 | \name{gdns} 5 | \alias{gdns} 6 | \title{Tools to Work with Google DNS Over HTTPS API} 7 | \description{ 8 | Traditional DNS queries and responses are sent over UDP or TCP without 9 | encryption. This is vulnerable to eavesdropping and spoofing (including 10 | DNS-based Internet filtering). Responses from recursive resolvers to clients 11 | are the most vulnerable to undesired or malicious changes, while 12 | communications between recursive resolvers and authoritative nameservers 13 | often incorporate additional protection.\cr 14 | \cr 15 | To address this problem, Google Public DNS offers DNS resolution over an 16 | encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and 17 | security between a client and a recursive resolver, and complements DNSSEC 18 | to provide end-to-end authenticated DNS lookups.\cr 19 | \cr 20 | Support for reverse lookups is also provided.\cr 21 | \cr 22 | See \url{https://developers.google.com/speed/public-dns/docs/dns-over-https} 23 | for more information. 24 | } 25 | \author{ 26 | Bob Rudis (bob@rud.is) 27 | } 28 | -------------------------------------------------------------------------------- /man/has_spf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/spf.r 3 | \name{has_spf} 4 | \alias{has_spf} 5 | \title{Test for whether a DNS TXT record is an SPF record} 6 | \usage{ 7 | has_spf(spf_rec) 8 | } 9 | \arguments{ 10 | \item{spf_rec}{a character vector of DNS TXT records} 11 | } 12 | \value{ 13 | character vector 14 | } 15 | \description{ 16 | Test for whether a DNS TXT record is an SPF record 17 | } 18 | \examples{ 19 | has_spf("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all") 20 | } 21 | -------------------------------------------------------------------------------- /man/is_soft_fail.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/spf.r 3 | \name{is_soft_fail} 4 | \alias{is_soft_fail} 5 | \alias{is_hard_fail} 6 | \alias{passes_all} 7 | \title{SPF "all" type test} 8 | \usage{ 9 | is_soft_fail(spf_rec) 10 | 11 | is_hard_fail(spf_rec) 12 | 13 | passes_all(spf_rec) 14 | } 15 | \arguments{ 16 | \item{spf_rec}{a character vector of DNS TXT records} 17 | } 18 | \value{ 19 | logical 20 | } 21 | \description{ 22 | SPF "all" type test 23 | } 24 | \examples{ 25 | is_soft_fail("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all") 26 | is_hard_fail("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all") 27 | passes_all("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all") 28 | } 29 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | See \code{magrittr::\link[magrittr]{\%>\%}} for details. 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /man/query.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/zgdns.r 3 | \name{query} 4 | \alias{query} 5 | \alias{dig} 6 | \title{Perform DNS over HTTPS queries using Google} 7 | \usage{ 8 | query( 9 | name, 10 | type = "1", 11 | cd = FALSE, 12 | ct = "application/x-javascript", 13 | do = FALSE, 14 | edns_client_subnet = "0.0.0.0/0", 15 | random_padding = NULL 16 | ) 17 | 18 | dig( 19 | name, 20 | type = "1", 21 | cd = FALSE, 22 | ct = "application/x-javascript", 23 | do = FALSE, 24 | edns_client_subnet = "0.0.0.0/0", 25 | random_padding = NULL 26 | ) 27 | } 28 | \arguments{ 29 | \item{name}{item to lookup. Valid characters are numbers, letters, hyphen, and dot. Length 30 | must be between 1 and 255. Names with escaped or non-ASCII characters 31 | are not supported. Internationalized domain names must use the 32 | punycode format (e.g. "\code{xn--qxam}").\cr 33 | \cr If an IPv4 string is input, it will be transformed into 34 | a proper format for reverse lookups.} 35 | 36 | \item{type}{RR type can be represented as a number in [1, 65535] or canonical 37 | string (A, aaaa, etc). More information on RR types can be 38 | found \href{http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4}{here}. 39 | You can use \code{255} for an \code{ANY} query.} 40 | 41 | \item{cd}{(Checking Disabled) flag. Use `TRUE` to disable DNSSEC validation; 42 | Default: `FALSE`.} 43 | 44 | \item{ct}{(Content Type) Desired content type option. Use `application/dns-message` 45 | to receive a binary DNS message in the response HTTP body instead of JSON text. 46 | Use `application/x-javascript` (the default) to explicitly request JSON text. 47 | Other content type values are ignored and default JSON content is returned.} 48 | 49 | \item{do}{(DNSSEC OK) flag. Use `TRUE` include DNSSEC records (RRSIG, NSEC, NSEC3); 50 | Default: `FALSE`.} 51 | 52 | \item{edns_client_subnet}{The edns0-client-subnet option. Format is an IP 53 | address with a subnet mask. Examples: \code{1.2.3.4/24}, 54 | \code{2001:700:300::/48}.\cr 55 | If you are using DNS-over-HTTPS because of privacy concerns, and do 56 | not want any part of your IP address to be sent to authoritative 57 | nameservers for geographic location accuracy, use 58 | \code{edns_client_subnet=0.0.0.0/0}. Google Public DNS normally sends 59 | approximate network information (usually replacing the last part of 60 | your IPv4 address with zeroes). \code{0.0.0.0/0} is the default.} 61 | 62 | \item{random_padding}{clients concerned about possible side-channel privacy 63 | attacks using the packet sizes of HTTPS GET requests can use this to 64 | make all requests exactly the same size by padding requests with random data. 65 | To prevent misinterpretation of the URL, restrict the padding characters to 66 | the unreserved URL characters: upper- and lower-case letters, digits, 67 | hyphen, period, underscore and tilde.} 68 | } 69 | \value{ 70 | a \code{list} with the query result or \code{NULL} if an error occurred 71 | } 72 | \description{ 73 | Traditional DNS queries and responses are sent over UDP or TCP without 74 | encryption. This is vulnerable to eavesdropping and spoofing (including 75 | DNS-based Internet filtering). Responses from recursive resolvers to clients 76 | are the most vulnerable to undesired or malicious changes, while 77 | communications between recursive resolvers and authoritative nameservers 78 | often incorporate additional protection.\cr 79 | \cr 80 | To address this problem, Google Public DNS offers DNS resolution over an 81 | encrypted HTTPS connection. DNS-over-HTTPS greatly enhances privacy and 82 | security between a client and a recursive resolver, and complements DNSSEC 83 | to provide end-to-end authenticated DNS lookups. 84 | } 85 | \details{ 86 | To perform vectorized queries with only answers (and no metadata) use 87 | \code{bulk_query()}). 88 | } 89 | \examples{ 90 | if (tinytest::at_home()) { 91 | query("rud.is") 92 | dig("example.com", "255") # ANY query 93 | query("microsoft.com", "MX") 94 | dig("google-public-dns-a.google.com", "TXT") 95 | query("apple.com") 96 | dig("17.142.160.59", "PTR") 97 | } 98 | } 99 | \references{ 100 | 101 | } 102 | -------------------------------------------------------------------------------- /man/resource_record_tbl.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gdns-package.r 3 | \docType{data} 4 | \name{resource_record_tbl} 5 | \alias{resource_record_tbl} 6 | \title{An overview of resource records (RRs) permissible in zone files of the Domain Name System (DNS)} 7 | \format{ 8 | A data frame with 39 rows and 4 variables: 9 | \describe{ 10 | \item{type}{numeric type of the resource record} 11 | \item{name}{short name of the resource record} 12 | \item{description}{short description of the resource record} 13 | \item{purpose}{long-form description of the resource record purpose/function/usage} 14 | } 15 | } 16 | \source{ 17 | \url{https://en.wikipedia.org/wiki/List_of_DNS_record_types} 18 | } 19 | \usage{ 20 | resource_record_tbl 21 | } 22 | \description{ 23 | A dataset containing the DNS resource record types, names, description and purpose 24 | } 25 | \keyword{datasets} 26 | -------------------------------------------------------------------------------- /man/rrtypes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/datasets.R 3 | \docType{data} 4 | \name{rrtypes} 5 | \alias{rrtypes} 6 | \title{Resource Record (RR) TYPEs (dataset)} 7 | \format{ 8 | data frame with columns: \code{type}, \code{value}, \code{meaning}, \code{reference}, \code{template}, \code{registration_date} 9 | } 10 | \usage{ 11 | data('rrtypes') 12 | } 13 | \description{ 14 | Resource Record (RR) TYPEs 15 | } 16 | \note{ 17 | Last updated 2019-06-27 11:16:48 18 | } 19 | \references{ 20 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4} 21 | 22 | \url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml} 23 | 24 | rfc6895, rfc1035 25 | } 26 | \keyword{datasets} 27 | -------------------------------------------------------------------------------- /man/spf_ipv4s.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/spf.r 3 | \name{spf_ipv4s} 4 | \alias{spf_ipv4s} 5 | \alias{spf_ipv6s} 6 | \alias{spf_includes} 7 | \alias{spf_ptrs} 8 | \alias{spf_exists} 9 | \title{SPF field extraction functions} 10 | \usage{ 11 | spf_ipv4s(spf_rec) 12 | 13 | spf_ipv6s(spf_rec) 14 | 15 | spf_includes(spf_rec) 16 | 17 | spf_ptrs(spf_rec) 18 | 19 | spf_exists(spf_rec) 20 | } 21 | \arguments{ 22 | \item{spf_rec}{a character vector of DNS TXT records} 23 | } 24 | \value{ 25 | list; each element is a character vector of the specified component 26 | spf_ipv4s("v=spf1 +mx ip4:214.3.140.16/32 ip4:214.3.140.255/32 ip4:214.3.115.12/32") 27 | } 28 | \description{ 29 | Various helper functions to extract SPF record components. 30 | } 31 | -------------------------------------------------------------------------------- /man/split_spf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/spf.r 3 | \name{split_spf} 4 | \alias{split_spf} 5 | \title{Split out all SPF records in a domain's TXT record} 6 | \usage{ 7 | split_spf(spf_rec) 8 | } 9 | \arguments{ 10 | \item{spf_rec}{a character vector of DNS TXT records} 11 | } 12 | \value{ 13 | list; each element is chr vector of spf components 14 | } 15 | \description{ 16 | Given a vector of TXT records, this function will return a list of vectors 17 | of all the SPF records for each. If the given TXT record is not an SPF 18 | record, \code{NA} is returned (which makes it easy to skip with \code{purrr} 19 | functions). 20 | } 21 | \examples{ 22 | split_spf("v=spf1 include:_spf.apple.com include:_spf-txn.apple.com ~all") 23 | } 24 | -------------------------------------------------------------------------------- /tests/tinytest.R: -------------------------------------------------------------------------------- 1 | 2 | if ( requireNamespace("tinytest", quietly=TRUE) ){ 3 | tinytest::test_package("gdns") 4 | } 5 | 6 | -------------------------------------------------------------------------------- /tools/mk-rsrc-rcrd-tbl.R: -------------------------------------------------------------------------------- 1 | library(rvest) 2 | library(tidyverse) 3 | 4 | read_html("https://en.wikipedia.org/wiki/List_of_DNS_record_types") %>% 5 | html_node(xpath=".//table[contains(., 'Address record')]") %>% 6 | html_table() %>% 7 | tbl_df() %>% 8 | janitor::clean_names() %>% 9 | select(type=2, name=1, description=4, purpose=5) %>% 10 | filter(name != "ALIAS") %>% 11 | mutate(type = as.numeric(type)) -> resource_record_tbl 12 | 13 | use_data(resource_record_tbl) 14 | 15 | --------------------------------------------------------------------------------