Commit a1ba8458 authored by Marek Vavruša's avatar Marek Vavruša Committed by Petr Špaček

daemon: allow opportunistic DNS over TLS to origins

This commit allows opportunistic DNS over TLS to origins configured
as supporting DoT on port 853. It also adds interface for clearing
configured TLS clients to allow runtime reconfiguration.

The general mode of operation is as follows:

1. Produce a new outgoing query
2. Check if the selected upstream address has configured TLS support on port 853
 2a. If it does: upgrade to DNS over TLS, it cannot be downgraded from this point
 2b. If not: continue with preferred protocol

This allows further automatic discovery as in [1], but right now it has to be configured
manually.

[1]: https://tools.ietf.org/id/draft-bortzmeyer-dprive-resolver-to-auth-00.html

(cherrypicked from cloudflare branch, need to be adapted)
parent 4d91c0a0
......@@ -599,6 +599,46 @@ static int net_tls_client(lua_State *L)
return 1;
}
static int net_tls_client_clear(lua_State *L)
{
struct engine *engine = engine_luaget(L);
if (!engine) {
return 0;
}
struct network *net = &engine->net;
if (!net) {
return 0;
}
if (lua_gettop(L) != 1 || !lua_isstring(L, 1)) {
format_error(L, "net.tls_client_clear() requires one parameter (\"address\")");
lua_error(L);
}
const char *full_addr = lua_tostring(L, 1);
char addr[INET6_ADDRSTRLEN];
uint16_t port = 0;
if (kr_straddr_split(full_addr, addr, sizeof(addr), &port) != kr_ok()) {
format_error(L, "invalid IP address");
lua_error(L);
}
if (port == 0) {
port = 853;
}
int r = tls_client_params_clear(&net->tls_client_params, addr, port);
if (r != 0) {
lua_pushstring(L, kr_strerror(r));
lua_error(L);
}
lua_pushboolean(L, true);
return 1;
}
static int net_tls_padding(lua_State *L)
{
struct engine *engine = engine_luaget(L);
......@@ -852,6 +892,7 @@ int lib_net(lua_State *L)
{ "tls", net_tls },
{ "tls_server", net_tls },
{ "tls_client", net_tls_client },
{ "tls_client_clear", net_tls_client_clear },
{ "tls_padding", net_tls_padding },
{ "tls_sticket_secret", net_tls_sticket_secret_string },
{ "tls_sticket_secret_file", net_tls_sticket_secret_file },
......
......@@ -805,6 +805,49 @@ static int client_paramlist_entry_clear(const char *k, void *v, void *baton)
return client_paramlist_entry_free(entry);
}
struct tls_client_paramlist_entry *tls_client_try_upgrade(map_t *tls_client_paramlist,
const struct sockaddr *addr)
{
/* Opportunistic upgrade from port 53 -> 853 */
if (kr_inaddr_port(addr) != KR_DNS_PORT) {
return NULL;
}
static char key[INET6_ADDRSTRLEN + 6];
size_t keylen = sizeof(key);
if (kr_inaddr_str(addr, key, &keylen) != 0) {
return NULL;
}
/* Rewrite 053 -> 853 */
strcpy(key + keylen - 3, "853");
return map_get(tls_client_paramlist, key);
}
int tls_client_params_clear(map_t *tls_client_paramlist, const char *addr, uint16_t port)
{
if (!tls_client_paramlist || !addr) {
return kr_error(EINVAL);
}
/* Parameters are OK */
char key[INET6_ADDRSTRLEN + 6];
size_t keylen = sizeof(key);
if (kr_straddr_join(addr, port, key, &keylen) != kr_ok()) {
return kr_error(EINVAL);
}
struct tls_client_paramlist_entry *entry = map_get(tls_client_paramlist, key);
if (entry != NULL) {
client_paramlist_entry_clear(NULL, (void *)entry, NULL);
map_del(tls_client_paramlist, key);
}
return kr_ok();
}
int tls_client_params_set(map_t *tls_client_paramlist,
const char *addr, uint16_t port,
const char *param, tls_client_param_t param_type)
......
......@@ -168,6 +168,9 @@ int tls_set_hs_state(struct tls_common_ctx *ctx, tls_hs_state_t state);
struct tls_client_paramlist_entry *tls_client_try_upgrade(map_t *tls_client_paramlist,
const struct sockaddr *addr);
/*! Clear (remove) TLS parameters for given address. */
int tls_client_params_clear(map_t *tls_client_paramlist, const char *addr, uint16_t port);
/*! Set TLS authentication parameters for given address.
* Note: hostnames must be imported before ca files,
* otherwise ca files will not be imported at all.
......
......@@ -1401,6 +1401,22 @@ static int qr_task_step(struct qr_task *task,
choice += 1;
}
/* Upgrade to TLS if the upstream address is configured as DoT capable. */
struct engine *engine = ctx->worker->engine;
struct network *net = &engine->net;
const struct sockaddr *addr = packet_source ? packet_source : task->addrlist;
struct tls_client_paramlist_entry *tls_entry = NULL;
if (kr_inaddr_port(task->addrlist) == KR_DNS_PORT) {
tls_entry = tls_client_try_upgrade(&net->tls_client_params, task->addrlist);
if (tls_entry != NULL) {
kr_inaddr_set_port(task->addrlist, KR_DNS_TLS_PORT);
sock_type = SOCK_STREAM;
}
} else if (sock_type == SOCK_STREAM) {
const char *key = tcpsess_key(addr);
tls_entry = map_get(&net->tls_client_params, key);
}
int ret = 0;
if (sock_type == SOCK_DGRAM) {
/* Start fast retransmit with UDP. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment