Compare commits

...

10 Commits

Author SHA1 Message Date
Nick Peng
80cb27c795 tlog: update tlog 2020-08-22 08:13:55 +08:00
Kevin Zhou
cb73eadf01 Make the ipset working as expected when the domain passthrough 2020-08-22 07:57:00 +08:00
Nick Peng
69ba3f8789 pending: fix pending server resolve issue 2020-08-16 17:05:51 +08:00
Nick Peng
c380bbe0e3 tlog: update tlog 2020-08-13 01:23:40 +08:00
Nick Peng
da74e877c5 dns_client: repeat same arguments with SSL_write 2020-08-13 00:56:51 +08:00
Nick Peng
a300873b3f dns-client: fix ssl send request issue 2020-08-11 00:09:38 +08:00
Nick Peng
a9829f6155 dns-server: fix race condition issue 2020-08-09 23:54:23 +08:00
Nick Peng
1923271630 compile: fix comile warnings 2020-08-09 18:01:33 +08:00
Nick Peng
c23ec7ea8f client: suppress log. 2020-08-03 01:07:47 +08:00
rhettor
aad751c1f5 Support docker 2020-08-02 18:10:31 +08:00
8 changed files with 330 additions and 55 deletions

18
Dockerfile Normal file
View File

@@ -0,0 +1,18 @@
FROM debian:buster-slim
RUN apt update && \
apt install -y git make gcc libssl-dev && \
git clone https://github.com/pymumu/smartdns.git --depth 1 && \
cd smartdns && \
sh ./package/build-pkg.sh --platform debian --arch `dpkg --print-architecture` && \
dpkg -i package/*.deb && \
cd / && \
rm -rf smartdns/ && \
apt autoremove -y git make gcc libssl-dev && \
apt clean && \
rm -rf /var/lib/apt/lists/*
EXPOSE 53/udp
VOLUME "/etc/smartdns/"
CMD ["/usr/sbin/smartdns", "-f"]

View File

@@ -110,7 +110,7 @@ struct dns_head {
unsigned short ancount; /* number of answer entries */
unsigned short nscount; /* number of authority entries */
unsigned short nrcount; /* number of addititional resource entries */
} __attribute__((packed));
} __attribute__((packed, aligned(2)));
struct dns_rrs {
unsigned short next;

View File

@@ -105,6 +105,7 @@ struct dns_server_info {
int ttl;
int ttl_range;
SSL *ssl;
int ssl_write_len;
SSL_CTX *ssl_ctx;
SSL_SESSION *ssl_session;
char skip_check_cert;
@@ -860,7 +861,8 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
}
SSL_CTX_set_options(server_info->ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
SSL_CTX_set_session_cache_mode(server_info->ssl_ctx, SSL_SESS_CACHE_CLIENT);
SSL_CTX_sess_set_cache_size(server_info->ssl_ctx, 64);
if (_dns_client_set_trusted_cert(server_info->ssl_ctx) != 0) {
tlog(TLOG_WARN, "disable check certificate for %s.", server_info->ip);
server_info->skip_check_cert = 1;
@@ -932,9 +934,12 @@ static void _dns_client_close_socket(struct dns_server_info *server_info)
if (server_info->ssl) {
/* Shutdown ssl */
SSL_shutdown(server_info->ssl);
if (server_info->status == DNS_SERVER_STATUS_CONNECTED) {
SSL_shutdown(server_info->ssl);
}
SSL_free(server_info->ssl);
server_info->ssl = NULL;
server_info->ssl_write_len = -1;
}
/* remove fd from epoll */
@@ -949,6 +954,36 @@ static void _dns_client_close_socket(struct dns_server_info *server_info)
tlog(TLOG_DEBUG, "server %s closed.", server_info->ip);
}
static void _dns_client_shutdown_socket(struct dns_server_info *server_info)
{
if (server_info->fd <= 0) {
return;
}
switch (server_info->type) {
case DNS_SERVER_UDP:
return;
break;
case DNS_SERVER_TCP:
if (server_info->fd > 0) {
shutdown(server_info->fd, SHUT_RDWR);
}
break;
case DNS_SERVER_TLS:
case DNS_SERVER_HTTPS:
if (server_info->ssl) {
/* Shutdown ssl */
if (server_info->status == DNS_SERVER_STATUS_CONNECTED) {
SSL_shutdown(server_info->ssl);
}
shutdown(server_info->fd, SHUT_RDWR);
}
break;
default:
break;
}
}
static void _dns_client_server_close(struct dns_server_info *server_info)
{
/* stop ping task */
@@ -1513,6 +1548,11 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
set_sock_keepalive(fd, 15, 3, 4);
if (connect(fd, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen) != 0) {
if (errno == ENETUNREACH) {
tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
goto errout;
}
if (errno != EINPROGRESS) {
tlog(TLOG_ERROR, "connect %s failed, %s", server_info->ip, strerror(errno));
goto errout;
@@ -1585,6 +1625,11 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, ch
setsockopt(fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
if (connect(fd, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen) != 0) {
if (errno == ENETUNREACH) {
tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
goto errout;
}
if (errno != EINPROGRESS) {
tlog(TLOG_ERROR, "connect %s failed, %s", server_info->ip, strerror(errno));
goto errout;
@@ -1617,6 +1662,7 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, ch
server_info->fd = fd;
server_info->ssl = ssl;
server_info->ssl_write_len = -1;
server_info->status = DNS_SERVER_STATUS_CONNECTING;
tlog(TLOG_DEBUG, "tls server %s connecting.\n", server_info->ip);
@@ -1628,7 +1674,6 @@ errout:
}
if (ssl) {
SSL_shutdown(ssl);
SSL_free(ssl);
}
@@ -1729,11 +1774,12 @@ static int _dns_client_socket_ssl_send(SSL *ssl, const void *buf, int num)
unsigned long ssl_err = 0;
if (ssl == NULL) {
errno = EINVAL;
return -1;
}
ret = SSL_write(ssl, buf, num);
if (ret >= 0) {
if (ret > 0) {
return ret;
}
@@ -1742,6 +1788,7 @@ static int _dns_client_socket_ssl_send(SSL *ssl, const void *buf, int num)
case SSL_ERROR_NONE:
return 0;
break;
case SSL_ERROR_ZERO_RETURN:
case SSL_ERROR_WANT_READ:
errno = EAGAIN;
ret = -1;
@@ -1752,12 +1799,15 @@ static int _dns_client_socket_ssl_send(SSL *ssl, const void *buf, int num)
break;
case SSL_ERROR_SSL:
ssl_err = ERR_get_error();
if (ERR_GET_REASON(ssl_err) == SSL_R_UNINITIALIZED || ERR_GET_REASON(ssl_err) == SSL_R_PROTOCOL_IS_SHUTDOWN) {
int ssl_reason = ERR_GET_REASON(ssl_err);
if (ssl_reason == SSL_R_UNINITIALIZED || ssl_reason == SSL_R_PROTOCOL_IS_SHUTDOWN ||
ssl_reason == SSL_R_BAD_LENGTH || ssl_reason == SSL_R_SHUTDOWN_WHILE_IN_INIT ||
ssl_reason == SSL_R_BAD_WRITE_RETRY) {
errno = EAGAIN;
return -1;
}
tlog(TLOG_DEBUG, "SSL write fail error no: %s(%ld)\n", ERR_reason_error_string(ssl_err), ssl_err);
tlog(TLOG_ERROR, "SSL write fail error no: %s(%d)\n", ERR_reason_error_string(ssl_err), ssl_reason);
errno = EFAULT;
ret = -1;
break;
@@ -1792,8 +1842,6 @@ static int _dns_client_socket_ssl_recv(SSL *ssl, void *buf, int num)
ssl_ret = SSL_get_error(ssl, ret);
switch (ssl_ret) {
case SSL_ERROR_NONE:
return 0;
break;
case SSL_ERROR_ZERO_RETURN:
return 0;
break;
@@ -1807,16 +1855,25 @@ static int _dns_client_socket_ssl_recv(SSL *ssl, void *buf, int num)
break;
case SSL_ERROR_SSL:
ssl_err = ERR_get_error();
if (ERR_GET_REASON(ssl_err) == SSL_R_UNINITIALIZED) {
int ssl_reason = ERR_GET_REASON(ssl_err);
if (ssl_reason == SSL_R_UNINITIALIZED) {
errno = EAGAIN;
return -1;
}
tlog(TLOG_ERROR, "SSL read fail error no: %s(%ld)\n", ERR_reason_error_string(ssl_err), ssl_err);
if (ssl_reason == SSL_R_SHUTDOWN_WHILE_IN_INIT || ssl_reason == SSL_R_PROTOCOL_IS_SHUTDOWN) {
return 0;
}
tlog(TLOG_ERROR, "SSL read fail error no: %s(%lx)\n", ERR_reason_error_string(ssl_err), ssl_err);
errno = EFAULT;
ret = -1;
break;
case SSL_ERROR_SYSCALL:
if (errno == 0) {
return 0;
}
if (errno != ECONNRESET) {
tlog(TLOG_INFO, "SSL syscall failed, %s ", strerror(errno));
}
@@ -1838,7 +1895,18 @@ static int _dns_client_socket_send(struct dns_server_info *server_info)
} else if (server_info->type == DNS_SERVER_TCP) {
return send(server_info->fd, server_info->send_buff.data, server_info->send_buff.len, MSG_NOSIGNAL);
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
return _dns_client_socket_ssl_send(server_info->ssl, server_info->send_buff.data, server_info->send_buff.len);
int write_len = server_info->send_buff.len;
if (server_info->ssl_write_len > 0) {
write_len = server_info->ssl_write_len;
server_info->ssl_write_len = -1;
}
int ret = _dns_client_socket_ssl_send(server_info->ssl, server_info->send_buff.data, write_len);
if (ret != 0) {
if (errno == EAGAIN) {
server_info->ssl_write_len = write_len;
}
}
return ret;
} else {
return -1;
}
@@ -2099,11 +2167,31 @@ static int _dns_client_tls_matchName(const char *host, const char *pattern, int
return match;
}
static int _dns_client_tls_get_cert_CN(X509 *cert, char *cn, int max_cn_len)
{
X509_NAME *cert_name = NULL;
cert_name = X509_get_subject_name(cert);
if (cert_name == NULL) {
tlog(TLOG_ERROR, "get subject name failed.");
goto errout;
}
if (X509_NAME_get_text_by_NID(cert_name, NID_commonName, cn, max_cn_len) == -1) {
tlog(TLOG_ERROR, "cannot found x509 name");
goto errout;
}
return 0;
errout:
return -1;
}
static int _dns_client_tls_verify(struct dns_server_info *server_info)
{
X509 *cert = NULL;
X509_PUBKEY *pubkey = NULL;
X509_NAME *cert_name = NULL;
char peer_CN[256];
char cert_fingerprint[256];
int i = 0;
@@ -2127,24 +2215,20 @@ static int _dns_client_tls_verify(struct dns_server_info *server_info)
if (server_info->skip_check_cert == 0) {
long res = SSL_get_verify_result(server_info->ssl);
if (res != X509_V_OK) {
tlog(TLOG_WARN, "peer server certificate verify failed.");
peer_CN[0] = '\0';
_dns_client_tls_get_cert_CN(cert, peer_CN, sizeof(peer_CN));
tlog(TLOG_WARN, "peer server %s certificate verify failed", server_info->ip);
tlog(TLOG_WARN, "peer CN: %s", peer_CN);
goto errout;
}
}
cert_name = X509_get_subject_name(cert);
if (cert_name == NULL) {
tlog(TLOG_ERROR, "get subject name failed.");
goto errout;
}
if (X509_NAME_get_text_by_NID(cert_name, NID_commonName, peer_CN, 256) == -1) {
tlog(TLOG_ERROR, "cannot found x509 name");
if (_dns_client_tls_get_cert_CN(cert, peer_CN, sizeof(peer_CN)) != 0) {
tlog(TLOG_ERROR, "get cert CN failed.");
goto errout;
}
tlog(TLOG_DEBUG, "peer CN: %s", peer_CN);
/* check tls host */
tls_host_verify = _dns_client_server_get_tls_host_verify(server_info);
if (tls_host_verify) {
@@ -2247,10 +2331,16 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
fd_event.events = EPOLLIN;
} else if (ssl_ret == SSL_ERROR_WANT_WRITE) {
fd_event.events = EPOLLOUT | EPOLLIN;
} else if (ssl_ret == SSL_ERROR_SYSCALL) {
if (errno != ENETUNREACH) {
tlog(TLOG_WARN, "Handshake with %s failed, %s", server_info->ip, strerror(errno));
}
goto errout;
} else {
unsigned long ssl_err = ERR_get_error();
tlog(TLOG_ERROR, "Handshake with %s failed, error no: %s(%ld)\n", server_info->ip,
ERR_reason_error_string(ssl_err), ssl_err);
int ssl_reason = ERR_GET_REASON(ssl_err);
tlog(TLOG_WARN, "Handshake with %s failed, error no: %s(%d, %d, %d)\n", server_info->ip,
ERR_reason_error_string(ssl_err), ret, ssl_ret, ssl_reason);
goto errout;
}
@@ -2289,7 +2379,7 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
server_info->status = DNS_SERVER_STATUS_CONNECTED;
memset(&fd_event, 0, sizeof(fd_event));
fd_event.events = EPOLLIN;
fd_event.events = EPOLLIN | EPOLLOUT;
fd_event.data.ptr = server_info;
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_MOD, server_info->fd, &fd_event) != 0) {
tlog(TLOG_ERROR, "epoll ctl failed, %s", strerror(errno));
@@ -2430,16 +2520,17 @@ static int _dns_client_send_tls(struct dns_server_info *server_info, void *packe
}
if (server_info->ssl == NULL) {
errno = EINVAL;
return -1;
}
send_len = _dns_client_socket_ssl_send(server_info->ssl, inpacket, len);
if (send_len < 0) {
if (send_len <= 0) {
if (errno == EAGAIN || errno == EPIPE || server_info->ssl == NULL) {
/* save data to buffer, and retry when EPOLLOUT is available */
return _dns_client_send_data_to_buffer(server_info, inpacket, len);
} else if (server_info->ssl && errno != ENOMEM) {
SSL_set_shutdown(server_info->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
SSL_shutdown(server_info->ssl);
}
return -1;
} else if (send_len < len) {
@@ -2480,11 +2571,12 @@ static int _dns_client_send_https(struct dns_server_info *server_info, void *pac
}
if (server_info->ssl == NULL) {
errno = EINVAL;
return -1;
}
send_len = _dns_client_socket_ssl_send(server_info->ssl, inpacket, http_len);
if (send_len < 0) {
if (send_len <= 0) {
if (errno == EAGAIN || errno == EPIPE || server_info->ssl == NULL) {
/* save data to buffer, and retry when EPOLLOUT is available */
return _dns_client_send_data_to_buffer(server_info, inpacket, http_len);
@@ -2507,11 +2599,12 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
struct dns_server_group_member *tmp = NULL;
int ret = 0;
int send_err = 0;
int i = 0;
query->send_tick = get_tick_count();
/* send query to all dns servers */
for (int i = 0; i < 2; i++) {
for (i = 0; i < 2; i++) {
pthread_mutex_lock(&client.server_list_lock);
list_for_each_entry_safe(group_member, tmp, &query->server_group->head, list)
{
@@ -2552,21 +2645,22 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
}
if (ret != 0) {
if (send_err != ENOMEM) {
tlog(TLOG_ERROR, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err),
server_info->type);
} else {
if (send_err == ENETUNREACH) {
tlog(TLOG_DEBUG, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err),
server_info->type);
time_t now;
time(&now);
if (now - 5 > server_info->last_recv) {
server_info->recv_buff.len = 0;
server_info->send_buff.len = 0;
tlog(TLOG_DEBUG, "server %s not response, retry.", server_info->ip);
_dns_client_close_socket(server_info);
}
_dns_client_close_socket(server_info);
atomic_dec(&query->dns_request_sent);
continue;
}
tlog(TLOG_DEBUG, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err),
server_info->type);
time_t now;
time(&now);
if (now - 5 > server_info->last_recv || send_err != ENOMEM) {
_dns_client_shutdown_socket(server_info);
}
atomic_dec(&query->dns_request_sent);
continue;
}
@@ -2838,7 +2932,6 @@ static void _dns_client_add_pending_servers(void)
/* if both A, AAAA has query result, select fastest IP address */
if (pending->has_v4 && pending->has_v6) {
if (pending->ping_time_v4 <= pending->ping_time_v6 && pending->ipv4[0]) {
dnsserver_ip = pending->ipv4;
} else {

View File

@@ -262,6 +262,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
return -1;
}
ip = argv[1];
if (index >= DNS_MAX_SERVERS) {
tlog(TLOG_WARN, "exceeds max server number, %s", ip);
return 0;
@@ -274,8 +275,6 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
server->httphost[0] = '\0';
server->tls_host_verify[0] = '\0';
ip = argv[1];
if (type == DNS_SERVER_HTTPS) {
if (parse_uri(ip, NULL, server->server, &port, server->path) != 0) {
return -1;
@@ -871,6 +870,7 @@ static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
goto errout;
}
ip = argv[1];
if (index >= DNS_MAX_SERVERS) {
tlog(TLOG_WARN, "exceeds max server number, %s", ip);
return 0;
@@ -879,7 +879,6 @@ static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
bind_ip = &dns_conf_bind_ip[index];
bind_ip->type = type;
bind_ip->flags = 0;
ip = argv[1];
safe_strncpy(bind_ip->ip, ip, DNS_MAX_IPLEN);
/* process extra options */

View File

@@ -880,6 +880,7 @@ static void _dns_server_select_possible_ipaddress(struct dns_request *request)
/* Return the most likely correct IP address */
/* Returns the IP with the most hits, or the last returned record is considered to be the most likely correct. */
pthread_mutex_lock(&request->ip_map_lock);
hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
{
if (addr_map->addr_type != request->qtype) {
@@ -896,6 +897,7 @@ static void _dns_server_select_possible_ipaddress(struct dns_request *request)
maxhit_addr_map = addr_map;
}
}
pthread_mutex_unlock(&request->ip_map_lock);
if (maxhit_addr_map && maxhit > 1) {
selected_addr_map = maxhit_addr_map;
@@ -966,11 +968,13 @@ static void _dns_server_request_release_complete(struct dns_request *request, in
_dns_server_request_complete(request);
}
pthread_mutex_lock(&request->ip_map_lock);
hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
{
hash_del(&addr_map->node);
free(addr_map);
}
pthread_mutex_unlock(&request->ip_map_lock);
_dns_server_delete_request(request);
}
@@ -1627,15 +1631,106 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, char
return -1;
}
static int _dns_server_get_answer(struct dns_request *request, struct dns_packet *packet)
{
int i = 0;
int j = 0;
int ttl = 0;
struct dns_rrs *rrs = NULL;
int rr_count = 0;
char name[DNS_MAX_CNAME_LEN] = {0};
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)) {
switch (rrs->type) {
case DNS_T_A: {
unsigned char addr[4];
char name[DNS_MAX_CNAME_LEN] = {0};
if (request->qtype != DNS_T_A) {
continue;
}
/* get A result */
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
memcpy(request->ipv4_addr, addr, DNS_RR_A_LEN);
request->ttl_v4 = _dns_server_get_conf_ttl(ttl);
request->has_ipv4 = 1;
request->rcode = packet->head.rcode;
} break;
case DNS_T_AAAA: {
unsigned char addr[16];
char name[DNS_MAX_CNAME_LEN] = {0};
if (request->qtype != DNS_T_AAAA) {
/* ignore non-matched query type */
continue;
}
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
memcpy(request->ipv6_addr, addr, DNS_RR_AAAA_LEN);
request->ttl_v6 = _dns_server_get_conf_ttl(ttl);
request->has_ipv6 = 1;
request->rcode = packet->head.rcode;
} break;
case DNS_T_NS: {
char cname[DNS_MAX_CNAME_LEN];
dns_get_CNAME(rrs, name, DNS_MAX_CNAME_LEN, &ttl, cname, DNS_MAX_CNAME_LEN);
tlog(TLOG_DEBUG, "NS: %s ttl:%d cname: %s\n", name, ttl, cname);
} break;
case DNS_T_CNAME: {
char cname[DNS_MAX_CNAME_LEN];
dns_get_CNAME(rrs, name, DNS_MAX_CNAME_LEN, &ttl, cname, DNS_MAX_CNAME_LEN);
tlog(TLOG_DEBUG, "name:%s ttl: %d cname: %s\n", name, ttl, cname);
safe_strncpy(request->cname, cname, DNS_MAX_CNAME_LEN);
request->ttl_cname = ttl;
request->has_cname = 1;
} break;
case DNS_T_SOA: {
request->has_soa = 1;
request->rcode = packet->head.rcode;
dns_get_SOA(rrs, name, 128, &ttl, &request->soa);
tlog(TLOG_DEBUG,
"domain: %s, qtype: %d, SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: "
"%d, minimum: %d",
request->domain, request->qtype, request->soa.mname, request->soa.rname, request->soa.serial,
request->soa.refresh, request->soa.retry, request->soa.expire, request->soa.minimum);
if (atomic_inc_return(&request->soa_num) >= (dns_server_num() / 2)) {
_dns_server_request_complete(request);
}
} break;
default:
tlog(TLOG_DEBUG, "%s, qtype: %d", name, rrs->type);
break;
}
}
}
return 0;
}
static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns_packet *packet,
unsigned char *inpacket, int inpacket_len)
{
int ttl;
char name[DNS_MAX_CNAME_LEN] = {0};
int rr_count;
int i = 0;
int j = 0;
struct dns_rrs *rrs = NULL;
struct dns_ipset_rule *ipset_rule = NULL;
struct dns_rule_flags *rule_flags = NULL;
int ret = 0;
if (atomic_inc_return(&request->notified) != 1) {
return 0;
}
if (request->result_callback) {
_dns_server_get_answer(request, packet);
_dns_result_callback(request);
}
if (request->conn == NULL) {
return 0;
}
@@ -1644,6 +1739,74 @@ static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns
dns_server_update_reply_packet_id(request, inpacket, inpacket_len);
ret = _dns_reply_inpacket(request, inpacket, inpacket_len);
if (packet->head.rcode != DNS_RC_NOERROR && packet->head.rcode != DNS_RC_NXDOMAIN) {
return ret;
}
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_RULE_IPSET) == 0) {
return ret;
}
/* check ipset rule */
rule_flags = request->domain_rule.rules[DOMAIN_RULE_FLAGS];
if (rule_flags) {
if (rule_flags->flags & DOMAIN_FLAG_IPSET_IGNORE) {
return ret;
}
}
ipset_rule = request->domain_rule.rules[DOMAIN_RULE_IPSET];
if (ipset_rule == NULL) {
return ret;
}
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)) {
switch (rrs->type) {
case DNS_T_A: {
unsigned char addr[4];
if (request->qtype != DNS_T_A) {
/* ignore non-matched query type */
if (request->dualstack_selection == 0) {
break;
}
}
/* get A result */
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
/* add IPV4 to ipset */
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
tlog(TLOG_DEBUG, "IPSET-MATCH-PASSTHROUTH: domain: %s, ipset: %s, IP: %d.%d.%d.%d",
request->domain, ipset_rule->ipsetname, addr[0], addr[1], addr[2], addr[3]);
} break;
case DNS_T_AAAA: {
unsigned char addr[16];
if (request->qtype != DNS_T_AAAA) {
/* ignore non-matched query type */
break;
}
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
/* add IPV6 to ipset */
if (request->has_ipv6) {
if (request->has_ipv4) {
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
}
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_AAAA_LEN, request->ttl_v6 * 2);
}
tlog(TLOG_DEBUG, "IPSET-MATCH-PASSTHROUTH: domain: %s, ipset: %s, IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
request->domain, ipset_rule->ipsetname, 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;
default:
break;
}
}
}
return ret;
}
@@ -1669,7 +1832,6 @@ static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsi
return _dns_server_reply_passthrouth(request, packet, inpacket, inpacket_len);
}
_dns_server_process_answer(request, domain, packet, result_flag);
return 0;
} else if (rtype == DNS_QUERY_ERR) {
@@ -2009,7 +2171,7 @@ errout:
return -1;
}
static void _dns_server_prolcess_speed_check_rule(struct dns_request *request)
static void _dns_server_process_speed_check_rule(struct dns_request *request)
{
struct dns_domain_check_order *check_order = NULL;
@@ -2041,7 +2203,7 @@ static int _dns_server_process_cache(struct dns_request *request)
if (dns_cache_get_ttl(dns_cache_A) == 0) {
_dns_server_prefetch_request(request->domain, request->qtype);
}
ret = _dns_server_reply_SOA(DNS_RC_NOERROR, request);
ret = _dns_server_reply_SOA(DNS_RC_NOERROR, request);
goto out;
}
}
@@ -2257,7 +2419,7 @@ static int _dns_server_do_query(struct dns_request *request, const char *domain,
}
/* process speed check rule */
_dns_server_prolcess_speed_check_rule(request);
_dns_server_process_speed_check_rule(request);
/* check and set passthrough */
_dns_server_check_set_passthrough(request);
@@ -2435,6 +2597,7 @@ int dns_server_query(char *domain, int qtype, dns_result_callback callback, void
return ret;
errout:
if (request) {
_dns_server_request_set_callback(request, NULL, NULL);
_dns_server_request_release(request);
}
@@ -3069,7 +3232,7 @@ static int _dns_create_socket(const char *host_ip, int type)
setsockopt(fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
if (bind(fd, gai->ai_addr, gai->ai_addrlen) != 0) {
tlog(TLOG_ERROR, "bind service failed, %s\n", strerror(errno));
tlog(TLOG_ERROR, "bind service %s failed, %s\n", host_ip, strerror(errno));
goto errout;
}

View File

@@ -439,6 +439,7 @@ int main(int argc, char *argv[])
goto errout;
}
signal(SIGPIPE, SIG_IGN);
if (dns_server_load_conf(config_file) != 0) {
fprintf(stderr, "load config failed.\n");
goto errout;
@@ -451,7 +452,6 @@ int main(int argc, char *argv[])
}
signal(SIGINT, _sig_exit);
signal(SIGPIPE, SIG_IGN);
atexit(_smartdns_exit);
return _smartdns_run();

View File

@@ -1,6 +1,6 @@
/*
* tinylog
* Copyright (C) 2018-2019 Nick Peng <pymumu@gmail.com>
* Copyright (C) 2018-2020 Nick Peng <pymumu@gmail.com>
* https://github.com/pymumu/tinylog
*/
#ifndef _GNU_SOURCE
@@ -1377,7 +1377,7 @@ static void *_tlog_work(void *arg)
log = _tlog_wait_log_locked(log);
if (log == NULL) {
pthread_mutex_unlock(&tlog.lock);
if (errno != ETIMEDOUT) {
if (errno != ETIMEDOUT && tlog.run) {
sleep(1);
}
continue;

View File

@@ -1,6 +1,6 @@
/*
* tinylog
* Copyright (C) 2018-2019 Ruilin Peng (Nick) <pymumu@gmail.com>
* Copyright (C) 2018-2020 Ruilin Peng (Nick) <pymumu@gmail.com>
* https://github.com/pymumu/tinylog
*/
@@ -196,6 +196,7 @@ public:
Buffer LogStream(tlog_level level, const char *file, int line, const char *func, void *userptr) {
return Buffer(new Stream, [=](Stream *st) {
tlog_ext(level, file, line, func, userptr, "%s", st->str().c_str());
delete st;
});
}
};
@@ -215,6 +216,7 @@ public:
Buffer Out(tlog_log *log) {
return Buffer(new Stream, [=](Stream *st) {
tlog_printf(log, "%s", st->str().c_str());
delete st;
});
}
};