Compare commits

...

10 Commits

Author SHA1 Message Date
Nick Peng
51e1ba6897 update readme 2022-10-20 23:18:45 +08:00
Nick Peng
efc18996a8 luci: remove unnecessary permissions 2022-10-15 10:41:48 +08:00
soffchen
9bc857f628 smartdns: fix typo 2022-10-11 18:45:44 +08:00
YiiSh
8523f26c62 update smartdns start priority same with dnsmasq 2022-10-08 23:24:13 +08:00
Nick Peng
6c800ea12f luci: Fix RPC error when config is empty and add restart button. 2022-10-08 21:59:35 +08:00
Nick Peng
eeaadcf313 openwrt: remove deprecated option and restore dnsmasq when stop 2022-09-29 23:53:51 +08:00
Nick Peng
ccb47ef327 conf: fix local domain handling issues 2022-09-28 20:28:01 +08:00
HiGarfield
a13433abac Update smartdns.lua (#1092)
luci-compat: fix dnsmasq redirect status
2022-09-28 09:22:51 +08:00
Nick Peng
799d19f233 conf: add option resolv-hostname to skip resolve local hostname 2022-09-28 00:53:39 +08:00
Nick Peng
0fa17063c0 luci: avoid unnecessary configuration writes 2022-09-27 21:50:08 +08:00
11 changed files with 188 additions and 71 deletions

View File

@@ -17,6 +17,8 @@ SmartDNS 同时支持指定特定域名 IP 地址,并高性匹配,可达到
- [特性](#特性)
- [架构](#架构)
- [下载](#下载)
- [使用官方安装源](#使用官方安装源)
- [手工下载安装](#手工下载安装)
- [安装和使用](#安装和使用)
- [标准 Linux 系统 / 树莓派](#标准-linux-系统--树莓派)
- [OpenWrt](#openwrt)
@@ -121,6 +123,9 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
9. **高性能、占用资源少**
多线程异步 IO 模式cache 缓存查询结果。
10. **主流系统官方支持**
主流路由系统官方软件源安装smartdns。
## 架构
![Architecture](https://github.com/pymumu/test/releases/download/blob/architecture.png)
@@ -132,6 +137,19 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
## 下载
### 使用官方安装源
smartdns已经合入主流系统的软件仓库可以直接使用系统安装命令直接安装。
系统|安装方式|说明|
--|--|--
openwrt|opkg update</br>opkg install luci-app-smartdns</br>opkg install smartdns|22.03之后的系统。软件源路径https://downloads.openwrt.org/releases/
ddwrt|官方最新固件service页面->SmartDNS Resolver->启用。|选择界面参考https://forum.dd-wrt.com/demo/Services.html
debian|apt-get install smartdns|
entware|ipkg update</br>ipkg install smartdns|软件源路径https://bin.entware.net/
### 手工下载安装
--------------
下载对应系统或固件版本的 SmartDNS 安装包,对应关系如下。
@@ -723,6 +741,9 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
...
```
14. 更多问题
如有更多问题请查阅或提交issue: [https://github.com/pymumu/smartdns/issues](https://github.com/pymumu/smartdns/issues)
## 编译
SmartDNS 提供了编译软件包的脚本(`package/build-pkg.sh`),支持编译 LuCI、Debian、OpenWrt 和 Optware 安装包。

View File

@@ -9,19 +9,27 @@ Support Raspberry Pi, openwrt, ASUS router, Windows and other devices.
## Table Of Content
1. [Software Show](#software-show)
1. [Features](#features)
1. [Architecture](#architecture)
1. [Usage](#usage)
1. [Download the package](#download-the-package)
1. [Standard Linux system installation/Raspberry Pi, X86_64 system](#standard-linux-system-installation/raspberry-pi,-x86_64-system)
1. [openwrt/LEDE](#openwrt/lede)
1. [ASUS router native firmware / Merlin firmware](#asus-router-native-firmware-/-merlin-firmware)
1. [optware/entware](#optware/entware)
1. [Windows 10 WSL Installation/WSL ubuntu](#windows-10-wsl-installation/wsl-ubuntu)
1. [Configuration parameter](#configuration-parameter)
1. [Donate](#Donate)
1. [FAQ](#FAQ)
- [SmartDNS](#smartdns)
- [Table Of Content](#table-of-content)
- [Software Show](#software-show)
- [Features](#features)
- [Architecture](#architecture)
- [Usage](#usage)
- [Use official installation source](#use-official-installation-source)
- [Download the package](#download-the-package)
- [Standard Linux system installation/Raspberry Pi, X86_64 system](#standard-linux-system-installationraspberry-pi-x86_64-system)
- [openwrt](#openwrt)
- [ASUS router native firmware / Merlin firmware](#asus-router-native-firmware--merlin-firmware)
- [optware/entware](#optwareentware)
- [Windows 10 WSL Installation/WSL ubuntu](#windows-10-wsl-installationwsl-ubuntu)
- [Configuration parameter](#configuration-parameter)
- [FAQ](#faq)
- [Compile](#compile)
- [Donate](#donate)
- [PayPal](#paypal)
- [Alipay](#alipay)
- [Wechat](#wechat)
- [Open Source License](#open-source-license)
## Software Show
@@ -121,6 +129,17 @@ From the comparison, smartdns found the fastest IP address to visit www.baidu.co
## Usage
### Use official installation source
smartdns can already be installed using system package management tools.
System|Installation|Instructions|
--|--|--
openwrt|opkg update</br>opkg install luci-app-smartdns</br>opkg install smartdns|systems after 22.03. Software source: https://downloads.openwrt.org/releases/
ddwrt|latest firmware. goto services page abd enable SmartDNS Resolver. |Demo: https://forum.dd-wrt.com/demo/Services.html
debian|apt-get install smartdns|
entware|ipkg update</br>ipkg install smartdns|Software source: https://bin.entware.net/
### Download the package
--------------
@@ -664,6 +683,9 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
...
````
1. More questions
More questions, please read issue: [https://github.com/pymumu/smartdns/issues](https://github.com/pymumu/smartdns/issues)
## Compile
smartdns contains scripts for compiling packages, supports compiling luci, debian, openwrt, opare installation packages, and can execute `package/build-pkg.sh` compilation.

View File

@@ -4,6 +4,9 @@
# server-name smartdns
#
# whether resolv local hostname to ip address
# resolv-hostname yes
# dns server run user
# user [username]
# example: run as nobody

View File

@@ -38,7 +38,7 @@ end
function act_status()
local e={}
local ipv6_server;
local dnsmasq_server = luci.sys.exec("uci get dhcp.@dnsmasq[0].server")
local dnsmasq_server = smartdns.get_config_option("dhcp", "dnsmasq", "server", {nil})[1]
local auto_set_dnsmasq = smartdns.get_config_option("smartdns", "smartdns", "auto_set_dnsmasq", nil);
e.auto_set_dnsmasq = auto_set_dnsmasq
@@ -47,7 +47,7 @@ function act_status()
if e.local_port ~= nil and e.local_port ~= "53" and auto_set_dnsmasq ~= nil and auto_set_dnsmasq == "1" then
local str;
str = "127.0.0.1#" .. e.local_port
if string.sub(dnsmasq_server,1,string.len(str)) ~= str then
if dnsmasq_server ~= str then
e.dnsmasq_redirect_failure = 1
end
end

View File

@@ -184,6 +184,12 @@ msgstr "解析本地主机名"
msgid "Resolve local hostnames by reading Dnsmasq lease file."
msgstr "读取Dnsmasq的租约文件解析本地主机名。"
msgid "Restart"
msgstr "重启"
msgid "Restart Service"
msgstr "重启服务"
msgid "Second Server Settings"
msgstr "第二DNS服务器"

View File

@@ -3,8 +3,7 @@
"description": "Grant access to LuCI app smartdns",
"read": {
"file": {
"/etc/smartdns/*": [ "read" ],
"/usr/sbin/smartdns": [ "exec" ]
"/etc/smartdns/*": [ "read" ]
},
"ubus": {
"service": [ "list" ]
@@ -13,7 +12,8 @@
},
"write": {
"file": {
"/etc/smartdns/*": [ "write" ]
"/etc/smartdns/*": [ "write" ],
"/etc/init.d/smartdns restart": [ "exec" ]
},
"uci": [ "smartdns" ]
}

View File

@@ -24,6 +24,7 @@
'require view';
'require poll';
'require rpc';
'require ui';
var conf = 'smartdns';
var callServiceList = rpc.declare({
@@ -32,6 +33,7 @@ var callServiceList = rpc.declare({
params: ['name'],
expect: { '': {} }
});
var pollAdded = false;
function getServiceStatus() {
return L.resolveDefault(callServiceList(conf), {})
@@ -106,14 +108,16 @@ return view.extend({
view.innerHTML = smartdnsRenderStatus(res);
});
}
poll.add(renderStatus, 1);
return E('div', { class: 'cbi-map' },
E('div', { class: 'cbi-section' }, [
E('div', { id: 'service_status' },
_('Collecting data ...'))
])
);
if (pollAdded == false) {
poll.add(renderStatus, 1);
pollAdded = true;
}
return E('div', { class: 'cbi-section' }, [
E('div', { id: 'service_status' },
_('Collecting data ...'))
]);
}
// Basic;
@@ -296,7 +300,12 @@ return view.extend({
return fs.trimmed('/etc/smartdns/custom.conf');
};
o.write = function (section_id, formvalue) {
return fs.write('/etc/smartdns/custom.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
return this.cfgvalue(section_id).then(function (value) {
if (value == formvalue) {
return
}
return fs.write('/etc/smartdns/custom.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
});
};
o = s.taboption("custom", form.Flag, "coredump", _("Generate Coredump"),
@@ -435,7 +444,12 @@ return view.extend({
return fs.trimmed('/etc/smartdns/address.conf');
};
o.write = function (section_id, formvalue) {
return fs.write('/etc/smartdns/address.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
return this.cfgvalue(section_id).then(function (value) {
if (value == formvalue) {
return
}
return fs.write('/etc/smartdns/address.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
});
};
// IP Blacklist;
@@ -447,7 +461,12 @@ return view.extend({
return fs.trimmed('/etc/smartdns/blacklist-ip.conf');
};
o.write = function (section_id, formvalue) {
return fs.write('/etc/smartdns/blacklist-ip.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
return this.cfgvalue(section_id).then(function (value) {
if (value == formvalue) {
return
}
return fs.write('/etc/smartdns/blacklist-ip.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
});
};
// Doman addresss;
@@ -471,6 +490,17 @@ return view.extend({
window.open("https://pymumu.github.io/smartdns/#donate", '_blank');
};
o = s.option(form.DummyValue, "_restart", _("Restart Service"));
o.renderWidget = function () {
return E('button', {
'class': 'btn cbi-button cbi-button-apply',
'id': 'btn_restart',
'click': ui.createHandlerFn(this, function () {
return fs.exec('/etc/init.d/smartdns', ['restart'])
.catch(function (e) { ui.addNotification(null, E('p', e.message), 'error') });
})
}, [_("Restart")]);
}
return m.render();
}
});

View File

@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
START=99
START=19
NAME=smartdns
USE_PROCD=1
SERVICE_USE_PID=1
@@ -31,6 +31,7 @@ CUSTOM_CONF="$SMARTDNS_CONF_DIR/custom.conf"
SMARTDNS_CONF_TMP="${SMARTDNS_CONF}.tmp"
COREDUMP="0"
RESPAWN="1"
DO_RELOAD="0"
set_forward_dnsmasq()
{
@@ -48,7 +49,7 @@ set_forward_dnsmasq()
uci -q set dhcp.@dnsmasq[0].rebind_protection=0
uci -q set dhcp.@dnsmasq[0].domainneeded=0
uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/dnsmasq reload
}
stop_forward_dnsmasq()
@@ -66,7 +67,7 @@ stop_forward_dnsmasq()
uci -q set dhcp.@dnsmasq[0].rebind_protection=1
uci -q set dhcp.@dnsmasq[0].domainneeded=1
uci commit dhcp
[ "$norestart" != "1" ] && /etc/init.d/dnsmasq restart
[ "$norestart" != "1" ] && /etc/init.d/dnsmasq reload
}
set_main_dns()
@@ -79,7 +80,7 @@ set_main_dns()
[ -z "$hostip" ] && return
[ "$dnsmasq_port" = "53" ] && {
uci -q set dhcp.@dnsmasq[0].port=0
uci -q set dhcp.lan.dhcp_option="6,$hostip"
uci -q add_list dhcp.lan.dhcp_option="6,$hostip"
}
# for some third-party firmware
@@ -90,12 +91,13 @@ set_main_dns()
}
uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/dnsmasq reload
}
stop_main_dns()
{
local norestart="$1"
hostip="$(uci -q get network.lan.ipaddr)"
dnsmasq_port="$(uci -q get dhcp.@dnsmasq[0].port)"
redir_dns="$(uci -q get dhcp.@dnsmasq[0].old_dns_redirect)"
[ "$dnsmasq_port" != "0" ] && return
@@ -104,9 +106,9 @@ stop_main_dns()
uci -q delete dhcp.@dnsmasq[0].old_dns_redirect
}
uci -q delete dhcp.@dnsmasq[0].port
uci -q delete dhcp.lan.dhcp_option
uci -q del_list dhcp.lan.dhcp_option="6,$hostip"
uci commit dhcp
[ "$norestart" != "1" ] && /etc/init.d/dnsmasq restart
[ "$norestart" != "1" ] && /etc/init.d/dnsmasq reload
}
clear_iptable()
@@ -452,10 +454,16 @@ load_service()
unload_service()
{
local section="$1"
[ "$DO_RELOAD" = "1" ] && return 0
config_get_bool enabled "$section" "enabled" '0'
dnsmasq_port="$(uci -q get dhcp.@dnsmasq[0].port)"
config_get port "$section" "port" "53"
config_get old_port "$section" "old_port" "0"
config_get auto_set_dnsmasq "$section" "auto_set_dnsmasq" "0"
config_get old_enabled "$section" "old_enabled" "0"
config_get old_port "$section" "old_port" "0"
config_get old_auto_set_dnsmasq "$section" "old_auto_set_dnsmasq" "0"
[ -z "${dnsmasq_port}" ] && dnsmasq_port="53"
[ "$enabled" = "1" ] && {
@@ -479,6 +487,8 @@ start_service()
reload_service()
{
DO_RELOAD="1"
stop
start
DO_RELOAD="0"
}

View File

@@ -83,6 +83,7 @@ int dns_conf_serve_expired_reply_ttl = 3;
struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
char dns_conf_server_name[DNS_MAX_SERVER_NAME_LEN];
int dns_conf_server_num;
int dns_conf_resolv_hostname = 1;
struct dns_domain_check_orders dns_conf_check_orders = {
.orders =
@@ -518,7 +519,8 @@ static void _config_address_destroy(radix_node_t *node, void *cbctx)
node->data = NULL;
}
static int _config_domain_set_rule_add_ext(char *set_name, enum domain_rule type, void *rule, unsigned int flags, int is_clear_flag)
static int _config_domain_set_rule_add_ext(char *set_name, enum domain_rule type, void *rule, unsigned int flags,
int is_clear_flag)
{
struct dns_domain_set_rule *set_rule = NULL;
struct dns_domain_set_rule_list *set_rule_list = NULL;
@@ -2121,26 +2123,42 @@ static int _config_log_level(void *data, int argc, char *argv[])
static void _config_setup_smartdns_domain(void)
{
char hostname[DNS_MAX_CNAME_LEN];
/* get local host name */
if (getdomainname(hostname, DNS_MAX_CNAME_LEN) != 0) {
gethostname(hostname, DNS_MAX_CNAME_LEN);
char domainname[DNS_MAX_CNAME_LEN];
hostname[0] = '\0';
domainname[0] = '\0';
/* get local domain name */
if (getdomainname(domainname, DNS_MAX_CNAME_LEN - 1) == 0) {
/* check domain is valid */
if (strncmp(domainname, "(none)", DNS_MAX_CNAME_LEN - 1) == 0) {
domainname[0] = '\0';
}
}
/* get host name again */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN - 1) == 0) {
gethostname(hostname, DNS_MAX_CNAME_LEN);
if (gethostname(hostname, DNS_MAX_CNAME_LEN - 1) == 0) {
/* check hostname is valid */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN - 1) == 0) {
hostname[0] = '\0';
}
}
/* if hostname is (none), return smartdns */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN - 1) == 0) {
safe_strncpy(hostname, "smartdns", DNS_MAX_CNAME_LEN);
if (dns_conf_resolv_hostname == 1) {
/* add hostname to rule table */
if (hostname[0] != '\0') {
_config_domain_rule_flag_set(hostname, DOMAIN_FLAG_SMARTDNS_DOMAIN, 0);
}
/* add domainname to rule table */
if (domainname[0] != '\0') {
char full_domain[DNS_MAX_CNAME_LEN];
snprintf(full_domain, DNS_MAX_CNAME_LEN, "%.64s.%.128s", hostname, domainname);
_config_domain_rule_flag_set(full_domain, DOMAIN_FLAG_SMARTDNS_DOMAIN, 0);
}
}
if (hostname[0] != '\0') {
_config_domain_rule_flag_set(hostname, DOMAIN_FLAG_SMARTDNS_DOMAIN, 0);
}
if (dns_conf_server_name[0] != '\0') {
/* add server name to rule table */
if (dns_conf_server_name[0] != '\0' && strncmp(dns_conf_server_name, "smartdns", DNS_MAX_CNAME_LEN - 1) != 0) {
_config_domain_rule_flag_set(dns_conf_server_name, DOMAIN_FLAG_SMARTDNS_DOMAIN, 0);
}
@@ -2149,6 +2167,7 @@ static void _config_setup_smartdns_domain(void)
static struct config_item _config_item[] = {
CONF_STRING("server-name", (char *)dns_conf_server_name, DNS_MAX_SERVER_NAME_LEN),
CONF_YESNO("resolv-hostname", &dns_conf_resolv_hostname),
CONF_CUSTOM("bind", _config_bind_ip_udp, NULL),
CONF_CUSTOM("bind-tcp", _config_bind_ip_tcp, NULL),
CONF_CUSTOM("server", _config_server_udp, NULL),
@@ -2372,8 +2391,6 @@ static int _dns_server_load_conf_init(void)
hash_init(dns_domain_set_rule_table.rule_list);
hash_init(dns_domain_set_name_table.names);
_config_setup_smartdns_domain();
return 0;
}
@@ -2456,6 +2473,7 @@ errout:
static int _dns_conf_load_post(void)
{
_config_setup_smartdns_domain();
_dns_conf_speed_check_mode_verify();
if (dns_conf_cachesize == 0 && dns_conf_response_mode == DNS_RESPONSE_MODE_FASTEST_RESPONSE) {

View File

@@ -3161,33 +3161,40 @@ static int _dns_server_process_local_ptr(struct dns_request *request)
goto errout;
}
char hostname[DNS_MAX_CNAME_LEN];
char full_hostname[DNS_MAX_CNAME_LEN];
if (dns_conf_server_name[0] == 0) {
/* get local host name */
if (getdomainname(hostname, DNS_MAX_CNAME_LEN) != 0) {
if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) {
return -1;
char hostname[DNS_MAX_CNAME_LEN];
char domainname[DNS_MAX_CNAME_LEN];
/* get local domain name */
if (getdomainname(domainname, DNS_MAX_CNAME_LEN - 1) == 0) {
/* check domain is valid */
if (strncmp(domainname, "(none)", DNS_MAX_CNAME_LEN - 1) == 0) {
domainname[0] = '\0';
}
}
/* get host name again */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN - 1) == 0) {
if (gethostname(hostname, DNS_MAX_CNAME_LEN) != 0) {
return -1;
if (gethostname(hostname, DNS_MAX_CNAME_LEN - 1) == 0) {
/* check hostname is valid */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN - 1) == 0) {
hostname[0] = '\0';
}
}
/* if hostname is (none), return smartdns */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN - 1) == 0) {
safe_strncpy(hostname, "smartdns", DNS_MAX_CNAME_LEN);
if (hostname[0] != '\0' && domainname[0] != '\0') {
snprintf(full_hostname, sizeof(full_hostname), "%.64s.%.128s", hostname, domainname);
} else if (hostname[0] != '\0') {
safe_strncpy(full_hostname, hostname, DNS_MAX_CNAME_LEN);
} else {
safe_strncpy(full_hostname, "smartdns", DNS_MAX_CNAME_LEN);
}
} else {
/* return configured server name */
safe_strncpy(hostname, dns_conf_server_name, DNS_MAX_CNAME_LEN);
safe_strncpy(full_hostname, dns_conf_server_name, DNS_MAX_CNAME_LEN);
}
request->has_ptr = 1;
safe_strncpy(request->ptr_hostname, hostname, DNS_MAX_CNAME_LEN);
safe_strncpy(request->ptr_hostname, full_hostname, DNS_MAX_CNAME_LEN);
freeifaddrs(ifaddr);
return 0;

View File

@@ -138,7 +138,7 @@ static void _help(void)
char *help = ""
"Usage: smartdns [OPTION]...\n"
"Start smartdns server.\n"
" -f run forground.\n"
" -f run foreground.\n"
" -c [conf] config file.\n"
" -p [pid] pid file path, '-' means don't create pid file.\n"
" -S ignore segment fault signal.\n"
@@ -518,7 +518,7 @@ static int _smartdns_init_pre(void)
int main(int argc, char *argv[])
{
int ret = 0;
int is_forground = 0;
int is_foreground = 0;
int opt = 0;
char config_file[MAX_LINE_LEN];
char pid_file[MAX_LINE_LEN];
@@ -535,7 +535,7 @@ int main(int argc, char *argv[])
while ((opt = getopt(argc, argv, "fhc:p:SvxN:")) != -1) {
switch (opt) {
case 'f':
is_forground = 1;
is_foreground = 1;
break;
case 'c':
snprintf(config_file, sizeof(config_file), "%s", optarg);
@@ -568,7 +568,7 @@ int main(int argc, char *argv[])
goto errout;
}
if (is_forground == 0) {
if (is_foreground == 0) {
if (daemon(0, 0) < 0) {
fprintf(stderr, "run daemon process failed, %s\n", strerror(errno));
return 1;