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