Parcourir la source

dns_server: fix bogus-nxdomain issue.

Nick Peng il y a 2 ans
Parent
commit
8d3a62c568
2 fichiers modifiés avec 64 ajouts et 64 suppressions
  1. 43 43
      src/dns_client.c
  2. 21 21
      src/dns_server.c

+ 43 - 43
src/dns_client.c

@@ -443,8 +443,8 @@ static struct addrinfo *_dns_client_getaddr(const char *host, char *port, int ty
 
 
 	ret = getaddrinfo(host, port, &hints, &result);
 	ret = getaddrinfo(host, port, &hints, &result);
 	if (ret != 0) {
 	if (ret != 0) {
-		tlog(TLOG_ERROR, "get addr info failed. %s\n", gai_strerror(ret));
-		tlog(TLOG_ERROR, "host = %s, port = %s, type = %d, protocol = %d", host, port, type, protocol);
+		tlog(TLOG_WARN, "get addr info failed. %s\n", gai_strerror(ret));
+		tlog(TLOG_WARN, "host = %s, port = %s, type = %d, protocol = %d", host, port, type, protocol);
 		goto errout;
 		goto errout;
 	}
 	}
 
 
@@ -1403,6 +1403,8 @@ static int _dns_client_add_server_pending(char *server_ip, char *server_host, in
 										  struct client_dns_server_flags *flags, int is_pending)
 										  struct client_dns_server_flags *flags, int is_pending)
 {
 {
 	int ret = 0;
 	int ret = 0;
+	struct addrinfo *gai = NULL;
+	char server_ip_tmp[DNS_HOSTNAME_LEN] = {0};
 
 
 	if (server_type >= DNS_SERVER_TYPE_END) {
 	if (server_type >= DNS_SERVER_TYPE_END) {
 		tlog(TLOG_ERROR, "server type is invalid.");
 		tlog(TLOG_ERROR, "server type is invalid.");
@@ -1415,6 +1417,22 @@ static int _dns_client_add_server_pending(char *server_ip, char *server_host, in
 			tlog(TLOG_INFO, "add pending server %s", server_ip);
 			tlog(TLOG_INFO, "add pending server %s", server_ip);
 			return 0;
 			return 0;
 		}
 		}
+	} else if (check_is_ipaddr(server_ip) && is_pending == 0) {
+		gai = _dns_client_getaddr(server_ip, 0, SOCK_STREAM, 0);
+		if (gai == NULL) {
+			return -1;
+		}
+
+		if (get_host_by_addr(server_ip_tmp, sizeof(server_ip_tmp), gai->ai_addr) != NULL) {
+			tlog(TLOG_INFO, "resolve %s to %s.", server_ip, server_ip_tmp);
+			server_ip = server_ip_tmp;
+		} else {
+			tlog(TLOG_INFO, "resolve %s failed.", server_ip);
+			freeaddrinfo(gai);
+			return -1;
+		}
+
+		freeaddrinfo(gai);
 	}
 	}
 
 
 	/* add server */
 	/* add server */
@@ -1784,13 +1802,8 @@ static int _dns_client_create_socket_udp_proxy(struct dns_server_info *server_in
 
 
 	ret = proxy_conn_connect(proxy);
 	ret = proxy_conn_connect(proxy);
 	if (ret != 0) {
 	if (ret != 0) {
-		if (errno == ENETUNREACH || errno == EHOSTUNREACH || errno == EPERM || errno == EACCES) {
-			tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
-			goto errout;
-		}
-
 		if (errno != EINPROGRESS) {
 		if (errno != EINPROGRESS) {
-			tlog(TLOG_ERROR, "connect %s failed, %s", server_info->ip, strerror(errno));
+			tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
 			goto errout;
 			goto errout;
 		}
 		}
 	}
 	}
@@ -1844,14 +1857,8 @@ static int _dns_client_create_socket_udp(struct dns_server_info *server_info)
 	server_info->status = DNS_SERVER_STATUS_CONNECTIONLESS;
 	server_info->status = DNS_SERVER_STATUS_CONNECTIONLESS;
 
 
 	if (connect(fd, &server_info->addr, server_info->ai_addrlen) != 0) {
 	if (connect(fd, &server_info->addr, server_info->ai_addrlen) != 0) {
-		if (errno == ENETUNREACH || errno == EHOSTUNREACH || errno == ECONNREFUSED || errno == EPERM ||
-			errno == EACCES) {
-			tlog(TLOG_INFO, "connect %s failed, %s", server_info->ip, strerror(errno));
-			goto errout;
-		}
-
 		if (errno != EINPROGRESS) {
 		if (errno != EINPROGRESS) {
-			tlog(TLOG_ERROR, "connect %s failed, %s", server_info->ip, strerror(errno));
+			tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
 			goto errout;
 			goto errout;
 		}
 		}
 	}
 	}
@@ -1951,13 +1958,8 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
 	}
 	}
 
 
 	if (ret != 0) {
 	if (ret != 0) {
-		if (errno == ENETUNREACH || errno == EHOSTUNREACH || errno == ECONNREFUSED) {
-			tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
-			goto errout;
-		}
-
 		if (errno != EINPROGRESS) {
 		if (errno != EINPROGRESS) {
-			tlog(TLOG_ERROR, "connect %s failed, %s", server_info->ip, strerror(errno));
+			tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
 			goto errout;
 			goto errout;
 		}
 		}
 	}
 	}
@@ -2065,13 +2067,8 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, ch
 	}
 	}
 
 
 	if (ret != 0) {
 	if (ret != 0) {
-		if (errno == ENETUNREACH || errno == EHOSTUNREACH || errno == ECONNREFUSED) {
-			tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
-			goto errout;
-		}
-
 		if (errno != EINPROGRESS) {
 		if (errno != EINPROGRESS) {
-			tlog(TLOG_ERROR, "connect %s failed, %s", server_info->ip, strerror(errno));
+			tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
 			goto errout;
 			goto errout;
 		}
 		}
 	}
 	}
@@ -4032,6 +4029,25 @@ static void _dns_client_add_pending_servers(void)
 		int add_success = 0;
 		int add_success = 0;
 		char *dnsserver_ip = NULL;
 		char *dnsserver_ip = NULL;
 
 
+		/* if has no bootstrap DNS, just call getaddrinfo to get address */
+		if (dns_client_has_bootstrap_dns == 0) {
+			list_del_init(&pending->retry_list);
+			_dns_client_server_pending_release(pending);
+			pending->retry_cnt++;
+			if (_dns_client_add_pendings(pending, pending->host) != 0) {
+				pthread_mutex_unlock(&pending_server_mutex);
+				tlog(TLOG_INFO, "add pending DNS server %s from resolv.conf failed, retry %d...", pending->host,
+					 pending->retry_cnt - 1);
+				if (pending->retry_cnt - 1 > DNS_PENDING_SERVER_RETRY) {
+					tlog(TLOG_WARN, "add pending DNS server %s from resolv.conf failed, exit...", pending->host);
+					exit(1);
+				}
+				continue;
+			}
+			_dns_client_server_pending_release(pending);
+			continue;
+		}
+
 		if (pending->query_v4 == 0) {
 		if (pending->query_v4 == 0) {
 			pending->query_v4 = 1;
 			pending->query_v4 = 1;
 			_dns_client_server_pending_get(pending);
 			_dns_client_server_pending_get(pending);
@@ -4093,22 +4109,6 @@ static void _dns_client_add_pending_servers(void)
 			pending->query_v4 = 0;
 			pending->query_v4 = 0;
 			pending->query_v6 = 0;
 			pending->query_v6 = 0;
 		}
 		}
-
-		/* if has no bootstrap DNS, just call getaddrinfo to get address */
-		if (dns_client_has_bootstrap_dns == 0) {
-			if (_dns_client_add_pendings(pending, pending->host) != 0) {
-				pthread_mutex_unlock(&pending_server_mutex);
-				tlog(TLOG_INFO, "add pending DNS server %s from resolv.conf failed, retry %d...", pending->host,
-					 pending->retry_cnt - 1);
-				if (pending->retry_cnt - 1 > DNS_PENDING_SERVER_RETRY) {
-					tlog(TLOG_WARN, "add pending DNS server %s from resolv.conf failed, exit...", pending->host);
-					exit(1);
-				}
-				continue;
-			}
-
-			_dns_client_server_pending_release(pending);
-		}
 	}
 	}
 }
 }
 
 

+ 21 - 21
src/dns_server.c

@@ -278,6 +278,7 @@ struct dns_request {
 
 
 	struct dns_soa soa;
 	struct dns_soa soa;
 	int has_soa;
 	int has_soa;
+	int force_soa;
 
 
 	atomic_t notified;
 	atomic_t notified;
 	atomic_t do_callback;
 	atomic_t do_callback;
@@ -2137,7 +2138,7 @@ out:
 	_dns_server_post_context_init(&context, request);
 	_dns_server_post_context_init(&context, request);
 	context.do_cache = 1;
 	context.do_cache = 1;
 	context.do_ipset = 1;
 	context.do_ipset = 1;
-	context.do_force_soa = request->dualstack_selection_force_soa;
+	context.do_force_soa = request->dualstack_selection_force_soa | request->force_soa;
 	context.do_audit = 1;
 	context.do_audit = 1;
 	context.do_reply = 1;
 	context.do_reply = 1;
 	context.reply_ttl = _dns_server_get_reply_ttl(request, ttl);
 	context.reply_ttl = _dns_server_get_reply_ttl(request, ttl);
@@ -2360,7 +2361,7 @@ static void _dns_server_complete_with_multi_ipaddress(struct dns_request *reques
 	context.do_log_result = 1;
 	context.do_log_result = 1;
 	context.select_all_best_ip = 1;
 	context.select_all_best_ip = 1;
 	context.skip_notify_count = 1;
 	context.skip_notify_count = 1;
-	context.do_force_soa = request->dualstack_selection_force_soa;
+	context.do_force_soa = request->dualstack_selection_force_soa | request->force_soa;
 	_dns_request_post(&context);
 	_dns_request_post(&context);
 	_dns_server_reply_all_pending_list(request, &context);
 	_dns_server_reply_all_pending_list(request, &context);
 }
 }
@@ -2767,8 +2768,9 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
 	if (rule->bogus) {
 	if (rule->bogus) {
 		request->rcode = DNS_RC_NXDOMAIN;
 		request->rcode = DNS_RC_NXDOMAIN;
 		request->has_soa = 1;
 		request->has_soa = 1;
+		request->force_soa = 1;
 		_dns_server_setup_soa(request);
 		_dns_server_setup_soa(request);
-		goto match;
+		goto nxdomain;
 	}
 	}
 
 
 	/* blacklist-ip */
 	/* blacklist-ip */
@@ -2796,6 +2798,8 @@ rule_not_found:
 	return -1;
 	return -1;
 skip:
 skip:
 	return -2;
 	return -2;
+nxdomain:
+	return -3;
 match:
 match:
 	if (request->rcode == DNS_RC_SERVFAIL) {
 	if (request->rcode == DNS_RC_SERVFAIL) {
 		request->rcode = DNS_RC_NXDOMAIN;
 		request->rcode = DNS_RC_NXDOMAIN;
@@ -2853,10 +2857,10 @@ static int _dns_server_process_answer_A(struct dns_rrs *rrs, struct dns_request
 		/* match */
 		/* match */
 		_dns_server_request_release(request);
 		_dns_server_request_release(request);
 		return -1;
 		return -1;
-	} else if (ip_check_result == -2) {
-		/* skip */
+	} else if (ip_check_result == -2 || ip_check_result == -3) {
+		/* skip, nxdomain */
 		_dns_server_request_release(request);
 		_dns_server_request_release(request);
-		return -2;
+		return ip_check_result;
 	}
 	}
 
 
 	if (atomic_read(&request->ip_map_num) == 0) {
 	if (atomic_read(&request->ip_map_num) == 0) {
@@ -2930,10 +2934,10 @@ static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct dns_reque
 		/* match */
 		/* match */
 		_dns_server_request_release(request);
 		_dns_server_request_release(request);
 		return -1;
 		return -1;
-	} else if (ip_check_result == -2) {
-		/* skip */
+	} else if (ip_check_result == -2 || ip_check_result == -3) {
+		/* skip, nxdomain */
 		_dns_server_request_release(request);
 		_dns_server_request_release(request);
-		return -2;
+		return ip_check_result;
 	}
 	}
 
 
 	if (atomic_read(&request->ip_map_num) == 0) {
 	if (atomic_read(&request->ip_map_num) == 0) {
@@ -3015,6 +3019,8 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
 					break;
 					break;
 				} else if (ret == -2) {
 				} else if (ret == -2) {
 					continue;
 					continue;
+				} else if (ret == -3) {
+					return -1;
 				}
 				}
 				request->rcode = packet->head.rcode;
 				request->rcode = packet->head.rcode;
 			} break;
 			} break;
@@ -3024,6 +3030,8 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
 					break;
 					break;
 				} else if (ret == -2) {
 				} else if (ret == -2) {
 					continue;
 					continue;
+				} else if (ret == -3) {
+					return -1;
 				}
 				}
 				request->rcode = packet->head.rcode;
 				request->rcode = packet->head.rcode;
 			} break;
 			} break;
@@ -3133,12 +3141,8 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, const
 
 
 				/* ip rule check */
 				/* ip rule check */
 				ip_check_result = _dns_server_ip_rule_check(request, addr, 4, DNS_T_A, result_flag);
 				ip_check_result = _dns_server_ip_rule_check(request, addr, 4, DNS_T_A, result_flag);
-				if (ip_check_result == 0) {
-					/* match */
-					_dns_server_request_release(request);
-					return 0;
-				} else if (ip_check_result == -2) {
-					/* skip */
+				if (ip_check_result == 0 || ip_check_result == -2 || ip_check_result == -3) {
+					/* match, skip, nxdomain */
 					_dns_server_request_release(request);
 					_dns_server_request_release(request);
 					return 0;
 					return 0;
 				}
 				}
@@ -3177,12 +3181,8 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, const
 					 addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
 					 addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
 
 
 				ip_check_result = _dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag);
 				ip_check_result = _dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag);
-				if (ip_check_result == 0) {
-					/* match */
-					_dns_server_request_release(request);
-					return 0;
-				} else if (ip_check_result == -2) {
-					/* skip */
+				if (ip_check_result == 0 || ip_check_result == -2 || ip_check_result == -3) {
+					/* match, skip, nxdomain */
 					_dns_server_request_release(request);
 					_dns_server_request_release(request);
 					return 0;
 					return 0;
 				}
 				}