Browse Source

GET only; done-ish

boB Rudis 8 months ago
parent
commit
15206ff4a1
No known key found for this signature in database
13 changed files with 215 additions and 174 deletions
  1. 2
    3
      DESCRIPTION
  2. 2
    2
      NAMESPACE
  3. 7
    0
      R/aaa.R
  4. 51
    0
      R/doh-get.R
  5. 0
    70
      R/doh-post.R
  6. 62
    20
      R/globals.R
  7. 1
    1
      R/playdoh-package.R
  8. 0
    29
      R/zzz.R
  9. 2
    2
      README.Rmd
  10. 29
    22
      README.md
  11. 32
    0
      man/doh_get.Rd
  12. 0
    25
      man/doh_post.Rd
  13. 27
    0
      man/doh_servers.Rd

+ 2
- 3
DESCRIPTION View File

@@ -8,7 +8,7 @@ Authors@R: c(
8 8
            comment = c(ORCID = "0000-0001-5670-2640"))
9 9
   )
10 10
 Maintainer: Bob Rudis <bob@rud.is>
11
-Description: Make 'DNS over HTTPS' (<https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html>) queries.
11
+Description: Make 'DNS over HTTPS' (<https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html>) queries via 'DoH' 'GET'/'REST API'.
12 12
 URL: https://gitlab.com/hrbrmstr/playdoh
13 13
 BugReports: https://gitlab.com/hrbrmstr/playdoh/issues
14 14
 Encoding: UTF-8
@@ -20,7 +20,6 @@ Depends:
20 20
     R (>= 3.2.0)
21 21
 Imports:
22 22
     httr,
23
-    jsonlite,
24
-    reticulate
23
+    jsonlite
25 24
 Roxygen: list(markdown = TRUE)
26 25
 RoxygenNote: 6.1.1

+ 2
- 2
NAMESPACE View File

@@ -1,6 +1,6 @@
1 1
 # Generated by roxygen2: do not edit by hand
2 2
 
3
-export(doh_post)
3
+export(doh_get)
4
+export(doh_servers)
4 5
 import(httr)
5
-import(reticulate)
6 6
 importFrom(jsonlite,fromJSON)

+ 7
- 0
R/aaa.R View File

@@ -0,0 +1,7 @@
1
+httr::user_agent(
2
+  sprintf(
3
+    "playdoh package v%s: (<%s>)",
4
+    utils::packageVersion("playdoh"),
5
+    utils::packageDescription("playdoh")$URL
6
+  )
7
+) -> .PLAYDOH_UA

+ 51
- 0
R/doh-get.R View File

@@ -0,0 +1,51 @@
1
+#' Make a DoH Request (GET/REST)
2
+#'
3
+#' Issue a `GET` REST API query of type `type` for `name` to the
4
+#' DoH endpoint specified at `server_path`.
5
+#'
6
+#' @param name name to query for
7
+#' @param type DNS query type (defaults to "`A`")
8
+#' @param server_path full URL path to the DoH server quer endpoint (defaults to Quad9).
9
+#' @param extra_params any special `GET` query parameter needed for a given server API endpoint.
10
+#'        this should be a named `list`.
11
+#' @return `NULL` (if the query failed) or a `data.frame` (tibble)
12
+#' @references <https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html>
13
+#' @export
14
+#' @examples
15
+#' doh_get("rud.is", "A")
16
+doh_get <- function(name, type = "a", extra_params = list(), service_path = "https://9.9.9.9/dns-query") {
17
+
18
+  stopifnot(is.list(extra_params))
19
+
20
+  extra_params[["name"]] <- tolower(name)
21
+  extra_params[["type"]] <- tolower(type[1])
22
+
23
+  httr::GET(
24
+    url = service_path,
25
+    query = extra_params,
26
+    .PLAYDOH_UA
27
+  ) -> res
28
+
29
+  httr::stop_for_status(res)
30
+
31
+  out <- httr::content(res, as = "text", encoding = "UTF-8")
32
+  out <- jsonlite::fromJSON(out)
33
+
34
+  # will be NULL or a data frame
35
+  ret <- out[["Answer"]]
36
+
37
+  # cleanup column names and add query metadata if query was OK
38
+  if (length(ret)) {
39
+
40
+    colnames(ret) <- tolower(colnames(ret))
41
+
42
+    attr(ret, "question") <- out[["Question"]]
43
+    attr(ret, "flags") <- out[c("Status", "TC", "RD", "RA", "AD", "CD")]
44
+    attr(ret, "edns_client_subnet") <- out[["edns_client_subnet"]]
45
+    attr(ret, "comment") <- out[["comment"]]
46
+
47
+  }
48
+
49
+  ret
50
+
51
+}

+ 0
- 70
R/doh-post.R View File

@@ -1,70 +0,0 @@
1
-#' Make a POST DoH Request (wireformat)
2
-#'
3
-#' Issue the query of type `type` for `name` to the DoH endpoint specified at `server_path`.
4
-#'
5
-#' @param name name to query for
6
-#' @param type DNS query type (defaults to "`A`")
7
-#' @param server_path full URL path to the DoH server quer endpoint (defaults to Quad9).
8
-#' @return `NULL` (if the query failed) or a `data.frame` (tibble)
9
-#' @references <https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html>
10
-#' @export
11
-doh_post <- function(name, type = "A", server_path = "https://dns.quad9.net/dns-query") {
12
-
13
-  # for now, use python's {dnslib} as a crutch to
14
-  # encode/decode wireformat DNS questions and answers
15
-
16
-  .dns$DNSRecord$question(
17
-    qname = tolower(name[1]),
18
-    qtype = toupper(type[1]),
19
-    qclass = "IN"
20
-  ) -> q
21
-
22
-  qpak <- q$pack()
23
-
24
-  # now, send it off to the server
25
-
26
-  httr::POST(
27
-    url = server_path[1],
28
-    httr::add_headers(
29
-      `Content-Type` = "application/dns-message",
30
-      `Accept` = "application/dns-message"
31
-    ),
32
-    encode = "raw",
33
-    body = qpak
34
-  ) -> res
35
-
36
-  httr::warn_for_status(res)
37
-
38
-  # if the response is OK, make it a data frame
39
-
40
-  if (httr::status_code(res) == 200) {
41
-
42
-    r <- .dns$DNSRecord$parse(httr::content(res))
43
-
44
-    q <- r$get_q()
45
-
46
-    do.call(
47
-      rbind.data.frame,
48
-      lapply(r$rr, function(.x) {
49
-        data.frame(
50
-          query = py_str(q$qname),
51
-          qtype = q$qtype,
52
-          rname = py_str(.x$rname),
53
-          rtype = .x$rtype,
54
-          rdata = py_str(.x$rdata),
55
-          ttl = .x$ttl,
56
-          stringsAsFactors = FALSE
57
-        )
58
-      })
59
-
60
-    ) -> xdf
61
-
62
-    class(xdf) <- c("tbl_df", "tbl", "data.frame")
63
-
64
-    xdf
65
-
66
-  } else {
67
-    NULL
68
-  }
69
-
70
-}

+ 62
- 20
R/globals.R View File

@@ -1,3 +1,65 @@
1
+
2
+c(
3
+  'A' = 1L, 'NS' = 2L, 'CNAME' = 5L, 'SOA' = 6L, 'PTR' = 12L, 'HINFO' = 13L,
4
+  'MX' = 15L, 'TXT' = 16L, 'RP' = 17L, 'AFSDB' = 18L, 'SIG' = 24L,
5
+  'KEY' = 25L, 'AAAA' = 28L, 'LOC' = 29, 'SRV' = 33L, 'NAPTR' = 35L,
6
+  'KX' = 36L, 'CERT' = 37L, 'A6' = 38L, 'DNAME' = 39L, 'OPT' = 41,
7
+  'APL' = 42L, 'DS' = 43L, 'SSHFP' = 44L, 'IPSECKEY' = 45L, 'RRSIG' = 46L,
8
+  'NSEC' = 47L, 'DNSKEY' = 48L, 'DHCID' = 49L, 'NSEC3' = 50L,
9
+  'NSEC3PARAM' = 51L, 'TLSA' = 52L, 'HIP' = 55L, 'CDS' = 59L,
10
+  'CDNSKEY' = 60L, 'OPENPGPKEY' = 61L, 'SPF' = 99L, 'TKEY' = 249L,
11
+  'TSIG' = 250L, 'IXFR' = 251L, 'AXFR' = 252L, 'ANY' = 255L,
12
+  'URI' = 256L, 'CAA' = 257L, 'TA' = 32768L, 'DLV' = 32769L
13
+) -> .qtype
14
+
15
+c(
16
+  'IN' = 1L,
17
+  'CS' = 2L,
18
+  'CH' = 3L,
19
+  'Hesiod' = 4L,
20
+  'None' = 254L,
21
+  '*' = 255L
22
+) -> .class
23
+
24
+.qr <- c('QUERY' = 0, 'RESPONSE' = 1)
25
+
26
+c(
27
+  'NOERROR' = 0L,
28
+  'FORMERR' = 1L,
29
+  'SERVFAIL' = 2L,
30
+  'NXDOMAIN' = 3L,
31
+  'NOTIMP' = 4L,
32
+  'REFUSED' = 5L,
33
+  'YXDOMAIN' = 6L,
34
+  'YXRRSET' = 7L,
35
+  'NXRRSET' = 8L,
36
+  'NOTAUTH' = 9L,
37
+  'NOTZONE' = 10L
38
+) -> .rcode
39
+
40
+c(
41
+  'QUERY' = 0L,
42
+  'IQUERY' = 1L,
43
+  'STATUS' = 2L,
44
+  'UPDATE' = 5L
45
+) -> .opcode
46
+
47
+#' Built-in list of DoH Servers
48
+#'
49
+#' The `url` element has the URL for the `GET` requests and
50
+#' the `extra_params` element has any needed query parameters
51
+#' for the `GET` requests.
52
+#'
53
+#' The list so far.
54
+#' - `google`: <https://dns.google.com/experimental>
55
+#' - `cloudflare`: <https://cloudflare-dns.com/dns-query>
56
+#' - `quad9`: <https://dns.quad9.net/dns-query>
57
+#' - `securedns_eu`: <https://doh.securedns.eu/dns-query>
58
+#' - `dnswarden_adblock`: <https://doh.dnswarden.com/adblock>
59
+#' - `dnswarden_uncensored`: <https://doh.dnswarden.com/uncensored>
60
+#'
61
+#' @docType data
62
+#' @export
1 63
 list(
2 64
   google = list(
3 65
     url = "https://dns.google.com/experimental",
@@ -28,25 +90,5 @@ list(
28 90
   dnswarden_uncensored = list(
29 91
     url = "https://doh.dnswarden.com/uncensored",
30 92
     extra_params = list()
31
-  ),
32
-  cleanbrowsing_security = list(
33
-    url = "https://doh.cleanbrowsing.org/doh/security-filter/",
34
-    extra_params = list(cd = "false")
35
-  ),
36
-  cleanbrowsing_family = list(
37
-    url = "https://doh.cleanbrowsing.org/doh/family-filter/",
38
-    extra_params = list()
39
-  ),
40
-  cleanbrowsing_adult = list(
41
-    url = "https://doh.cleanbrowsing.org/doh/adult-filter/",
42
-    extra_params = list()
43
-  ),
44
-  power_dns = list(
45
-    url = "https://doh.powerdns.org",
46
-    extra_params = list()
47
-  ),
48
-  appliedprivacy = list(
49
-    url = "https://doh.appliedprivacy.net/query",
50
-    extra_params = list()
51 93
   )
52 94
 ) -> doh_servers

+ 1
- 1
R/playdoh-package.R View File

@@ -9,6 +9,6 @@
9 9
 #' @docType package
10 10
 #' @keywords internal
11 11
 #' @author Bob Rudis (bob@@rud.is)
12
-#' @import httr reticulate
12
+#' @import httr
13 13
 #' @importFrom jsonlite fromJSON
14 14
 NULL

+ 0
- 29
R/zzz.R View File

@@ -1,29 +0,0 @@
1
-py_c <- reticulate::py_config()
2
-
3
-.dns <- NULL
4
-
5
-.onLoad <- function(libname, pkgname) {
6
-
7
-  if (utils::compareVersion(py_c$version, "3.5") < 0) {
8
-    stop(
9
-      paste0(
10
-        c(
11
-          "Python 3.5+ is required. If this is installed please set RETICULATE_PYTHON ",
12
-          "to the path to the Python 3 binary on your system and try re-installing/",
13
-          "re-loading the package."
14
-        ),
15
-        collapse = ""
16
-      )
17
-    )
18
-    return()
19
-  }
20
-
21
-  if (!reticulate::py_module_available("dnslib")) {
22
-    packageStartupMessage(
23
-      "The 'dnslib' Python module must be installed."
24
-    )
25
-  } else {
26
-    .dns <<- reticulate::import("dnslib", delay_load = TRUE)
27
-  }
28
-
29
-}

+ 2
- 2
README.Rmd View File

@@ -52,9 +52,9 @@ packageVersion("playdoh")
52 52
 ### Basic functionality
53 53
 
54 54
 ```{r}
55
-doh_post("rud.is")
55
+doh_get("rud.is")
56 56
 
57
-doh_post("lenovo.com", "txt")
57
+doh_get("lenovo.com", "txt")
58 58
 ```
59 59
 
60 60
 ## playdoh Metrics

+ 29
- 22
README.md View File

@@ -46,34 +46,41 @@ packageVersion("playdoh")
46 46
 ### Basic functionality
47 47
 
48 48
 ``` r
49
-doh_post("rud.is")
50
-## # A tibble: 1 x 6
51
-##   query   qtype rname   rtype rdata           ttl
52
-##   <chr>   <int> <chr>   <int> <chr>         <int>
53
-## 1 rud.is.     1 rud.is.     1 172.93.49.183  3600
54
-
55
-doh_post("lenovo.com", "txt")
56
-## # A tibble: 10 x 6
57
-##    query      qtype rname      rtype rdata                                                                           ttl
58
-##    <chr>      <int> <chr>      <int> <chr>                                                                         <int>
59
-##  1 lenovo.co…    16 lenovo.co…    16 "\"qh7hdmqm4lzs85p704d6wsybgrpsly0j\""                                            1
60
-##  2 lenovo.co…    16 lenovo.co…    16 "\"ece42d7743c84d6889abda7011fe6f53\""                                            1
61
-##  3 lenovo.co…    16 lenovo.co…    16 "\"a82c74b37aa84e7c8580f0e32f4d795d\""                                            1
62
-##  4 lenovo.co…    16 lenovo.co…    16 "\"google-site-verification=VxW_e6r_Ka7A518qfX2MmIMHGnkpGbnACsjSxKFCBw0\""        1
63
-##  5 lenovo.co…    16 lenovo.co…    16 "\"google-site-verification=sHIlSlj0U6UnCDkfHp1AolWgVEvDjWvc0TR4KaysD2c\""        1
64
-##  6 lenovo.co…    16 lenovo.co…    16 "\"Visit www.lenovo.com/think for information about Lenovo products and serv…     1
65
-##  7 lenovo.co…    16 lenovo.co…    16 "\"google-site-verification=nGgukcp60rC-gFxMOJw1NHH0B4VnSchRrlfWV-He_tE\""        1
66
-##  8 lenovo.co…    16 lenovo.co…    16 "\"iHzQJvsKnyGP2Nm2qBgL3fyBJ0CC9z4GkY/flfk4EzLP8lPxWHDDPKqZWm1TkeF5kEIL+NotY…     1
67
-##  9 lenovo.co…    16 lenovo.co…    16 "\"v=spf1 include:spf.messagelabs.com include:_netblocks.eloqua.com ~all\""       1
68
-## 10 lenovo.co…    16 lenovo.co…    16 "\"facebook-domain-verification=1r2am7c2bhzrxpqyt0mda0djoquqsi\""                 1
49
+doh_get("rud.is")
50
+##      name type  ttl                       expires          data
51
+## 1 rud.is.    1 2300 Sun, 26 May 2019 18:08:58 UTC 172.93.49.183
52
+
53
+doh_get("lenovo.com", "txt")
54
+##           name type  ttl                       expires
55
+## 1  lenovo.com.   16 7200 Sun, 26 May 2019 19:30:38 UTC
56
+## 2  lenovo.com.   16 7200 Sun, 26 May 2019 19:30:38 UTC
57
+## 3  lenovo.com.   16 7200 Sun, 26 May 2019 19:30:38 UTC
58
+## 4  lenovo.com.   16 7200 Sun, 26 May 2019 19:30:38 UTC
59
+## 5  lenovo.com.   16 7200 Sun, 26 May 2019 19:30:38 UTC
60
+## 6  lenovo.com.   16 7200 Sun, 26 May 2019 19:30:38 UTC
61
+## 7  lenovo.com.   16 7200 Sun, 26 May 2019 19:30:38 UTC
62
+## 8  lenovo.com.   16 7200 Sun, 26 May 2019 19:30:38 UTC
63
+## 9  lenovo.com.   16 7200 Sun, 26 May 2019 19:30:38 UTC
64
+## 10 lenovo.com.   16 7200 Sun, 26 May 2019 19:30:38 UTC
65
+##                                                                                          data
66
+## 1                               "facebook-domain-verification=1r2am7c2bhzrxpqyt0mda0djoquqsi"
67
+## 2                      "google-site-verification=sHIlSlj0U6UnCDkfHp1AolWgVEvDjWvc0TR4KaysD2c"
68
+## 3                      "google-site-verification=nGgukcp60rC-gFxMOJw1NHH0B4VnSchRrlfWV-He_tE"
69
+## 4                                                          "a82c74b37aa84e7c8580f0e32f4d795d"
70
+## 5             "Visit www.lenovo.com/think for information about Lenovo products and services"
71
+## 6                                                          "qh7hdmqm4lzs85p704d6wsybgrpsly0j"
72
+## 7                      "google-site-verification=VxW_e6r_Ka7A518qfX2MmIMHGnkpGbnACsjSxKFCBw0"
73
+## 8                                                          "ece42d7743c84d6889abda7011fe6f53"
74
+## 9  "iHzQJvsKnyGP2Nm2qBgL3fyBJ0CC9z4GkY/flfk4EzLP8lPxWHDDPKqZWm1TkeF5kEIL+NotYOF1wo7JtUDXXw=="
75
+## 10                    "v=spf1 include:spf.messagelabs.com include:_netblocks.eloqua.com ~all"
69 76
 ```
70 77
 
71 78
 ## playdoh Metrics
72 79
 
73 80
 | Lang | \# Files |  (%) | LoC |  (%) | Blank lines |  (%) | \# Lines |  (%) |
74 81
 | :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: |
75
-| R    |        6 | 0.86 | 122 | 0.92 |          23 | 0.51 |       26 | 0.42 |
76
-| Rmd  |        1 | 0.14 |  11 | 0.08 |          22 | 0.49 |       36 | 0.58 |
82
+| R    |        6 | 0.86 | 107 | 0.91 |          20 | 0.48 |       47 | 0.57 |
83
+| Rmd  |        1 | 0.14 |  11 | 0.09 |          22 | 0.52 |       36 | 0.43 |
77 84
 
78 85
 ## Code of Conduct
79 86
 

+ 32
- 0
man/doh_get.Rd View File

@@ -0,0 +1,32 @@
1
+% Generated by roxygen2: do not edit by hand
2
+% Please edit documentation in R/doh-get.R
3
+\name{doh_get}
4
+\alias{doh_get}
5
+\title{Make a DoH Request (GET/REST)}
6
+\usage{
7
+doh_get(name, type = "a", extra_params = list(),
8
+  service_path = "https://9.9.9.9/dns-query")
9
+}
10
+\arguments{
11
+\item{name}{name to query for}
12
+
13
+\item{type}{DNS query type (defaults to "\code{A}")}
14
+
15
+\item{extra_params}{any special \code{GET} query parameter needed for a given server API endpoint.
16
+this should be a named \code{list}.}
17
+
18
+\item{server_path}{full URL path to the DoH server quer endpoint (defaults to Quad9).}
19
+}
20
+\value{
21
+\code{NULL} (if the query failed) or a \code{data.frame} (tibble)
22
+}
23
+\description{
24
+Issue a \code{GET} REST API query of type \code{type} for \code{name} to the
25
+DoH endpoint specified at \code{server_path}.
26
+}
27
+\examples{
28
+doh_get("rud.is", "A")
29
+}
30
+\references{
31
+\url{https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html}
32
+}

+ 0
- 25
man/doh_post.Rd View File

@@ -1,25 +0,0 @@
1
-% Generated by roxygen2: do not edit by hand
2
-% Please edit documentation in R/doh-post.R
3
-\name{doh_post}
4
-\alias{doh_post}
5
-\title{Make a POST DoH Request (wireformat)}
6
-\usage{
7
-doh_post(name, type = "A",
8
-  server_path = "https://dns.quad9.net/dns-query")
9
-}
10
-\arguments{
11
-\item{name}{name to query for}
12
-
13
-\item{type}{DNS query type (defaults to "\code{A}")}
14
-
15
-\item{server_path}{full URL path to the DoH server quer endpoint (defaults to Quad9).}
16
-}
17
-\value{
18
-\code{NULL} (if the query failed) or a \code{data.frame} (tibble)
19
-}
20
-\description{
21
-Issue the query of type \code{type} for \code{name} to the DoH endpoint specified at \code{server_path}.
22
-}
23
-\references{
24
-\url{https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-05.html}
25
-}

+ 27
- 0
man/doh_servers.Rd View File

@@ -0,0 +1,27 @@
1
+% Generated by roxygen2: do not edit by hand
2
+% Please edit documentation in R/globals.R
3
+\docType{data}
4
+\name{doh_servers}
5
+\alias{doh_servers}
6
+\title{Built-in list of DoH Servers}
7
+\format{An object of class \code{list} of length 6.}
8
+\usage{
9
+doh_servers
10
+}
11
+\description{
12
+The \code{url} element has the URL for the \code{GET} requests and
13
+the \code{extra_params} element has any needed query parameters
14
+for the \code{GET} requests.
15
+}
16
+\details{
17
+The list so far.
18
+\itemize{
19
+\item \code{google}: \url{https://dns.google.com/experimental}
20
+\item \code{cloudflare}: \url{https://cloudflare-dns.com/dns-query}
21
+\item \code{quad9}: \url{https://dns.quad9.net/dns-query}
22
+\item \code{securedns_eu}: \url{https://doh.securedns.eu/dns-query}
23
+\item \code{dnswarden_adblock}: \url{https://doh.dnswarden.com/adblock}
24
+\item \code{dnswarden_uncensored}: \url{https://doh.dnswarden.com/uncensored}
25
+}
26
+}
27
+\keyword{datasets}

Loading…
Cancel
Save