UDP nat bug-fix

This commit is contained in:
Nick Peng
2018-06-18 14:40:35 +08:00
parent 7b62739c13
commit 2fec5f7e14
5 changed files with 151 additions and 95 deletions

View File

@@ -11,6 +11,7 @@
PATH=/sbin:/bin:/usr/sbin:/usr/bin PATH=/sbin:/bin:/usr/sbin:/usr/bin
. /etc/default/smartdns
SMARTDNS=/usr/sbin/smartdns SMARTDNS=/usr/sbin/smartdns
PIDFILE=/var/run/smartdns.pid PIDFILE=/var/run/smartdns.pid
@@ -18,7 +19,7 @@ test -x $SMARTDNS || exit 5
case $1 in case $1 in
start) start)
$SMARTDNS $JAIL_SHELL_OPTS $SMARTDNS $SMART_DNS_OPTS
while true; do while true; do
if [ -e "$PIDFILE" ]; then if [ -e "$PIDFILE" ]; then
break; break;

View File

@@ -1,19 +1,19 @@
# bind # bind
bind [::]:53 bind [::]:53
cache-size 1024 cache-size 1024
loglevel error loglevel error
#server 8.8.8.8 #server 8.8.8.8
server 114.114.114.114 server 114.114.114.114
server 123.207.137.88 server 123.207.137.88
server 119.29.29.29 server 119.29.29.29
server 223.5.5.5 server 223.5.5.5
#BAU DNS #BAU DNS
server 223.113.97.99 server 223.113.97.99
server 208.67.222.222:5353 server 208.67.222.222:5353
server 202.141.178.13:5353 server 202.141.178.13:5353
#server 77.88.8.8:53 #server 77.88.8.8:53
server 202.141.162.123:53 server 202.141.162.123:53
#server 101.132.183.99:53 #server 101.132.183.99:53

View File

@@ -67,6 +67,9 @@ struct dns_client {
/* client socket */ /* client socket */
int udp; int udp;
time_t last_send;
time_t last_recv;
}; };
/* dns server information */ /* dns server information */
@@ -188,6 +191,7 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ
struct dns_server_info *server_info = NULL; struct dns_server_info *server_info = NULL;
if (_dns_client_server_exist(gai, server_type) == 0) { if (_dns_client_server_exist(gai, server_type) == 0) {
tlog(TLOG_WARN, "server exists.");
goto errout; goto errout;
} }
@@ -206,10 +210,13 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ
memcpy(&server_info->addr, gai->ai_addr, gai->ai_addrlen); memcpy(&server_info->addr, gai->ai_addr, gai->ai_addrlen);
/* start ping task */ /* start ping task */
#if 0
server_info->ping_host = fast_ping_start(server_ip, 0, 60000, 1000, NULL, server_info); server_info->ping_host = fast_ping_start(server_ip, 0, 60000, 1000, NULL, server_info);
if (server_info->ping_host == NULL) { if (server_info->ping_host == NULL) {
tlog(TLOG_ERROR, "start ping failed.");
goto errout; goto errout;
} }
#endif
/* add to list */ /* add to list */
pthread_mutex_lock(&client.server_list_lock); pthread_mutex_lock(&client.server_list_lock);
@@ -236,8 +243,10 @@ void _dns_client_server_remove_all(void)
{ {
list_del(&server_info->list); list_del(&server_info->list);
/* stop ping task */ /* stop ping task */
if (fast_ping_stop(server_info->ping_host) != 0) { if (server_info->ping_host) {
tlog(TLOG_ERROR, "stop ping failed.\n"); if (fast_ping_stop(server_info->ping_host) != 0) {
tlog(TLOG_ERROR, "stop ping failed.\n");
}
} }
free(server_info); free(server_info);
} }
@@ -280,6 +289,7 @@ int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t serv
struct addrinfo *gai = NULL; struct addrinfo *gai = NULL;
if (server_type >= DNS_SERVER_TYPE_END) { if (server_type >= DNS_SERVER_TYPE_END) {
tlog(TLOG_ERROR, "server type is invalid.");
return -1; return -1;
} }
@@ -399,6 +409,107 @@ void _dns_client_query_get(struct dns_query_struct *query)
atomic_inc(&query->refcnt); atomic_inc(&query->refcnt);
} }
static struct addrinfo *_dns_server_getaddr(const char *host, const char *port, int type, int protocol)
{
struct addrinfo hints;
struct addrinfo *result = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = type;
hints.ai_protocol = protocol;
hints.ai_flags = AI_PASSIVE;
if (getaddrinfo(host, port, &hints, &result) != 0) {
tlog(TLOG_ERROR, "get addr info failed. %s\n", strerror(errno));
goto errout;
}
return result;
errout:
if (result) {
freeaddrinfo(result);
}
return NULL;
}
int dns_client_start(void)
{
struct epoll_event event;
memset(&event, 0, sizeof(event));
event.events = EPOLLIN;
event.data.fd = client.udp;
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, client.udp, &event) != 0) {
tlog(TLOG_ERROR, "epoll ctl failed.");
return -1;
}
return 0;
}
int dns_client_socket(void)
{
int fd = -1;
struct addrinfo *gai = NULL;
/* create udp socket */
gai = _dns_server_getaddr(NULL, "53", SOCK_DGRAM, 0);
if (gai == NULL) {
tlog(TLOG_ERROR, "get address failed.\n");
goto errout;
}
fd = socket(gai->ai_family, gai->ai_socktype, gai->ai_protocol);
if (fd < 0) {
tlog(TLOG_ERROR, "create socket failed.\n");
goto errout;
}
client.udp = fd;
freeaddrinfo(gai);
return fd;
errout:
if (fd > 0) {
close(fd);
}
if (gai) {
freeaddrinfo(gai);
}
return -1;
}
void _dns_client_recreate_socket(void)
{
int fd = -1;
int oldfd = client.udp;
pthread_mutex_lock(&client.server_list_lock);
fd = dns_client_socket();
if (fd < 0) {
tlog(TLOG_ERROR, "create socket failed.");
goto errout;
}
if (dns_client_start() != 0) {
tlog(TLOG_ERROR, "start socket failed.");
goto errout;
}
client.udp = fd;
close(oldfd);
pthread_mutex_unlock(&client.server_list_lock);
return;
errout:
if (fd > 0) {
close(fd);
}
client.udp = oldfd;
pthread_mutex_unlock(&client.server_list_lock);
return;
}
void _dns_client_period_run(void) void _dns_client_period_run(void)
{ {
struct dns_query_struct *query, *tmp; struct dns_query_struct *query, *tmp;
@@ -423,7 +534,18 @@ void _dns_client_period_run(void)
list_del_init(&query->period_list); list_del_init(&query->period_list);
_dns_client_query_remove(query); _dns_client_query_remove(query);
_dns_client_query_release(query); _dns_client_query_release(query);
/* For udp nat case.
* when router reconnect to internet, udp port may always marked as UNREPLIED.
* dns query will timeout, and cannot reconnect again,
* create a new socket to communicate.
*/
if (client.last_send - 5 > client.last_recv) {
_dns_client_recreate_socket();
client.last_recv = client.last_send;
}
} }
return; return;
} }
@@ -575,6 +697,7 @@ static int _dns_client_process(struct dns_query_struct *dns_query, unsigned long
tlog(TLOG_DEBUG, "recv from %s", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len)); tlog(TLOG_DEBUG, "recv from %s", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len));
time(&client.last_recv);
if (_dns_client_recv(inpacket, len, &from, from_len) != 0) { if (_dns_client_recv(inpacket, len, &from, from_len) != 0) {
return -1; return -1;
} }
@@ -676,6 +799,7 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
atomic_dec(&query->dns_request_sent); atomic_dec(&query->dns_request_sent);
continue; continue;
} }
time(&client.last_send);
} }
pthread_mutex_unlock(&client.server_list_lock); pthread_mutex_unlock(&client.server_list_lock);
return 0; return 0;
@@ -771,76 +895,6 @@ errout:
return -1; return -1;
} }
static struct addrinfo *_dns_server_getaddr(const char *host, const char *port, int type, int protocol)
{
struct addrinfo hints;
struct addrinfo *result = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = type;
hints.ai_protocol = protocol;
hints.ai_flags = AI_PASSIVE;
if (getaddrinfo(host, port, &hints, &result) != 0) {
tlog(TLOG_ERROR, "get addr info failed. %s\n", strerror(errno));
goto errout;
}
return result;
errout:
if (result) {
freeaddrinfo(result);
}
return NULL;
}
int dns_client_start(void)
{
struct epoll_event event;
memset(&event, 0, sizeof(event));
event.events = EPOLLIN;
event.data.fd = client.udp;
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, client.udp, &event) != 0) {
tlog(TLOG_ERROR, "epoll ctl failed.");
return -1;
}
return 0;
}
int dns_client_socket(void)
{
int fd = -1;
struct addrinfo *gai = NULL;
/* create udp socket */
gai = _dns_server_getaddr(NULL, "53", SOCK_DGRAM, 0);
if (gai == NULL) {
tlog(TLOG_ERROR, "get address failed.\n");
goto errout;
}
fd = socket(gai->ai_family, gai->ai_socktype, gai->ai_protocol);
if (fd < 0) {
tlog(TLOG_ERROR, "create socket failed.\n");
goto errout;
}
client.udp = fd;
freeaddrinfo(gai);
return fd;
errout:
if (fd > 0) {
close(fd);
}
if (gai) {
freeaddrinfo(gai);
}
return -1;
}
int dns_client_init() int dns_client_init()
{ {
pthread_attr_t attr; pthread_attr_t attr;

View File

@@ -1,7 +1,7 @@
/* /*
* Copyright (C) 2018 Ruilin Peng (Nick) <pymumu@gmail.com> * Copyright (C) 2018 Ruilin Peng (Nick) <pymumu@gmail.com>
*/ */
#define _GNU_SOURCE
#include "tlog.h" #include "tlog.h"
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>

View File

@@ -4,10 +4,11 @@ After=network.target
[Service] [Service]
PIDFile=/var/run/smartdns.pid PIDFile=/var/run/smartdns.pid
EnvironmentFile=/etc/default/smartdns EnvironmentFile=-/etc/default/smartdns
ExecStart=/usr/sbin/smartdns $SMART_DNS_OPTS ExecStart=/usr/sbin/smartdns $SMART_DNS_OPTS
KillMode=process KillMode=process
Restart=on-failure Restart=always
RestartSec=0
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target