Add Bogus ip filter
This commit is contained in:
@@ -381,6 +381,7 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
||||
|server|Upstream UDP DNS server|None|[ip][:port], Repeatable| server 8.8.8.8:53
|
||||
|server-tcp|Upstream TCP DNS server|None|[IP][:port], Repeatable| server-tcp 8.8.8.8:53
|
||||
|address|Domain IP address|None|address /domain/ip| address /www.example.com/1.2.3.4
|
||||
|bogus-nxdomain|bogus IP address|None|[IP],Repeatable| bogus-nxdomain 1.2.3.4
|
||||
|
||||
## [Donate](#Donate)
|
||||
|
||||
|
||||
@@ -381,6 +381,7 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
||||
|server|上游UDP DNS|无|[ip][:port],可重复| server 8.8.8.8:53
|
||||
|server-tcp|上游TCP DNS|无|[IP][:port],可重复| server-tcp 8.8.8.8:53
|
||||
|address|指定域名IP地址|无|address /domain/ip| address /www.example.com/1.2.3.4
|
||||
|bogus-nxdomain|假冒IP地址过滤|无|[ip],可重复| bogus-nxdomain 1.2.3.4
|
||||
|
||||
## [Donate](#Donate)
|
||||
|
||||
|
||||
@@ -45,3 +45,6 @@ log-level error
|
||||
# specific address to domain
|
||||
# address /domain/ip
|
||||
# address /www.example.com/1.2.3.4
|
||||
|
||||
# List of hosts that supply bogus NX domain results
|
||||
# bogus-nxdomain [ip]
|
||||
|
||||
@@ -8,4 +8,7 @@
|
||||
# log-size 128k
|
||||
|
||||
# log-file /var/log/smartdns.log
|
||||
# log-num 2
|
||||
# log-num 2
|
||||
|
||||
# List of hosts that supply bogus NX domain results
|
||||
# bogus-nxdomain [ip]
|
||||
115
src/conf.c
115
src/conf.c
@@ -1,7 +1,7 @@
|
||||
#include "conf.h"
|
||||
#include "tlog.h"
|
||||
#include "list.h"
|
||||
#include "rbtree.h"
|
||||
#include "tlog.h"
|
||||
#include "util.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -16,6 +16,7 @@
|
||||
char dns_conf_server_ip[DNS_MAX_IPLEN];
|
||||
int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE;
|
||||
struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
|
||||
struct dns_bogus_nxdomain dns_conf_bogus_nxdomain;
|
||||
char dns_conf_server_name[DNS_MAX_CONF_CNAME_LEN];
|
||||
int dns_conf_server_num;
|
||||
int dns_conf_log_level = TLOG_ERROR;
|
||||
@@ -119,7 +120,7 @@ int config_address(char *value)
|
||||
memset(address, 0, sizeof(*address));
|
||||
len = end - begin;
|
||||
memcpy(domain + 1, begin, len);
|
||||
|
||||
|
||||
/* add dot for subdomain */
|
||||
domain[0] = '.';
|
||||
len++;
|
||||
@@ -306,9 +307,113 @@ int config_rr_ttl_max(char *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_bogus_nxdomain_exists(unsigned char *ip, dns_type_t addr_type)
|
||||
{
|
||||
uint32_t key = 0;
|
||||
struct dns_bogus_ip_address *ip_addr = NULL;
|
||||
int addr_len = 0;
|
||||
|
||||
if (addr_type == DNS_T_A) {
|
||||
addr_len = 4;
|
||||
} else if (addr_type == DNS_T_AAAA) {
|
||||
addr_len = 16;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
key = jhash(ip, addr_len, 0);
|
||||
hash_for_each_possible(dns_conf_bogus_nxdomain.ip_hash, ip_addr, node, key)
|
||||
{
|
||||
if (addr_type == DNS_T_A) {
|
||||
if (memcmp(ip_addr->ipv4_addr, ip, addr_len) == 0) {
|
||||
return 0;
|
||||
}
|
||||
} else if (addr_type == DNS_T_AAAA) {
|
||||
if (memcmp(ip_addr->ipv6_addr, ip, addr_len) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void conf_bogus_nxdomain_destroy(void)
|
||||
{
|
||||
struct dns_bogus_ip_address *ip_addr = NULL;
|
||||
struct hlist_node *tmp = NULL;
|
||||
int i;
|
||||
|
||||
hash_for_each_safe(dns_conf_bogus_nxdomain.ip_hash, i, tmp, ip_addr, node)
|
||||
{
|
||||
hlist_del_init(&ip_addr->node);
|
||||
free(ip_addr);
|
||||
}
|
||||
}
|
||||
|
||||
int conf_bogus_nxdomain(char *value)
|
||||
{
|
||||
struct dns_bogus_ip_address *ip_addr = NULL;
|
||||
char ip[MAX_IP_LEN];
|
||||
int port;
|
||||
int ret = -1;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
uint32_t key;
|
||||
|
||||
ip_addr = malloc(sizeof(*ip_addr));
|
||||
if (ip_addr == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
memset(ip_addr, 0, sizeof(*ip_addr));
|
||||
|
||||
if (parse_ip(value, ip, &port) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
switch (addr.ss_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *addr_in;
|
||||
addr_in = (struct sockaddr_in *)&addr;
|
||||
memcpy(ip_addr->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
||||
ip_addr->addr_type = DNS_T_A;
|
||||
addr_len = 4;
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *addr_in6;
|
||||
addr_in6 = (struct sockaddr_in6 *)&addr;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||
memcpy(ip_addr->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
||||
ip_addr->addr_type = DNS_T_A;
|
||||
addr_len = 4;
|
||||
} else {
|
||||
memcpy(ip_addr->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
||||
addr_len = 16;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (dns_bogus_nxdomain_exists(ip_addr->addr, ip_addr->addr_type) == 0) {
|
||||
ret = 0;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
key = jhash(ip_addr->addr, addr_len, 0);
|
||||
hash_add(dns_conf_bogus_nxdomain.ip_hash, &ip_addr->node, key);
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
if (ip_addr) {
|
||||
free(ip_addr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int config_addtional_file(char *value)
|
||||
@@ -323,7 +428,6 @@ int config_addtional_file(char *value)
|
||||
return load_conf_file(file_path);
|
||||
}
|
||||
|
||||
|
||||
struct config_item {
|
||||
const char *item;
|
||||
int (*item_func)(char *value);
|
||||
@@ -344,7 +448,7 @@ struct config_item config_item[] = {
|
||||
{"rr-ttl", config_rr_ttl},
|
||||
{"rr-ttl-min", config_rr_ttl_min},
|
||||
{"rr-ttl-max", config_rr_ttl_max},
|
||||
{"bogus-nxdomain", conf_bogus_nxdomain},
|
||||
{"bogus-nxdomain", conf_bogus_nxdomain},
|
||||
{"conf-file", config_addtional_file},
|
||||
};
|
||||
int config_item_num = sizeof(config_item) / sizeof(struct config_item);
|
||||
@@ -352,12 +456,13 @@ int config_item_num = sizeof(config_item) / sizeof(struct config_item);
|
||||
int load_conf_init(void)
|
||||
{
|
||||
art_tree_init(&dns_conf_address);
|
||||
|
||||
hash_init(dns_conf_bogus_nxdomain.ip_hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void load_exit(void)
|
||||
{
|
||||
conf_bogus_nxdomain_destroy();
|
||||
config_address_destroy();
|
||||
}
|
||||
|
||||
|
||||
20
src/conf.h
20
src/conf.h
@@ -5,6 +5,8 @@
|
||||
#include "art.h"
|
||||
#include "dns.h"
|
||||
#include "dns_client.h"
|
||||
#include "hash.h"
|
||||
#include "hashtable.h"
|
||||
|
||||
#define DNS_MAX_SERVERS 32
|
||||
#define DNS_MAX_IPLEN 64
|
||||
@@ -27,11 +29,28 @@ struct dns_address {
|
||||
};
|
||||
};
|
||||
|
||||
/* ip address lists of domain */
|
||||
struct dns_bogus_ip_address {
|
||||
struct hlist_node node;
|
||||
dns_type_t addr_type;
|
||||
union {
|
||||
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
||||
unsigned char ipv6_addr[DNS_RR_AAAA_LEN];
|
||||
unsigned char addr[0];
|
||||
};
|
||||
};
|
||||
|
||||
struct dns_bogus_nxdomain {
|
||||
DECLARE_HASHTABLE(ip_hash, 12);
|
||||
};
|
||||
|
||||
extern char dns_conf_server_ip[DNS_MAX_IPLEN];
|
||||
extern int dns_conf_cachesize;
|
||||
extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
|
||||
extern int dns_conf_server_num;
|
||||
|
||||
extern struct dns_bogus_nxdomain dns_conf_bogus_nxdomain;
|
||||
|
||||
extern int dns_conf_log_level;
|
||||
extern char dns_conf_log_file[DNS_MAX_PATH];
|
||||
extern int dns_conf_log_size;
|
||||
@@ -44,6 +63,7 @@ extern int dns_conf_rr_ttl;
|
||||
extern int dns_conf_rr_ttl_min;
|
||||
extern int dns_conf_rr_ttl_max;
|
||||
|
||||
int dns_bogus_nxdomain_exists(unsigned char *ip, dns_type_t addr_type);
|
||||
|
||||
int load_conf(const char *file);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ void dns_cache_release(struct dns_cache *dns_cache)
|
||||
|
||||
int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len)
|
||||
{
|
||||
unsigned int key = 0;
|
||||
uint32_t key = 0;
|
||||
struct dns_cache *dns_cache = NULL;
|
||||
|
||||
if (dns_cache_head.size <= 0) {
|
||||
@@ -120,7 +120,7 @@ errout:
|
||||
|
||||
struct dns_cache *dns_cache_get(char *domain, dns_type_t qtype)
|
||||
{
|
||||
unsigned int key = 0;
|
||||
uint32_t key = 0;
|
||||
struct dns_cache *dns_cache = NULL;
|
||||
struct dns_cache *dns_cache_ret = NULL;
|
||||
time_t now;
|
||||
|
||||
@@ -492,7 +492,7 @@ static struct dns_query_struct *_dns_client_get_request(unsigned short sid, char
|
||||
struct dns_query_struct *query = NULL;
|
||||
struct dns_query_struct *query_result = NULL;
|
||||
struct hlist_node *tmp = NULL;
|
||||
unsigned int key;
|
||||
uint32_t key;
|
||||
|
||||
/* get query by hash key : id + domain */
|
||||
key = hash_string(domain);
|
||||
@@ -518,7 +518,7 @@ static struct dns_query_struct *_dns_client_get_request(unsigned short sid, char
|
||||
|
||||
int _dns_replied_check_add(struct dns_query_struct *dns_query, struct sockaddr *addr, socklen_t addr_len)
|
||||
{
|
||||
int key = 0;
|
||||
uint32_t key = 0;
|
||||
struct dns_query_replied *replied_map = NULL;
|
||||
|
||||
if (addr_len > sizeof(struct sockaddr_in6)) {
|
||||
@@ -1068,7 +1068,7 @@ int dns_client_query(char *domain, int qtype, dns_client_callback callback, void
|
||||
{
|
||||
struct dns_query_struct *query = NULL;
|
||||
int ret = 0;
|
||||
unsigned int key = 0;
|
||||
uint32_t key = 0;
|
||||
|
||||
query = malloc(sizeof(*query));
|
||||
if (query == NULL) {
|
||||
|
||||
@@ -441,7 +441,7 @@ int _dns_server_ping(struct dns_request *request, char *ip)
|
||||
|
||||
int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr, dns_type_t addr_type)
|
||||
{
|
||||
int key = 0;
|
||||
uint32_t key = 0;
|
||||
struct dns_ip_address *addr_map = NULL;
|
||||
int addr_len = 0;
|
||||
|
||||
@@ -499,6 +499,22 @@ static int _dns_server_get_conf_ttl(int ttl)
|
||||
return ttl;
|
||||
}
|
||||
|
||||
static int _dns_server_bogus_nxdomain_exists(struct dns_request *request, unsigned char *ip, dns_type_t addr_type)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = dns_bogus_nxdomain_exists(ip, addr_type);
|
||||
if (ret != 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (request->rcode == DNS_RC_SERVFAIL) {
|
||||
request->rcode = DNS_RC_NXDOMAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet)
|
||||
{
|
||||
int ttl;
|
||||
@@ -517,8 +533,6 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
||||
return -1;
|
||||
}
|
||||
|
||||
request->rcode = packet->head.rcode;
|
||||
|
||||
for (j = 1; j < DNS_RRS_END; j++) {
|
||||
rrs = dns_get_rrs_start(packet, j, &rr_count);
|
||||
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
|
||||
@@ -534,6 +548,13 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
||||
|
||||
tlog(TLOG_DEBUG, "domain: %s TTL:%d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
|
||||
|
||||
/* bogus ip address, skip */
|
||||
if (_dns_server_bogus_nxdomain_exists(request, addr, DNS_T_A) == 0) {
|
||||
_dns_server_request_release(request);
|
||||
tlog(TLOG_DEBUG, "bogus-nxdomain: %s TTL:%d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
break;
|
||||
@@ -560,6 +581,8 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
||||
_dns_server_request_release(request);
|
||||
break;
|
||||
}
|
||||
|
||||
request->rcode = packet->head.rcode;
|
||||
sprintf(ip, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
|
||||
|
||||
if (_dns_server_ping(request, ip) != 0) {
|
||||
@@ -577,6 +600,16 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
||||
|
||||
tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", name, ttl, addr[0], addr[1],
|
||||
addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
|
||||
/* bogus ip address, skip */
|
||||
if (_dns_server_bogus_nxdomain_exists(request, addr, DNS_T_AAAA) == 0) {
|
||||
_dns_server_request_release(request);
|
||||
tlog(TLOG_DEBUG, "bogus-nxdomain: %s TTL: %d IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", name, ttl, addr[0], addr[1],
|
||||
addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
break;
|
||||
@@ -597,6 +630,8 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
||||
break;
|
||||
}
|
||||
|
||||
request->rcode = packet->head.rcode;
|
||||
|
||||
sprintf(ip, "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
|
||||
addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user