diff --git a/https-dns-proxy/Makefile b/https-dns-proxy/Makefile index 73d0a07cf..abfb4be7a 100755 --- a/https-dns-proxy/Makefile +++ b/https-dns-proxy/Makefile @@ -1,15 +1,15 @@ include $(TOPDIR)/rules.mk PKG_NAME:=https-dns-proxy -PKG_VERSION:=2021-06-03 -PKG_RELEASE:=1 +PKG_VERSION:=2021-11-22 +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/aarond10/https_dns_proxy -PKG_SOURCE_DATE:=2021-06-03 -PKG_SOURCE_VERSION:=5651b984f770a8bcecb14aeffc224703f8f82586 -PKG_MIRROR_HASH:=b65161936269aa3117debad0fcfce157024726b78d7e7da77c226f7aa8da5b4d -PKG_MAINTAINER:=Stan Grishin +PKG_SOURCE_URL:=https://github.com/aarond10/https_dns_proxy/ +PKG_SOURCE_DATE:=2021-11-22 +PKG_SOURCE_VERSION:=9336fd6272d67e8bb6e304fa54f3139a3d26f08f +PKG_MIRROR_HASH:=60b1ddabaf1db3a9ee19f3294a1df714364d580cef5e3c2161363c371a557456 +PKG_MAINTAINER:=Stan Grishin PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE @@ -38,7 +38,10 @@ define Package/https-dns-proxy/conffiles endef define Package/https-dns-proxy/install - $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/init.d ${1}/etc/config + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_DIR) ${1}/etc/config + $(INSTALL_DIR) $(1)/etc/hotplug.d/iface $(INSTALL_BIN) $(PKG_BUILD_DIR)/https_dns_proxy $(1)/usr/sbin/https-dns-proxy $(INSTALL_BIN) ./files/https-dns-proxy.init $(1)/etc/init.d/https-dns-proxy $(SED) "s|^\(PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/https-dns-proxy diff --git a/https-dns-proxy/files/https-dns-proxy.config b/https-dns-proxy/files/https-dns-proxy.config index 3c5eecf4d..f08e03ca9 100755 --- a/https-dns-proxy/files/https-dns-proxy.config +++ b/https-dns-proxy/files/https-dns-proxy.config @@ -1,13 +1,16 @@ config main 'config' option update_dnsmasq_config '*' - -config https-dns-proxy - option bootstrap_dns '8.8.8.8,8.8.4.4' - option resolver_url 'https://dns.google/dns-query' - option listen_addr '127.0.0.1' - option listen_port '5053' - option user 'nobody' - option group 'nogroup' + option force_dns '1' + list force_dns_port '53' + list force_dns_port '853' +# ports listed below are used by some +# of the dnscrypt-proxy v1 resolvers +# list force_dns_port '553' +# list force_dns_port '1443' +# list force_dns_port '4343' +# list force_dns_port '4434' +# list force_dns_port '5443' +# list force_dns_port '8443' config https-dns-proxy option bootstrap_dns '1.1.1.1,1.0.0.1' @@ -16,3 +19,11 @@ config https-dns-proxy option listen_port '5054' option user 'nobody' option group 'nogroup' + +config https-dns-proxy + option bootstrap_dns '8.8.8.8,8.8.4.4' + option resolver_url 'https://dns.google/dns-query' + option listen_addr '127.0.0.1' + option listen_port '5053' + option user 'nobody' + option group 'nogroup' diff --git a/https-dns-proxy/files/https-dns-proxy.hotplug.iface b/https-dns-proxy/files/https-dns-proxy.hotplug.iface new file mode 100644 index 000000000..c25b9e26d --- /dev/null +++ b/https-dns-proxy/files/https-dns-proxy.hotplug.iface @@ -0,0 +1,6 @@ +#!/bin/sh + +if [ "$ACTION" = 'ifup' ] && [ "$INTERFACE" = 'wan' ] && /etc/init.d/https-dns-proxy enabled; then + logger -t "https-dns-proxy" "Restarting https-dns-proxy due to $ACTION of $INTERFACE" + /etc/init.d/https-dns-proxy restart +fi diff --git a/https-dns-proxy/files/https-dns-proxy.init b/https-dns-proxy/files/https-dns-proxy.init index 8b8680763..0b9a620a5 100755 --- a/https-dns-proxy/files/https-dns-proxy.init +++ b/https-dns-proxy/files/https-dns-proxy.init @@ -1,6 +1,6 @@ #!/bin/sh /etc/rc.common -# Copyright 2019-2020 Stan Grishin (stangri@melmac.net) -# shellcheck disable=SC2039,SC3043,SC3060 +# Copyright 2019-2022 Stan Grishin (stangri@melmac.ca) +# shellcheck disable=SC1091,SC2039,SC3043,SC3060 PKG_VERSION='dev-test' # shellcheck disable=SC2034 @@ -15,9 +15,52 @@ else EXTRA_COMMANDS='version' fi +readonly packageName='https-dns-proxy' +readonly serviceName="$packageName $PKG_VERSION" +readonly sharedMemoryOutput="/dev/shm/$packageName-output" +readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m' +readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m' readonly PROG=/usr/sbin/https-dns-proxy +readonly DEFAULT_BOOTSTRAP='1.1.1.1,1.0.0.1,2606:4700:4700::1111,2606:4700:4700::1001,8.8.8.8,8.8.4.4,2001:4860:4860::8888,2001:4860:4860::8844' +readonly canaryDomains='use-application-dns.net' dnsmasqConfig=''; forceDNS=''; forceDNSPorts=''; +str_contains() { [ -n "$1" ] &&[ -n "$2" ] && [ "${1//$2}" != "$1" ]; } +is_mac_address() { expr "$1" : '[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]$' >/dev/null; } +is_ipv4() { expr "$1" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; } +is_ipv6() { ! is_mac_address "$1" && str_contains "$1" ":"; } +output() { + local msg memmsg logmsg + [ -t 1 ] && printf "%b" "$@" + msg="${1//$serviceName /service }"; + if [ "$(printf "%b" "$msg" | wc -l)" -gt 0 ]; then + [ -s "$sharedMemoryOutput" ] && memmsg="$(cat "$sharedMemoryOutput")" + logmsg="$(printf "%b" "${memmsg}${msg}" | sed 's/\x1b\[[0-9;]*m//g')" + logger -t "$packageName" "$(printf "%b" "$logmsg")" + rm -f "$sharedMemoryOutput" + else + printf "%b" "$msg" >> "$sharedMemoryOutput" + fi +} +output_ok() { output "$_OK_"; } +output_okn() { output "${_OK_}\\n"; } +output_fail() { output "$_FAIL_"; } +output_failn() { output "${_FAIL_}\\n"; } +uci_add_list_if_new() { + local key="$1" value="$2" i + if [ -z "$value" ]; then + value="${key#*=}" + key="${key%=*}" + fi + [ -n "$key" ] && [ -n "$value" ] || return 1 + for i in $(uci -q get "$key"); do + [ "$i" = "$value" ] && return 0 + done + uci -q add_list "${key}=${value}" +} + +dnsmasq_restart() { [ -x /etc/init.d/dnsmasq ] || return 0; /etc/init.d/dnsmasq restart >/dev/null 2>&1; } + version() { echo "$PKG_VERSION"; } xappend() { param="$param $1"; } @@ -26,11 +69,10 @@ append_bool() { local section="$1" local option="$2" local value="$3" - local default="$4" + local default="${4:-0}" local _loctmp - [ -z "$default" ] && default="0" config_get_bool _loctmp "$section" "$option" "$default" - [ "$_loctmp" != "0" ] && xappend "$value" + [ "$_loctmp" -ne 0 ] && xappend "$value" } append_parm() { @@ -40,137 +82,191 @@ append_parm() { local default="$4" local _loctmp config_get _loctmp "$section" "$option" "$default" + [ -n "$_loctmp" ] && xappend "$switch $_loctmp" +} + +append_counter() { + local section="$1" + local option="$2" + local switch="$3" + local default="${4:-0}" + local _loctmp i + config_get _loctmp "$section" "$option" "$default" +# shellcheck disable=SC2086,SC2154 + for i in $(seq 1 $_loctmp); do + xappend '-v' + done +} + +append_bootstrap() { + local section="$1" + local option="$2" + local switch="$3" + local default="$4" + local _old_ifs="$IFS" + local _loctmp _newtmp i + config_get _loctmp "$section" "$option" "$default" [ -z "$_loctmp" ] && return 0 - xappend "$switch $_loctmp" + IFS=" ," + for i in $_loctmp; do + if { [ "$ipv6_resolvers_only" -eq 0 ] && is_ipv4 "$i"; } || \ + { [ "$ipv6_resolvers_only" -ne 0 ] && is_ipv6 "$i"; }; then + [ -z "$_newtmp" ] && _newtmp="$i" || _newtmp="${_newtmp},${i}" + fi + done + IFS="$_old_ifs" + [ -n "$_newtmp" ] && xappend "$switch $_newtmp" + [ "$ipv6_resolvers_only" -eq 0 ] && xappend '-4' } start_instance() { - local cfg="$1" param listen_addr listen_port i + local cfg="$1" param listen_addr listen_port ipv6_resolvers_only p + config_get_bool ipv6_resolvers_only "$cfg" 'use_ipv6_resolvers_only' '0' append_parm "$cfg" 'resolver_url' '-r' append_parm "$cfg" 'polling_interval' '-i' append_parm "$cfg" 'listen_addr' '-a' '127.0.0.1' - append_parm "$cfg" 'listen_port' '-p' "$p" + append_parm "$cfg" 'listen_port' '-p' "$port" append_parm "$cfg" 'dscp_codepoint' '-c' - append_parm "$cfg" 'bootstrap_dns' '-b' + append_bootstrap "$cfg" 'bootstrap_dns' '-b' "$DEFAULT_BOOTSTRAP" append_parm "$cfg" 'user' '-u' 'nobody' append_parm "$cfg" 'group' '-g' 'nogroup' append_parm "$cfg" 'proxy_server' '-t' append_parm "$cfg" 'logfile' '-l' append_bool "$cfg" 'use_http1' '-x' - config_get_bool ipv6_resolvers_only "$cfg" 'use_ipv6_resolvers_only' '0' - config_get verbosity "$cfg" 'verbosity' '0' - -# shellcheck disable=SC2086,SC2154 - for i in $(seq 1 $verbosity); do - xappend '-v' - done -# shellcheck disable=SC2154 - if [ "$ipv6_resolvers_only" = 0 ]; then - xappend '-4' - fi + append_counter "$cfg" 'verbosity' '-v' '0' procd_open_instance # shellcheck disable=SC2086 - procd_set_param command ${PROG} ${param} + procd_set_param command $PROG $param procd_set_param stderr 1 procd_set_param stdout 1 procd_set_param respawn - procd_close_instance - - config_get listen_addr "$cfg" 'listen_addr' '127.0.0.1' - config_get listen_port "$cfg" 'listen_port' "$p" - - if [ "$dnsmasqConfig" = "*" ]; then - config_load 'dhcp' - config_foreach dnsmasq_add_doh_server 'dnsmasq' "${listen_addr}" "${listen_port}" - elif [ -n "$dnsmasqConfig" ]; then - for i in $dnsmasqConfig; do - dnsmasq_add_doh_server "@dnsmasq[${i}]" "${listen_addr}" "${listen_port}" - done - fi - p="$((p+1))" -} - -is_force_dns_active() { iptables-save | grep -q -w -- '--dport 53'; } - -start_service() { - local p=5053 c - config_load 'https-dns-proxy' - config_get dnsmasqConfig 'config' 'update_dnsmasq_config' '*' - config_get_bool forceDNS 'config' 'force_dns' '1' - config_get forceDNSPorts 'config' 'force_dns_port' '53 853' - dhcp_backup 'create' - config_load 'https-dns-proxy' - config_foreach start_instance 'https-dns-proxy' if [ "$forceDNS" -ne 0 ]; then - procd_open_instance 'main' - procd_set_param command /bin/true - procd_set_param stdout 1 - procd_set_param stderr 1 procd_open_data json_add_array firewall - for c in $forceDNSPorts; do - if netstat -tuln | grep 'LISTEN' | grep ":${c}" >/dev/null 2>&1 || [ "$c" = "53" ]; then - json_add_object "" + for p in $forceDNSPorts; do + if netstat -tuln | grep 'LISTEN' | grep ":${p}" >/dev/null 2>&1 || [ "$p" = '53' ]; then + json_add_object '' json_add_string type redirect json_add_string target DNAT json_add_string src lan - json_add_string proto "tcp udp" - json_add_string src_dport "$c" - json_add_string dest_port "$c" + json_add_string proto 'tcp udp' + json_add_string src_dport "$p" + json_add_string dest_port "$p" json_add_boolean reflection 0 json_close_object else - json_add_object "" + json_add_object '' json_add_string type rule json_add_string src lan - json_add_string dest "*" - json_add_string proto "tcp udp" - json_add_string dest_port "$c" + json_add_string dest '*' + json_add_string proto 'tcp udp' + json_add_string dest_port "$p" json_add_string target REJECT json_close_object fi done json_close_array procd_close_data - procd_close_instance fi - if [ -n "$(uci -q changes dhcp)" ]; then - uci -q commit dhcp - [ -x /etc/init.d/dnsmasq ] && /etc/init.d/dnsmasq restart >/dev/null 2>&1 + procd_close_instance + + if [ "$?" ]; then + config_get listen_addr "$cfg" 'listen_addr' '127.0.0.1' + config_get listen_port "$cfg" 'listen_port' "$port" + if [ "$dnsmasqConfig" = '*' ]; then + config_load 'dhcp' + config_foreach dnsmasq_doh_server 'dnsmasq' 'add' "${listen_addr}" "${listen_port}" + elif [ -n "$dnsmasqConfig" ]; then + for i in $dnsmasqConfig; do + if [ -n "$(uci -q get "dhcp.@dnsmasq[$i]")" ]; then + dnsmasq_doh_server "@dnsmasq[$i]" 'add' "${listen_addr}" "${listen_port}" + elif [ -n "$(uci -q get "dhcp.${i}")" ]; then + dnsmasq_doh_server "${i}" 'add' "${listen_addr}" "${listen_port}" + fi + done + fi + output_ok + port="$((port+1))" + forceDNS=0 + else + output_fail fi } +start_service() { + local port=5053 + output "Starting $serviceName " + config_load "$packageName" + config_get dnsmasqConfig 'config' 'update_dnsmasq_config' '*' + config_get_bool forceDNS 'config' 'force_dns' '1' + config_get forceDNSPorts 'config' 'force_dns_port' '53 853' + dhcp_backup 'create' + config_load "$packageName" + config_foreach start_instance "$packageName" + if [ -n "$(uci -q changes dhcp)" ]; then + uci -q commit dhcp + dnsmasq_restart + fi + output "\\n" +} + stop_service() { - config_load 'https-dns-proxy' + local s=0 + output "Stopping $serviceName " + config_load "$packageName" config_get dnsmasqConfig 'config' 'update_dnsmasq_config' '*' dhcp_backup 'restore' if [ -n "$(uci -q changes dhcp)" ]; then uci -q commit dhcp - [ -x /etc/init.d/dnsmasq ] && /etc/init.d/dnsmasq restart >/dev/null 2>&1 + dnsmasq_restart || s=1 fi +# shellcheck disable=SC2015 + [ "$s" -eq 0 ] && output_okn || output_failn } -service_triggers() { - procd_add_config_trigger "config.change" "https-dns-proxy" /etc/init.d/https-dns-proxy reload +# shellcheck disable=SC1091 +service_triggers() { + local iface + . /lib/functions/network.sh + network_flush_cache + network_find_wan iface + iface="${iface:-wan}" + if [ -n "$iface" ]; then + procd_add_interface_trigger "interface.*" "$iface" "/etc/init.d/${packageName}" restart + fi + procd_add_config_trigger "config.change" "$packageName" "/etc/init.d/${packageName}" restart } service_started() { procd_set_config_changed firewall; } service_stopped() { procd_set_config_changed firewall; } -dnsmasq_add_doh_server() { - local cfg="$1" address="$2" port="$3" - case $address in - 0.0.0.0|::ffff:0.0.0.0) address='127.0.0.1';; - ::) address='::1';; +dnsmasq_doh_server() { + local cfg="$1" param="$2" address="${3:-127.0.0.1}" port="$4" i + case "$param" in + add) + if [ "$forceDNS" -ne 0 ]; then + for i in $canaryDomains; do + uci_add_list_if_new "dhcp.${cfg}.server" "/${i}/" + done + fi + case $address in + 0.0.0.0|::ffff:0.0.0.0) address='127.0.0.1';; + ::) address='::1';; + esac + uci_add_list_if_new "dhcp.${cfg}.server" "${address}#${port}" + ;; + remove) + eval "$(ubus call service list "{ 'verbose': true, 'name': '$packageName' }" | jsonfilter -F '# ' -e 'TUPLES=@[*].instances[*].command[4,6]')" + for i in $TUPLES; do + uci -q del_list "dhcp.${cfg}.server=${i}" + done + ;; esac - uci -q del_list "dhcp.${cfg}.server=${address}#${port}" - uci -q add_list "dhcp.${cfg}.server=${address}#${port}" } dnsmasq_create_server_backup() { - local cfg="$1" - local i + local cfg="$1" i uci -q get "dhcp.${cfg}" >/dev/null || return 1 if ! uci -q get "dhcp.${cfg}.doh_backup_noresolv" >/dev/null; then if [ -z "$(uci -q get "dhcp.${cfg}.noresolv")" ]; then @@ -196,23 +292,22 @@ dnsmasq_create_server_backup() { } dnsmasq_restore_server_backup() { - local cfg="$1" - local i + local cfg="$1" i uci -q get "dhcp.${cfg}" >/dev/null || return 0 if uci -q get "dhcp.${cfg}.doh_backup_noresolv" >/dev/null; then if [ "$(uci -q get "dhcp.${cfg}.doh_backup_noresolv")" = "0" ]; then uci -q set "dhcp.${cfg}.noresolv=0" - else + else uci -q del "dhcp.${cfg}.noresolv" fi uci -q del "dhcp.${cfg}.doh_backup_noresolv" fi if uci -q get "dhcp.${cfg}.doh_backup_server" >/dev/null; then - uci -q del "dhcp.${cfg}.server" + dnsmasq_doh_server "$cfg" 'remove' for i in $(uci -q get "dhcp.${cfg}.doh_backup_server"); do - uci -q add_list "dhcp.${cfg}.server=$i" + uci_add_list_if_new "dhcp.${cfg}.server" "$i" done - uci -q del "dhcp.${cfg}.doh_backup_server" + uci -q del "dhcp.${cfg}.doh_backup_server" fi } @@ -225,8 +320,11 @@ dhcp_backup() { config_foreach dnsmasq_create_server_backup 'dnsmasq' elif [ -n "$dnsmasqConfig" ]; then for i in $dnsmasqConfig; do - dnsmasq_create_server_backup "@dnsmasq[${i}]" || \ + if [ -n "$(uci -q get "dhcp.@dnsmasq[$i]")" ]; then + dnsmasq_create_server_backup "@dnsmasq[$i]" + elif [ -n "$(uci -q get "dhcp.${i}")" ]; then dnsmasq_create_server_backup "$i" + fi done fi ;; diff --git a/https-dns-proxy/patches/010-fix-cmakelists.patch b/https-dns-proxy/patches/010-fix-cmakelists.patch new file mode 100644 index 000000000..106142579 --- /dev/null +++ b/https-dns-proxy/patches/010-fix-cmakelists.patch @@ -0,0 +1,15 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -21,9 +21,9 @@ if(NOT CMAKE_BUILD_TYPE) + message(STATUS "Setting build type to '${CMAKE_BUILD_TYPE}' as none was specified.") + endif() + +-set(CMAKE_C_FLAGS "-Wall -Wextra --pedantic -Wno-strict-aliasing -Wno-variadic-macros") +-set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG") +-set(CMAKE_C_FLAGS_RELEASE "-O2") ++#set(CMAKE_C_FLAGS "-Wall -Wextra --pedantic -Wno-strict-aliasing -Wno-variadic-macros") ++#set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG") ++#set(CMAKE_C_FLAGS_RELEASE "-O2") + + if ((CMAKE_C_COMPILER_ID MATCHES GNU AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 9) OR + (CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10))