dns_server: fix edns subnet not working issue.

This commit is contained in:
Nick Peng
2023-07-11 23:30:39 +08:00
parent c2b072b523
commit 7ff6ae3ea0
4 changed files with 176 additions and 20 deletions

View File

@@ -875,6 +875,22 @@ int dns_get_PTR(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *
return _dns_get_RAW(rrs, domain, maxsize, ttl, cname, &len); return _dns_get_RAW(rrs, domain, maxsize, ttl, cname, &len);
} }
int dns_add_TXT(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, const char *text)
{
int rr_len = strnlen(text, DNS_MAX_CNAME_LEN);
char data[DNS_MAX_CNAME_LEN];
data[0] = rr_len;
rr_len++;
memcpy(data + 1, text, rr_len);
data[rr_len] = 0;
return _dns_add_RAW(packet, type, DNS_T_TXT, domain, ttl, data, rr_len);
}
int dns_get_TXT(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *text, int txt_size)
{
return -1;
}
int dns_add_NS(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, const char *cname) int dns_add_NS(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, const char *cname)
{ {
int rr_len = strnlen(cname, DNS_MAX_CNAME_LEN) + 1; int rr_len = strnlen(cname, DNS_MAX_CNAME_LEN) + 1;

View File

@@ -262,6 +262,9 @@ int dns_get_A(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned
int dns_add_PTR(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, const char *cname); int dns_add_PTR(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, const char *cname);
int dns_get_PTR(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size); int dns_get_PTR(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size);
int dns_add_TXT(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, const char *text);
int dns_get_TXT(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *text, int txt_size);
int dns_add_AAAA(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, int dns_add_AAAA(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl,
unsigned char addr[DNS_RR_AAAA_LEN]); unsigned char addr[DNS_RR_AAAA_LEN]);
int dns_get_AAAA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned char addr[DNS_RR_AAAA_LEN]); int dns_get_AAAA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned char addr[DNS_RR_AAAA_LEN]);

View File

@@ -3378,16 +3378,7 @@ static int _dns_client_setup_server_packet(struct dns_server_info *server_info,
*packet_data = default_packet; *packet_data = default_packet;
*packet_data_len = default_packet_len; *packet_data_len = default_packet_len;
if (query->qtype != DNS_T_AAAA && query->qtype != DNS_T_A) { if (server_info->ecs_ipv4.enable == true || server_info->ecs_ipv6.enable == true) {
/* no need to encode packet */
return 0;
}
if (server_info->ecs_ipv4.enable == true && query->qtype == DNS_T_A) {
repack = 1;
}
if (server_info->ecs_ipv6.enable == true && query->qtype == DNS_T_AAAA) {
repack = 1; repack = 1;
} }
@@ -3429,12 +3420,16 @@ static int _dns_client_setup_server_packet(struct dns_server_info *server_info,
dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE); dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
/* dns_add_OPT_TCP_KEEPALIVE(packet, 600); */ /* dns_add_OPT_TCP_KEEPALIVE(packet, 600); */
if ((query->qtype == DNS_T_A && server_info->ecs_ipv4.enable) || if ((query->qtype == DNS_T_A && server_info->ecs_ipv4.enable)) {
(query->qtype == DNS_T_AAAA && server_info->ecs_ipv6.enable == 0 && server_info->ecs_ipv4.enable)) {
dns_add_OPT_ECS(packet, &server_info->ecs_ipv4.ecs); dns_add_OPT_ECS(packet, &server_info->ecs_ipv4.ecs);
} else if ((query->qtype == DNS_T_AAAA && server_info->ecs_ipv6.enable) || } else if ((query->qtype == DNS_T_AAAA && server_info->ecs_ipv6.enable)) {
(query->qtype == DNS_T_A && server_info->ecs_ipv4.enable == 0 && server_info->ecs_ipv6.enable)) {
dns_add_OPT_ECS(packet, &server_info->ecs_ipv6.ecs); dns_add_OPT_ECS(packet, &server_info->ecs_ipv6.ecs);
} else {
if (server_info->ecs_ipv6.enable) {
dns_add_OPT_ECS(packet, &server_info->ecs_ipv6.ecs);
} else if (server_info->ecs_ipv4.enable) {
dns_add_OPT_ECS(packet, &server_info->ecs_ipv4.ecs);
}
} }
/* encode packet */ /* encode packet */
@@ -3671,20 +3666,20 @@ static int _dns_client_query_setup_default_ecs(struct dns_query_struct *query)
if (client.ecs_ipv4.enable) { if (client.ecs_ipv4.enable) {
add_ipv4_ecs = 1; add_ipv4_ecs = 1;
} else if (client.ecs_ipv6.enable) { } else if (client.ecs_ipv6.enable) {
add_ipv4_ecs = 1; add_ipv6_ecs = 1;
} }
} }
if (add_ipv4_ecs) {
memcpy(&query->ecs, &client.ecs_ipv4, sizeof(query->ecs));
return 0;
}
if (add_ipv6_ecs) { if (add_ipv6_ecs) {
memcpy(&query->ecs, &client.ecs_ipv6, sizeof(query->ecs)); memcpy(&query->ecs, &client.ecs_ipv6, sizeof(query->ecs));
return 0; return 0;
} }
if (add_ipv4_ecs) {
memcpy(&query->ecs, &client.ecs_ipv4, sizeof(query->ecs));
return 0;
}
return 0; return 0;
} }

View File

@@ -245,6 +245,148 @@ cache-persist no)""");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "2001:db8::1"); EXPECT_EQ(client.GetAnswer()[0].GetData(), "2001:db8::1");
} }
TEST_F(SubNet, v4_server_subnet_txt)
{
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_TXT) {
return smartdns::SERVER_REQUEST_SOA;
}
struct dns_opt_ecs ecs;
struct dns_rrs *rrs = NULL;
int rr_count = 0;
int i = 0;
int ret = 0;
int has_ecs = 0;
rr_count = 0;
rrs = dns_get_rrs_start(request->packet, DNS_RRS_OPT, &rr_count);
if (rr_count <= 0) {
return smartdns::SERVER_REQUEST_ERROR;
}
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}
has_ecs = 1;
break;
}
if (has_ecs == 0) {
return smartdns::SERVER_REQUEST_ERROR;
}
if (ecs.family != DNS_OPT_ECS_FAMILY_IPV4) {
return smartdns::SERVER_REQUEST_ERROR;
}
if (memcmp(ecs.addr, "\x08\x08\x08\x00", 4) != 0) {
return smartdns::SERVER_REQUEST_ERROR;
}
if (ecs.source_prefix != 24) {
return smartdns::SERVER_REQUEST_ERROR;
}
dns_add_TXT(request->response_packet, DNS_RRS_AN, request->domain.c_str(), 6, "hello world");
return smartdns::SERVER_REQUEST_OK;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053 -subnet 8.8.8.8/24
log-num 0
log-console yes
dualstack-ip-selection no
log-level debug
rr-ttl-min 0
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com TXT", 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(), 6);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "TXT");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "\"hello world\"");
}
TEST_F(SubNet, v6_default_subnet_txt)
{
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_TXT) {
return smartdns::SERVER_REQUEST_SOA;
}
struct dns_opt_ecs ecs;
struct dns_rrs *rrs = NULL;
int rr_count = 0;
int i = 0;
int ret = 0;
int has_ecs = 0;
rr_count = 0;
rrs = dns_get_rrs_start(request->packet, DNS_RRS_OPT, &rr_count);
if (rr_count <= 0) {
return smartdns::SERVER_REQUEST_ERROR;
}
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}
has_ecs = 1;
break;
}
if (has_ecs == 0) {
return smartdns::SERVER_REQUEST_ERROR;
}
if (ecs.family != DNS_OPT_ECS_FAMILY_IPV6) {
return smartdns::SERVER_REQUEST_ERROR;
}
if (memcmp(ecs.addr, "\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00", 16) != 0) {
return smartdns::SERVER_REQUEST_ERROR;
}
if (ecs.source_prefix != 64) {
return smartdns::SERVER_REQUEST_ERROR;
}
dns_add_TXT(request->response_packet, DNS_RRS_AN, request->domain.c_str(), 6, "hello world");
return smartdns::SERVER_REQUEST_OK;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
dualstack-ip-selection no
rr-ttl-min 0
edns-client-subnet ffff:ffff:ffff:ffff:ffff::/64
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com TXT", 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(), 6);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "TXT");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "\"hello world\"");
}
TEST_F(SubNet, per_server) TEST_F(SubNet, per_server)
{ {
smartdns::MockServer server_upstream1; smartdns::MockServer server_upstream1;