Compare commits

..

4 Commits

Author SHA1 Message Date
Nick Peng
c5ca3ccf43 luci: add dns64 option 2023-02-21 23:28:17 +08:00
Nick Peng
a6cb6061ec optware: fix optware init script issue 2023-02-21 22:59:50 +08:00
Nick Peng
995d5dce95 dns-client: fix tcp connect timeout issue. 2023-02-21 22:38:55 +08:00
Nick Peng
c21be04632 dns_server: update ttl issue for domain-rule 2023-02-18 21:10:44 +08:00
12 changed files with 235 additions and 53 deletions

View File

@@ -126,7 +126,7 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
1. **高性能、占用资源少**
多线程异步 IO 模式cache 缓存查询结果。
1. **主流系统官方支持**
1. **主流系统官方支持**
主流路由系统官方软件源安装smartdns。
## 架构

View File

@@ -121,7 +121,7 @@ From the comparison, smartdns found the fastest IP address to visit www.baidu.co
1. **High performance, low resource consumption**
Multi-threaded asynchronous IO mode, cache cache query results.
1. **DNS domain forwarding**
1. **DNS domain forwarding**
Support DNS forwarding, ipset and nftables. Support setting the domain result to ipset and nftset set when speed check fails.
## Architecture

View File

@@ -82,6 +82,9 @@ msgstr "协议类型"
msgid "DNS domain result cache size"
msgstr "缓存DNS的结果缓存大小配置零则不缓存"
msgid "DNS64 Server Settings"
msgstr "DNS64服务器配置"
msgid "Description"
msgstr "描述"

View File

@@ -34,6 +34,7 @@ s.anonymous = true
s:tab("settings", translate("General Settings"))
s:tab("advanced", translate('Advanced Settings'))
s:tab("seconddns", translate("Second Server Settings"))
s:tab("dns64", translate("DNS64 Server Settings"))
s:tab("proxy", translate("Proxy Server Settings"))
s:tab("custom", translate("Custom Settings"))
@@ -371,6 +372,12 @@ function o.validate(self, value)
return value
end
----- dns64 server settings
o = s:taboption("dns64", Value, "dns64", translate("DNS64"));
o.placeholder = "64:ff9b::/96"
o.datatype = 'ip6addr'
o.rmempty = true
----- custom settings
custom = s:taboption("custom", Value, "Custom Settings",
translate(""),

View File

@@ -90,6 +90,9 @@ msgstr "协议类型"
msgid "DNS domain result cache size"
msgstr "缓存DNS的结果缓存大小配置零则不缓存"
msgid "DNS64 Server Settings"
msgstr "DNS64服务器配置"
msgid "default"
msgstr "默认"

View File

@@ -131,6 +131,7 @@ return view.extend({
s.tab("settings", _("General Settings"));
s.tab("advanced", _('Advanced Settings'));
s.tab("seconddns", _("Second Server Settings"));
s.tab("dns64", _("DNS64 Server Settings"));
s.tab("files", _("Download Files Setting"), _("Download domain list files for domain-rule and include config files, please refresh the page after download to take effect."));
s.tab("proxy", _("Proxy Server Settings"));
s.tab("custom", _("Custom Settings"));
@@ -430,6 +431,14 @@ return view.extend({
o.rmempty = false;
o.default = o.disabled;
///////////////////////////////////////
// DNS64 Settings
///////////////////////////////////////
o = s.taboption("dns64", form.Value, "dns64", _("DNS64"));
o.placeholder = "64:ff9b::/96";
o.datatype = "ip6addr";
o.rempty = true;
///////////////////////////////////////
// download Files Settings
///////////////////////////////////////

View File

@@ -480,6 +480,7 @@ load_service()
config_get port "$section" "port" "53"
config_get ipv6_server "$section" "ipv6_server" "1"
config_get tcp_server "$section" "tcp_server" "1"
config_get server_flags "$section" "server_flags" ""
config_get speed_check_mode "$section" "speed_check_mode" ""
[ ! -z "$speed_check_mode" ] && conf_append "speed-check-mode" "$speed_check_mode"
@@ -563,6 +564,9 @@ load_service()
config_get proxy_server "$section" "proxy_server" ""
[ -z "$proxy_server" ] || conf_append "proxy-server" "$proxy_server -name default-proxy"
config_get dns64 "$section" "dns64" ""
[ -z "$dns64" ] || conf_append "dns64" "$dns64"
config_get redirect "$section" "redirect" ""
config_get old_port "$section" "old_port" "0"
config_get old_enabled "$section" "old_enabled" "0"
@@ -629,7 +633,7 @@ load_service()
[ "$auto_set_dnsmasq" = "0" ] && [ "$old_auto_set_dnsmasq" = "1" ] && stop_forward_dnsmasq "$old_port" "0"
}
conf_append_bind "$port" "$device" "$tcp_server" "$ipv6_server" "$ARGS"
conf_append_bind "$port" "$device" "$tcp_server" "$ipv6_server" "$server_flags"
load_second_server "$section"

View File

@@ -343,28 +343,28 @@ case "$1" in
$SMARTDNS_BIN -c "$SMARTDNS_CONF" -p $SMARTDNS_PID
if [ $? -ne 0 ]; then
clear_rule
exit 1
fi
;;
status)
pid="$(cat $SMARTDNS_PID |head -n 1 2>/dev/null)"
if [ -z "$pid" ]; then
echo "smartdns not running."
return 0
exit 0
fi
if [ -d "/proc/$pid" ]; then
echo "smartdns running"
return 0;
echo "smartdns is running"
exit 0
fi
echo "smartdns not running."
return 0;
exit 0
;;
stop)
clear_rule
pid="$(cat "$SMARTDNS_PID" | head -n 1 2>/dev/null)"
if [ -z "$pid" ]; then
echo "smartdns not running."
return 0
exit 0
fi
kill -15 "$pid" 2>/dev/null
@@ -379,17 +379,17 @@ case "$1" in
do
pid="$(cat "$SMARTDNS_PID" | head -n 1 2>/dev/null)"
if [ -z "$pid" ]; then
return 0
break
fi
if [ ! -d "/proc/$pid" ]; then
return 0
break
fi
stat="$(cat /proc/${pid}/stat | awk '{print $3}' 2>/dev/null)"
if [ "$stat" = "Z" ]; then
$SLEEP $SLEEPTIME
return 0
break
fi
$SLEEP $SLEEPTIME 2>/dev/null
@@ -397,11 +397,15 @@ case "$1" in
done
kill -9 "$pid" 2>/dev/null
clear_rule
exit 0
;;
restart)
$0 stop
$0 start
;;
reload)
;;
enable)
nvram set apps_state_enable=2
nvram set apps_state_error=0

View File

@@ -41,13 +41,14 @@
#include <netinet/ip_icmp.h>
#include <netinet/tcp.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -196,7 +197,6 @@ struct dns_client {
/* query list */
struct list_head dns_request_list;
pthread_cond_t run_cond;
atomic_t run_period;
atomic_t dns_server_num;
@@ -208,6 +208,8 @@ struct dns_client {
pthread_mutex_t domain_map_lock;
DECLARE_HASHTABLE(domain_map, 6);
DECLARE_HASHTABLE(group, 4);
int fd_wakeup;
};
/* dns replied server info */
@@ -264,6 +266,8 @@ static pthread_mutex_t pending_server_mutex = PTHREAD_MUTEX_INITIALIZER;
static int dns_client_has_bootstrap_dns = 0;
static int _dns_client_send_udp(struct dns_server_info *server_info, void *packet, int len);
static void _dns_client_clear_wakeup_event(void);
static void _dns_client_do_wakeup_event(void);
static ssize_t _ssl_read(struct dns_server_info *server, void *buff, int num)
{
@@ -1337,9 +1341,8 @@ static int _dns_client_server_pending(char *server_ip, int port, dns_server_type
atomic_set(&client.run_period, 1);
pthread_mutex_unlock(&pending_server_mutex);
pthread_mutex_lock(&client.domain_map_lock);
pthread_cond_signal(&client.run_cond);
pthread_mutex_unlock(&client.domain_map_lock);
_dns_client_do_wakeup_event();
return 0;
errout:
if (pending) {
@@ -1514,7 +1517,7 @@ static void _dns_client_check_tcp(void)
}
if (server_info->status == DNS_SERVER_STATUS_CONNECTING) {
if (server_info->last_send + DNS_TCP_CONNECT_TIMEOUT < now) {
if (server_info->last_recv + DNS_TCP_CONNECT_TIMEOUT < now) {
tlog(TLOG_DEBUG, "server %s connect timeout.", server_info->ip);
_dns_client_close_socket(server_info);
}
@@ -3569,7 +3572,7 @@ int dns_client_query(const char *domain, int qtype, dns_client_callback callback
pthread_mutex_lock(&client.domain_map_lock);
if (hash_hashed(&query->domain_node)) {
if (list_empty(&client.dns_request_list)) {
pthread_cond_signal(&client.run_cond);
_dns_client_do_wakeup_event();
}
list_add_tail(&query->dns_request_list, &client.dns_request_list);
@@ -3818,15 +3821,12 @@ static void _dns_client_period_run_second(void)
_dns_client_add_pending_servers();
}
static void _dns_client_period_run(void)
static void _dns_client_period_run(unsigned int msec)
{
struct dns_query_struct *query = NULL;
struct dns_query_struct *tmp = NULL;
static unsigned int msec = 0;
msec++;
LIST_HEAD(check_list);
unsigned long now = get_tick_count();
/* get query which timed out to check list */
@@ -3869,9 +3869,11 @@ static void *_dns_client_work(void *arg)
int i = 0;
unsigned long now = {0};
unsigned long last = {0};
unsigned int msec = 0;
unsigned int sleep = 100;
int sleep_time = 0;
unsigned long expect_time = 0;
int unused __attribute__((unused));
sleep_time = sleep;
now = get_tick_count() - sleep;
@@ -3884,11 +3886,17 @@ static void *_dns_client_work(void *arg)
if (sleep_time <= 0) {
sleep_time = 0;
}
int cnt = sleep_time / sleep;
msec -= cnt;
expect_time -= cnt * sleep;
sleep_time -= cnt * sleep;
}
if (now >= expect_time) {
msec++;
if (last != now) {
_dns_client_period_run();
_dns_client_period_run(msec);
}
sleep_time = sleep - (now - expect_time);
@@ -3896,19 +3904,21 @@ static void *_dns_client_work(void *arg)
sleep_time = 0;
expect_time = now;
}
/* When client is idle, the sleep time is 1000ms, to reduce CPU usage */
pthread_mutex_lock(&client.domain_map_lock);
if (list_empty(&client.dns_request_list)) {
int cnt = 10 - (msec % 10) - 1;
sleep_time += sleep * cnt;
msec += cnt;
/* sleep to next second */
expect_time += sleep * cnt;
}
pthread_mutex_unlock(&client.domain_map_lock);
expect_time += sleep;
}
last = now;
pthread_mutex_lock(&client.domain_map_lock);
if (list_empty(&client.dns_request_list) && atomic_read(&client.run_period) == 0) {
pthread_cond_wait(&client.run_cond, &client.domain_map_lock);
expect_time = get_tick_count();
pthread_mutex_unlock(&client.domain_map_lock);
continue;
}
pthread_mutex_unlock(&client.domain_map_lock);
num = epoll_wait(client.epoll_fd, events, DNS_MAX_EVENTS, sleep_time);
if (num < 0) {
usleep(100000);
@@ -3918,6 +3928,11 @@ static void *_dns_client_work(void *arg)
for (i = 0; i < num; i++) {
struct epoll_event *event = &events[i];
struct dns_server_info *server_info = (struct dns_server_info *)event->data.ptr;
if (event->data.fd == client.fd_wakeup) {
_dns_client_clear_wakeup_event();
continue;
}
if (server_info == NULL) {
tlog(TLOG_WARN, "server info is invalid.");
continue;
@@ -3971,10 +3986,71 @@ int dns_client_set_ecs(char *ip, int subnet)
return 0;
}
static int _dns_client_create_wakeup_event(void)
{
int fd_wakeup = -1;
fd_wakeup = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
if (fd_wakeup < 0) {
tlog(TLOG_ERROR, "create eventfd failed, %s\n", strerror(errno));
goto errout;
}
struct epoll_event event;
memset(&event, 0, sizeof(event));
event.events = EPOLLIN;
event.data.fd = fd_wakeup;
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, fd_wakeup, &event) < 0) {
tlog(TLOG_ERROR, "add eventfd to epoll failed, %s\n", strerror(errno));
goto errout;
}
return fd_wakeup;
errout:
if (fd_wakeup > 0) {
close(fd_wakeup);
}
return -1;
}
static void _dns_client_close_wakeup_event(void)
{
if (client.fd_wakeup > 0) {
close(client.fd_wakeup);
client.fd_wakeup = -1;
}
}
static void _dns_client_clear_wakeup_event(void)
{
uint64_t val = 0;
int unused __attribute__((unused));
if (client.fd_wakeup <= 0) {
return;
}
unused = read(client.fd_wakeup, &val, sizeof(val));
}
static void _dns_client_do_wakeup_event(void)
{
uint64_t val = 1;
int unused __attribute__((unused));
if (client.fd_wakeup <= 0) {
return;
}
unused = write(client.fd_wakeup, &val, sizeof(val));
}
int dns_client_init(void)
{
pthread_attr_t attr;
int epollfd = -1;
int fd_wakeup = -1;
int ret = 0;
if (client.epoll_fd > 0) {
@@ -4002,8 +4078,6 @@ int dns_client_init(void)
hash_init(client.group);
INIT_LIST_HEAD(&client.dns_request_list);
pthread_cond_init(&client.run_cond, NULL);
if (dns_client_add_group(DNS_SERVER_GROUP_DEFAULT) != 0) {
tlog(TLOG_ERROR, "add default server group failed.");
goto errout;
@@ -4020,6 +4094,14 @@ int dns_client_init(void)
goto errout;
}
fd_wakeup = _dns_client_create_wakeup_event();
if (fd_wakeup < 0) {
tlog(TLOG_ERROR, "create wakeup event failed, %s\n", strerror(errno));
goto errout;
}
client.fd_wakeup = fd_wakeup;
return 0;
errout:
if (client.tid) {
@@ -4029,13 +4111,16 @@ errout:
client.tid = 0;
}
if (epollfd) {
if (epollfd > 0) {
close(epollfd);
}
if (fd_wakeup > 0) {
close(fd_wakeup);
}
pthread_mutex_destroy(&client.server_list_lock);
pthread_mutex_destroy(&client.domain_map_lock);
pthread_cond_destroy(&client.run_cond);
return -1;
}
@@ -4045,14 +4130,13 @@ void dns_client_exit(void)
if (client.tid) {
void *ret = NULL;
atomic_set(&client.run, 0);
pthread_mutex_lock(&client.domain_map_lock);
pthread_cond_signal(&client.run_cond);
pthread_mutex_unlock(&client.domain_map_lock);
_dns_client_do_wakeup_event();
pthread_join(client.tid, &ret);
client.tid = 0;
}
/* free all resources */
_dns_client_close_wakeup_event();
_dns_client_remove_all_pending_servers();
_dns_client_server_remove_all();
_dns_client_query_remove_all();
@@ -4060,7 +4144,6 @@ void dns_client_exit(void)
pthread_mutex_destroy(&client.server_list_lock);
pthread_mutex_destroy(&client.domain_map_lock);
pthread_cond_destroy(&client.run_cond);
if (client.ssl_ctx) {
SSL_CTX_free(client.ssl_ctx);
client.ssl_ctx = NULL;

View File

@@ -346,9 +346,9 @@ static int _dns_server_get_conf_ttl(struct dns_request *request, int ttl)
return rr_ttl;
}
if (rr_ttl_max > 0 && ttl > rr_ttl_max) {
if (rr_ttl_max > 0 && ttl >= rr_ttl_max) {
ttl = rr_ttl_max;
} else if (rr_ttl_min > 0 && ttl < rr_ttl_min) {
} else if (rr_ttl_min > 0 && ttl <= rr_ttl_min) {
ttl = rr_ttl_min;
}
@@ -2948,6 +2948,12 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, const
dns_get_CNAME(rrs, name, DNS_MAX_CNAME_LEN, &ttl, cname, DNS_MAX_CNAME_LEN);
} break;
default:
if (ttl == 0) {
/* Get TTL */
char tmpname[DNS_MAX_CNAME_LEN];
char tmpbuf[DNS_MAX_CNAME_LEN];
dns_get_CNAME(rrs, tmpname, DNS_MAX_CNAME_LEN, &ttl, tmpbuf, DNS_MAX_CNAME_LEN);
}
break;
}
}

View File

@@ -110,6 +110,7 @@ struct tlog {
tlog_log_output_func output_func;
struct tlog_log *wait_on_log;
int is_wait;
char gzip_cmd[PATH_MAX];
};
struct tlog_segment_log_head {
@@ -520,7 +521,7 @@ static int _tlog_vprintf(struct tlog_log *log, vprint_callback print_callback, v
return -1;
}
if (unlikely(log->logcount <= 0 && log->logscreen == 0) ) {
if (unlikely(log->logcount <= 0 && log->logscreen == 0)) {
return 0;
}
@@ -1018,7 +1019,6 @@ errout:
static int _tlog_archive_log_compressed(struct tlog_log *log)
{
char gzip_file[TLOG_BUFF_LEN];
char gzip_cmd[PATH_MAX * 2];
char log_file[TLOG_BUFF_LEN];
char pending_file[TLOG_BUFF_LEN];
@@ -1046,12 +1046,11 @@ static int _tlog_archive_log_compressed(struct tlog_log *log)
}
/* start gzip process to compress log file */
snprintf(gzip_cmd, sizeof(gzip_cmd), "gzip -1 %s", pending_file);
if (log->zip_pid <= 0) {
int pid = vfork();
if (pid == 0) {
_tlog_close_all_fd();
execl("/bin/sh", "sh", "-c", gzip_cmd, NULL);
execl(tlog.gzip_cmd, "-1", pending_file, NULL);
_exit(1);
} else if (pid < 0) {
goto errout;
@@ -1363,12 +1362,26 @@ static struct tlog_log *_tlog_wait_log_locked(struct tlog_log *last_log)
int ret = 0;
struct timespec tm;
struct tlog_log *log = NULL;
struct tlog_log *next = NULL;
int need_wait_pid = 0;
for (next = tlog.log; next != NULL; next = next->next) {
if (next->zip_pid > 0) {
need_wait_pid = 1;
break;
}
}
clock_gettime(CLOCK_REALTIME, &tm);
tm.tv_sec += 2;
tlog.is_wait = 1;
tlog.wait_on_log = last_log;
ret = pthread_cond_timedwait(&tlog.cond, &tlog.lock, &tm);
if (need_wait_pid != 0) {
ret = pthread_cond_timedwait(&tlog.cond, &tlog.lock, &tm);
} else {
ret = pthread_cond_wait(&tlog.cond, &tlog.lock);
}
tlog.is_wait = 0;
tlog.wait_on_log = NULL;
errno = ret;
@@ -1676,6 +1689,15 @@ int tlog_setlevel(tlog_level level)
return 0;
}
int tlog_log_enabled(tlog_level level)
{
if (level >= TLOG_END) {
return 0;
}
return (tlog_set_level >= level) ? 1 : 0;
}
tlog_level tlog_getlevel(void)
{
return tlog_set_level;
@@ -1686,6 +1708,35 @@ void tlog_set_logfile(const char *logfile)
tlog_rename_logfile(tlog.root, logfile);
}
static void _tlog_get_gzip_cmd_path(void)
{
char *copy_path = NULL;
char gzip_cmd_path[PATH_MAX];
const char *env_path = getenv("PATH");
char *save_ptr = NULL;
if (env_path == NULL) {
env_path = "/bin:/usr/bin:/usr/local/bin";
}
copy_path = strdup(env_path);
if (copy_path == NULL) {
return;
}
for (char *tok = strtok_r(copy_path, ":", &save_ptr); tok; tok = strtok_r(NULL, ":", &save_ptr)) {
snprintf(gzip_cmd_path, sizeof(gzip_cmd_path), "%s/gzip", tok);
if (access(gzip_cmd_path, X_OK) != 0) {
continue;
}
snprintf(tlog.gzip_cmd, sizeof(tlog.gzip_cmd), "%s", gzip_cmd_path);
break;
}
free(copy_path);
}
tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag)
{
struct tlog_log *log = NULL;
@@ -1726,6 +1777,10 @@ tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int bu
log->file_perm = S_IRUSR | S_IWUSR | S_IRGRP;
log->archive_perm = S_IRUSR | S_IRGRP;
if (log->nocompress == 0 && tlog.gzip_cmd[0] == '\0') {
log->nocompress = 1;
}
tlog_rename_logfile(log, logfile);
if (log->nocompress) {
strncpy(log->suffix, TLOG_SUFFIX_LOG, sizeof(log->suffix));
@@ -1859,6 +1914,7 @@ int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize
memset(&tlog, 0, sizeof(tlog));
tlog.is_wait = 0;
_tlog_get_gzip_cmd_path();
pthread_attr_init(&attr);
pthread_cond_init(&tlog.cond, NULL);
pthread_mutex_init(&tlog.lock, NULL);
@@ -1871,6 +1927,10 @@ int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize
}
tlog_reg_output_func(log, _tlog_root_write_log);
if ((flag & TLOG_NOCOMPRESS) == 0 && tlog.gzip_cmd[0] == '\0') {
fprintf(stderr, "can not find gzip command, disable compress.\n");
}
tlog.root = log;
ret = pthread_create(&tlog.tid, &attr, _tlog_work, NULL);
if (ret != 0) {

View File

@@ -79,9 +79,9 @@ level: Current log Levels
format: Log formats
*/
#ifndef BASE_FILE_NAME
#define BASE_FILE_NAME \
(__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 \
: __FILE__)
#define BASE_FILE_NAME \
(__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 \
: __FILE__)
#endif
#define tlog(level, format, ...) tlog_ext(level, BASE_FILE_NAME, __LINE__, __func__, NULL, format, ##__VA_ARGS__)
@@ -95,6 +95,9 @@ extern int tlog_write_log(char *buff, int bufflen);
/* set log level */
extern int tlog_setlevel(tlog_level level);
/* is log level enabled*/
extern int tlog_log_enabled(tlog_level level);
/* get log level */
extern tlog_level tlog_getlevel(void);
@@ -137,7 +140,7 @@ read _tlog_format for example.
typedef int (*tlog_format_func)(char *buff, int maxlen, struct tlog_loginfo *info, void *userptr, const char *format, va_list ap);
extern int tlog_reg_format_func(tlog_format_func func);
/* register log output callback
/* register log output callback
Note: info is invalid when flag TLOG_SEGMENT is not set.
*/
typedef int (*tlog_log_output_func)(struct tlog_loginfo *info, const char *buff, int bufflen, void *private_data);
@@ -213,7 +216,7 @@ file: log file permission, default is 640
archive: archive file permission, default is 440
*/
extern void tlog_set_permission(struct tlog_log *log, mode_t file, mode_t archive);
extern void tlog_set_permission(struct tlog_log *log, mode_t file, mode_t archive);
#ifdef __cplusplus
class Tlog {