Skip to content

Commit

Permalink
dns-server: simple support proxy dnssec
Browse files Browse the repository at this point in the history
  • Loading branch information
pymumu committed Dec 16, 2023
1 parent a0f82ea commit a19ac7e
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 20 deletions.
27 changes: 25 additions & 2 deletions src/dns.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
#define TC_MASK 0x0200
#define RD_MASK 0x0100
#define RA_MASK 0x0080
#define Z_MASK 0x0040
#define AD_MASK 0x0020
#define CD_MASK 0x0010
#define RCODE_MASK 0x000F
#define DNS_RR_END (0XFFFF)

Expand Down Expand Up @@ -1011,6 +1014,17 @@ int dns_get_OPT_payload_size(struct dns_packet *packet)
return packet->payloadsize;
}

int dns_set_OPT_option(struct dns_packet *packet, unsigned int option)
{
packet->opt_option = option;
return 0;
}

unsigned int dns_get_OPT_option(struct dns_packet *packet)
{
return packet->opt_option;
}

int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs)
{
unsigned char opt_data[DNS_MAX_OPT_LEN];
Expand Down Expand Up @@ -1402,6 +1416,9 @@ static int _dns_decode_head(struct dns_context *context)
head->tc = (fields & TC_MASK) >> 9;
head->rd = (fields & RD_MASK) >> 8;
head->ra = (fields & RA_MASK) >> 7;
head->z = (fields & Z_MASK) >> 6;
head->ad = (fields & AD_MASK) >> 5;
head->cd = (fields & CD_MASK) >> 4;
head->rcode = (fields & RCODE_MASK) >> 0;
head->qdcount = _dns_read_short(&context->ptr);
head->ancount = _dns_read_short(&context->ptr);
Expand Down Expand Up @@ -1429,6 +1446,9 @@ static int _dns_encode_head(struct dns_context *context)
fields |= (head->tc << 9) & TC_MASK;
fields |= (head->rd << 8) & RD_MASK;
fields |= (head->ra << 7) & RA_MASK;
fields |= (head->z << 6) & Z_MASK;
fields |= (head->ad << 5) & AD_MASK;
fields |= (head->cd << 4) & CD_MASK;
fields |= (head->rcode << 0) & RCODE_MASK;
_dns_write_short(&context->ptr, fields);

Expand Down Expand Up @@ -1976,7 +1996,7 @@ static int _dns_encode_opts(struct dns_packet *packet, struct dns_context *conte
int i = 0;
int len = 0;
int ret = 0;
unsigned int rcode = 0;
unsigned int rcode = packet->opt_option;
int rr_len = 0;
int payloadsize = packet->payloadsize;
unsigned char *rr_len_ptr = NULL;
Expand Down Expand Up @@ -2429,7 +2449,7 @@ static int _dns_decode_an(struct dns_context *context, dns_rr_type type)
tlog(TLOG_DEBUG, "opt length mismatch, %s\n", domain);
return -1;
}

dns_set_OPT_option(packet, ttl);
dns_set_OPT_payload_size(packet, qclass);
} break;
case DNS_T_HTTPS: {
Expand Down Expand Up @@ -2680,6 +2700,9 @@ int dns_packet_init(struct dns_packet *packet, int size, struct dns_head *head)
init_head->tc = head->tc;
init_head->rd = head->rd;
init_head->ra = head->ra;
init_head->z = head->z;
init_head->ad = head->ad;
init_head->cd = head->cd;
init_head->rcode = head->rcode;
packet->questions = DNS_RR_END;
packet->answers = DNS_RR_END;
Expand Down
10 changes: 10 additions & 0 deletions src/dns.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ extern "C" {
#define DNS_MAX_ALPN_LEN 32
#define DNS_MAX_ECH_LEN 256

#define DNS_OPT_FLAG_DO 0x8000

#define DNS_ADDR_FAMILY_IP 1
#define DNS_ADDR_FAMILY_IPV6 2

Expand Down Expand Up @@ -132,6 +134,10 @@ struct dns_head {
unsigned char tc; /* Truncation Flag */
unsigned char rd; /* Recursion Desired */
unsigned char ra; /* Recursion Available */
unsigned char z; /* Reserved for future use. Must be Zero! */
unsigned char ad; /* Authentic Data Flag */
unsigned char cd; /* Checking Disabled Flag */
unsigned char padding; /* Padding */
unsigned short rcode; /* Response Code */
unsigned short qdcount; /* number of question entries */
unsigned short ancount; /* number of answer entries */
Expand Down Expand Up @@ -160,6 +166,7 @@ struct dns_packet {
unsigned short optcount;
unsigned short optional;
unsigned short payloadsize;
unsigned int opt_option;
struct dns_packet_dict namedict;
int size;
int len;
Expand Down Expand Up @@ -276,6 +283,9 @@ int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct
int dns_add_NS(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, const char *cname);
int dns_get_NS(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size);

int dns_set_OPT_option(struct dns_packet *packet, unsigned int option);
unsigned int dns_get_OPT_option(struct dns_packet *packet);

int dns_set_OPT_payload_size(struct dns_packet *packet, int payload_size);
int dns_get_OPT_payload_size(struct dns_packet *packet);

Expand Down
18 changes: 17 additions & 1 deletion src/dns_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ struct dns_query_struct {
/* ECS */
struct dns_client_ecs ecs;

/* EDNS0_DO */
int edns0_do;

/* replied hash table */
DECLARE_HASHTABLE(replied_map, 4);
};
Expand Down Expand Up @@ -2460,7 +2463,8 @@ static int _dns_client_socket_ssl_recv(struct dns_server_info *server, void *buf
}
#endif

tlog(TLOG_WARN, "SSL read fail error no: %s(%lx), reason: %d\n", ERR_reason_error_string(ssl_err), ssl_err, ssl_reason);
tlog(TLOG_WARN, "SSL read fail error no: %s(%lx), reason: %d\n", ERR_reason_error_string(ssl_err), ssl_err,
ssl_reason);
errno = EFAULT;
ret = -1;
break;
Expand Down Expand Up @@ -3430,6 +3434,7 @@ static int _dns_client_setup_server_packet(struct dns_server_info *server_info,
head.aa = 0;
head.rd = 1;
head.ra = 0;
head.ad = query->edns0_do;
head.rcode = 0;

if (dns_packet_init(packet, DNS_PACKSIZE, &head) != 0) {
Expand All @@ -3449,6 +3454,9 @@ static int _dns_client_setup_server_packet(struct dns_server_info *server_info,
}

dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
if (query->edns0_do) {
dns_set_OPT_option(packet, DNS_OPT_FLAG_DO);
}

if (server_info->type != DNS_SERVER_UDP) {
dns_add_OPT_TCP_KEEPALIVE(packet, 6000);
Expand Down Expand Up @@ -3651,6 +3659,7 @@ static int _dns_client_send_query(struct dns_query_struct *query)
head.aa = 0;
head.rd = 1;
head.ra = 0;
head.ad = query->edns0_do;
head.rcode = 0;

if (dns_packet_init(packet, DNS_PACKSIZE, &head) != 0) {
Expand All @@ -3665,6 +3674,9 @@ static int _dns_client_send_query(struct dns_query_struct *query)
}

dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
if (query->edns0_do) {
dns_set_OPT_option(packet, DNS_OPT_FLAG_DO);
}
/* dns_add_OPT_TCP_KEEPALIVE(packet, 1200); */
if (_dns_client_dns_add_ecs(query, packet) != 0) {
tlog(TLOG_ERROR, "add ecs failed.");
Expand Down Expand Up @@ -3777,6 +3789,10 @@ static int _dns_client_query_parser_options(struct dns_query_struct *query, stru
_dns_client_query_setup_default_ecs(query);
}

if (options->enable_flag & DNS_QUEY_OPTION_EDNS0_DO) {
query->edns0_do = 1;
}

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions src/dns_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ typedef enum dns_result_type {

#define DNS_QUEY_OPTION_ECS_DNS (1 << 0)
#define DNS_QUEY_OPTION_ECS_IP (1 << 1)
#define DNS_QUEY_OPTION_EDNS0_DO (1 << 2)

int dns_client_init(void);

Expand Down
82 changes: 65 additions & 17 deletions src/dns_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@

#define PREFETCH_FLAGS_NO_DUALSTACK (1 << 0)
#define PREFETCH_FLAGS_EXPIRED (1 << 1)
#define PREFETCH_FLAGS_NOPREFETCH (1 << 2)

#define RECV_ERROR_AGAIN 1
#define RECV_ERROR_OK 0
Expand Down Expand Up @@ -256,6 +257,7 @@ struct dns_request {
struct sockaddr_storage localaddr;
int has_ecs;
struct dns_opt_ecs ecs;
int edns0_do;

dns_result_callback result_callback;
void *user_ptr;
Expand Down Expand Up @@ -422,21 +424,6 @@ static void *_dns_server_get_bind_ipset_nftset_rule(struct dns_request *request,
return NULL;
}

static int _dns_server_get_reply_ttl(struct dns_request *request, int ttl)
{
int reply_ttl = ttl;

if ((request->passthrough == 0 || request->passthrough == 2) && dns_conf_cachesize > 0 &&
request->check_order_list->orders[0].type != DOMAIN_CHECK_NONE) {
reply_ttl = dns_conf_serve_expired_reply_ttl;
if (reply_ttl < 2) {
reply_ttl = 2;
}
}

return reply_ttl;
}

static int _dns_server_get_conf_ttl(struct dns_request *request, int ttl)
{
int rr_ttl = dns_conf_rr_ttl;
Expand Down Expand Up @@ -483,6 +470,26 @@ static int _dns_server_get_conf_ttl(struct dns_request *request, int ttl)
return ttl;
}

static int _dns_server_get_reply_ttl(struct dns_request *request, int ttl)
{
int reply_ttl = ttl;

if ((request->passthrough == 0 || request->passthrough == 2) && dns_conf_cachesize > 0 &&
request->check_order_list->orders[0].type != DOMAIN_CHECK_NONE) {
reply_ttl = dns_conf_serve_expired_reply_ttl;
if (reply_ttl < 2) {
reply_ttl = 2;
}
}

int rr_ttl = _dns_server_get_conf_ttl(request, ttl);
if (reply_ttl > rr_ttl) {
reply_ttl = rr_ttl;
}

return reply_ttl;
}

static int _dns_server_epoll_ctl(struct dns_server_conn_head *head, int op, uint32_t events)
{
struct epoll_event event;
Expand Down Expand Up @@ -1396,12 +1403,25 @@ static int _dns_cache_is_specify_packet(int qtype)
static int _dns_server_get_cache_timeout(struct dns_request *request, struct dns_cache_key *cache_key, int ttl)
{
int timeout = 0;
int prefetch_time = 0;

if (request->rcode != DNS_RC_NOERROR) {
return ttl + 1;
}

if (dns_conf_prefetch && _dns_cache_is_specify_packet(request->qtype) != 0) {
prefetch_time = 1;
}

if ((request->prefetch_flags & PREFETCH_FLAGS_NOPREFETCH)) {
prefetch_time = 0;
}

if (request->edns0_do == 1) {
prefetch_time = 0;
}

if (prefetch_time == 1) {
if (dns_conf_serve_expired) {
timeout = dns_conf_serve_expired_prefetch_time;
if (timeout == 0) {
Expand Down Expand Up @@ -1431,6 +1451,8 @@ static int _dns_server_get_cache_timeout(struct dns_request *request, struct dns
if (dns_conf_serve_expired) {
timeout += dns_conf_serve_expired_ttl;
}

timeout += 3;
}

if (timeout <= 0) {
Expand Down Expand Up @@ -5066,6 +5088,13 @@ static int _dns_server_process_cache_packet(struct dns_request *request, struct
goto out;
}

/* Check if records in cache contain DNSSEC, if not exist, skip cache */
if (request->passthrough == 1) {
if ((dns_get_OPT_option(context.packet) & DNS_OPT_FLAG_DO) == 0 && request->edns0_do == 1) {
goto out;
}
}

request->rcode = context.packet->head.rcode;
context.do_cache = 0;
context.do_ipset = do_ipset;
Expand Down Expand Up @@ -5173,6 +5202,7 @@ static int _dns_server_process_cache(struct dns_request *request)
out_update_cache:
if (dns_cache_get_ttl(dns_cache) == 0) {
struct dns_server_query_option dns_query_options;
int prefetch_flags = 0;
dns_query_options.server_flags = request->server_flags;
dns_query_options.dns_group_name = request->dns_group_name;
if (request->conn == NULL) {
Expand All @@ -5186,7 +5216,12 @@ static int _dns_server_process_cache(struct dns_request *request)
memcpy(&dns_query_options.ecs_dns, &request->ecs, sizeof(dns_query_options.ecs_dns));
}

_dns_server_prefetch_request(request->domain, request->qtype, &dns_query_options, 0);
if (request->edns0_do) {
dns_query_options.ecs_enable_flag |= DNS_QUEY_OPTION_EDNS0_DO;
prefetch_flags |= PREFETCH_FLAGS_NOPREFETCH;
}

_dns_server_prefetch_request(request->domain, request->qtype, &dns_query_options, prefetch_flags);
} else {
dns_cache_update(dns_cache);
}
Expand Down Expand Up @@ -5407,7 +5442,8 @@ static void _dns_server_check_set_passthrough(struct dns_request *request)
request->dualstack_selection = 0;
}

if (request->passthrough == 1 && (request->qtype == DNS_T_A || request->qtype == DNS_T_AAAA)) {
if (request->passthrough == 1 && (request->qtype == DNS_T_A || request->qtype == DNS_T_AAAA) &&
request->edns0_do == 0) {
request->passthrough = 2;
}
}
Expand Down Expand Up @@ -5485,6 +5521,10 @@ static int _dns_server_setup_query_option(struct dns_request *request, struct dn
options->enable_flag |= DNS_QUEY_OPTION_ECS_DNS;
}

if (request->edns0_do) {
options->enable_flag |= DNS_QUEY_OPTION_EDNS0_DO;
}

return 0;
}

Expand Down Expand Up @@ -5718,6 +5758,10 @@ static int _dns_server_parser_request(struct dns_request *request, struct dns_pa
goto errout;
}

if ((dns_get_OPT_option(packet) & DNS_OPT_FLAG_DO) && packet->head.ad == 1) {
request->edns0_do = 1;
}

/* get request opts */
rr_count = 0;
rrs = dns_get_rrs_start(packet, DNS_RRS_OPT, &rr_count);
Expand Down Expand Up @@ -5836,6 +5880,10 @@ static int _dns_server_setup_server_query_options(struct dns_request *request,
memcpy(&request->ecs, &server_query_option->ecs_dns, sizeof(request->ecs));
}

if (server_query_option->ecs_enable_flag & DNS_QUEY_OPTION_EDNS0_DO) {
request->edns0_do = 1;
}

return 0;
}

Expand Down

0 comments on commit a19ac7e

Please sign in to comment.