From ee9059bb37de34383dc1be7eac4dfe1b5e5b925d Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Thu, 17 Feb 2022 22:32:03 +0800 Subject: [PATCH] server: Support specific qtype to return SOA --- ReadMe.md | 1 + ReadMe_en.md | 1 + etc/smartdns/smartdns.conf | 4 ++++ src/dns_conf.c | 41 ++++++++++++++++++++++++++++++++++++++ src/dns_conf.h | 10 ++++++++++ src/dns_server.c | 28 +++++++++++++++++++++++--- 6 files changed, 82 insertions(+), 3 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 0e9b8e2..b8a4521 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -541,6 +541,7 @@ https://github.com/pymumu/smartdns/releases |whitelist-ip|白名单IP地址|无|[ip/subnet],可重复| whitelist-ip 1.2.3.4/16 |blacklist-ip|黑名单IP地址|无|[ip/subnet],可重复| blacklist-ip 1.2.3.4/16 |force-AAAA-SOA|强制AAAA地址返回SOA|no|[yes\|no]|force-AAAA-SOA yes +|force-qtype-SOA|强制指定qtype返回SOA|qtype id|[qtypeid | ...]|force-qtype-SOA 65 28 |prefetch-domain|域名预先获取功能|no|[yes\|no]|prefetch-domain yes |serve-expired|过期缓存服务功能|no|[yes\|no],开启此功能后,如果有请求时尝试回应TTL为0的过期记录,并并发查询记录,以避免查询等待|serve-expired yes |serve-expired-ttl|过期缓存服务最长超时时间|0|秒,0:表示停用超时,> 0表示指定的超时的秒数|serve-expired-ttl 0 diff --git a/ReadMe_en.md b/ReadMe_en.md index 4f20667..8e01529 100755 --- a/ReadMe_en.md +++ b/ReadMe_en.md @@ -528,6 +528,7 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use |whitelist-ip|ip whitelist|None|[ip/subnet], Repeatable,When the filtering server responds IPs in the IP whitelist, only result in whitelist will be accepted| whitelist-ip 1.2.3.4/16 |blacklist-ip|ip blacklist|None|[ip/subnet], Repeatable,When the filtering server responds IPs in the IP blacklist, The result will be discarded directly| blacklist-ip 1.2.3.4/16 |force-AAAA-SOA|force AAAA query return SOA|no|[yes\|no]|force-AAAA-SOA yes +|force-qtype-SOA|force specific qtype return SOA|qtype id|[qtypeid | ...]|force-qtype-SOA 65 28 |prefetch-domain|domain prefetch feature|no|[yes\|no]|prefetch-domain yes |serve-expired|Cache serve expired feature|no|[yes\|no], Attempts to serve old responses from cache with a TTL of 0 in the response without waiting for the actual resolution to finish.|serve-expired yes |serve-expired-ttl|Cache serve expired limite TTL|0|second,0:disable,> 0 seconds after expiration|serve-expired-ttl 0 diff --git a/etc/smartdns/smartdns.conf b/etc/smartdns/smartdns.conf index 355cfe3..d950e74 100644 --- a/etc/smartdns/smartdns.conf +++ b/etc/smartdns/smartdns.conf @@ -84,6 +84,10 @@ cache-size 4096 # force AAAA query return SOA # force-AAAA-SOA [yes|no] +# force specific qtype return soa +# force-qtype-SOA [qtypeid |...] +# force-qtype-SOA 65 28 + # Enable IPV4, IPV6 dual stack IP optimization selection strategy # dualstack-ip-selection-threshold [num] (0~1000) # dualstack-ip-selection [yes|no] diff --git a/src/dns_conf.c b/src/dns_conf.c index c59a763..09cd724 100644 --- a/src/dns_conf.c +++ b/src/dns_conf.c @@ -37,6 +37,8 @@ struct dns_ipset_table { }; static struct dns_ipset_table dns_ipset_table; +struct dns_qtype_soa_table dns_qtype_soa_table; + /* dns groups */ struct dns_group_table dns_group_table; @@ -1171,6 +1173,42 @@ static int _config_iplist_rule(char *subnet, enum address_rule rule) return 0; } +static int _config_qtype_soa(void *data, int argc, char *argv[]) +{ + struct dns_qtype_soa_list *soa_list; + if (argc <= 1) { + return -1; + } + + for (int i = 1; i < argc; i++) { + soa_list = malloc(sizeof(*soa_list)); + if (soa_list == NULL) { + tlog(TLOG_ERROR, "cannot malloc memory"); + return -1; + } + + memset(soa_list, 0, sizeof(*soa_list)); + soa_list->qtypeid = atol(argv[i]); + uint32_t key = hash_32_generic(soa_list->qtypeid, 32); + hash_add(dns_qtype_soa_table.qtype, &soa_list->node, key); + } + + return 0; +} + +static void _config_qtype_soa_table_destroy(void) +{ + struct dns_qtype_soa_list *soa_list = NULL; + struct hlist_node *tmp = NULL; + int i; + + hash_for_each_safe(dns_qtype_soa_table.qtype, i, tmp, soa_list, node) + { + hlist_del_init(&soa_list->node); + free(soa_list); + } +} + static int _config_blacklist_ip(void *data, int argc, char *argv[]) { if (argc <= 1) { @@ -1448,6 +1486,7 @@ static struct config_item _config_item[] = { CONF_INT("rr-ttl-min", &dns_conf_rr_ttl_min, 0, CONF_INT_MAX), CONF_INT("rr-ttl-max", &dns_conf_rr_ttl_max, 0, CONF_INT_MAX), CONF_YESNO("force-AAAA-SOA", &dns_conf_force_AAAA_SOA), + CONF_CUSTOM("force-qtype-SOA", _config_qtype_soa, NULL), CONF_CUSTOM("blacklist-ip", _config_blacklist_ip, NULL), CONF_CUSTOM("whitelist-ip", _conf_whitelist_ip, NULL), CONF_CUSTOM("bogus-nxdomain", _conf_bogus_nxdomain, NULL), @@ -1518,6 +1557,7 @@ static int _dns_server_load_conf_init(void) art_tree_init(&dns_conf_domain_rule); hash_init(dns_ipset_table.ipset); + hash_init(dns_qtype_soa_table.qtype); hash_init(dns_group_table.group); return 0; @@ -1530,6 +1570,7 @@ void dns_server_load_exit(void) Destroy_Radix(dns_conf_address_rule.ipv6, _config_address_destroy, NULL); _config_ipset_table_destroy(); _config_group_table_destroy(); + _config_qtype_soa_table_destroy(); } static int _dns_conf_speed_check_mode_verify(void) diff --git a/src/dns_conf.h b/src/dns_conf.h index b86dcda..bc77bee 100644 --- a/src/dns_conf.h +++ b/src/dns_conf.h @@ -203,6 +203,16 @@ struct dns_bind_ip { const char *group; }; +struct dns_qtype_soa_list { + struct hlist_node node; + uint32_t qtypeid; +}; + +struct dns_qtype_soa_table { + DECLARE_HASHTABLE(qtype, 8); +}; +extern struct dns_qtype_soa_table dns_qtype_soa_table; + extern struct dns_bind_ip dns_conf_bind_ip[DNS_MAX_BIND_IP]; extern int dns_conf_bind_ip_num; diff --git a/src/dns_server.c b/src/dns_server.c index b771390..e954945 100644 --- a/src/dns_server.c +++ b/src/dns_server.c @@ -2328,6 +2328,25 @@ errout: return -1; } +static int _dns_server_qtype_soa(struct dns_request *request) +{ + struct dns_qtype_soa_list *soa_list = NULL; + + uint32_t key = hash_32_generic(request->qtype, 32); + hash_for_each_possible(dns_qtype_soa_table.qtype, soa_list, node, key) + { + if (request->qtype != soa_list->qtypeid) { + continue; + } + + _dns_server_reply_SOA(DNS_RC_NOERROR, request); + tlog(TLOG_DEBUG, "force qtype %d soa", request->qtype); + return 0; + } + + return -1; +} + static void _dns_server_process_speed_check_rule(struct dns_request *request) { struct dns_domain_check_order *check_order = NULL; @@ -2351,7 +2370,6 @@ static int _dns_server_get_expired_ttl_reply(struct dns_cache *dns_cache) return dns_conf_serve_expired_reply_ttl; } - static int _dns_server_get_expired_cname_ttl_reply(struct dns_cache *dns_cache) { int ttl = dns_cache_get_cname_ttl(dns_cache); @@ -2429,13 +2447,12 @@ static int _dns_server_process_cache_packet(struct dns_request *request, struct } _dns_server_get_answer(request, packet); - + _dns_server_audit_log(request); if (request->result_callback) { _dns_result_callback(request); } - if (request->conn == NULL) { return 0; } @@ -2703,6 +2720,11 @@ static int _dns_server_do_query(struct dns_request *request, const char *domain, goto clean_exit; } + /* process qtype soa */ + if (_dns_server_qtype_soa(request) == 0) { + goto clean_exit; + } + /* process speed check rule */ _dns_server_process_speed_check_rule(request);