feature: support marking packet on upstream server

This commit is contained in:
Nick Peng
2022-12-19 22:41:43 +08:00
parent fb1c5d2438
commit 2f71fe2490
13 changed files with 75 additions and 11 deletions

View File

@@ -584,10 +584,10 @@ entware|ipkg update<br>ipkg install smartdns|软件源路径https://bin.entwa
| audit-size | 审计大小 | 128K | 数字 + K、M 或 G | audit-size 128K |
| audit-num | 审计归档个数 | 2 | 大于等于 0 的数字 | audit-num 2 |
| conf-file | 附加配置文件 | 无 | 合法路径字符串 | conf-file /etc/smartdns/smartdns.more.conf |
| server | 上游 UDP DNS | 无 | 可重复。<br>[ip][:port]:服务器 IP:端口(可选)<br>[-blacklist-ip]:配置 IP 过滤结果。<br>[-whitelist-ip]:指定仅接受参数中配置的 IP 范围<br>[-group [group] ...]DNS 服务器所属组,比如 office 和 foreign和 nameserver 配套使用<br>[-exclude-default-group]:将 DNS 服务器从默认组中排除 | server 8.8.8.8:53 -blacklist-ip -group g1 |
| server-tcp | 上游 TCP DNS | 无 | 可重复。<br>[ip][:port]:服务器 IP:端口(可选)<br>[-blacklist-ip]:配置 IP 过滤结果<br>[-whitelist-ip]:指定仅接受参数中配置的 IP 范围。<br>[-group [group] ...]DNS 服务器所属组,比如 office 和 foreign和 nameserver 配套使用<br>[-exclude-default-group]:将 DNS 服务器从默认组中排除 | server-tcp 8.8.8.8:53 |
| server-tls | 上游 TLS DNS | 无 | 可重复。<br>[ip][:port]:服务器 IP:端口(可选)<br>[-spki-pin [sha256-pin]]TLS 合法性校验 SPKI 值base64 编码的 sha256 SPKI pin 值<br>[-host-name]TLS SNI 名称, 名称设置为-表示停用SNI名称<br>[-tls-host-verify]TLS 证书主机名校验<br> [-no-check-certificate]:跳过证书校验<br>[-blacklist-ip]:配置 IP 过滤结果<br>[-whitelist-ip]:仅接受参数中配置的 IP 范围<br>[-group [group] ...]DNS 服务器所属组,比如 office 和 foreign和 nameserver 配套使用<br>[-exclude-default-group]:将 DNS 服务器从默认组中排除 | server-tls 8.8.8.8:853 |
| server-https | 上游 HTTPS DNS | 无 | 可重复。<br>https://[host][:port]/path服务器 IP:端口(可选)<br>[-spki-pin [sha256-pin]]TLS 合法性校验 SPKI 值base64 编码的 sha256 SPKI pin 值<br>[-host-name]TLS SNI 名称<br>[-http-host]http 协议头主机名<br>[-tls-host-verify]TLS 证书主机名校验<br> [-no-check-certificate]:跳过证书校验<br>[-blacklist-ip]:配置 IP 过滤结果<br>[-whitelist-ip]:仅接受参数中配置的 IP 范围。<br>[-group [group] ...]DNS 服务器所属组,比如 office 和 foreign和 nameserver 配套使用<br>[-exclude-default-group]:将 DNS 服务器从默认组中排除 | server-https https://cloudflare-dns.com/dns-query |
| server | 上游 UDP DNS | 无 | 可重复。<br>[ip][:port]:服务器 IP:端口(可选)<br>[-blacklist-ip]:配置 IP 过滤结果。<br>[-whitelist-ip]:指定仅接受参数中配置的 IP 范围<br>[-group [group] ...]DNS 服务器所属组,比如 office 和 foreign和 nameserver 配套使用<br>[-exclude-default-group]:将 DNS 服务器从默认组中排除。<br>[-set-mark]设置数据包标记so-mark| server 8.8.8.8:53 -blacklist-ip -group g1 |
| server-tcp | 上游 TCP DNS | 无 | 可重复。<br>[ip][:port]:服务器 IP:端口(可选)<br>[-blacklist-ip]:配置 IP 过滤结果<br>[-whitelist-ip]:指定仅接受参数中配置的 IP 范围。<br>[-group [group] ...]DNS 服务器所属组,比如 office 和 foreign和 nameserver 配套使用<br>[-exclude-default-group]:将 DNS 服务器从默认组中排除。<br>[-set-mark]设置数据包标记so-mark | server-tcp 8.8.8.8:53 |
| server-tls | 上游 TLS DNS | 无 | 可重复。<br>[ip][:port]:服务器 IP:端口(可选)<br>[-spki-pin [sha256-pin]]TLS 合法性校验 SPKI 值base64 编码的 sha256 SPKI pin 值<br>[-host-name]TLS SNI 名称, 名称设置为-表示停用SNI名称<br>[-tls-host-verify]TLS 证书主机名校验<br> [-no-check-certificate]:跳过证书校验<br>[-blacklist-ip]:配置 IP 过滤结果<br>[-whitelist-ip]:仅接受参数中配置的 IP 范围<br>[-group [group] ...]DNS 服务器所属组,比如 office 和 foreign和 nameserver 配套使用<br>[-exclude-default-group]:将 DNS 服务器从默认组中排除。<br>[-set-mark]设置数据包标记so-mark | server-tls 8.8.8.8:853 |
| server-https | 上游 HTTPS DNS | 无 | 可重复。<br>https://[host][:port]/path服务器 IP:端口(可选)<br>[-spki-pin [sha256-pin]]TLS 合法性校验 SPKI 值base64 编码的 sha256 SPKI pin 值<br>[-host-name]TLS SNI 名称<br>[-http-host]http 协议头主机名<br>[-tls-host-verify]TLS 证书主机名校验<br> [-no-check-certificate]:跳过证书校验<br>[-blacklist-ip]:配置 IP 过滤结果<br>[-whitelist-ip]:仅接受参数中配置的 IP 范围。<br>[-group [group] ...]DNS 服务器所属组,比如 office 和 foreign和 nameserver 配套使用<br>[-exclude-default-group]:将 DNS 服务器从默认组中排除。<br>[-set-mark]设置数据包标记so-mark | server-https https://cloudflare-dns.com/dns-query |
| speed-check-mode | 测速模式选择 | 无 | [ping\|tcp:[80]\|none] | speed-check-mode ping,tcp:80,tcp:443 |
| response-mode | 首次查询响应模式 | first-ping |模式:[fisrt-ping\|fastest-ip\|fastest-response]<br> [first-ping]: 最快ping响应地址模式DNS上游最快查询时延+ping时延最短查询等待与链接体验最佳;<br>[fastest-ip]: 最快IP地址模式查询到的所有IP地址中ping最短的IP。需等待IP测速; <br>[fastest-response]: 最快响应的DNS结果DNS查询等待时间最短返回的IP地址可能不是最快。| response-mode first-ping |
| address | 指定域名 IP 地址 | 无 | address /domain/[ip\|-\|-4\|-6\|#\|#4\|#6] <br>- 表示忽略 <br># 表示返回 SOA <br>4 表示 IPv4 <br>6 表示 IPv6 | address /www.example.com/1.2.3.4 |

View File

@@ -118,6 +118,9 @@ From the comparison, smartdns found the fastest IP address to visit www.baidu.co
8. **High performance, low resource consumption**
Multi-threaded asynchronous IO mode, cache cache query results.
9. **DNS domain forwarding**
Support DNS forwarding, ipset and nftables.
## Architecture
![Architecture](doc/architecture.png)
@@ -543,10 +546,10 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|audit-size|audit log size|128K|number+K,M,G|audit-size 128K
|audit-num|archived audit log number|2|Integer|audit-num 2
|conf-file|additional conf file|None|File path|conf-file /etc/smartdns/smartdns.more.conf
|server|Upstream UDP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server 8.8.8.8:53 -blacklist-ip
|server-tcp|Upstream TCP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-tcp 8.8.8.8:53
|server-tls|Upstream TLS DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[-host-name]`:TLS Server name. `-` to disable SNI name.<br>`[-tls-host-verify]`: TLS cert hostname to verify. <br>`-no-check-certificate:`: No check certificate. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-tls 8.8.8.8:853
|server-https|Upstream HTTPS DNS server|None|Repeatable <br>`https://[host][:port]/path`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[-host-name]`:TLS Server name<br>`[-http-host]`http header host. <br>`[-tls-host-verify]`: TLS cert hostname to verify. <br>`-no-check-certificate:`: No check certificate. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-https https://cloudflare-dns.com/dns-query
|server|Upstream UDP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group. <br>`[-set-mark]`set mark on packets | server 8.8.8.8:53 -blacklist-ip
|server-tcp|Upstream TCP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group <br>`[-set-mark]`set mark on packets | server-tcp 8.8.8.8:53
|server-tls|Upstream TLS DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[-host-name]`:TLS Server name. `-` to disable SNI name.<br>`[-tls-host-verify]`: TLS cert hostname to verify. <br>`-no-check-certificate:`: No check certificate. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group <br> `[-set-mark]`set mark on packets | server-tls 8.8.8.8:853
|server-https|Upstream HTTPS DNS server|None|Repeatable <br>`https://[host][:port]/path`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[-host-name]`:TLS Server name<br>`[-http-host]`http header host. <br>`[-tls-host-verify]`: TLS cert hostname to verify. <br>`-no-check-certificate:`: No check certificate. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group <br> `[-set-mark]`set mark on packets | server-https https://cloudflare-dns.com/dns-query
|speed-check-mode|Speed mode|None|[ping\|tcp:[80]\|none]|speed-check-mode ping,tcp:80,tcp:443
|response-mode|First query response mode|first-ping|Mode: [fisrt-ping\|fastest-ip\|fastest-response]<br> [first-ping]: The fastest dns + ping response mode, DNS query delay + ping delay is the shortest;<br>[fastest-ip]: The fastest IP address mode, return the fastest ip address, may take some time to test speed. <br>[fastest-response]: The fastest response DNS result mode, the DNS query waiting time is the shortest. | response-mode first-ping |
|address|Domain IP address|None|address /domain/[ip\|-\|-4\|-6\|#\|#4\|#6], `-` for ignore, `#` for return SOA, `4` for IPV4, `6` for IPV6| address /www.example.com/1.2.3.4

View File

@@ -32,6 +32,7 @@
# -no-rule-soa: Skip address SOA(#) rules.
# -no-dualstack-selection: Disable dualstack ip selection.
# -force-aaaa-soa: force AAAA query return SOA.
# -set-mark: set mark on packets.
# example:
# IPV4:
# bind :53

View File

@@ -230,6 +230,12 @@ msgstr "下载的文件列表。"
msgid "Local Port"
msgstr "本地端口"
msgid "Marking Packets"
msgstr "数据包标记"
msgid "Set mark on packets."
msgstr "设置数据包标记。"
msgid "Maximum TTL for all domain result."
msgstr "所有域名的最大 TTL 值。"

View File

@@ -127,6 +127,12 @@ o.rempty = true
o:depends("type", "tls")
o:depends("type", "https")
---- mark
o = s:option(Value, "set_mark", translate("Marking Packets"), translate("Set mark on packets."))
o.default = ""
o.rempty = true
o.datatype = "uinteger"
---- other args
o = s:option(Value, "addition_arg", translate("Additional Server Args"), translate("Additional Args for upstream dns servers"))
o.default = ""

View File

@@ -256,6 +256,12 @@ msgstr "下载文件列表"
msgid "Local Port"
msgstr "本地端口"
msgid "Marking Packets"
msgstr "数据包标记"
msgid "Set mark on packets."
msgstr "设置数据包标记。"
msgid "Maximum TTL for all domain result."
msgstr "所有域名的最大 TTL 值。"

View File

@@ -584,6 +584,14 @@ return view.extend({
o.depends("type", "tls")
o.depends("type", "https")
// mark
o = s.taboption("advanced", form.Value, "set_mark", _("Marking Packets"),
_("Set mark on packets."))
o.default = ""
o.rempty = true
o.datatype = "uinteger"
o.modalonly = true;
// other args
o = s.taboption("advanced", form.Value, "addition_arg", _("Additional Server Args"),
_("Additional Args for upstream dns servers"))

View File

@@ -183,6 +183,7 @@ load_server()
config_get check_edns "$section" "check_edns" "0"
config_get spki_pin "$section" "spki_pin" ""
config_get addition_arg "$section" "addition_arg" ""
config_get set_mark "$section" "set_mark" ""
[ "$enabled" = "0" ] && return
@@ -214,6 +215,7 @@ load_server()
[ "$blacklist_ip" = "0" ] || ADDITIONAL_ARGS="$ADDITIONAL_ARGS -blacklist-ip"
[ "$check_edns" = "0" ] || ADDITIONAL_ARGS="$ADDITIONAL_ARGS -check-edns"
[ -z "$spki_pin" ] || ADDITIONAL_ARGS="$ADDITIONAL_ARGS -spki-pin $spki_pin"
[ -z "$set_mark" ] || ADDITIONAL_ARGS="$ADDITIONAL_ARGS -set-mark $set_mark"
if [ -z "$port" ]; then
DNS_ADDRESS="$ip"

View File

@@ -93,6 +93,7 @@ struct dns_server_info {
int port;
/* server type */
dns_server_type_t type;
long long so_mark;
/* client socket */
int fd;
@@ -1045,6 +1046,7 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
server_info->ttl_range = 0;
server_info->skip_check_cert = skip_check_cert;
server_info->prohibit = 0;
server_info->so_mark = flags->set_mark;
pthread_mutex_init(&server_info->lock, NULL);
memcpy(&server_info->flags, flags, sizeof(server_info->flags));
@@ -1694,6 +1696,13 @@ static int _dns_client_create_socket_udp(struct dns_server_info *server_info)
return -1;
}
if (server_info->so_mark >= 0) {
unsigned int so_mark = server_info->so_mark;
if (setsockopt(fd, SOL_SOCKET, SO_MARK, &so_mark, sizeof(so_mark)) != 0) {
tlog(TLOG_DEBUG, "set socket mark failed, %s", strerror(errno));
}
}
setsockopt(server_info->fd, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
setsockopt(server_info->fd, SOL_IP, IP_TTL, &val, sizeof(val));
setsockopt(server_info->fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority));
@@ -1736,6 +1745,13 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
goto errout;
}
if (server_info->so_mark >= 0) {
unsigned int so_mark = server_info->so_mark;
if (setsockopt(fd, SOL_SOCKET, SO_MARK, &so_mark, sizeof(so_mark)) != 0) {
tlog(TLOG_DEBUG, "set socket mark failed, %s", strerror(errno));
}
}
/* enable tcp fast open */
if (setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, &yes, sizeof(yes)) != 0) {
tlog(TLOG_DEBUG, "enable TCP fast open failed, %s", strerror(errno));
@@ -1818,6 +1834,13 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, ch
goto errout;
}
if (server_info->so_mark >= 0) {
unsigned int so_mark = server_info->so_mark;
if (setsockopt(fd, SOL_SOCKET, SO_MARK, &so_mark, sizeof(so_mark)) != 0) {
tlog(TLOG_DEBUG, "set socket mark failed, %s", strerror(errno));
}
}
if (setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, &yes, sizeof(yes)) != 0) {
tlog(TLOG_DEBUG, "enable TCP fast open failed.");
}

View File

@@ -111,6 +111,7 @@ struct client_dns_server_flags {
dns_server_type_t type;
unsigned int server_flag;
unsigned int result_flag;
long long set_mark;
union {
struct client_dns_server_flag_udp udp;

View File

@@ -370,6 +370,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
{"tls-host-verify", required_argument, NULL, 'V' }, /* verify tls hostname */
{"group", required_argument, NULL, 'g'}, /* add to group */
{"exclude-default-group", no_argument, NULL, 'E'}, /* ecluse this from default group */
{"set-mark", required_argument, NULL, 254}, /* set mark */
{NULL, no_argument, NULL, 0}
};
/* clang-format on */
@@ -390,6 +391,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
server->hostname[0] = '\0';
server->httphost[0] = '\0';
server->tls_host_verify[0] = '\0';
server->set_mark = -1;
if (type == DNS_SERVER_HTTPS) {
if (parse_uri(ip, NULL, server->server, &port, server->path) != 0) {
@@ -467,6 +469,10 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
server->skip_check_cert = 1;
break;
}
case 254: {
server->set_mark = atoll(optarg);
break;
}
default:
break;
}
@@ -533,7 +539,7 @@ static void _config_address_destroy(radix_node_t *node, void *cbctx)
node->data = NULL;
}
static int _config_domain_set_rule_add_ext(char *set_name, enum domain_rule type, void *rule, unsigned int flags,
static int _config_domain_set_rule_add_ext(const char *set_name, enum domain_rule type, void *rule, unsigned int flags,
int is_clear_flag)
{
struct dns_domain_set_rule *set_rule = NULL;
@@ -587,7 +593,7 @@ errout:
return -1;
}
static int _config_domian_set_rule_flags(char *set_name, unsigned int flags, int is_clear_flag)
static int _config_domian_set_rule_flags(const char *set_name, unsigned int flags, int is_clear_flag)
{
return _config_domain_set_rule_add_ext(set_name, DOMAIN_RULE_FLAGS, NULL, flags, is_clear_flag);
}
@@ -664,7 +670,7 @@ errout:
return -1;
}
static int _config_domain_rule_flag_set(char *domain, unsigned int flag, unsigned int is_clear)
static int _config_domain_rule_flag_set(const char *domain, unsigned int flag, unsigned int is_clear)
{
struct dns_domain_rule *domain_rule = NULL;
struct dns_domain_rule *old_domain_rule = NULL;

View File

@@ -231,6 +231,7 @@ struct dns_servers {
unsigned int server_flag;
int ttl;
dns_server_type_t type;
long long set_mark;
char skip_check_cert;
char spki[DNS_MAX_SPKI_LEN];
char hostname[DNS_MAX_CNAME_LEN];

View File

@@ -269,6 +269,7 @@ static int _smartdns_add_servers(void)
flags.type = dns_conf_servers[i].type;
flags.server_flag = dns_conf_servers[i].server_flag;
flags.result_flag = dns_conf_servers[i].result_flag;
flags.set_mark = dns_conf_servers[i].set_mark;
ret = dns_client_add_server(dns_conf_servers[i].server, dns_conf_servers[i].port, dns_conf_servers[i].type,
&flags);
if (ret != 0) {