dns-server: simple support proxy dnssec
This commit is contained in:
27
src/dns.c
27
src/dns.c
@@ -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)
|
||||
|
||||
@@ -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];
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
@@ -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: {
|
||||
@@ -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;
|
||||
|
||||
10
src/dns.h
10
src/dns.h
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
@@ -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);
|
||||
@@ -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) {
|
||||
@@ -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.");
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
@@ -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) {
|
||||
@@ -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;
|
||||
@@ -5173,6 +5202,7 @@ reply_cache:
|
||||
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) {
|
||||
@@ -5186,7 +5216,12 @@ out_update_cache:
|
||||
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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user