Skip to content

Instantly share code, notes, and snippets.

@ahupowerdns
Last active June 7, 2018 13:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahupowerdns/b2e2c6edac0f4b738127b0d582bef5c1 to your computer and use it in GitHub Desktop.
Save ahupowerdns/b2e2c6edac0f4b738127b0d582bef5c1 to your computer and use it in GitHub Desktop.
H2O dnsdist usecase

h2o 2.2.5

So it is likely I am doing it wrong, or that I have unrealistic expectations.

The repo is: https://github.com/ahupowerdns/pdns/tree/dnsdist-doh The file with all the H2O in there: https://github.com/ahupowerdns/pdns/blob/dnsdist-doh/pdns/dnsdistdist/doh.cc

The model is that I register a handler (in register_handler). This receives DNS over HTTPS requests, in the function doh_handler, and forwards these queries to a DNS thread which does no h2o interactions. Crucially, it forwards the h2o_req_t pointer to that thread too.

This separate DNS thread does its thing, and then forwards the answer to yet another thread that receives DNS responses and feeds them back to h2o. This sender thread receives the h2o_req_t pointer that was originally sent from the doh_handler and uses it to send the response.

So there are two threads that talk to h2o, the main loop, plus a separate thread that makes calls to h2o_send_inline.

In short:

Main H2O thread: doh_handler, sends data + req pointer to dnsdist thread
dnsdist thread: receives data, sends it back to the H2O sender thread
H2O sender thread: receives data from dnsdist thread, calls h2o_send_inline on the req pointer

The observation is that the first request sent out sometimes ends up as 0 bytes in the log:

Warning, this configuration can use more than 1053 file descriptors, web server and console connections not included, and the current limit is 1024.
You can increase this value by using ulimit.
Marking downstream 192.168.1.91:53 as 'up'
> New accept
0xa0abc30, POST qname: example.com, qtype: 2
Attempt to send out 77 bytes over https, TC=0, RCODE=0, qtype=2, req=0xa0abc30
127.0.0.1 - - [07/Jun/2018:15:48:00 +0200] "POST / HTTP/2" 200 0 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"

Firefox is also not happy with the answer. I lack the skills to get this in Wireshark (can I feed it the session key somehow?).

Relevant code snippet:

void responsesender(int rpair[2])
{
  DOHUnit *du;
  for(;;) {
    recv(rpair[1], &du, sizeof(du), 0);

    du->req->res.status = 200;
    du->req->res.reason = "OK";
    
    h2o_add_header(&du->req->pool, &du->req->res.headers, H2O_TOKEN_CONTENT_TYPE, NULL, H2O_STRLIT("application/dns-udpwireformat"));

    struct dnsheader* dh = (struct dnsheader*)du->query.c_str();
    cout<<"Attempt to send out "<<du->query.size()<<" bytes over https, TC="<<dh->tc<<", RCODE="<<dh->rcode<<", qtype="<<du->qtype<<", req="<<(void*)du->req<<endl;

    du->req->res.content_length = du->query.size();
    h2o_send_inline(du->req, du->query.c_str(), du->query.size());
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment