Browse Source

dns_server: fix DNS64 issue and add group config support for DNS64

Nick Peng 1 năm trước cách đây
mục cha
commit
484251c6f5
5 tập tin đã thay đổi với 128 bổ sung27 xóa
  1. 1 1
      etc/smartdns/smartdns.conf
  2. 8 5
      src/dns_conf.c
  3. 11 7
      src/dns_conf.h
  4. 26 14
      src/dns_server.c
  5. 82 0
      test/cases/test-dns64.cc

+ 1 - 1
etc/smartdns/smartdns.conf

@@ -203,7 +203,7 @@ log-level info
 
 # certificate path
 # ca-path [path]
-# ca-path /etc/ss/certs
+# ca-path /etc/ssl/certs
 
 # remote udp dns server list
 # server [IP]:[PORT]|URL [-blacklist-ip] [-whitelist-ip] [-check-edns] [-group [group] ...] [-exclude-default-group]

+ 8 - 5
src/dns_conf.c

@@ -61,9 +61,6 @@ static time_t dns_conf_dnsmasq_lease_file_time;
 struct dns_hosts_table dns_hosts_table;
 int dns_hosts_record_num;
 
-/* DNS64 */
-struct dns_dns64 dns_conf_dns_dns64;
-
 /* SRV-HOST */
 struct dns_srv_record_table dns_conf_srv_record_table;
 
@@ -2833,6 +2830,11 @@ static int _config_dns64(void *data, int argc, char *argv[])
 
 	subnet = argv[1];
 
+	if (strncmp(subnet, "-", 2U) == 0) {
+		memset(&_config_current_rule_group()->dns_dns64, 0, sizeof(struct dns_dns64));
+		return 0;
+	}
+
 	p = prefix_pton(subnet, -1, &prefix, &errmsg);
 	if (p == NULL) {
 		goto errout;
@@ -2848,8 +2850,9 @@ static int _config_dns64(void *data, int argc, char *argv[])
 		goto errout;
 	}
 
-	memcpy(&dns_conf_dns_dns64.prefix, &prefix.add.sin6.s6_addr, sizeof(dns_conf_dns_dns64.prefix));
-	dns_conf_dns_dns64.prefix_len = prefix.bitlen;
+	struct dns_dns64 *dns64 = &(_config_current_rule_group()->dns_dns64);
+	memcpy(&dns64->prefix, &prefix.add.sin6.s6_addr, sizeof(dns64->prefix));
+	dns64->prefix_len = prefix.bitlen;
 
 	return 0;
 

+ 11 - 7
src/dns_conf.h

@@ -448,17 +448,27 @@ struct dns_conf_ipset_nftset {
 	struct dns_nftset_names nftset_no_speed;
 };
 
+struct dns_dns64 {
+	unsigned char prefix[DNS_RR_AAAA_LEN];
+	uint32_t prefix_len;
+};
+
 struct dns_conf_group {
 	struct hlist_node node;
 	struct dns_conf_domain_rule domain_rule;
 	struct dns_conf_address_rule address_rule;
 	uint8_t *soa_table;
+	/* === AUTO COPY FIELD BEGIN === */
 	char copy_data_section_begin[0];
 	struct dns_conf_ipset_nftset ipset_nftset;
 	struct dns_domain_check_orders check_orders;
 	/* ECS */
 	struct dns_edns_client_subnet ipv4_ecs;
 	struct dns_edns_client_subnet ipv6_ecs;
+
+	/* DNS64 */
+	struct dns_dns64 dns_dns64;
+
 	int force_AAAA_SOA;
 	int dualstack_ip_selection;
 	int dns_dualstack_ip_allow_force_AAAA;
@@ -477,6 +487,7 @@ struct dns_conf_group {
 	int dns_max_reply_ip_num;
 	enum response_mode_type dns_response_mode;
 	char copy_data_section_end[0];
+	/* === AUTO COPY FIELD END === */
 	const char *group_name;
 };
 
@@ -616,11 +627,6 @@ struct dns_set_rule_flags_callback_args {
 	int is_clear_flag;
 };
 
-struct dns_dns64 {
-	unsigned char prefix[DNS_RR_AAAA_LEN];
-	uint32_t prefix_len;
-};
-
 struct dns_srv_record {
 	struct list_head list;
 	char host[DNS_MAX_CNAME_LEN];
@@ -640,8 +646,6 @@ struct dns_srv_record_table {
 };
 extern struct dns_srv_record_table dns_conf_srv_record_table;
 
-extern struct dns_dns64 dns_conf_dns_dns64;
-
 extern struct dns_bind_ip dns_conf_bind_ip[DNS_MAX_BIND_IP];
 extern int dns_conf_bind_ip_num;
 

+ 26 - 14
src/dns_server.c

@@ -625,7 +625,7 @@ static int _dns_server_is_dns64_request(struct dns_request *request)
 		return 0;
 	}
 
-	if (dns_conf_dns_dns64.prefix_len <= 0) {
+	if (request->conf->dns_dns64.prefix_len <= 0) {
 		return 0;
 	}
 
@@ -4138,6 +4138,9 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
 			case DNS_T_SOA: {
 				/* if DNS64 enabled, skip check SOA. */
 				if (_dns_server_is_dns64_request(request)) {
+					if (request->has_ip) {
+						_dns_server_request_complete(request);
+					}
 					break;
 				}
 
@@ -4513,7 +4516,7 @@ static void _dns_server_query_end(struct dns_request *request)
 		if (request->dualstack_selection_query == 1) {
 			if ((conf->ipset_nftset.ipset_no_speed.ipv4_enable || conf->ipset_nftset.nftset_no_speed.ip_enable ||
 				 conf->ipset_nftset.ipset_no_speed.ipv6_enable || conf->ipset_nftset.nftset_no_speed.ip6_enable) &&
-				dns_conf_dns_dns64.prefix_len == 0) {
+				request->conf->dns_dns64.prefix_len == 0) {
 				/* if speed check fail enabled, we need reply quickly, otherwise wait for ping result.*/
 				_dns_server_request_complete(request);
 			}
@@ -5961,7 +5964,7 @@ _dns_server_process_dns64_callback(struct dns_request *request, struct dns_reque
 	int addr_len = 0;
 
 	if (request->has_ip == 1) {
-		if (memcmp(request->ip_addr, dns_conf_dns_dns64.prefix, 12) != 0) {
+		if (memcmp(request->ip_addr, request->conf->dns_dns64.prefix, 12) != 0) {
 			return DNS_CHILD_POST_SKIP;
 		}
 	}
@@ -5976,11 +5979,12 @@ _dns_server_process_dns64_callback(struct dns_request *request, struct dns_reque
 		request->ttl_cname = child_request->ttl_cname;
 	}
 
-	if (child_request->has_ip == 0) {
+	if (child_request->has_ip == 0 && request->has_ip == 0) {
+		request->rcode = child_request->rcode;
 		if (child_request->has_soa) {
 			memcpy(&request->soa, &child_request->soa, sizeof(struct dns_soa));
 			request->has_soa = 1;
-			return DNS_CHILD_POST_SUCCESS;
+			return DNS_CHILD_POST_SKIP;
 		}
 
 		if (request->has_soa == 0) {
@@ -5990,13 +5994,15 @@ _dns_server_process_dns64_callback(struct dns_request *request, struct dns_reque
 		return DNS_CHILD_POST_FAIL;
 	}
 
-	memcpy(request->ip_addr, dns_conf_dns_dns64.prefix, 16);
-	memcpy(request->ip_addr + 12, child_request->ip_addr, 4);
-	request->ip_ttl = child_request->ip_ttl;
-	request->has_ip = 1;
-	request->has_soa = 0;
+	if (request->has_ip == 0 && child_request->has_ip == 1) {
+		request->rcode = child_request->rcode;
+		memcpy(request->ip_addr, request->conf->dns_dns64.prefix, 12);
+		memcpy(request->ip_addr + 12, child_request->ip_addr, 4);
+		request->ip_ttl = child_request->ip_ttl;
+		request->has_ip = 1;
+		request->has_soa = 0;
+	}
 
-	request->rcode = child_request->rcode;
 	pthread_mutex_lock(&request->ip_map_lock);
 	hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
 	{
@@ -6026,7 +6032,7 @@ _dns_server_process_dns64_callback(struct dns_request *request, struct dns_reque
 
 		new_addr_map->addr_type = DNS_T_AAAA;
 		addr_len = DNS_RR_AAAA_LEN;
-		memcpy(new_addr_map->ip_addr, dns_conf_dns_dns64.prefix, 16);
+		memcpy(new_addr_map->ip_addr, request->conf->dns_dns64.prefix, 16);
 		memcpy(new_addr_map->ip_addr + 12, addr_map->ip_addr, 4);
 
 		new_addr_map->ping_time = addr_map->ping_time;
@@ -6042,7 +6048,7 @@ _dns_server_process_dns64_callback(struct dns_request *request, struct dns_reque
 		return DNS_CHILD_POST_NO_RESPONSE;
 	}
 
-	return DNS_CHILD_POST_SUCCESS;
+	return DNS_CHILD_POST_SKIP;
 }
 
 static int _dns_server_process_dns64(struct dns_request *request)
@@ -6060,6 +6066,8 @@ static int _dns_server_process_dns64(struct dns_request *request)
 		return -1;
 	}
 
+	request->dualstack_selection = 0;
+	child_request->prefetch_flags |= PREFETCH_FLAGS_NO_DUALSTACK;
 	request->request_wait++;
 	int ret = _dns_server_do_query(child_request, 0);
 	if (ret != 0) {
@@ -6069,7 +6077,7 @@ static int _dns_server_process_dns64(struct dns_request *request)
 	}
 
 	_dns_server_request_release_complete(child_request, 0);
-	return 1;
+	return 0;
 
 errout:
 
@@ -6288,6 +6296,10 @@ static int _dns_server_process_cache(struct dns_request *request)
 			goto reply_cache;
 		}
 
+		if (_dns_server_is_dns64_request(request) == 1) {
+			goto reply_cache;
+		}
+
 		cache_key.qtype = dualstack_qtype;
 		dualstack_dns_cache = dns_cache_lookup(&cache_key);
 		if (dualstack_dns_cache == NULL && request->cname[0] != '\0') {

+ 82 - 0
test/cases/test-dns64.cc

@@ -59,3 +59,85 @@ dualstack-ip-selection no
 	EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
 	EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::102:304");
 }
+
+TEST_F(DNS64, with_dualstack)
+{
+	smartdns::MockServer server_upstream;
+	smartdns::Server server;
+
+	server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
+		if (request->qtype == DNS_T_A) {
+			smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
+			return smartdns::SERVER_REQUEST_OK;
+		}
+		return smartdns::SERVER_REQUEST_SOA;
+	});
+
+	server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 200);
+
+	server.Start(R"""(bind [::]:60053
+server 127.0.0.1:61053
+dns64 64:ff9b::/96
+)""");
+	smartdns::Client client;
+	ASSERT_TRUE(client.Query("a.com AAAA", 60053));
+	std::cout << client.GetResult() << std::endl;
+	ASSERT_EQ(client.GetAnswerNum(), 1);
+	EXPECT_EQ(client.GetStatus(), "NOERROR");
+	EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
+	EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
+	EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
+	EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::102:304");
+	EXPECT_LT(client.GetQueryTime(), 100);
+
+	usleep(500000);
+	ASSERT_TRUE(client.Query("a.com AAAA", 60053));
+	std::cout << client.GetResult() << std::endl;
+	ASSERT_EQ(client.GetAnswerNum(), 1);
+	EXPECT_EQ(client.GetStatus(), "NOERROR");
+	EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
+	EXPECT_GT(client.GetAnswer()[0].GetTTL(), 500);
+	EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
+	EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::102:304");
+	EXPECT_LT(client.GetQueryTime(), 100);
+}
+
+
+TEST_F(DNS64, with_AAAA_result)
+{
+	smartdns::MockServer server_upstream;
+	smartdns::Server server;
+
+	server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
+		if (request->qtype == DNS_T_A) {
+			smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
+			return smartdns::SERVER_REQUEST_OK;
+		} 
+
+		if (request->qtype == DNS_T_AAAA) {
+			smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::1");
+			smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::2");
+			return smartdns::SERVER_REQUEST_OK;
+		}
+		return smartdns::SERVER_REQUEST_SOA;
+	});
+
+	server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 300);
+	server.MockPing(PING_TYPE_ICMP, "2001:db8::1", 60, 90);
+	server.MockPing(PING_TYPE_ICMP, "2001:db8::2", 60, 100);
+
+	server.Start(R"""(bind [::]:60053
+server 127.0.0.1:61053
+dns64 64:ff9b::/96
+)""");
+	smartdns::Client client;
+	ASSERT_TRUE(client.Query("a.com AAAA", 60053));
+	std::cout << client.GetResult() << std::endl;
+	ASSERT_EQ(client.GetAnswerNum(), 1);
+	EXPECT_EQ(client.GetStatus(), "NOERROR");
+	EXPECT_LT(client.GetQueryTime(), 1200);
+	EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
+	EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
+	EXPECT_EQ(client.GetAnswer()[0].GetData(), "2001:db8::1");
+}
+