From: Petr Špaček Date: Tue, 2 Apr 2019 17:12:46 +0000 (+0200) Subject: doh: make client and server address available to modules X-Git-Tag: v4.0.0~10^2~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b99df0874a61d763dc495fedc838f83749356189;p=thirdparty%2Fknot-resolver.git doh: make client and server address available to modules This will allow modules like view etc. work in the same way with packets received over HTTP. --- diff --git a/daemon/lua/kres-gen.lua b/daemon/lua/kres-gen.lua index c369c6499..1b7571fbd 100644 --- a/daemon/lua/kres-gen.lua +++ b/daemon/lua/kres-gen.lua @@ -312,6 +312,7 @@ const char *kr_inaddr(const struct sockaddr *); int kr_inaddr_family(const struct sockaddr *); int kr_inaddr_len(const struct sockaddr *); int kr_inaddr_str(const struct sockaddr *, char *, size_t *); +int kr_sockaddr_cmp(const struct sockaddr *, const struct sockaddr *); int kr_sockaddr_len(const struct sockaddr *); uint16_t kr_inaddr_port(const struct sockaddr *); int kr_straddr_family(const char *); diff --git a/daemon/lua/kres-gen.sh b/daemon/lua/kres-gen.sh index 83d46c069..1365f1fe0 100755 --- a/daemon/lua/kres-gen.sh +++ b/daemon/lua/kres-gen.sh @@ -174,6 +174,7 @@ ${CDEFS} ${LIBKRES} functions <<-EOF kr_inaddr_family kr_inaddr_len kr_inaddr_str + kr_sockaddr_cmp kr_sockaddr_len kr_inaddr_port kr_straddr_family diff --git a/modules/http/http_doh.lua b/modules/http/http_doh.lua index 8a061ee0f..4088ad07b 100644 --- a/modules/http/http_doh.lua +++ b/modules/http/http_doh.lua @@ -8,6 +8,13 @@ local function get_http_ttl(pkt) return ffi.C.packet_ttl(pkt, is_negative) end +local function convert_sockaddr(family, ipaddr, port) + if not (family and ipaddr and port) then + panic('failed to obtain peer IP address') + end + return ffi.gc(ffi.C.kr_straddr_socket(ipaddr, port), ffi.C.free) +end + -- Trace execution of DNS queries local function serve_doh(h, stream) local input @@ -81,8 +88,14 @@ local function serve_doh(h, stream) end print(pkt) + -- set source address so filters can work + local function init_cb(req) + req.qsource.addr = convert_sockaddr(stream:peername()) + req.qsource.dst_addr = convert_sockaddr(stream:localname()) + end + -- resolve query - worker.resolve_pkt(pkt, finish_cb) + worker.resolve_pkt(pkt, finish_cb, init_cb) -- Wait for asynchronous query and free callbacks -- FIXME if not done then waiting = true diff --git a/modules/http/http_doh.test.lua b/modules/http/http_doh.test.lua index 2b41edf54..9dd387156 100644 --- a/modules/http/http_doh.test.lua +++ b/modules/http/http_doh.test.lua @@ -178,6 +178,47 @@ else check_err(req, '415', 'unsupported request content type finishes with 415') end + local function test_dstaddr() + local triggered = false + local exp_dstaddr = ffi.gc(ffi.C.kr_straddr_socket(host, port), ffi.C.free) + local function check_dstaddr(state, req) + triggered = true + print(exp_dstaddr) + print(req.qsource.dst_addr) + same(ffi.C.kr_sockaddr_cmp(req.qsource.dst_addr, exp_dstaddr), 0, + 'request has correct server address') + return state + end + policy.add(policy.suffix(check_dstaddr, policy.todnames({'dstaddr.test'}))) + local desc = 'valid POST query has server address available in request' + local req = req_templ:clone() + req.headers:upsert(':method', 'POST') + req:set_body(basexx.from_base64( -- dstaddr.test. A + 'FnkBAAABAAAAAAAAB2RzdGFkZHIEdGVzdAAAAQAB')) + check_ok(req, desc) + ok(triggered, 'dstaddr policy was triggered') + end + + local function test_srcaddr() + modules.load('view') + assert(view) + local policy_refuse = policy.suffix(policy.REFUSE, policy.todnames({'srcaddr.test.knot-resolver.cz'})) + -- these netmasks would not work if the request did not contain IP addresses + view:addr('0.0.0.0/0', policy_refuse) + view:addr('::/0', policy_refuse) + + local desc = 'valid POST query has source address available in request' + local req = req_templ:clone() + req.headers:upsert(':method', 'POST') + req:set_body(basexx.from_base64( -- srcaddr.test.knot-resolver.cz TXT + 'QNQBAAABAAAAAAAAB3NyY2FkZHIEdGVzdA1rbm90LXJlc29sdmVyAmN6AAAQAAE')) + headers, pkt = check_ok(req, desc) + same(pkt:rcode(), kres.rcode.REFUSED, desc .. ': view module caught it') + + modules.unload('view') + end + + -- not implemented -- local function test_post_unsupp_accept() -- local req = assert(req_templ:clone()) @@ -197,7 +238,9 @@ else test_post_unsupp_type, test_doh_servfail, test_doh_nxdomain, - test_doh_noerror + test_doh_noerror, + test_dstaddr, + test_srcaddr } return tests