Perform Secure-by-default or Woefully Insecure ‘DNS’ Queries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
2.1 KiB

5 years ago
#' Make a DoH Request (POST/wireformat)
#'
#' Issue a `POST` wireformat query of type `type` for `name` to
#' the DoH endpoint specified at `server_path`.
#'
#' @param name name to query for
#' @param type DNS query type (defaults to "`A`")
#' @param server_path full URL path to the DoH server quer endpoint (defaults to Quad9).
#' @return `NULL` (if the query failed) or a `data.frame` (tibble)
#' @references <https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html>
#' @export
#' @examples
#' doh_post("rud.is", "A")
doh_post <- function(name, type = "A", server_path = "https://dns.quad9.net/dns-query") {
DNSRecord$new()$question(
qname = tolower(name[1]),
qtype = toupper(type[1]),
qclass = "IN"
) -> q
# now, send it off to the server
httr::POST(
url = server_path[1],
httr::add_headers(
`Content-Type` = "application/dns-message",
`Accept` = "application/dns-message"
),
5 years ago
.CLANDNSTINE_UA,
5 years ago
encode = "raw",
body = q$pack()
) -> res
httr::stop_for_status(res)
res <- int_dns_wire_to_list(httr::content(res, as = "raw"))
if (length(res)) {
out <- jsonlite::fromJSON(res)
class(out) <- c("gdns_doh_response", "list")
5 years ago
out
} else {
NULL
}
}
#' Tidy generic
#'
#' @keywords internal
#' @export
#' @param x an object
#' @param ... unused
tidy <- function (x, ...) {
UseMethod("tidy")
}
#' Tidy a DoH POST response
#'
#' @param x a DoH POST response
#' @param ... unused
#' @export
tidy.gdns_doh_response <- function(x, ...) {
rawdat <- x$answer[, c("rdata")]
nr <- colnames(rawdat)
if ("txt_strings" %in% nr) {
vapply(rawdat[["txt_strings"]], function(.x) {
.x
}, FUN.VALUE = character(1)) -> rawdat[["txt_strings"]]
}
lapply(rawdat[["rdata_raw"]], function(.x) {
if (x$question$qtype %in% c(2, 5, 12)) {
charToRaw(.x)
} else {
as.raw(.x)
}
}) -> rawdat[["rdata_raw"]]
cbind.data.frame(
x$answer[, c("name", "class", "type", "ttl")],
rawdat,
stringsAsFactors = FALSE
) -> out
class(out) <- c("tbl_df", "tbl", "data.frame")
out
}