From 70df7938f3802e9344cfb237d6069263574f9a14 Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Sun, 18 Dec 2022 22:33:01 +0800 Subject: [PATCH] conf: support disable expired cache on specific domain. --- ReadMe.md | 2 +- ReadMe_en.md | 2 +- etc/smartdns/smartdns.conf | 1 + .../files/luci/i18n/smartdns.zh-cn.po | 6 +++++ .../luci/model/cbi/smartdns/smartdns.lua | 6 +++++ .../luci/files/luci/i18n/smartdns.zh-cn.po | 6 +++++ .../resources/view/smartdns/smartdns.js | 14 +++++++++++ package/openwrt/files/etc/init.d/smartdns | 6 +++++ src/dns_cache.c | 18 +++++++------ src/dns_cache.h | 7 +++--- src/dns_conf.c | 14 +++++++++++ src/dns_conf.h | 1 + src/dns_server.c | 25 +++++++++++++------ 13 files changed, 87 insertions(+), 21 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 45260b1..e63152d 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -597,7 +597,7 @@ entware|ipkg update
ipkg install smartdns|软件源路径:https://bin.entwa | nftset | 域名 nftset | 无 | nftset /domain/[#4\|#6\|-]:[family#nftable#nftset\|-][,#[4\|6]:[family#nftable#nftset\|-]]],-表示忽略;ipv4 地址的 family 只支持 inet 和 ip;ipv6 地址的 family 只支持 inet 和 ip6;由于 nft 限制,两种地址只能分开存放于两个 set 中。| nftset /www.example.com/#4:inet#mytab#dns4,#6:- | | nftset-timeout | 设置 nftset 超时功能启用 | no | [yes\|no] | nftset-timeout yes | | nftset-debug | 设置 nftset 调试功能启用 | no | [yes\|no] | nftset-debug yes | -| domain-rules | 设置域名规则 | 无 | domain-rules /domain/ [-rules...]
[-c\|-speed-check-mode]:测速模式,参考 speed-check-mode 配置
[-a\|-address]:参考 address 配置
[-n\|-nameserver]:参考 nameserver 配置
[-p\|-ipset]:参考ipset配置
[-t\|-nftset]:参考nftset配置
[-d\|-dualstack-ip-selection]:参考 dualstack-ip-selection | domain-rules /www.example.com/ -speed-check-mode none | +| domain-rules | 设置域名规则 | 无 | domain-rules /domain/ [-rules...]
[-c\|-speed-check-mode]:测速模式,参考 speed-check-mode 配置
[-a\|-address]:参考 address 配置
[-n\|-nameserver]:参考 nameserver 配置
[-p\|-ipset]:参考ipset配置
[-t\|-nftset]:参考nftset配置
[-d\|-dualstack-ip-selection]:参考 dualstack-ip-selection
[-no-serve-expired]:禁用过期缓存 | domain-rules /www.example.com/ -speed-check-mode none | | domain-set | 设置域名集合 | 无 | domain-set [options...]
[-n\|-name]:域名集合名称
[-t\|-type]:域名集合类型,当前仅支持list,格式为域名列表,一行一个域名。
[-f\|-file]:域名集合文件路径。
选项需要配合address, nameserver, ipset, nftset等需要指定域名的地方使用,使用方式为 /domain-set:[name]/| domain-set -name set -type list -file /path/to/list
address /domain-set:set/1.2.4.8 | | bogus-nxdomain | 假冒 IP 地址过滤 | 无 | [ip/subnet],可重复 | bogus-nxdomain 1.2.3.4/16 | | ignore-ip | 忽略 IP 地址 | 无 | [ip/subnet],可重复 | ignore-ip 1.2.3.4/16 | diff --git a/ReadMe_en.md b/ReadMe_en.md index be1abfa..7cf1af5 100644 --- a/ReadMe_en.md +++ b/ReadMe_en.md @@ -556,7 +556,7 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use |nftset|Domain nftset|None|nftset /domain/[#4\|#6\|-]:[family#nftable#nftset\|-][,#[4\|6]:[family#nftable#nftset\|-]]], `-` to ignore; the valid families are inet and ip for ipv4 addresses while the valid ones are inet and ip6 for ipv6 addresses; due to the limitation of nft, two types of addresses have to be stored in two sets|nftset /www.example.com/#4:inet#mytab#dns4,#6:- |nftset-timeout|nftset timeout enable|no|[yes\|no]|nftset-timeout yes |nftset-debug|nftset debug enable|no|[yes\|no]|nftset-debug yes -|domain-rules|set domain rules|None|domain-rules /domain/ [-rules...]
[-c\|-speed-check-mode]: set speed check mode,same as parameter speed-check-mode
[-a\|-address]: same as parameter `address`
[-n\|-nameserver]: same as parameter `nameserver`
[-p\|-ipset]: same as parameter `nftset`
[-t\|-nftset]: same as parameter `nftset`
[-d\|-dualstack-ip-selection]: same as parameter `dualstack-ip-selection`|domain-rules /www.example.com/ -speed-check-mode none +|domain-rules|set domain rules|None|domain-rules /domain/ [-rules...]
[-c\|-speed-check-mode]: set speed check mode,same as parameter speed-check-mode
[-a\|-address]: same as parameter `address`
[-n\|-nameserver]: same as parameter `nameserver`
[-p\|-ipset]: same as parameter `nftset`
[-t\|-nftset]: same as parameter `nftset`
[-d\|-dualstack-ip-selection]: same as parameter `dualstack-ip-selection`
[-no-serve-expired]:disable serve expired|domain-rules /www.example.com/ -speed-check-mode none | domain-set | collection of domains|None| domain-set [options...]
[-n\|-name]:name of set
[-t\|-type] [list]: set type, only support list, one domain per line
[-f\|-file]:file path of domain set
used with address, nameserver, ipset, nftset, example: /domain-set:[name]/ | domain-set -name set -type list -file /path/to/list
address /domain-set:set/1.2.4.8 | |bogus-nxdomain|bogus IP address|None|[IP/subnet], Repeatable| bogus-nxdomain 1.2.3.4/16 |ignore-ip|ignore ip address|None|[ip/subnet], Repeatable| ignore-ip 1.2.3.4/16 diff --git a/etc/smartdns/smartdns.conf b/etc/smartdns/smartdns.conf index db865ae..0079507 100644 --- a/etc/smartdns/smartdns.conf +++ b/etc/smartdns/smartdns.conf @@ -237,6 +237,7 @@ log-level info # [-p] -ipset [ipset|-]: same as ipset option # [-t] -nftset [nftset|-]: same as nftset option # [-d] -dualstack-ip-selection [yes|no]: same as dualstack-ip-selection option +# -no-serve-expired: ignore expired domain # collection of domains # the domain-set can be used with /domain/ for address, nameserver, ipset, etc. diff --git a/package/luci-compat/files/luci/i18n/smartdns.zh-cn.po b/package/luci-compat/files/luci/i18n/smartdns.zh-cn.po index fbfc49c..37a56a8 100644 --- a/package/luci-compat/files/luci/i18n/smartdns.zh-cn.po +++ b/package/luci-compat/files/luci/i18n/smartdns.zh-cn.po @@ -2,6 +2,12 @@ msgid "Additional Args for upstream dns servers" msgstr "额外的上游 DNS 服务器参数" +msgid "Additional Rule Flag" +msgstr "额外规则标识" + +msgid "Additional Flags for rules, read help on domain-rule for more information." +msgstr "额外的规则标识,具体参考domain-rule的帮助说明。" + msgid "Additional Server Args" msgstr "额外的服务器参数" diff --git a/package/luci-compat/files/luci/model/cbi/smartdns/smartdns.lua b/package/luci-compat/files/luci/model/cbi/smartdns/smartdns.lua index 1f222d8..ebfa18a 100644 --- a/package/luci-compat/files/luci/model/cbi/smartdns/smartdns.lua +++ b/package/luci-compat/files/luci/model/cbi/smartdns/smartdns.lua @@ -448,6 +448,12 @@ function o.validate(self, value) return nil, translate("NFTset name format error, format: [#[4|6]:[family#table#set]]") end +---- other args +o = s:taboption("forwarding", Value, "addition_flag", translate("Additional Rule Flag"), translate("Additional Flags for rules, read help on domain-rule for more information.")) +o.default = "" +o.rempty = true +o.modalonly = true; + o = s:taboption("forwarding", FileUpload, "forwarding_domain_set_file", translate("Domain List File"), translate("Upload domain list file, or configure auto download from Download File Setting page.")) o.rmempty = true diff --git a/package/luci/files/luci/i18n/smartdns.zh-cn.po b/package/luci/files/luci/i18n/smartdns.zh-cn.po index de6efc8..0252d16 100644 --- a/package/luci/files/luci/i18n/smartdns.zh-cn.po +++ b/package/luci/files/luci/i18n/smartdns.zh-cn.po @@ -2,6 +2,12 @@ msgid "Additional Args for upstream dns servers" msgstr "额外的上游 DNS 服务器参数" +msgid "Additional Rule Flag" +msgstr "额外规则标识" + +msgid "Additional Flags for rules, read help on domain-rule for more information." +msgstr "额外的规则标识,具体参考domain-rule的帮助说明。" + msgid "Additional Server Args" msgstr "额外的服务器参数" diff --git a/package/luci/files/root/www/luci-static/resources/view/smartdns/smartdns.js b/package/luci/files/root/www/luci-static/resources/view/smartdns/smartdns.js index 0458822..417822b 100644 --- a/package/luci/files/root/www/luci-static/resources/view/smartdns/smartdns.js +++ b/package/luci/files/root/www/luci-static/resources/view/smartdns/smartdns.js @@ -664,6 +664,13 @@ return view.extend({ return true; } + // other args + o = s.taboption("forwarding", form.Value, "addition_flag", _("Additional Rule Flag"), + _("Additional Flags for rules, read help on domain-rule for more information.")) + o.default = "" + o.rempty = true + o.modalonly = true; + o = s.taboption("forwarding", form.FileUpload, "forwarding_domain_set_file", _("Domain List File"), _("Upload domain list file, or configure auto download from Download File Setting page.")); o.rmempty = true @@ -861,6 +868,13 @@ return view.extend({ return true; } + // other args + so = ss.option(form.Value, "addition_flag", _("Additional Rule Flag"), + _("Additional Flags for rules, read help on domain-rule for more information.")) + so.default = "" + so.rempty = true + so.modalonly = true; + /////////////////////////////////////// // IP Blacklist; /////////////////////////////////////// diff --git a/package/openwrt/files/etc/init.d/smartdns b/package/openwrt/files/etc/init.d/smartdns index 2792010..ec38bef 100644 --- a/package/openwrt/files/etc/init.d/smartdns +++ b/package/openwrt/files/etc/init.d/smartdns @@ -281,6 +281,9 @@ load_domain_rules() config_get nftset_name "$section" "nftset_name" "" [ ! -z "$nftset_name" ] && domain_set_args="$domain_set_args -nftset '$nftset_name'" + config_get addition_flag "$section" "addition_flag" "" + [ ! -z "$addition_flag" ] && domain_set_args="$domain_set_args $addition_flag" + config_get forwarding_domain_set_file "$section" "forwarding_domain_set_file" "" [ ! -z "$forwarding_domain_set_file" ] && { conf_append "domain-set" "-name ${domain_set_name}-forwarding-file -file '$forwarding_domain_set_file'" @@ -336,6 +339,9 @@ load_domain_rule_list() config_get domain_list_file "$section" "domain_list_file" "" [ -z "$domain_list_file" ] && return + config_get addition_flag "$section" "addition_flag" "" + [ ! -z "$addition_flag" ] && domain_set_args="$domain_set_args $addition_flag" + conf_append "domain-set" "-name domain-rule-list-${domain_set_name} -file '$domain_list_file'" conf_append "domain-rules" "/domain-set:domain-rule-list-${domain_set_name}/ $domain_set_args" } diff --git a/src/dns_cache.c b/src/dns_cache.c index 69814e0..6c96b5c 100644 --- a/src/dns_cache.c +++ b/src/dns_cache.c @@ -245,7 +245,7 @@ struct dns_cache_data *dns_cache_new_data_packet(void *packet, size_t packet_len return (struct dns_cache_data *)cache_packet; } -static int _dns_cache_replace(struct dns_cache_key *cache_key, int ttl, int speed, int inactive, +static int _dns_cache_replace(struct dns_cache_key *cache_key, int ttl, int speed, int no_inactive, int inactive, struct dns_cache_data *cache_data) { struct dns_cache *dns_cache = NULL; @@ -258,7 +258,7 @@ static int _dns_cache_replace(struct dns_cache_key *cache_key, int ttl, int spee /* lookup existing cache */ dns_cache = dns_cache_lookup(cache_key); if (dns_cache == NULL) { - return dns_cache_insert(cache_key, ttl, speed, cache_data); + return dns_cache_insert(cache_key, ttl, speed, no_inactive, cache_data); } if (ttl < DNS_CACHE_TTL_MIN) { @@ -273,6 +273,7 @@ static int _dns_cache_replace(struct dns_cache_key *cache_key, int ttl, int spee dns_cache->info.query_flag = cache_key->query_flag; dns_cache->info.ttl = ttl; dns_cache->info.speed = speed; + dns_cache->info.no_inactive = no_inactive; old_cache_data = dns_cache->cache_data; dns_cache->cache_data = cache_data; list_del_init(&dns_cache->list); @@ -293,14 +294,14 @@ static int _dns_cache_replace(struct dns_cache_key *cache_key, int ttl, int spee return 0; } -int dns_cache_replace(struct dns_cache_key *cache_key, int ttl, int speed, struct dns_cache_data *cache_data) +int dns_cache_replace(struct dns_cache_key *cache_key, int ttl, int speed, int no_inactive, struct dns_cache_data *cache_data) { - return _dns_cache_replace(cache_key, ttl, speed, 0, cache_data); + return _dns_cache_replace(cache_key, ttl, speed, no_inactive, 0, cache_data); } -int dns_cache_replace_inactive(struct dns_cache_key *cache_key, int ttl, int speed, struct dns_cache_data *cache_data) +int dns_cache_replace_inactive(struct dns_cache_key *cache_key, int ttl, int speed, int no_inactive, struct dns_cache_data *cache_data) { - return _dns_cache_replace(cache_key, ttl, speed, 1, cache_data); + return _dns_cache_replace(cache_key, ttl, speed, no_inactive, 1, cache_data); } static void _dns_cache_remove_by_domain(struct dns_cache_key *cache_key) @@ -390,7 +391,7 @@ errout: return -1; } -int dns_cache_insert(struct dns_cache_key *cache_key, int ttl, int speed, struct dns_cache_data *cache_data) +int dns_cache_insert(struct dns_cache_key *cache_key, int ttl, int speed, int no_inactive, struct dns_cache_data *cache_data) { struct dns_cache_info info; @@ -415,6 +416,7 @@ int dns_cache_insert(struct dns_cache_key *cache_key, int ttl, int speed, struct info.ttl = ttl; info.hitnum_update_add = DNS_CACHE_HITNUM_STEP; info.speed = speed; + info.no_inactive = no_inactive; time(&info.insert_time); time(&info.replace_time); @@ -663,7 +665,7 @@ void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, unsigned } if (ttl < 0) { - if (dns_cache_head.enable_inactive) { + if (dns_cache_head.enable_inactive && dns_cache->info.no_inactive == 0) { _dns_cache_move_inactive(dns_cache); } else { _dns_cache_remove(dns_cache); diff --git a/src/dns_cache.h b/src/dns_cache.h index 76b6675..835ecbf 100644 --- a/src/dns_cache.h +++ b/src/dns_cache.h @@ -87,6 +87,7 @@ struct dns_cache_info { int ttl; int hitnum; int speed; + int no_inactive; int hitnum_update_add; time_t insert_time; time_t replace_time; @@ -135,11 +136,11 @@ struct dns_cache_data *dns_cache_new_data_packet(void *packet, size_t packet_len int dns_cache_init(int size, int enable_inactive, int inactive_list_expired); -int dns_cache_replace(struct dns_cache_key *key, int ttl, int speed, struct dns_cache_data *cache_data); +int dns_cache_replace(struct dns_cache_key *key, int ttl, int speed, int no_inactive, struct dns_cache_data *cache_data); -int dns_cache_replace_inactive(struct dns_cache_key *key, int ttl, int speed, struct dns_cache_data *cache_data); +int dns_cache_replace_inactive(struct dns_cache_key *key, int ttl, int speed, int no_inactive, struct dns_cache_data *cache_data); -int dns_cache_insert(struct dns_cache_key *key, int ttl, int speed, struct dns_cache_data *cache_data); +int dns_cache_insert(struct dns_cache_key *key, int ttl, int speed, int no_inactive, struct dns_cache_data *cache_data); struct dns_cache *dns_cache_lookup(struct dns_cache_key *key); diff --git a/src/dns_conf.c b/src/dns_conf.c index d7a8bc5..fcf0aea 100644 --- a/src/dns_conf.c +++ b/src/dns_conf.c @@ -1842,6 +1842,11 @@ errout: return -1; } +static int _conf_domain_rule_no_serve_expired(const char *domain) +{ + return _config_domain_rule_flag_set(domain, DOMAIN_FLAG_NO_SERVE_EXPIRED, 0); +} + static int _conf_domain_rules(void *data, int argc, char *argv[]) { int opt = 0; @@ -1856,6 +1861,7 @@ static int _conf_domain_rules(void *data, int argc, char *argv[]) {"nftset", required_argument, NULL, 't'}, {"nameserver", required_argument, NULL, 'n'}, {"dualstack-ip-selection", required_argument, NULL, 'd'}, + {"no-serve-expired", no_argument, NULL, 254}, {NULL, no_argument, NULL, 0} }; /* clang-format on */ @@ -1952,6 +1958,14 @@ static int _conf_domain_rules(void *data, int argc, char *argv[]) break; } + case 254: { + if (_conf_domain_rule_no_serve_expired(domain) != 0) { + tlog(TLOG_ERROR, "set no-serve-expired rule failed."); + goto errout; + } + + break; + } default: break; } diff --git a/src/dns_conf.h b/src/dns_conf.h index 166da40..6a6566b 100644 --- a/src/dns_conf.h +++ b/src/dns_conf.h @@ -97,6 +97,7 @@ typedef enum { #define DOMAIN_FLAG_NFTSET_INET_IGN (1 << 12) #define DOMAIN_FLAG_NFTSET_IP_IGN (1 << 13) #define DOMAIN_FLAG_NFTSET_IP6_IGN (1 << 14) +#define DOMAIN_FLAG_NO_SERVE_EXPIRED (1 << 15) #define SERVER_FLAG_EXCLUDE_DEFAULT (1 << 0) diff --git a/src/dns_server.c b/src/dns_server.c index 1625936..e1dab10 100644 --- a/src/dns_server.c +++ b/src/dns_server.c @@ -236,6 +236,7 @@ struct dns_request { int dualstack_selection_ping_time; int dualstack_selection_has_ip; struct dns_request *dualstack_request; + int no_serve_expired; pthread_mutex_t ip_map_lock; @@ -1070,17 +1071,17 @@ static int _dns_server_request_update_cache(struct dns_request *request, dns_typ if (request->prefetch) { if (request->prefetch_expired_domain == 0) { - if (dns_cache_replace(&cache_key, ttl, speed, cache_data) != 0) { + if (dns_cache_replace(&cache_key, ttl, speed, request->no_serve_expired, cache_data) != 0) { goto errout; } } else { - if (dns_cache_replace_inactive(&cache_key, ttl, speed, cache_data) != 0) { + if (dns_cache_replace_inactive(&cache_key, ttl, speed, request->no_serve_expired, cache_data) != 0) { goto errout; } } } else { /* insert result to cache */ - if (dns_cache_insert(&cache_key, ttl, speed, cache_data) != 0) { + if (dns_cache_insert(&cache_key, ttl, speed, request->no_serve_expired, cache_data) != 0) { goto errout; } } @@ -1218,17 +1219,17 @@ static int _dns_cache_cname_packet(struct dns_server_post_context *context) if (request->prefetch) { if (request->prefetch_expired_domain == 0) { - if (dns_cache_replace(&cache_key, ttl, speed, cache_packet) != 0) { + if (dns_cache_replace(&cache_key, ttl, speed, request->no_serve_expired, cache_packet) != 0) { goto errout; } } else { - if (dns_cache_replace_inactive(&cache_key, ttl, speed, cache_packet) != 0) { + if (dns_cache_replace_inactive(&cache_key, ttl, speed, request->no_serve_expired, cache_packet) != 0) { goto errout; } } } else { /* insert result to cache */ - if (dns_cache_insert(&cache_key, ttl, speed, cache_packet) != 0) { + if (dns_cache_insert(&cache_key, ttl, speed, request->no_serve_expired, cache_packet) != 0) { goto errout; } } @@ -1260,12 +1261,12 @@ static int _dns_cache_packet(struct dns_server_post_context *context) cache_key.query_flag = request->server_flags; if (request->prefetch) { - if (dns_cache_replace(&cache_key, context->reply_ttl, -1, cache_packet) != 0) { + if (dns_cache_replace(&cache_key, context->reply_ttl, -1, request->no_serve_expired, cache_packet) != 0) { goto errout; } } else { /* insert result to cache */ - if (dns_cache_insert(&cache_key, context->reply_ttl, -1, cache_packet) != 0) { + if (dns_cache_insert(&cache_key, context->reply_ttl, -1, request->no_serve_expired, cache_packet) != 0) { goto errout; } } @@ -3603,6 +3604,10 @@ static int _dns_server_pre_process_rule_flags(struct dns_request *request) } flags = rule_flag->flags; + if (flags & DOMAIN_FLAG_NO_SERVE_EXPIRED) { + request->no_serve_expired = 1; + } + if (flags & DOMAIN_FLAG_ADDR_IGN) { /* ignore this domain */ goto out; @@ -3937,6 +3942,10 @@ reply_cache: goto out; } + if (dns_cache_get_ttl(dns_cache) <= 0 && request->no_serve_expired == 1) { + goto out; + } + ret = _dns_server_process_cache_data(request, dns_cache); if (ret != 0) { goto out;