Compare commits

...

16 Commits

Author SHA1 Message Date
Nick Peng
4db61f2677 Fix TimeZone issue when static compile 2019-12-15 01:27:14 +08:00
Nick Peng
7746ecb46d Fix script issue on padavan 2019-12-15 01:27:13 +08:00
Nick Peng
4357847641 Add display version 2019-12-15 01:27:12 +08:00
Nick Peng
e7e0a5d4af Fix openssl version issue 2019-12-15 01:27:11 +08:00
Nick Peng
57aa9c013d Fix optware startup script issue 2019-12-15 01:27:10 +08:00
Nick Peng
7216dcf526 Update ReadMe.md 2019-12-15 01:27:09 +08:00
Nick Peng
41e2067628 Fix build issue 2019-12-15 01:27:06 +08:00
Nick Peng
dda785ec5f Support TLS 1.3 2019-12-15 01:27:05 +08:00
Nick Peng
99972c36ad Fix ps bug 2019-12-15 01:27:04 +08:00
Nick Peng
ef50ea9c5e Change rule domain to lowercase 2019-12-15 01:27:03 +08:00
Nick Peng
cb3656cb57 Change config accept-ip to whitelist-ip 2019-12-15 01:27:02 +08:00
Nick Peng
3ef325d75d Support GCC 8.x and support static compile 2019-12-15 01:27:02 +08:00
Nick Peng
a09e63d333 Support IP accept list 2019-12-15 01:27:01 +08:00
Nick Peng
9a067e99c7 Fix group pending add issue 2019-12-15 01:27:00 +08:00
Nick Peng
1e88305df8 Support Delay DNS server bootstrap 2019-12-15 01:26:59 +08:00
Nick Peng
93d9ef4095 Remove checkedns 2019-12-15 01:26:58 +08:00
27 changed files with 758 additions and 237 deletions

View File

@@ -3,7 +3,7 @@
**[English](ReadMe_en.md)**
![SmartDNS](doc/smartdns-banner.png)
SmartDNS是一个运行在本地的DNS服务器SmartDNS接受本地客户端的DNS查询请求从多个上游DNS服务器获取DNS查询结果并将访问速度最快的结果返回给客户端避免DNS污染提高网络访问速度。
SmartDNS是一个运行在本地的DNS服务器SmartDNS接受本地客户端的DNS查询请求从多个上游DNS服务器获取DNS查询结果并将访问速度最快的结果返回给客户端提高网络访问速度。
同时支持指定特定域名IP地址并高性匹配达到过滤广告的效果。
与dnsmasq的all-servers不同smartdns返回的是访问速度最快的解析结果。 (详细差异请看[FAQ](#faq))
@@ -93,10 +93,10 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
支持配置多个上游DNS服务器并同时进行查询即使其中有DNS服务器异常也不会影响查询。
1. **返回最快IP地址**
支持从域名所属IP地址列表中查找到访问速度最快的IP地址并返回给客户端避免DNS污染提高网络访问速度。
支持从域名所属IP地址列表中查找到访问速度最快的IP地址并返回给客户端提高网络访问速度。
1. **支持多种查询协议**
支持UDPTCPTLS, HTTPS查询以及非53端口查询有效避免DNS污染
支持UDPTCPTLS, HTTPS查询以及非53端口查询。
1. **特定域名IP地址指定**
支持指定域名的IP地址达到广告过滤效果避免恶意网站的效果。
@@ -560,16 +560,17 @@ https://github.com/pymumu/smartdns/releases
|audit-size|审计大小|128K|数字+K,M,G|audit-size 128K
|audit-num|审计归档个数|2|数字|audit-num 2
|conf-file|附加配置文件|无|文件路径|conf-file /etc/smartdns/smartdns.more.conf
|server|上游UDP DNS|无|可重复<br>`[ip][:port]`服务器IP端口可选。<br>`[-blacklist-ip]`blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-check-edns]`edns过滤。<br>`[-group [group] ...]`DNS服务器所属组比如office, foreign和nameserver配套使用。<br>`[-exclude-default-group]`将DNS服务器从默认组中排除| server 8.8.8.8:53 -blacklist-ip -check-edns -group g1
|server-tcp|上游TCP DNS|无|可重复<br>`[ip][:port]`服务器IP端口可选。<br>`[-blacklist-ip]`blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-group [group] ...]`DNS服务器所属组比如office, foreign和nameserver配套使用。<br>`[-exclude-default-group]`将DNS服务器从默认组中排除| server-tcp 8.8.8.8:53
|server-tls|上游TLS DNS|无|可重复<br>`[ip][:port]`服务器IP端口可选。<br>`[-spki-pin [sha256-pin]]`: TLS合法性校验SPKI值base64编码的sha256 SPKI pin值<br>`[host-name]`TLS SNI名称<br>`[-blacklist-ip]`blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-group [group] ...]`DNS服务器所属组比如office, foreign和nameserver配套使用。<br>`[-exclude-default-group]`将DNS服务器从默认组中排除| server-tls 8.8.8.8:853
|server-https|上游HTTPS DNS|无|可重复<br>`https://[host][:port]/path`服务器IP端口可选。<br>`[-spki-pin [sha256-pin]]`: TLS合法性校验SPKI值base64编码的sha256 SPKI pin值<br>`[host-name]`TLS SNI名称<br>`[http-host]`http协议头主机名<br>`[-blacklist-ip]`blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-group [group] ...]`DNS服务器所属组比如office, foreign和nameserver配套使用。<br>`[-exclude-default-group]`将DNS服务器从默认组中排除| server-https https://cloudflare-dns.com/dns-query
|server|上游UDP DNS|无|可重复<br>`[ip][:port]`服务器IP端口可选。<br>`[-blacklist-ip]`blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-whitelist-ip]`whitelist-ip参数指定仅接受whitelist-ip中配置IP范围。<br>`[-group [group] ...]`DNS服务器所属组比如office, foreign和nameserver配套使用。<br>`[-exclude-default-group]`将DNS服务器从默认组中排除| server 8.8.8.8:53 -blacklist-ip -group g1
|server-tcp|上游TCP DNS|无|可重复<br>`[ip][:port]`服务器IP端口可选。<br>`[-blacklist-ip]`blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-whitelist-ip]`whitelist-ip参数指定仅接受whitelist-ip中配置IP范围。<br>`[-group [group] ...]`DNS服务器所属组比如office, foreign和nameserver配套使用。<br>`[-exclude-default-group]`将DNS服务器从默认组中排除| server-tcp 8.8.8.8:53
|server-tls|上游TLS DNS|无|可重复<br>`[ip][:port]`服务器IP端口可选。<br>`[-spki-pin [sha256-pin]]`: TLS合法性校验SPKI值base64编码的sha256 SPKI pin值<br>`[-host-name]`TLS SNI名称<br>`[-blacklist-ip]`blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-whitelist-ip]`whitelist-ip参数指定仅接受whitelist-ip中配置IP范围。<br>`[-group [group] ...]`DNS服务器所属组比如office, foreign和nameserver配套使用。<br>`[-exclude-default-group]`将DNS服务器从默认组中排除| server-tls 8.8.8.8:853
|server-https|上游HTTPS DNS|无|可重复<br>`https://[host][:port]/path`服务器IP端口可选。<br>`[-spki-pin [sha256-pin]]`: TLS合法性校验SPKI值base64编码的sha256 SPKI pin值<br>`[-host-name]`TLS SNI名称<br>`[-http-host]`http协议头主机名<br>`[-blacklist-ip]`blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-whitelist-ip]`whitelist-ip参数指定仅接受whitelist-ip中配置IP范围。<br>`[-group [group] ...]`DNS服务器所属组比如office, foreign和nameserver配套使用。<br>`[-exclude-default-group]`将DNS服务器从默认组中排除| server-https https://cloudflare-dns.com/dns-query
|address|指定域名IP地址|无|address /domain/[ip\|-\|-4\|-6\|#\|#4\|#6] <br>`-`表示忽略 <br>`#`表示返回SOA <br>`4`表示IPV4 <br>`6`表示IPV6| address /www.example.com/1.2.3.4
|nameserver|指定域名使用server组解析|无|nameserver /domain/[group\|-], `group`为组名,`-`表示忽略此规则配套server中的`-group`参数使用| nameserver /www.example.com/office
|ipset|域名IPSET|None|ipset /domain/[ipset\|-], `-`表示忽略|ipset /www.example.com/pass
|ipset-timeout|设置IPSET超时功能启用|auto|[yes]|ipset-timeout yes
|bogus-nxdomain|假冒IP地址过滤|无|[ip/subnet],可重复| bogus-nxdomain 1.2.3.4/16
|ignore-ip|忽略IP地址|无|[ip/subnet],可重复| ignore-ip 1.2.3.4/16
|whitelist-ip|白名单IP地址|无|[ip/subnet],可重复| whitelist-ip 1.2.3.4/16
|blacklist-ip|黑名单IP地址|无|[ip/subnet],可重复| blacklist-ip 1.2.3.4/16
|force-AAAA-SOA|强制AAAA地址返回SOA|no|[yes\|no]|force-AAAA-SOA yes
|prefetch-domain|域名预先获取功能|no|[yes\|no]|prefetch-domain yes
@@ -586,7 +587,6 @@ https://github.com/pymumu/smartdns/releases
* 针对广告屏蔽功能做增强返回SOA屏蔽广告效果更佳
* IPV4IPV6双栈IP优选机制在双网情况下选择最快的网络通讯。
* 支持最新的TLS, HTTPS协议提供安全的DNS查询能力。
* DNS防抢答机制及多种机制避免DNS污染。
* ECS支持是查询结果更佳准确。
* IP黑名单忽略IP机制使域名查询更佳准确。
* 域名预查询,访问常用网站更加快速。
@@ -601,8 +601,6 @@ https://github.com/pymumu/smartdns/releases
* 国内公共DNS如`119.29.29.29`, `223.5.5.5`。
* 国外公共DNS如`8.8.8.8`, `8.8.4.4`。
对于特定的域名,如果有污染情况,可以启用防污染机制。
1. 如何启用审计日志
审计日志记录客户端请求的域名记录信息包括请求时间请求IP请求域名请求类型如果要启用审计日志在配置界面配置`audit-enable yes`启用,`audit-size`, `audit-file`, `audit-num`分别配置审计日志文件大小,审计日志文件路径,和审计日志文件个数。审计日志文件将会压缩存储以节省空间。

View File

@@ -555,16 +555,17 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|audit-size|audit log size|128K|number+K,M,G|audit-size 128K
|audit-num|archived audit log number|2|Integer|audit-num 2
|conf-file|additional conf file|None|File path|conf-file /etc/smartdns/smartdns.more.conf
|server|Upstream UDP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-check-edns]`: edns filter. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server 8.8.8.8:53 -blacklist-ip -check-edns
|server-tcp|Upstream TCP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-tcp 8.8.8.8:53
|server-tls|Upstream TLS DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[host-name]`:TLS Server name<br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-tls 8.8.8.8:853
|server-https|Upstream HTTPS DNS server|None|Repeatable <br>`https://[host][:port]/path`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[host-name]`:TLS Server name<br>`[http-host]`http header host<br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-https https://cloudflare-dns.com/dns-query
|server|Upstream UDP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server 8.8.8.8:53 -blacklist-ip
|server-tcp|Upstream TCP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-tcp 8.8.8.8:53
|server-tls|Upstream TLS DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[-host-name]`:TLS Server name. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-tls 8.8.8.8:853
|server-https|Upstream HTTPS DNS server|None|Repeatable <br>`https://[host][:port]/path`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[-host-name]`:TLS Server name<br>`[-http-host]`http header host. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-https https://cloudflare-dns.com/dns-query
|address|Domain IP address|None|address /domain/[ip\|-\|-4\|-6\|#\|#4\|#6], `-` for ignore, `#` for return SOA, `4` for IPV4, `6` for IPV6| address /www.example.com/1.2.3.4
|nameserver|To query domain with specific server group|None|nameserver /domain/[group\|-], `group` is the group name, `-` means ignore this rule, use the `-group` parameter in the related server|nameserver /www.example.com/office
|ipset|Domain IPSet|None|ipset /domain/[ipset\|-], `-` for ignore|ipset /www.example.com/pass
|ipset-timeout|ipset timeout enable|auto|[yes]|ipset-timeout yes
|bogus-nxdomain|bogus IP address|None|[IP/subnet], Repeatable| bogus-nxdomain 1.2.3.4/16
|ignore-ip|ignore ip address|None|[ip/subnet], Repeatable| ignore-ip 1.2.3.4/16
|whitelist-ip|ip whitelist|None|[ip/subnet], RepeatableWhen the filtering server responds IPs in the IP whitelist, only result in whitelist will be accepted| whitelist-ip 1.2.3.4/16
|blacklist-ip|ip blacklist|None|[ip/subnet], RepeatableWhen the filtering server responds IPs in the IP blacklist, The result will be discarded directly| blacklist-ip 1.2.3.4/16
|force-AAAA-SOA|force AAAA query return SOA|no|[yes\|no]|force-AAAA-SOA yes
|prefetch-domain|domain prefetch feature|no|[yes\|no]|prefetch-domain yes

View File

@@ -36,6 +36,9 @@ cache-size 512
# List of IPs that will be filtered when nameserver is configured -blacklist-ip parameter
# blacklist-ip [ip/subnet]
# List of IPs that will be accepted when nameserver is configured -whitelist-ip parameter
# whitelist-ip [ip/subnet]
# List of IPs that will be ignored
# ignore-ip [ip/subnet]
@@ -80,30 +83,31 @@ log-level info
# audit-num 2
# remote udp dns server list
# server [IP]:[PORT] [-blacklist-ip] [-check-edns] [-group [group] ...] [-exclude-default-group]
# server [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-check-edns] [-group [group] ...] [-exclude-default-group]
# default port is 53
# -blacklist-ip: filter result with blacklist ip
# -whitelist-ip: filter result whth whitelist ip, result in whitelist-ip will be accepted.
# -check-edns: result must exist edns RR, or discard result.
# -group [group]: set server to group, use with nameserver /domain/group.
# -exclude-default-group: exclude this server from default group.
# server 8.8.8.8 -blacklist-ip -check-edns -group g1 -group g2
# remote tcp dns server list
# server-tcp [IP]:[PORT] [-blacklist-ip] [-group [group] ...] [-exclude-default-group]
# server-tcp [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-group [group] ...] [-exclude-default-group]
# default port is 53
# server-tcp 8.8.8.8
# remote tls dns server list
# server-tls [IP]:[PORT] [-blacklist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
# server-tls [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
# -spki-pin: TLS spki pin to verify.
# Get SKPI with this command:
# Get SPKI with this command:
# echo | openssl s_client -connect '[ip]:853' | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
# default port is 853
# server-tls 8.8.8.8
# server-tls 1.0.0.1
# remote https dns server list
# server-https https://[host]:[port]/path [-blacklist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
# server-https https://[host]:[port]/path [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
# -spki-pin: TLS spki pin to verify.
# default port is 443
# server-https https://cloudflare-dns.com/dns-query
@@ -126,4 +130,3 @@ log-level info
# ipset /domain/[ipset|-]
# ipset /www.example.com/block, set ipset with ipset name of block
# ipset /www.example.com/-, ignore this domain

View File

@@ -39,14 +39,14 @@ build()
cp $SMARTDNS_DIR/src/smartdns $ROOT/usr/sbin
chmod +x $ROOT/usr/sbin/smartdns
dpkg -b $ROOT $OUTPUTDIR/smartdns.$VER.$ARCH.deb
dpkg -b $ROOT $OUTPUTDIR/smartdns.$VER.$FILEARCH.deb
rm -fr $ROOT/
}
main()
{
OPTS=`getopt -o o:h --long arch:,ver: \
OPTS=`getopt -o o:h --long arch:,ver:,filearch: \
-n "" -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
@@ -59,6 +59,9 @@ main()
--arch)
ARCH="$2"
shift 2;;
--filearch)
FILEARCH="$2"
shift 2;;
--ver)
VER="$2"
shift 2;;
@@ -79,6 +82,10 @@ main()
return 1;
fi
if [ -z "$FILEARCH" ]; then
FILEARCH=$ARCH
fi
if [ -z "$OUTPUTDIR" ]; then
OUTPUTDIR=$CURR_DIR;
fi

View File

@@ -11,7 +11,7 @@ msgid "SmartDNS Server"
msgstr "SmartDNS 服务器"
msgid "SmartDNS is a local high-performance DNS server, supports finding fastest IP, supports ad filtering, and supports avoiding DNS poisoning."
msgstr "SmartDNS是一个本地高性能DNS服务器支持避免域名污染,支持返回最快IP支持广告过滤。"
msgstr "SmartDNS是一个本地高性能DNS服务器支持返回最快IP支持广告过滤。"
msgid "Custom Settings"
msgstr "自定义设置"

View File

@@ -70,13 +70,13 @@ o.cfgvalue = function(...)
end
---- anti-Answer-Forgery
o = s:option(Flag, "check_edns", translate("Anti Answer Forgery"), translate("Anti answer forgery, if DNS does not work properly after enabling, please turn off this feature"))
o.rmempty = false
o.default = o.disabled
o:depends("type", "udp")
o.cfgvalue = function(...)
return Flag.cfgvalue(...) or "0"
end
-- o = s:option(Flag, "check_edns", translate("Anti Answer Forgery"), translate("Anti answer forgery, if DNS does not work properly after enabling, please turn off this feature"))
-- o.rmempty = false
-- o.default = o.disabled
-- o:depends("type", "udp")
-- o.cfgvalue = function(...)
-- return Flag.cfgvalue(...) or "0"
-- end
---- SPKI pin
o = s:option(Value, "spki_pin", translate("TLS SPKI Pinning"), translate("Used to verify the validity of the TLS server, The value is Base64 encoded SPKI fingerprint, leaving blank to indicate that the validity of TLS is not verified."))

View File

@@ -61,14 +61,14 @@ build()
cd $ROOT
tar zcf $ROOT/data.tar.gz -C root .
tar zcf $OUTPUTDIR/luci-app-smartdns.$VER.$ARCH.ipk control.tar.gz data.tar.gz debian-binary
tar zcf $OUTPUTDIR/luci-app-smartdns.$VER.$FILEARCH.ipk control.tar.gz data.tar.gz debian-binary
rm -fr $ROOT/
}
main()
{
OPTS=`getopt -o o:h --long arch:,ver: \
OPTS=`getopt -o o:h --long arch:,ver:,filearch: \
-n "" -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
@@ -81,6 +81,9 @@ main()
--arch)
ARCH="$2"
shift 2;;
--filearch)
FILEARCH="$2"
shift 2;;
--ver)
VER="$2"
shift 2;;
@@ -101,6 +104,10 @@ main()
return 1;
fi
if [ -z "$FILEARCH" ]; then
FILEARCH=$ARCH
fi
if [ -z "$OUTPUTDIR" ]; then
OUTPUTDIR=$CURR_DIR;
fi

View File

@@ -126,6 +126,30 @@ conf_append()
echo "$1 $2" >> $SMARTDNS_CONF_TMP
}
get_tz()
{
SET_TZ=""
if [ -e "/etc/localtime" ]; then
return
fi
for tzfile in /etc/TZ /var/etc/TZ
do
if [ ! -e "$tzfile" ]; then
continue
fi
tz="`cat $tzfile 2>/dev/null`"
done
if [ -z "$tz" ]; then
return
fi
SET_TZ=$tz
}
load_server()
{
local section="$1"
@@ -336,6 +360,11 @@ load_service() {
procd_set_param limits core="unlimited"
fi
get_tz
if [ ! -z "$SET_TZ" ]; then
procd_set_param env TZ="$SET_TZ"
fi
procd_set_param command /usr/sbin/smartdns -f -c $SMARTDNS_CONF $args
if [ "$RESPAWN" = "1" ]; then
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}

View File

@@ -55,13 +55,13 @@ build()
cd $ROOT
tar zcf $ROOT/data.tar.gz -C root --owner=0 --group=0 .
tar zcf $OUTPUTDIR/smartdns.$VER.$ARCH.ipk --owner=0 --group=0 control.tar.gz data.tar.gz debian-binary
tar zcf $OUTPUTDIR/smartdns.$VER.$FILEARCH.ipk --owner=0 --group=0 control.tar.gz data.tar.gz debian-binary
rm -fr $ROOT/
}
main()
{
OPTS=`getopt -o o:h --long arch:,ver: \
OPTS=`getopt -o o:h --long arch:,ver:,filearch: \
-n "" -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
@@ -74,6 +74,9 @@ main()
--arch)
ARCH="$2"
shift 2;;
--filearch)
FILEARCH="$2"
shift 2;;
--ver)
VER="$2"
shift 2;;
@@ -94,6 +97,10 @@ main()
return 1;
fi
if [ -z "$FILEARCH" ]; then
FILEARCH=$ARCH
fi
if [ -z "$OUTPUTDIR" ]; then
OUTPUTDIR=$CURR_DIR;
fi

View File

@@ -2,8 +2,8 @@
SMARTDNS_BIN=/opt/usr/sbin/smartdns
SMARTDNS_CONF=/opt/etc/smartdns/smartdns.conf
DNSMASQ_CONF=/etc/dnsmasq.conf
SMARTDNS_PID="/var/run/smartdns.pid"
DNSMASQ_CONF="/etc/dnsmasq.conf /var/etc/dnsmasq.conf /etc/storage/dnsmasq/dnsmasq.conf"
SMARTDNS_PID=/var/run/smartdns.pid
SMARTDNS_PORT=535
SMARTDNS_OPT=/opt/etc/smartdns/smartdns-opt.conf
# workmode
@@ -54,7 +54,13 @@ restart_dnsmasq()
{
CMD="`ps | grep " dnsmasq" | grep -v grep 2>/dev/null`"
if [ -z "$CMD" ]; then
CMD="`ps ax | grep dnsmasq | grep -v grep 2>/dev/null`"
CMD="`ps | grep "/usr/sbin/dnsmasq" | grep -v grep 2>/dev/null`"
if [ -z "$CMD" ]; then
CMD="`ps ax | grep " dnsmasq" | grep -v grep 2>/dev/null`"
if [ -z "$CMD" ]; then
CMD="`ps ax | grep /usr/sbin/dnsmasq | grep -v grep 2>/dev/null`"
fi
fi
fi
if [ -z "$CMD" ]; then
@@ -77,6 +83,7 @@ restart_dnsmasq()
get_server_ip()
{
CONF_FILE=$1
IPS="`ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}'`"
LOCAL_SERVER_IP=""
for IP in $IPS
@@ -85,9 +92,9 @@ get_server_ip()
while [ $N -gt 0 ]
do
ADDR=`echo $IP | awk -F. "{for(i=1;i<=$N;i++)printf \\$i\".\"}"`
grep "dhcp-range=" $DNSMASQ_CONF | grep $ADDR >/dev/null 2>&1
grep "dhcp-range=" $CONF_FILE | grep $ADDR >/dev/null 2>&1
if [ $? -eq 0 ]; then
SERVER_TAG="`grep "^dhcp-range *=" $DNSMASQ_CONF | grep $ADDR | awk -F= '{print $2}' | awk -F, '{print $1}'`"
SERVER_TAG="`grep "^dhcp-range *=" $CONF_FILE | grep $ADDR | awk -F= '{print $2}' | awk -F, '{print $1}'`"
LOCAL_SERVER_IP="$IP"
return 0
fi
@@ -98,53 +105,82 @@ get_server_ip()
return 1
}
set_dnsmasq()
set_dnsmasq_conf()
{
local RESTART_DNSMASQ=0
local LOCAL_SERVER_IP=""
local SERVER_TAG=""
get_server_ip
local CONF_FILE=$1
get_server_ip $CONF_FILE
if [ "$LOCAL_SERVER_IP" ] && [ "$SERVER_TAG" ]; then
grep "dhcp-option *=" $DNSMASQ_CONF | grep "$SERVER_TAG,6,$LOCAL_SERVER_IP" > /dev/null 2>&1
grep "dhcp-option *=" $CONF_FILE | grep "$SERVER_TAG,6,$LOCAL_SERVER_IP" > /dev/null 2>&1
if [ $? -ne 0 ]; then
sed -i "/^dhcp-option *=$SERVER_TAG,6,/d" $DNSMASQ_CONF
echo "dhcp-option=$SERVER_TAG,6,$LOCAL_SERVER_IP" >> $DNSMASQ_CONF
sed -i "/^dhcp-option *=$SERVER_TAG,6,/d" $CONF_FILE
echo "dhcp-option=$SERVER_TAG,6,$LOCAL_SERVER_IP" >> $CONF_FILE
RESTART_DNSMASQ=1
fi
fi
grep "^port *=0" $DNSMASQ_CONF > /dev/null 2>&1
grep "^port *=0" $CONF_FILE > /dev/null 2>&1
if [ $? -ne 0 ]; then
sed -i "/^port *=/d" $DNSMASQ_CONF
echo "port=0" >> $DNSMASQ_CONF
sed -i "/^port *=/d" $CONF_FILE
echo "port=0" >> $CONF_FILE
RESTART_DNSMASQ=1
fi
}
set_dnsmasq()
{
local RESTART_DNSMASQ=0
for conf in $DNSMASQ_CONF
do
if [ ! -e "$conf" ]; then
continue
fi
set_dnsmasq_conf $conf
done
if [ $RESTART_DNSMASQ -ne 0 ]; then
restart_dnsmasq
fi
}
clear_dnsmasq_conf()
{
local LOCAL_SERVER_IP=""
local SERVER_TAG=""
local CONF_FILE=$1
get_server_ip $CONF_FILE
if [ "$LOCAL_SERVER_IP" ] && [ "$SERVER_TAG" ]; then
grep "dhcp-option *=" $CONF_FILE | grep "$SERVER_TAG,6,$LOCAL_SERVER_IP" > /dev/null 2>&1
if [ $? -eq 0 ]; then
sed -i "/^dhcp-option *=$SERVER_TAG,6,/d" $CONF_FILE
RESTART_DNSMASQ=1
fi
fi
grep "^port *=" $CONF_FILE > /dev/null 2>&1
if [ $? -eq 0 ]; then
sed -i "/^port *=/d" $CONF_FILE
RESTART_DNSMASQ=1
fi
}
clear_dnsmasq()
{
local RESTART_DNSMASQ=0
local LOCAL_SERVER_IP=""
local SERVER_TAG=""
get_server_ip
if [ "$LOCAL_SERVER_IP" ] && [ "$SERVER_TAG" ]; then
grep "dhcp-option *=" $DNSMASQ_CONF | grep "$SERVER_TAG,6,$LOCAL_SERVER_IP" > /dev/null 2>&1
if [ $? -eq 0 ]; then
sed -i "/^dhcp-option *=$SERVER_TAG,6,/d" $DNSMASQ_CONF
RESTART_DNSMASQ=1
fi
fi
grep "^port *=" $DNSMASQ_CONF > /dev/null 2>&1
if [ $? -eq 0 ]; then
sed -i "/^port *=/d" $DNSMASQ_CONF
RESTART_DNSMASQ=1
fi
for conf in $DNSMASQ_CONF
do
if [ ! -e "$conf" ]; then
continue
fi
clear_dnsmasq_conf $conf
done
if [ $RESTART_DNSMASQ -ne 0 ]; then
restart_dnsmasq
@@ -198,6 +234,28 @@ clear_rule()
fi
}
get_tz()
{
if [ -e "/etc/localtime" ]; then
return
fi
for tzfile in /etc/TZ /var/etc/TZ
do
if [ ! -e "$tzfile" ]; then
continue
fi
tz="`cat $tzfile 2>/dev/null`"
done
if [ -z "$tz" ]; then
return
fi
export TZ=$tz
}
case "$1" in
start)
set_rule
@@ -206,6 +264,7 @@ case "$1" in
fi
set_smartdns_port
get_tz
$SMARTDNS_BIN -c $SMARTDNS_CONF -p $SMARTDNS_PID
if [ $? -ne 0 ]; then
clear_rule

View File

@@ -44,13 +44,13 @@ build()
cd $ROOT
tar zcf data.tar.gz --owner=0 --group=0 opt
tar zcf $OUTPUTDIR/smartdns.$VER.$ARCH.ipk --owner=0 --group=0 control.tar.gz data.tar.gz debian-binary
tar zcf $OUTPUTDIR/smartdns.$VER.$FILEARCH.ipk --owner=0 --group=0 control.tar.gz data.tar.gz debian-binary
rm -fr $ROOT/
}
main()
{
OPTS=`getopt -o o:h --long arch:,ver: \
OPTS=`getopt -o o:h --long arch:,ver:,filearch: \
-n "" -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
@@ -63,6 +63,9 @@ main()
--arch)
ARCH="$2"
shift 2;;
--filearch)
FILEARCH="$2"
shift 2;;
--ver)
VER="$2"
shift 2;;
@@ -83,6 +86,10 @@ main()
return 1;
fi
if [ -z "$FILEARCH" ]; then
FILEARCH=$ARCH
fi
if [ -z "$OUTPUTDIR" ]; then
OUTPUTDIR=$CURR_DIR;
fi

View File

@@ -5,9 +5,16 @@ OBJS=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_co
CFLAGS +=-O2 -g -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing
CFLAGS +=-Iinclude
CFLAGS += -DBASE_FILE_NAME=\"$(notdir $<)\"
ifdef VER
CFLAGS += -DSMARTDNS_VERION=\"$(VER)\"
endif
CXXFLAGS=-O2 -g -Wall -std=c++11
CXXFLAGS +=-Iinclude
LDFLAGS += -lpthread -lssl -lcrypto
ifeq ($(STATIC), yes)
LDFLAGS += -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -ldl -static
else
LDFLAGS += -lssl -lcrypto -lpthread
endif
.PHONY: all

View File

@@ -19,6 +19,7 @@
#define _GNU_SOURCE
#include "dns.h"
#include "tlog.h"
#include "stringutil.h"
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
@@ -612,9 +613,9 @@ int dns_add_SOA(struct dns_packet *packet, dns_rr_type type, char *domain, int t
unsigned char data[sizeof(*soa)];
unsigned char *ptr = data;
int len = 0;
strncpy((char *)ptr, soa->mname, DNS_MAX_CNAME_LEN - 1);
safe_strncpy((char *)ptr, soa->mname, DNS_MAX_CNAME_LEN);
ptr += strnlen(soa->mname, DNS_MAX_CNAME_LEN - 1) + 1;
strncpy((char *)ptr, soa->rname, DNS_MAX_CNAME_LEN - 1);
safe_strncpy((char *)ptr, soa->rname, DNS_MAX_CNAME_LEN);
ptr += strnlen(soa->rname, DNS_MAX_CNAME_LEN - 1) + 1;
*((unsigned int *)ptr) = soa->serial;
ptr += 4;
@@ -650,12 +651,12 @@ int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct
return -1;
}
strncpy(soa->mname, (char *)ptr, DNS_MAX_CNAME_LEN - 1);
safe_strncpy(soa->mname, (char *)ptr, DNS_MAX_CNAME_LEN - 1);
ptr += strnlen(soa->mname, DNS_MAX_CNAME_LEN - 1) + 1;
if (ptr - data >= len) {
return -1;
}
strncpy(soa->rname, (char *)ptr, DNS_MAX_CNAME_LEN - 1);
safe_strncpy(soa->rname, (char *)ptr, DNS_MAX_CNAME_LEN - 1);
ptr += strnlen(soa->rname, DNS_MAX_CNAME_LEN - 1) + 1;
if (ptr - data + 20 > len) {
return -1;

View File

@@ -1,5 +1,6 @@
#include "dns_cache.h"
#include "tlog.h"
#include "stringutil.h"
#include <pthread.h>
struct dns_cache_head {
@@ -110,7 +111,7 @@ int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_typ
}
if (cname) {
strncpy(dns_cache->cname, cname, DNS_MAX_CNAME_LEN);
safe_strncpy(dns_cache->cname, cname, DNS_MAX_CNAME_LEN);
dns_cache->cname_ttl = cname_ttl;
}
pthread_mutex_unlock(&dns_cache_head.lock);
@@ -154,7 +155,7 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type
key = hash_string(domain);
key = jhash(&qtype, sizeof(qtype), key);
strncpy(dns_cache->domain, domain, DNS_MAX_CNAME_LEN);
safe_strncpy(dns_cache->domain, domain, DNS_MAX_CNAME_LEN);
dns_cache->cname[0] = 0;
dns_cache->qtype = qtype;
dns_cache->ttl = ttl;
@@ -178,7 +179,7 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type
}
if (cname) {
strncpy(dns_cache->cname, cname, DNS_MAX_CNAME_LEN);
safe_strncpy(dns_cache->cname, cname, DNS_MAX_CNAME_LEN);
dns_cache->cname_ttl = cname_ttl;
}

View File

@@ -20,6 +20,7 @@
#include "atomic.h"
#include "dns.h"
#include "dns_conf.h"
#include "dns_server.h"
#include "fast_ping.h"
#include "hashtable.h"
#include "http_parse.h"
@@ -94,6 +95,7 @@ struct dns_server_info {
struct ping_host_struct *ping_host;
char ip[DNS_HOSTNAME_LEN];
int port;
/* server type */
dns_server_type_t type;
@@ -125,6 +127,33 @@ struct dns_server_info {
struct client_dns_server_flags flags;
};
struct dns_server_pending_group {
struct list_head list;
char group_name[DNS_GROUP_NAME_LEN];
};
struct dns_server_pending {
struct list_head list;
char host[DNS_HOSTNAME_LEN];
char ipv4[DNS_HOSTNAME_LEN];
char ipv6[DNS_HOSTNAME_LEN];
unsigned int ping_time_v6;
unsigned int ping_time_v4;
unsigned int has_v4;
unsigned int has_v6;
unsigned int query_v4;
unsigned int query_v6;
/* server type */
dns_server_type_t type;
int port;
struct client_dns_server_flags flags;
struct list_head group_list;
};
/* upstream server group member */
struct dns_server_group_member {
struct list_head list;
@@ -211,6 +240,9 @@ struct dns_query_struct {
static struct dns_client client;
static atomic_t dns_client_sid = ATOMIC_INIT(0);
static LIST_HEAD(pending_servers);
pthread_mutex_t pending_server_mutex = PTHREAD_MUTEX_INITIALIZER;
static int dns_client_has_bootstrap_dns = 0;
/* get addr info */
static struct addrinfo *_dns_client_getaddr(const char *host, char *port, int type, int protocol)
@@ -240,21 +272,17 @@ errout:
}
/* check whether server exists */
static int _dns_client_server_exist(struct addrinfo *gai, dns_server_type_t server_type)
static int _dns_client_server_exist(const char *server_ip, int port, dns_server_type_t server_type)
{
struct dns_server_info *server_info, *tmp;
pthread_mutex_lock(&client.server_list_lock);
list_for_each_entry_safe(server_info, tmp, &client.dns_server_list, list)
{
if (server_info->ai_addrlen != gai->ai_addrlen || server_info->ai_family != gai->ai_family) {
if (server_info->port != port || server_info->type != server_type) {
continue;
}
if (server_info->type != server_type) {
continue;
}
if (memcmp(&server_info->addr, gai->ai_addr, gai->ai_addrlen) != 0) {
if (strncmp(server_info->ip, server_ip, DNS_HOSTNAME_LEN)) {
continue;
}
@@ -284,49 +312,15 @@ static struct dns_server_info *_dns_client_get_server(char *server_ip, int port,
{
struct dns_server_info *server_info, *tmp;
struct dns_server_info *server_info_return = NULL;
char port_s[8];
int sock_type;
struct addrinfo *gai = NULL;
if (server_type >= DNS_SERVER_TYPE_END) {
tlog(TLOG_ERROR, "server type is invalid.");
return NULL;
}
switch (server_type) {
case DNS_SERVER_UDP:
sock_type = SOCK_DGRAM;
break;
case DNS_SERVER_TCP:
case DNS_SERVER_TLS:
case DNS_SERVER_HTTPS:
sock_type = SOCK_STREAM;
break;
default:
return NULL;
break;
}
/* get addr info */
snprintf(port_s, 8, "%d", port);
gai = _dns_client_getaddr(server_ip, port_s, sock_type, 0);
if (gai == NULL) {
tlog(TLOG_ERROR, "get address failed, %s:%d", server_ip, port);
goto errout;
}
pthread_mutex_lock(&client.server_list_lock);
list_for_each_entry_safe(server_info, tmp, &client.dns_server_list, list)
{
if (server_info->ai_addrlen != gai->ai_addrlen || server_info->ai_family != gai->ai_family) {
if (server_info->port != port || server_info->type != server_type) {
continue;
}
if (server_info->type != server_type) {
continue;
}
if (memcmp(&server_info->addr, gai->ai_addr, gai->ai_addrlen) != 0) {
if (strncmp(server_info->ip, server_ip, DNS_HOSTNAME_LEN)) {
continue;
}
@@ -337,13 +331,7 @@ static struct dns_server_info *_dns_client_get_server(char *server_ip, int port,
pthread_mutex_unlock(&client.server_list_lock);
freeaddrinfo(gai);
return server_info_return;
errout:
if (gai) {
freeaddrinfo(gai);
}
return NULL;
}
/* get server group by name */
@@ -421,19 +409,69 @@ errout:
return -1;
}
static int _dns_client_add_to_pending_group(char *group_name, char *server_ip, int port, dns_server_type_t server_type)
{
struct dns_server_pending *item, *tmp;
struct dns_server_pending *pending = NULL;
struct dns_server_pending_group *group = NULL;
pthread_mutex_lock(&pending_server_mutex);
list_for_each_entry_safe(item, tmp, &pending_servers, list)
{
if (strncmp(item->host, server_ip, DNS_HOSTNAME_LEN) == 0 && item->port == port && item->type == server_type) {
pending = item;
break;
}
}
pthread_mutex_unlock(&pending_server_mutex);
if (pending == NULL) {
tlog(TLOG_ERROR, "cannot found server for group %s: %s, %d, %d", group_name, server_ip, port, server_type);
goto errout;
}
group = malloc(sizeof(*group));
if (group == NULL) {
goto errout;
}
memset(group, 0, sizeof(*group));
safe_strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
pthread_mutex_lock(&pending_server_mutex);
list_add_tail(&group->list, &pending->group_list);
pthread_mutex_unlock(&pending_server_mutex);
return 0;
errout:
if (group) {
free(group);
}
return -1;
}
/* add server to group */
int dns_client_add_to_group(char *group_name, char *server_ip, int port, dns_server_type_t server_type)
int _dns_client_add_to_group_pending(char *group_name, char *server_ip, int port, dns_server_type_t server_type, int ispending)
{
struct dns_server_info *server_info = NULL;
server_info = _dns_client_get_server(server_ip, port, server_type);
if (server_info == NULL) {
return -1;
if (ispending == 0) {
tlog(TLOG_ERROR, "add server %s:%d to group %s failed", server_ip, port, group_name);
return -1;
}
return _dns_client_add_to_pending_group(group_name, server_ip, port, server_type);
}
return _dns_client_add_to_group(group_name, server_info);
}
int dns_client_add_to_group(char *group_name, char *server_ip, int port, dns_server_type_t server_type)
{
return _dns_client_add_to_group_pending(group_name, server_ip, port, server_type, 1);
}
/* free group member */
static int _dns_client_remove_member(struct dns_server_group_member *group_member)
{
@@ -509,7 +547,7 @@ int dns_client_add_group(char *group_name)
memset(group, 0, sizeof(*group));
INIT_LIST_HEAD(&group->head);
strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
safe_strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
key = hash_string(group_name);
hash_add(client.group, &group->node, key);
@@ -618,12 +656,15 @@ static char *_dns_client_server_get_spki(struct dns_server_info *server_info, in
}
/* add dns server information */
static int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_type_t server_type, struct client_dns_server_flags *flags)
static int _dns_client_server_add(char *server_ip, char *server_host, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags)
{
struct dns_server_info *server_info = NULL;
struct addrinfo *gai = NULL;
unsigned char *spki_data = NULL;
int spki_data_len = 0;
int ttl = 0;
char port_s[8];
int sock_type;
switch (server_type) {
case DNS_SERVER_UDP: {
@@ -634,20 +675,29 @@ static int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_ser
} else if (ttl < -32) {
ttl = -32;
}
sock_type = SOCK_DGRAM;
} break;
case DNS_SERVER_HTTPS: {
struct client_dns_server_flag_https *flag_https = &flags->https;
spki_data_len = flag_https->spi_len;
if (flag_https->httphost[0] == 0) {
strncpy(flag_https->httphost, server_ip, DNS_MAX_CNAME_LEN);
if (server_host) {
safe_strncpy(flag_https->httphost, server_host, DNS_MAX_CNAME_LEN);
} else {
safe_strncpy(flag_https->httphost, server_ip, DNS_MAX_CNAME_LEN);
}
}
sock_type = SOCK_STREAM;
} break;
case DNS_SERVER_TLS: {
struct client_dns_server_flag_tls *flag_tls = &flags->tls;
spki_data_len = flag_tls->spi_len;
sock_type = SOCK_STREAM;
} break;
break;
case DNS_SERVER_TCP:
sock_type = SOCK_STREAM;
break;
default:
return -1;
@@ -660,10 +710,17 @@ static int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_ser
}
/* if server exist, return */
if (_dns_client_server_exist(gai, server_type) == 0) {
if (_dns_client_server_exist(server_ip, port, server_type) == 0) {
return 0;
}
snprintf(port_s, 8, "%d", port);
gai = _dns_client_getaddr(server_ip, port_s, sock_type, 0);
if (gai == NULL) {
tlog(TLOG_DEBUG, "get address failed, %s:%d", server_ip, port);
goto errout;
}
server_info = malloc(sizeof(*server_info));
if (server_info == NULL) {
goto errout;
@@ -674,7 +731,8 @@ static int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_ser
}
memset(server_info, 0, sizeof(*server_info));
strncpy(server_info->ip, server_ip, sizeof(server_info->ip));
safe_strncpy(server_info->ip, server_ip, sizeof(server_info->ip));
server_info->port = port;
server_info->ai_family = gai->ai_family;
server_info->ai_addrlen = gai->ai_addrlen;
server_info->type = server_type;
@@ -694,7 +752,11 @@ static int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_ser
/* if server type is TLS, create ssl context */
if (server_type == DNS_SERVER_TLS || server_type == DNS_SERVER_HTTPS) {
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
server_info->ssl_ctx = SSL_CTX_new(TLS_client_method());
#else
server_info->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
#endif
if (server_info->ssl_ctx == NULL) {
tlog(TLOG_ERROR, "init ssl failed.");
goto errout;
@@ -729,6 +791,8 @@ static int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_ser
pthread_mutex_unlock(&client.server_list_lock);
atomic_inc(&client.dns_server_num);
freeaddrinfo(gai);
return 0;
errout:
if (spki_data) {
@@ -747,6 +811,10 @@ errout:
free(server_info);
}
if (gai) {
freeaddrinfo(gai);
}
return -1;
}
@@ -812,7 +880,7 @@ static void _dns_client_server_remove_all(void)
}
/* remove single server */
static int _dns_client_server_remove(char *server_ip, struct addrinfo *gai, dns_server_type_t server_type)
static int _dns_client_server_remove(char *server_ip, int port, dns_server_type_t server_type)
{
struct dns_server_info *server_info, *tmp;
@@ -820,11 +888,11 @@ static int _dns_client_server_remove(char *server_ip, struct addrinfo *gai, dns_
pthread_mutex_lock(&client.server_list_lock);
list_for_each_entry_safe(server_info, tmp, &client.dns_server_list, list)
{
if (server_info->ai_addrlen != gai->ai_addrlen || server_info->ai_family != gai->ai_family) {
if (server_info->port != port || server_info->type != server_type) {
continue;
}
if (memcmp(&server_info->addr, gai->ai_addr, gai->ai_addrlen) != 0) {
if (strncmp(server_info->ip, server_ip, DNS_HOSTNAME_LEN)) {
continue;
}
@@ -840,70 +908,79 @@ static int _dns_client_server_remove(char *server_ip, struct addrinfo *gai, dns_
return -1;
}
static int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags, int operate)
static int _dns_client_server_pending(char *server_ip, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags)
{
struct dns_server_pending *pending = NULL;
pending = malloc(sizeof(*pending));
if (pending == NULL) {
tlog(TLOG_ERROR, "malloc failed");
goto errout;
}
memset(pending, 0, sizeof(*pending));
safe_strncpy(pending->host, server_ip, DNS_HOSTNAME_LEN);
pending->port = port;
pending->type = server_type;
pending->ping_time_v4 = -1;
pending->ping_time_v6 = -1;
pending->ipv4[0] = 0;
pending->ipv6[0] = 0;
pending->has_v4 = 0;
pending->has_v6 = 0;
INIT_LIST_HEAD(&pending->group_list);
memcpy(&pending->flags, flags, sizeof(struct client_dns_server_flags));
pthread_mutex_lock(&pending_server_mutex);
list_add_tail(&pending->list, &pending_servers);
pthread_mutex_unlock(&pending_server_mutex);
return 0;
errout:
if (pending) {
free(pending);
}
return -1;
}
static int _dns_client_add_server_pending(char *server_ip, char *server_host, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags, int ispending)
{
char port_s[8];
int sock_type;
int ret;
struct addrinfo *gai = NULL;
if (server_type >= DNS_SERVER_TYPE_END) {
tlog(TLOG_ERROR, "server type is invalid.");
return -1;
}
switch (server_type) {
case DNS_SERVER_UDP:
sock_type = SOCK_DGRAM;
break;
case DNS_SERVER_TCP:
case DNS_SERVER_TLS:
case DNS_SERVER_HTTPS:
sock_type = SOCK_STREAM;
break;
default:
return -1;
break;
if (check_is_ipaddr(server_ip) && ispending) {
ret = _dns_client_server_pending(server_ip, port, server_type, flags);
if (ret == 0) {
tlog(TLOG_INFO, "add pending server %s", server_ip);
return 0;
}
}
/* get addr info */
snprintf(port_s, 8, "%d", port);
gai = _dns_client_getaddr(server_ip, port_s, sock_type, 0);
if (gai == NULL) {
tlog(TLOG_ERROR, "get address failed, %s:%d", server_ip, port);
/* add server */
ret = _dns_client_server_add(server_ip, server_host, port, server_type, flags);
if (ret != 0) {
goto errout;
}
if (operate == 0) {
/* add server */
ret = _dns_client_server_add(server_ip, gai, server_type, flags);
if (ret != 0) {
goto errout;
}
} else {
/* remove server */
ret = _dns_client_server_remove(server_ip, gai, server_type);
if (ret != 0) {
goto errout;
}
}
freeaddrinfo(gai);
dns_client_has_bootstrap_dns = 1;
return 0;
errout:
if (gai) {
freeaddrinfo(gai);
}
return -1;
}
int dns_client_add_server(char *server_ip, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags)
{
return _dns_client_server_operate(server_ip, port, server_type, flags, 0);
return _dns_client_add_server_pending(server_ip, NULL, port, server_type, flags, 1);
}
int dns_client_remove_server(char *server_ip, int port, dns_server_type_t server_type)
{
return _dns_client_server_operate(server_ip, port, server_type, NULL, 1);
return _dns_client_server_remove(server_ip, port, server_type);
}
int dns_server_num(void)
@@ -1399,7 +1476,7 @@ static int _dns_client_create_socket(struct dns_server_info *server_info)
struct client_dns_server_flag_https *flag_https;
flag_https = &server_info->flags.https;
return _DNS_client_create_socket_tls(server_info, flag_https->hostname);
}else {
} else {
return -1;
}
@@ -2302,7 +2379,7 @@ int dns_client_query(char *domain, int qtype, dns_client_callback callback, void
atomic_set(&query->dns_request_sent, 0);
atomic_set(&query->retry_count, DNS_QUERY_RETRY);
hash_init(query->replied_map);
strncpy(query->domain, domain, DNS_MAX_CNAME_LEN);
safe_strncpy(query->domain, domain, DNS_MAX_CNAME_LEN);
query->user_ptr = user_ptr;
query->callback = callback;
query->qtype = qtype;
@@ -2378,10 +2455,114 @@ static void _dns_client_check_servers(void)
pthread_mutex_unlock(&client.server_list_lock);
}
static int _dns_client_pending_server_resolve(char *domain, dns_rtcode_t rtcode, dns_type_t addr_type, char *ip, unsigned int ping_time, void *user_ptr)
{
struct dns_server_pending *pending = user_ptr;
if (addr_type == DNS_T_A) {
pending->has_v4 = 1;
pending->ping_time_v4 = -1;
if (rtcode == DNS_RC_NOERROR) {
pending->ping_time_v4 = ping_time;
safe_strncpy(pending->ipv4, ip, DNS_HOSTNAME_LEN);
}
} else if (addr_type == DNS_T_AAAA) {
pending->has_v6 = 1;
pending->ping_time_v6 = -1;
if (rtcode == DNS_RC_NOERROR) {
pending->ping_time_v6 = ping_time;
safe_strncpy(pending->ipv6, ip, DNS_HOSTNAME_LEN);
}
} else {
return -1;
}
return 0;
}
static int _dns_client_add_pendings(struct dns_server_pending *pending, char *ip)
{
struct dns_server_pending_group *group, *tmp;
if (_dns_client_add_server_pending(ip, pending->host, pending->port, pending->type, &pending->flags, 0) != 0) {
return -1;
}
list_for_each_entry_safe(group, tmp, &pending->group_list, list)
{
if (_dns_client_add_to_group_pending(group->group_name, ip, pending->port, pending->type, 0) != 0) {
tlog(TLOG_WARN, "add server to group failed, skip add.");
}
list_del_init(&group->list);
free(group);
}
return 0;
}
static void _dns_client_add_pending_servers(void)
{
struct dns_server_pending *pending, *tmp;
static int dely = 0;
/* add pending server after 3 seconds */
if (++dely < 3) {
return;
}
pthread_mutex_lock(&pending_server_mutex);
list_for_each_entry_safe(pending, tmp, &pending_servers, list)
{
/* send dns type A, AAAA query to bootstrap DNS server */
if (pending->query_v4 == 0) {
pending->query_v4 = 1;
dns_server_query(pending->host, DNS_T_A, _dns_client_pending_server_resolve, pending);
}
if (pending->query_v6 == 0) {
pending->query_v6 = 1;
dns_server_query(pending->host, DNS_T_AAAA, _dns_client_pending_server_resolve, pending);
}
/* if both A, AAAA has query result, select fastest IP address */
if (pending->has_v4 && pending->has_v6) {
char *ip = NULL;
if (pending->ping_time_v4 <= pending->ping_time_v6 && pending->ipv4[0]) {
ip = pending->ipv4;
} else {
ip = pending->ipv6;
}
if (ip[0]) {
if (_dns_client_add_pendings(pending, ip) != 0) {
tlog(TLOG_WARN, "add pending DNS server %s failed.", pending->host);
}
}
list_del_init(&pending->list);
free(pending);
}
/* if has no bootstrap DNS, just call getaddrinfo to get address */
if (dns_client_has_bootstrap_dns == 0) {
if (_dns_client_add_pendings(pending, pending->host) != 0) {
tlog(TLOG_ERROR, "add pending DNS server %s failed", pending->host);
exit(1);
pthread_mutex_unlock(&pending_server_mutex);
return;
}
list_del_init(&pending->list);
free(pending);
}
}
pthread_mutex_unlock(&pending_server_mutex);
}
static void _dns_client_period_run_second(void)
{
_dns_client_check_tcp();
_dns_client_check_servers();
_dns_client_add_pending_servers();
}
static void _dns_client_period_run(void)

View File

@@ -20,8 +20,9 @@ typedef enum dns_result_type {
} dns_result_type;
#define DNSSERVER_FLAG_BLACKLIST_IP (0x1 << 0)
#define DNSSERVER_FLAG_CHECK_EDNS (0x1 << 1)
#define DNSSERVER_FLAG_CHECK_TTL (0x1 << 2)
#define DNSSERVER_FLAG_WHITELIST_IP (0x1 << 1)
#define DNSSERVER_FLAG_CHECK_EDNS (0x1 << 2)
#define DNSSERVER_FLAG_CHECK_TTL (0x1 << 3)
int dns_client_init(void);

View File

@@ -9,7 +9,7 @@
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <libgen.h>
#include <libgen.h>
#define DEFAULT_DNS_CACHE_SIZE 512
@@ -90,7 +90,7 @@ static struct dns_server_groups *_dns_conf_get_group(const char *group_name)
}
memset(group, 0, sizeof(*group));
strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
safe_strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
hash_add(dns_group_table.group, &group->node, key);
return group;
@@ -168,7 +168,11 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
/* clang-format off */
static struct option long_options[] = {
{"blacklist-ip", no_argument, NULL, 'b'}, /* filtering with blacklist-ip */
{"whitelist-ip", no_argument, NULL, 'w'}, /* filtering with whitelist-ip */
#ifdef FEATURE_CHECK_EDNS
/* experimental feature */
{"check-edns", no_argument, NULL, 'e'}, /* check edns */
#endif
{"spki-pin", required_argument, NULL, 'p'}, /* check SPKI pin */
{"host-name", required_argument, NULL, 'h'}, /* host name */
{"http-host", required_argument, NULL, 'H'}, /* http host */
@@ -199,8 +203,8 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
if (parse_uri(ip, NULL, server->server, &port, server->path) != 0) {
return -1;
}
strncpy(server->hostname, server->server, sizeof(server->hostname));
strncpy(server->httphost, server->httphost, sizeof(server->hostname));
safe_strncpy(server->hostname, server->server, sizeof(server->hostname));
safe_strncpy(server->httphost, server->server, sizeof(server->httphost));
if (server->path[0] == 0) {
strcpy(server->path, "/");
}
@@ -229,16 +233,20 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
result_flag |= DNSSERVER_FLAG_BLACKLIST_IP;
break;
}
case 'w': {
result_flag |= DNSSERVER_FLAG_WHITELIST_IP;
break;
}
case 'e': {
result_flag |= DNSSERVER_FLAG_CHECK_EDNS;
break;
}
case 'h': {
strncpy(server->hostname, optarg, DNS_MAX_CNAME_LEN);
safe_strncpy(server->hostname, optarg, DNS_MAX_CNAME_LEN);
break;
}
case 'H': {
strncpy(server->httphost, optarg, DNS_MAX_CNAME_LEN);
safe_strncpy(server->httphost, optarg, DNS_MAX_CNAME_LEN);
break;
}
case 'E': {
@@ -253,7 +261,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
break;
}
case 'p': {
strncpy(server->spki, optarg, DNS_MAX_SPKI_LEN);
safe_strncpy(server->spki, optarg, DNS_MAX_SPKI_LEN);
break;
}
default:
@@ -336,7 +344,7 @@ static int _config_domain_rule_add(char *domain, enum domain_rule type, void *ru
tlog(TLOG_ERROR, "domain name %s too long", domain);
goto errout;
}
reverse_string(domain_key, domain, len);
reverse_string(domain_key, domain, len, 1);
domain_key[len] = '.';
len++;
domain_key[len] = 0;
@@ -397,7 +405,7 @@ static int _config_domain_rule_flag_set(char *domain, unsigned int flag)
tlog(TLOG_ERROR, "domain %s too long", domain);
return -1;
}
reverse_string(domain_key, domain, len);
reverse_string(domain_key, domain, len, 1);
domain_key[len] = '.';
len++;
domain_key[len] = 0;
@@ -473,7 +481,7 @@ static const char *_dns_conf_get_ipset(const char *ipsetname)
}
key = hash_string(ipsetname);
strncpy(ipset_name->ipsetname, ipsetname, DNS_MAX_IPSET_NAMELEN);
safe_strncpy(ipset_name->ipsetname, ipsetname, DNS_MAX_IPSET_NAMELEN);
hash_add(dns_ipset_table.ipset, &ipset_name->node, key);
return ipset_name->ipsetname;
@@ -489,7 +497,7 @@ static int _config_ipset(void *data, int argc, char *argv[])
{
struct dns_ipset_rule *ipset_rule = NULL;
char domain[DNS_MAX_CONF_CNAME_LEN];
char ipsetname[DNS_MAX_CONF_CNAME_LEN];
char ipsetname[DNS_MAX_IPSET_NAMELEN];
const char *ipset = NULL;
char *begin = NULL;
char *end = NULL;
@@ -536,7 +544,7 @@ static int _config_ipset(void *data, int argc, char *argv[])
/* Process domain option */
if (strncmp(end + 1, "-", sizeof("-")) != 0) {
/* new ipset domain */
strncpy(ipsetname, end + 1, DNS_MAX_IPSET_NAMELEN);
safe_strncpy(ipsetname, end + 1, DNS_MAX_IPSET_NAMELEN);
ipset = _dns_conf_get_ipset(ipsetname);
if (ipset == NULL) {
goto errout;
@@ -791,7 +799,7 @@ static int _config_nameserver(void *data, int argc, char *argv[])
}
if (strncmp(end + 1, "-", sizeof("-")) != 0) {
strncpy(group_name, end + 1, DNS_GROUP_NAME_LEN);
safe_strncpy(group_name, end + 1, DNS_GROUP_NAME_LEN);
group = _dns_conf_get_group_name(group_name);
if (group == NULL) {
goto errout;
@@ -878,11 +886,17 @@ static int _config_iplist_rule(char *subnet, enum address_rule rule)
case ADDRESS_RULE_BLACKLIST:
ip_rule->blacklist = 1;
break;
case ADDRESS_RULE_WHITELIST:
ip_rule->whitelist = 1;
break;
case ADDRESS_RULE_BOGUS:
ip_rule->bogus = 1;
break;
case ADDRESS_RULE_IP_IGNORE:
ip_rule->ip_ignore = 1;
break;
default:
return -1;
}
return 0;
@@ -915,6 +929,15 @@ static int _conf_ip_ignore(void *data, int argc, char *argv[])
return _config_iplist_rule(argv[1], ADDRESS_RULE_IP_IGNORE);
}
static int _conf_whitelist_ip(void *data, int argc, char *argv[])
{
if (argc <= 1) {
return -1;
}
return _config_iplist_rule(argv[1], ADDRESS_RULE_WHITELIST);
}
static int _conf_edns_client_subnet(void *data, int argc, char *argv[])
{
char *slash = NULL;
@@ -955,7 +978,7 @@ static int _conf_edns_client_subnet(void *data, int argc, char *argv[])
goto errout;
}
strncpy(ecs->ip, value, DNS_MAX_IPLEN);
safe_strncpy(ecs->ip, value, DNS_MAX_IPLEN);
ecs->subnet = subnet;
ecs->enable = 1;
@@ -1019,6 +1042,7 @@ static struct config_item _config_item[] = {
CONF_INT("rr-ttl-max", &dns_conf_rr_ttl_max, 0, CONF_INT_MAX),
CONF_YESNO("force-AAAA-SOA", &dns_conf_force_AAAA_SOA),
CONF_CUSTOM("blacklist-ip", _config_blacklist_ip, NULL),
CONF_CUSTOM("whitelist-ip", _conf_whitelist_ip, NULL),
CONF_CUSTOM("bogus-nxdomain", _conf_bogus_nxdomain, NULL),
CONF_CUSTOM("ignore-ip", _conf_ip_ignore, NULL),
CONF_CUSTOM("edns-client-subnet", _conf_edns_client_subnet, NULL),
@@ -1048,11 +1072,13 @@ int config_addtional_file(void *data, int argc, char *argv[])
char file_path_dir[DNS_MAX_PATH];
if (conf_file[0] != '/') {
strncpy(file_path_dir, conf_get_conf_file(), DNS_MAX_PATH);
safe_strncpy(file_path_dir, conf_get_conf_file(), DNS_MAX_PATH);
dirname(file_path_dir);
snprintf(file_path, DNS_MAX_PATH, "%s/%s", file_path_dir, conf_file);
if (snprintf(file_path, DNS_MAX_PATH, "%s/%s", file_path_dir, conf_file) < 0) {
return -1;
}
} else {
strncpy(file_path, conf_file, DNS_MAX_PATH);
safe_strncpy(file_path, conf_file, DNS_MAX_PATH);
}
if (access(file_path, R_OK) != 0) {

View File

@@ -114,12 +114,14 @@ struct dns_bogus_ip_address {
enum address_rule {
ADDRESS_RULE_BLACKLIST = 1,
ADDRESS_RULE_BOGUS = 2,
ADDRESS_RULE_IP_IGNORE = 3,
ADDRESS_RULE_WHITELIST = 2,
ADDRESS_RULE_BOGUS = 3,
ADDRESS_RULE_IP_IGNORE = 4,
};
struct dns_ip_address_rule {
unsigned int blacklist : 1;
unsigned int whitelist : 1;
unsigned int bogus : 1;
unsigned int ip_ignore : 1;
};

View File

@@ -246,11 +246,11 @@ static int _dns_add_rrs(struct dns_packet *packet, struct dns_request *request)
/* if hostname is (none), return smartdns */
if (strncmp(hostname, "(none)", DNS_MAX_CNAME_LEN) == 0) {
strncpy(hostname, "smartdns", DNS_MAX_CNAME_LEN);
safe_strncpy(hostname, "smartdns", DNS_MAX_CNAME_LEN);
}
} else {
/* return configured server name */
strncpy(hostname, dns_conf_server_name, DNS_MAX_CNAME_LEN);
safe_strncpy(hostname, dns_conf_server_name, DNS_MAX_CNAME_LEN);
}
ret = dns_add_PTR(packet, DNS_RRS_AN, request->domain, 30, hostname);
@@ -471,8 +471,8 @@ static int _dns_server_reply_SOA(int rcode, struct dns_request *request, struct
soa = &request->soa;
strncpy(soa->mname, "a.gtld-servers.net", DNS_MAX_CNAME_LEN);
strncpy(soa->rname, "nstld.verisign-grs.com", DNS_MAX_CNAME_LEN);
safe_strncpy(soa->mname, "a.gtld-servers.net", DNS_MAX_CNAME_LEN);
safe_strncpy(soa->rname, "nstld.verisign-grs.com", DNS_MAX_CNAME_LEN);
soa->serial = 1800;
soa->refresh = 1800;
soa->retry = 900;
@@ -528,6 +528,7 @@ static int _dns_setup_ipset(struct dns_request *request)
static int _dns_result_callback(struct dns_request *request)
{
char ip[DNS_MAX_CNAME_LEN];
unsigned int ping_time = -1;
if (request->result_callback == NULL) {
return 0;
@@ -540,8 +541,8 @@ static int _dns_result_callback(struct dns_request *request)
}
sprintf(ip, "%d.%d.%d.%d", request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
return request->result_callback(request->domain, request->rcode, request->qtype, ip, request->user_ptr);
ping_time = request->ping_ttl_v4;
return request->result_callback(request->domain, request->rcode, request->qtype, ip, ping_time, request->user_ptr);
} else if (request->qtype == DNS_T_AAAA) {
if (request->has_ipv6 == 0) {
goto out;
@@ -551,16 +552,16 @@ static int _dns_result_callback(struct dns_request *request)
request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], request->ipv6_addr[6], request->ipv6_addr[7],
request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12], request->ipv6_addr[13],
request->ipv6_addr[14], request->ipv6_addr[15]);
return request->result_callback(request->domain, request->rcode, request->qtype, ip, request->user_ptr);
ping_time = request->ping_ttl_v6;
return request->result_callback(request->domain, request->rcode, request->qtype, ip, ping_time, request->user_ptr);
}
request->result_callback(request->domain, DNS_RC_NXDOMAIN, request->qtype, ip, request->user_ptr);
request->result_callback(request->domain, DNS_RC_NXDOMAIN, request->qtype, ip, ping_time, request->user_ptr);
return 0;
out:
request->result_callback(request->domain, DNS_RC_NXDOMAIN, request->qtype, ip, request->user_ptr);
request->result_callback(request->domain, DNS_RC_NXDOMAIN, request->qtype, ip, ping_time, request->user_ptr);
return 0;
}
@@ -961,11 +962,11 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
}
if (node == NULL) {
return -1;
goto rule_not_found;
}
if (node->data == NULL) {
return -1;
goto rule_not_found;
}
/* bogux-nxdomain */
@@ -985,7 +986,17 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
if (rule->ip_ignore) {
goto skip;
}
rule_not_found:
if (result_flag & DNSSERVER_FLAG_WHITELIST_IP) {
if (rule == NULL) {
goto skip;
}
if (!rule->whitelist) {
goto skip;
}
}
return -1;
skip:
return -2;
@@ -1184,7 +1195,7 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
char cname[128];
dns_get_CNAME(rrs, name, 128, &ttl, cname, 128);
tlog(TLOG_DEBUG, "name:%s ttl: %d cname: %s\n", name, ttl, cname);
strncpy(request->cname, cname, DNS_MAX_CNAME_LEN);
safe_strncpy(request->cname, cname, DNS_MAX_CNAME_LEN);
request->ttl_cname = ttl;
request->has_cname = 1;
} break;
@@ -1364,7 +1375,7 @@ static void _dns_server_log_rule(char *domain, unsigned char *rule_key, int rule
return;
}
reverse_string(rule_name, (char *)rule_key, rule_key_len);
reverse_string(rule_name, (char *)rule_key, rule_key_len, 1);
rule_name[rule_key_len] = 0;
tlog(TLOG_INFO, "RULE-MATCH, domain: %s, rule: %s", domain, rule_name);
}
@@ -1379,7 +1390,7 @@ static struct dns_domain_rule *_dns_server_get_domain_rule(char *domain)
/* reverse domain string */
domain_len = strlen(domain);
reverse_string(domain_key, domain, domain_len);
reverse_string(domain_key, domain, domain_len, 1);
domain_key[domain_len] = '.';
domain_len++;
domain_key[domain_len] = 0;
@@ -1552,7 +1563,7 @@ static int _dns_server_process_cache(struct dns_request *request, struct dns_pac
}
if (dns_cache->cname[0] != 0) {
strncpy(request->cname, dns_cache->cname, DNS_MAX_CNAME_LEN);
safe_strncpy(request->cname, dns_cache->cname, DNS_MAX_CNAME_LEN);
request->has_cname = 1;
request->ttl_cname = dns_cache->cname_ttl;
}
@@ -1785,7 +1796,7 @@ static int _dns_server_prefetch_request(char *domain, dns_type_t qtype)
request->id = 0;
hash_init(request->ip_map);
strncpy(request->domain, domain, DNS_MAX_CNAME_LEN);
safe_strncpy(request->domain, domain, DNS_MAX_CNAME_LEN);
/* lookup domain rule */
request->domain_rule = _dns_server_get_domain_rule(request->domain);
@@ -1857,7 +1868,7 @@ int dns_server_query(char *domain, int qtype, dns_result_callback callback, void
request->id = 0;
hash_init(request->ip_map);
strncpy(request->domain, domain, DNS_MAX_CNAME_LEN);
safe_strncpy(request->domain, domain, DNS_MAX_CNAME_LEN);
/* lookup domain rule */
request->domain_rule = _dns_server_get_domain_rule(request->domain);

View File

@@ -18,7 +18,7 @@ void dns_server_stop(void);
void dns_server_exit(void);
/* query result notify function */
typedef int (*dns_result_callback)(char *domain, dns_rtcode_t rtcode, dns_type_t addr_type, char *ip, void *user_ptr);
typedef int (*dns_result_callback)(char *domain, dns_rtcode_t rtcode, dns_type_t addr_type, char *ip, unsigned int ping_time, void *user_ptr);
/* query domain */
int dns_server_query(char *domain, int qtype, dns_result_callback callback, void *user_ptr);

View File

@@ -867,7 +867,7 @@ struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int c
}
memset(ping_host, 0, sizeof(*ping_host));
strncpy(ping_host->host, host, PING_MAX_HOSTLEN);
safe_strncpy(ping_host->host, host, PING_MAX_HOSTLEN);
ping_host->fd = -1;
ping_host->timeout = timeout;
ping_host->count = count;

23
src/include/stringutil.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef _GENERIC_STRING_UITL_H
#define _GENERIC_STRING_UITL_H
#include <stddef.h>
#include <string.h>
static inline char *safe_strncpy(char *dest, const char *src, size_t n)
{
#if __GNUC__ > 7
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
#endif
char *ret = strncpy(dest, src, n - 1);
if (n > 0) {
dest[n - 1] = '\0';
}
#if __GNUC__ > 7
#pragma GCC diagnostic pop
#endif
return ret;
}
#endif

0
src/lib/stringutil.c Normal file
View File

View File

@@ -59,7 +59,8 @@ static void _help(void)
" -c [conf] config file.\n"
" -p [pid] pid file path\n"
" -S ignore segment fault signal.\n"
" -v verbose screent.\n"
" -x verbose screen.\n"
" -v dispaly version.\n"
" -h show this help message.\n"
"Online help: http://pymumu.github.io/smartdns\n"
@@ -69,6 +70,21 @@ static void _help(void)
printf("%s", help);
}
static void _show_version(void)
{
char str_ver[256] = {0};
#ifdef SMARTDNS_VERION
const char *ver = SMARTDNS_VERION;
snprintf(str_ver, sizeof(str_ver), "%s", ver);
#else
struct tm tm;
get_compiled_time(&tm);
snprintf(str_ver, sizeof(str_ver), "1.%.4d%.2d%.2d-%.2d%.2d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
tm.tm_min);
#endif
printf("smartdns %s\n", str_ver);
}
static int _smartdns_load_from_resolv(void)
{
FILE *fp = NULL;
@@ -108,7 +124,7 @@ static int _smartdns_load_from_resolv(void)
port = DEFAULT_DNS_PORT;
}
strncpy(dns_conf_servers[dns_conf_server_num].server, ns_ip, DNS_MAX_IPLEN);
safe_strncpy(dns_conf_servers[dns_conf_server_num].server, ns_ip, DNS_MAX_IPLEN);
dns_conf_servers[dns_conf_server_num].port = port;
dns_conf_servers[dns_conf_server_num].type = DNS_SERVER_UDP;
dns_conf_server_num++;
@@ -139,14 +155,14 @@ static int _smartdns_add_servers(void)
case DNS_SERVER_HTTPS: {
struct client_dns_server_flag_https *flag_http = &flags.https;
flag_http->spi_len = dns_client_spki_decode(dns_conf_servers[i].spki, (unsigned char *)flag_http->spki);
strncpy(flag_http->hostname, dns_conf_servers[i].hostname, sizeof(flag_http->hostname));
strncpy(flag_http->path, dns_conf_servers[i].path, sizeof(flag_http->path));
strncpy(flag_http->httphost, dns_conf_servers[i].httphost, sizeof(flag_http->httphost));
safe_strncpy(flag_http->hostname, dns_conf_servers[i].hostname, sizeof(flag_http->hostname));
safe_strncpy(flag_http->path, dns_conf_servers[i].path, sizeof(flag_http->path));
safe_strncpy(flag_http->httphost, dns_conf_servers[i].httphost, sizeof(flag_http->httphost));
} break;
case DNS_SERVER_TLS: {
struct client_dns_server_flag_tls *flag_tls = &flags.tls;
flag_tls->spi_len = dns_client_spki_decode(dns_conf_servers[i].spki, (unsigned char *)flag_tls->spki);
strncpy(flag_tls->hostname, dns_conf_servers[i].hostname, sizeof(flag_tls->hostname));
safe_strncpy(flag_tls->hostname, dns_conf_servers[i].hostname, sizeof(flag_tls->hostname));
} break;
break;
case DNS_SERVER_TCP:
@@ -359,10 +375,10 @@ int main(int argc, char *argv[])
char pid_file[MAX_LINE_LEN];
int signal_ignore = 0;
strncpy(config_file, SMARTDNS_CONF_FILE, MAX_LINE_LEN);
strncpy(pid_file, SMARTDNS_PID_FILE, MAX_LINE_LEN);
safe_strncpy(config_file, SMARTDNS_CONF_FILE, MAX_LINE_LEN);
safe_strncpy(pid_file, SMARTDNS_PID_FILE, MAX_LINE_LEN);
while ((opt = getopt(argc, argv, "fhc:p:Sv")) != -1) {
while ((opt = getopt(argc, argv, "fhc:p:Svx")) != -1) {
switch (opt) {
case 'f':
is_forground = 1;
@@ -376,9 +392,13 @@ int main(int argc, char *argv[])
case 'S':
signal_ignore = 1;
break;
case 'v':
case 'x':
verbose_screen = 1;
break;
case 'v':
_show_version();
return 0;
break;
case 'h':
_help();
return 1;

View File

@@ -141,8 +141,9 @@ static int _tlog_mkdir(const char *path)
}
strncpy(path_c, path, sizeof(path_c) - 1);
len = strnlen(path_c, sizeof(path_c) - 1);
path_c[len] = '/';
path_c[sizeof(path_c) - 1] = 0;
len = strnlen(path_c, sizeof(path_c) - 1);
path_c[len] = '/';
path_c[len + 1] = '\0';
path_end = path_c;
@@ -592,9 +593,10 @@ static int _tlog_get_oldest_callback(const char *path, struct dirent *entry, voi
if (oldestlog->mtime == 0 || oldestlog->mtime > sb.st_mtime) {
oldestlog->mtime = sb.st_mtime;
strncpy(oldestlog->name, entry->d_name, sizeof(oldestlog->name));
return 0;
}
strncpy(oldestlog->name, entry->d_name, sizeof(oldestlog->name) - 1);
oldestlog->name[sizeof(oldestlog->name) - 1] = 0;
return 0;
}
return 0;
}
@@ -1197,12 +1199,17 @@ tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int bl
log->is_exit = 0;
log->multi_log = (multiwrite != 0) ? 1 : 0;
strncpy(log_file, logfile, PATH_MAX);
strncpy(log->logdir, dirname(log_file), sizeof(log->logdir));
strncpy(log_file, logfile, PATH_MAX);
strncpy(log->logname, basename(log_file), sizeof(log->logname));
strncpy(log_file, logfile, PATH_MAX - 1);
log_file[PATH_MAX - 1] = 0;
strncpy(log->logdir, dirname(log_file), sizeof(log->logdir) - 1);
log->logdir[sizeof(log->logdir) - 1] = 0;
log->buff = malloc(log->buffsize);
strncpy(log_file, logfile, PATH_MAX - 1);
log_file[PATH_MAX - 1] = 0;
strncpy(log->logname, basename(log_file), sizeof(log->logname));
log->logname[sizeof(log->logname) - 1] = 0;
log->buff = malloc(log->buffsize);
if (log->buff == NULL) {
fprintf(stderr, "malloc log buffer failed, %s\n", strerror(errno));
goto errout;

View File

@@ -193,6 +193,98 @@ int parse_ip(const char *value, char *ip, int *port)
return 0;
}
static int _check_is_ipv4(const char *ip)
{
const char *ptr = ip;
char c = 0;
int dot_num = 0;
int dig_num = 0;
while ( (c = *ptr++) != '\0') {
if (c == '.') {
dot_num++;
dig_num = 0;
continue;
}
/* check number count of one field */
if (dig_num >= 4) {
return -1;
}
if (c >= '0' && c <= '9') {
dig_num++;
continue;
}
return -1;
}
/* check field number */
if (dot_num != 3) {
return -1;
}
return 0;
}
static int _check_is_ipv6(const char *ip)
{
const char *ptr = ip;
char c = 0;
int colon_num = 0;
int dig_num = 0;
while ( (c = *ptr++) != '\0') {
if (c == '[' || c == ']') {
continue;
}
if (c == ':') {
colon_num++;
dig_num = 0;
continue;
}
/* check number count of one field */
if (dig_num >= 5) {
return -1;
}
dig_num++;
if (c >= '0' && c <= '9') {
continue;
}
if (c >= 'a' && c <= 'f') {
continue;
}
if (c >= 'A' && c <= 'F') {
continue;
}
return -1;
}
/* check field number */
if (colon_num > 7) {
return -1;
}
return 0;
}
int check_is_ipaddr(const char *ip)
{
if (strstr(ip, ".")) {
/* IPV4 */
return _check_is_ipv4(ip);
} else if (strstr(ip, ":")) {
/* IPV6 */
return _check_is_ipv6(ip);
}
return -1;
}
int parse_uri(char *value, char *scheme, char *host, int *port, char *path)
{
char *scheme_end = NULL;
@@ -258,7 +350,7 @@ int set_fd_nonblock(int fd, int nonblock)
return 0;
}
char *reverse_string(char *output, char *input, int len)
char *reverse_string(char *output, char *input, int len, int to_lower_case)
{
char *begin = output;
if (len <= 0) {
@@ -269,6 +361,12 @@ char *reverse_string(char *output, char *input, int len)
len--;
while (len >= 0) {
*output = *(input + len);
if (to_lower_case) {
if (*output >= 'A' && *output <= 'Z') {
/* To lower case */
*output = *output + 32;
}
}
output++;
len--;
}
@@ -741,3 +839,22 @@ static int parse_server_name_extension(const char *data, size_t data_len, char *
return -2;
}
void get_compiled_time(struct tm *tm)
{
char s_month[5];
int month, day, year;
int hour, min, sec;
static const char *month_names = "JanFebMarAprMayJunJulAugSepOctNovDec";
sscanf(__DATE__, "%s %d %d", s_month, &day, &year);
month = (strstr(month_names, s_month) - month_names) / 3;
sscanf(__TIME__, "%d:%d:%d", &hour, &min, &sec);
tm->tm_year = year - 1900;
tm->tm_mon = month;
tm->tm_mday = day;
tm->tm_isdst = -1;
tm->tm_hour = hour;
tm->tm_min = min;
tm->tm_sec = sec;
}

View File

@@ -4,6 +4,8 @@
#define SMART_DNS_UTIL_H
#include <netdb.h>
#include <time.h>
#include "stringutil.h"
#define PORT_NOT_DEFINED -1
#define MAX_IP_LEN 64
@@ -16,11 +18,13 @@ int getaddr_by_host(char *host, struct sockaddr *addr, socklen_t *addr_len);
int parse_ip(const char *value, char *ip, int *port);
int check_is_ipaddr(const char *ip);
int parse_uri(char *value, char *scheme, char *host, int *port, char *path);
int set_fd_nonblock(int fd, int nonblock);
char *reverse_string(char *output, char *input, int len);
char *reverse_string(char *output, char *input, int len, int to_lower_case);
void print_stack(void);
@@ -53,4 +57,6 @@ int create_pid_file(const char *pid_file);
*/
int parse_tls_header(const char *data, size_t data_len, char *hostname, const char **hostname_ptr);
void get_compiled_time(struct tm *tm);
#endif