dns_server: support query smartdns server ip

This commit is contained in:
Nick Peng
2022-05-21 02:18:44 +08:00
parent dae263444f
commit 94b84cd32c
5 changed files with 238 additions and 48 deletions

View File

@@ -311,8 +311,6 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
* **检测上游服务是否配置成功**
* 方法一
执行
```shell
@@ -329,22 +327,15 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
Non-authoritative answer:
smartdns name = smartdns.
```
* 方法二
使用 `nslookup` 查询域名(例如 `www.baidu.com`),查看结果中 IP 地址是否**只有一个**,如有多个 IP 地址返回,则表示未生效,请多尝试几个域名检查。
或执行
```shell
$ nslookup www.baidu.com 192.168.1.1
Server: 192.168.1.1
Address: 192.168.1.1#53
Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
Name: www.a.shifen.com
Address: 14.215.177.38
$ nslookup smartdns
```
查看命令结果是否有解析出路由器的IP地址如果是则表示生效。
4. 启动服务
勾选配置页面中的 `Enable启用`来启动 SmartDNS。

View File

@@ -281,7 +281,7 @@ https://github.com/pymumu/smartdns/releases
* **Check if the service is configured successfully**
* Method 1: Query domain name with `nslookup -querytype=ptr 0.0.0.1`
* Query domain name with `nslookup -querytype=ptr 0.0.0.1`
See if the `name` item in the command result is displayed as `smartdns` or `hostname`, such as `smartdns`
```shell
@@ -293,18 +293,12 @@ https://github.com/pymumu/smartdns/releases
smartdns name = smartdns.
```
* Method 2: Use `nslookup` to query the `www.baidu.com` domain name to see if the IP address of Baidu in the result is `only one. If there are multiple IP addresses returned, it means that it is not valid. Please try to check several domain names.
* or Query doman name `smartdns `with `nslookup smartdns`
```shell
$ nslookup smartdns
```
```shell
pi@raspberrypi:~ $ nslookup www.baidu.com 192.168.1.1
Server: 192.168.1.1
Address: 192.168.1.1#53
Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
Name: www.a.shifen.com
Address: 14.215.177.38
```
Check whether the command result resolves the IP address of the router, if so, it means it is working.
1. Start Service

View File

@@ -1749,6 +1749,10 @@ int dns_server_check_update_hosts(void)
struct stat statbuf;
time_t now;
if (dns_conf_dnsmasq_lease_file[0] == '\0') {
return -1;
}
if (stat(dns_conf_dnsmasq_lease_file, &statbuf) != 0) {
return -1;
}
@@ -1798,6 +1802,35 @@ static int _config_log_level(void *data, int argc, char *argv[])
return 0;
}
static void _config_setup_smartdns_domain(void)
{
char hostname[DNS_MAX_CNAME_LEN];
/* get local host name */
if (getdomainname(hostname, DNS_MAX_CNAME_LEN) != 0) {
gethostname(hostname, DNS_MAX_CNAME_LEN);
}
/* get host name again */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) {
gethostname(hostname, DNS_MAX_CNAME_LEN);
}
/* if hostname is (none), return smartdns */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) {
safe_strncpy(hostname, "smartdns", DNS_MAX_CNAME_LEN);
}
if (hostname[0] != '\0') {
_config_domain_rule_flag_set(hostname, DOMAIN_FLAG_SMARTDNS_DOMAIN, 0);
}
if (dns_conf_server_name[0] != '\0') {
_config_domain_rule_flag_set(dns_conf_server_name, DOMAIN_FLAG_SMARTDNS_DOMAIN, 0);
}
_config_domain_rule_flag_set("smartdns", DOMAIN_FLAG_SMARTDNS_DOMAIN, 0);
}
static struct config_item _config_item[] = {
CONF_STRING("server-name", (char *)dns_conf_server_name, DNS_MAX_SERVER_NAME_LEN),
CONF_CUSTOM("bind", _config_bind_ip_udp, NULL),
@@ -1918,6 +1951,8 @@ static int _dns_server_load_conf_init(void)
hash_init(dns_hosts_table.hosts);
hash_init(dns_ptr_table.ptr);
_config_setup_smartdns_domain();
return 0;
}

View File

@@ -86,6 +86,7 @@ typedef enum {
#define DOMAIN_FLAG_IPSET_IPV6_IGN (1 << 8)
#define DOMAIN_FLAG_NAMESERVER_IGNORE (1 << 9)
#define DOMAIN_FLAG_DUALSTACK_SELECT (1 << 10)
#define DOMAIN_FLAG_SMARTDNS_DOMAIN (1 << 11)
#define SERVER_FLAG_EXCLUDE_DEFAULT (1 << 0)

View File

@@ -665,11 +665,11 @@ static int _dns_add_rrs(struct dns_server_post_context *context)
tlog(TLOG_INFO,
"result: %s, rcode: %d, index: %d, rtt: %d, "
"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
request->domain, request->rcode, context->ip_num, request->ping_ttl_v6, request->ipv6_addr[0], request->ipv6_addr[1],
request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5],
request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9],
request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12], request->ipv6_addr[13],
request->ipv6_addr[14], request->ipv6_addr[15]);
request->domain, request->rcode, context->ip_num, request->ping_ttl_v6, request->ipv6_addr[0],
request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4],
request->ipv6_addr[5], request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8],
request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12],
request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
}
ret |= _dns_rrs_add_all_best_ip(context);
@@ -1328,7 +1328,8 @@ out:
return _dns_server_reply_all_pending_list(request, &context);
}
static int _dns_ip_address_check_add(struct dns_request *request, char *cname, unsigned char *addr, dns_type_t addr_type)
static int _dns_ip_address_check_add(struct dns_request *request, char *cname, unsigned char *addr,
dns_type_t addr_type)
{
uint32_t key = 0;
struct dns_ip_address *addr_map = NULL;
@@ -1684,7 +1685,8 @@ static void _dns_server_ping_result(struct ping_host_struct *ping_host, const ch
if (is_ipv6_ready) {
if (error == EADDRNOTAVAIL || errno == EACCES) {
is_ipv6_ready = 0;
tlog(TLOG_ERROR, "IPV6 is not ready, disable all ipv6 feature, recheck after %ds", IPV6_READY_CHECK_TIME);
tlog(TLOG_ERROR, "IPV6 is not ready, disable all ipv6 feature, recheck after %ds",
IPV6_READY_CHECK_TIME);
}
}
return;
@@ -1753,8 +1755,7 @@ static void _dns_server_ping_result(struct ping_host_struct *ping_host, const ch
request->has_ping_result = 1;
}
} else {
addr_map = _dns_ip_address_get(request, addr_in6->sin6_addr.s6_addr,
DNS_T_AAAA);
addr_map = _dns_ip_address_get(request, addr_in6->sin6_addr.s6_addr, DNS_T_AAAA);
if (addr_map) {
addr_map->ping_ttl = rtt;
}
@@ -1766,8 +1767,7 @@ static void _dns_server_ping_result(struct ping_host_struct *ping_host, const ch
memcpy(request->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
if (addr_map && addr_map->cname[0] != 0) {
request->has_cname = 1;
safe_strncpy(request->cname, addr_map->cname,
DNS_MAX_CNAME_LEN);
safe_strncpy(request->cname, addr_map->cname, DNS_MAX_CNAME_LEN);
} else {
request->has_cname = 0;
}
@@ -2414,7 +2414,7 @@ static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsi
}
ttl = _dns_server_get_conf_ttl(ttl);
if ( ttl > dns_conf_rr_ttl_reply_max && dns_conf_rr_ttl_reply_max > 0) {
if (ttl > dns_conf_rr_ttl_reply_max && dns_conf_rr_ttl_reply_max > 0) {
ttl = dns_conf_rr_ttl_reply_max;
}
@@ -2454,6 +2454,153 @@ static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsi
return 0;
}
static int _dns_server_get_inet_by_addr(struct sockaddr_storage *localaddr, struct sockaddr_storage *addr, int family)
{
struct ifaddrs *ifaddr = NULL;
struct ifaddrs *ifa = NULL;
char ethname[16] = {0};
if (getifaddrs(&ifaddr) == -1) {
return -1;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL) {
continue;
}
if (localaddr->ss_family != ifa->ifa_addr->sa_family) {
continue;
}
switch (ifa->ifa_addr->sa_family) {
case AF_INET: {
struct sockaddr_in *addr_in_1;
struct sockaddr_in *addr_in_2;
addr_in_1 = (struct sockaddr_in *)ifa->ifa_addr;
addr_in_2 = (struct sockaddr_in *)localaddr;
if (memcmp(&(addr_in_1->sin_addr.s_addr), &(addr_in_2->sin_addr.s_addr), 4) != 0) {
continue;
}
} break;
case AF_INET6: {
struct sockaddr_in6 *addr_in6_1;
struct sockaddr_in6 *addr_in6_2;
addr_in6_1 = (struct sockaddr_in6 *)ifa->ifa_addr;
addr_in6_2 = (struct sockaddr_in6 *)localaddr;
if (IN6_IS_ADDR_V4MAPPED(&addr_in6_1->sin6_addr)) {
unsigned char *addr1 = addr_in6_1->sin6_addr.s6_addr + 12;
unsigned char *addr2 = addr_in6_2->sin6_addr.s6_addr + 12;
if (memcmp(addr1, addr2, 4) != 0) {
continue;
}
} else {
unsigned char *addr1 = addr_in6_1->sin6_addr.s6_addr;
unsigned char *addr2 = addr_in6_2->sin6_addr.s6_addr;
if (memcmp(addr1, addr2, 16) != 0) {
continue;
}
}
} break;
default:
continue;
break;
}
safe_strncpy(ethname, ifa->ifa_name, sizeof(ethname));
break;
}
if (ethname[0] == '\0') {
goto errout;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL) {
continue;
}
if (ifa->ifa_addr->sa_family != family) {
continue;
}
if (strncmp(ethname, ifa->ifa_name, sizeof(ethname)) != 0) {
continue;
}
if (family == AF_INET) {
memcpy(addr, ifa->ifa_addr, sizeof(struct sockaddr_in));
} else if (family == AF_INET6) {
memcpy(addr, ifa->ifa_addr, sizeof(struct sockaddr_in6));
}
break;
}
freeifaddrs(ifaddr);
return 0;
errout:
if (ifaddr) {
freeifaddrs(ifaddr);
}
return -1;
}
static int _dns_server_reply_request_eth_ip(struct dns_request *request)
{
struct sockaddr_in *addr_in = NULL;
struct sockaddr_in6 *addr_in6 = NULL;
struct sockaddr_storage *localaddr;
struct sockaddr_storage localaddr_buff;
localaddr = &request->localaddr;
/* address /domain/ rule */
switch (request->qtype) {
case DNS_T_A:
if (localaddr->ss_family != AF_INET) {
if (_dns_server_get_inet_by_addr(localaddr, &localaddr_buff, AF_INET) != 0) {
_dns_server_reply_SOA(DNS_RC_NOERROR, request);
return 0;
}
localaddr = &localaddr_buff;
}
addr_in = (struct sockaddr_in *)localaddr;
memcpy(request->ipv4_addr, &addr_in->sin_addr.s_addr, DNS_RR_A_LEN);
request->ttl_v4 = 600;
request->has_ipv4 = 1;
break;
case DNS_T_AAAA:
if (localaddr->ss_family != AF_INET6) {
if (_dns_server_get_inet_by_addr(localaddr, &localaddr_buff, AF_INET6) != 0) {
_dns_server_reply_SOA(DNS_RC_NOERROR, request);
return 0;
}
localaddr = &localaddr_buff;
}
addr_in6 = (struct sockaddr_in6 *)localaddr;
memcpy(request->ipv6_addr, &addr_in6->sin6_addr.s6_addr, DNS_RR_AAAA_LEN);
request->ttl_v6 = 600;
request->has_ipv6 = 1;
break;
default:
goto out;
break;
}
request->rcode = DNS_RC_NOERROR;
struct dns_server_post_context context;
_dns_server_post_context_init(&context, request);
context.do_reply = 1;
_dns_request_post(&context);
return 0;
out:
return -1;
}
static int _dns_server_process_ptrs(struct dns_request *request)
{
@@ -2462,7 +2609,7 @@ static int _dns_server_process_ptrs(struct dns_request *request)
struct dns_ptr *ptr_tmp = NULL;
key = hash_string(request->domain);
hash_for_each_possible(dns_ptr_table.ptr, ptr_tmp, node, key)
{
{
if (strncmp(ptr_tmp->ptr_domain, request->domain, DNS_MAX_CNAME_LEN) != 0) {
continue;
}
@@ -2482,7 +2629,7 @@ errout:
return -1;
}
static int _dns_server_process_local_ptr(struct dns_request *request)
static int _dns_server_process_local_ptr(struct dns_request *request)
{
struct ifaddrs *ifaddr = NULL;
struct ifaddrs *ifa = NULL;
@@ -2541,14 +2688,12 @@ static int _dns_server_process_local_ptr(struct dns_request *request)
}
/* Determine if the smartdns service is in effect. */
if (strncmp(request->domain, "0.0.0.0.in-addr.arpa", DNS_MAX_CNAME_LEN) ==
0) {
if (strncmp(request->domain, "0.0.0.0.in-addr.arpa", DNS_MAX_CNAME_LEN) == 0) {
found = 1;
}
/* Determine if the smartdns service is in effect. */
if (found == 0 &&
strncmp(request->domain, "smartdns", sizeof("smartdns")) == 0) {
if (found == 0 && strncmp(request->domain, "smartdns", sizeof("smartdns")) == 0) {
found = 1;
}
@@ -3176,10 +3321,33 @@ static void _dns_server_request_set_callback(struct dns_request *request, dns_re
request->user_ptr = user_ptr;
}
static int _dns_server_process_smartdns_domain(struct dns_request *request)
{
struct dns_rule_flags *rule_flag = NULL;
unsigned int flags = 0;
/* get domain rule flag */
rule_flag = request->domain_rule.rules[DOMAIN_RULE_FLAGS];
if (rule_flag == NULL) {
return -1;
}
flags = rule_flag->flags;
if (!(flags & DOMAIN_FLAG_SMARTDNS_DOMAIN)) {
return -1;
}
return _dns_server_reply_request_eth_ip(request);
}
static int _dns_server_process_special_query(struct dns_request *request)
{
int ret = 0;
if (_dns_server_process_smartdns_domain(request) == 0) {
goto clean_exit;
}
switch (request->qtype) {
case DNS_T_PTR:
/* return PTR record */
@@ -3266,7 +3434,7 @@ static int _dns_server_process_host(struct dns_request *request)
if (host_tmp->dns_type != dns_type) {
continue;
}
if (strncmp(host_tmp->domain, hostname_lower, DNS_MAX_CNAME_LEN) != 0) {
continue;
}
@@ -3283,7 +3451,7 @@ static int _dns_server_process_host(struct dns_request *request)
request->has_soa = 1;
return _dns_server_reply_SOA(DNS_RC_NOERROR, request);
}
switch (request->qtype) {
case DNS_T_A:
memcpy(request->ipv4_addr, host->ipv4_addr, DNS_RR_A_LEN);
@@ -4446,7 +4614,8 @@ int dns_server_init(void)
}
_dns_server_check_ipv6_ready();
tlog(TLOG_INFO, "%s", (is_ipv6_ready) ? "IPV6 is ready, enable IPV6 features" : "IPV6 is not ready, disable IPV6 features");
tlog(TLOG_INFO, "%s",
(is_ipv6_ready) ? "IPV6 is ready, enable IPV6 features" : "IPV6 is not ready, disable IPV6 features");
return 0;
errout: