mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-30 18:35:13 +08:00
🌴 Sync 2026-03-05 23:51:42
This commit is contained in:
1 parent
97c049ed0a
commit
0acff03804
14253 files changed
+3893239
No files matched your search
@@ -0,0 +1,11 @@
|
||||
|
||||
config dnscrypt-proxy 'ns1'
|
||||
option enable '0'
|
||||
list resolvers 'public-resolvers'
|
||||
option netprobe_address '114.114.114.114:53'
|
||||
option bootstrap_resolvers '114.114.114.114:53'
|
||||
option listen_addresses '127.0.0.1:5335'
|
||||
option force 'cache dnscrypt_servers lb_estimator ignore_system_dns cert_ignore_timestamp block_unqualified block_undelegated ipv4_servers require_nofilter require_nolog doh_servers block_ipv6'
|
||||
list forwarding_rules '/etc/dnsmasq.oversea/oversea_list.conf'
|
||||
list blocked_names '/usr/share/adbyby/dnsmasq.adblock'
|
||||
|
||||
@@ -0,0 +1,464 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (C) 2019 p.t. <peter-tank@github.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
START=30
|
||||
|
||||
USE_PROCD=1
|
||||
INIT_TRACE=
|
||||
EXTRA_COMMANDS=
|
||||
|
||||
PROG=/usr/sbin/dnscrypt-proxy
|
||||
CONFIG_DIR=/var/etc
|
||||
USER=nobody
|
||||
NAME=dnscrypt-proxy
|
||||
|
||||
SERVICE_DAEMONIZE=
|
||||
SERVICE_USE_PID=1
|
||||
SERVICE_MATCH_EXEC=1
|
||||
SERVICE_STOP_TIME=15
|
||||
SERVICE_PID_FILE=/var/run/$NAME.pid
|
||||
|
||||
LUCI_STATUS=/var/run/luci-reload-status
|
||||
LOG_FILE="/var/etc/dnscrypt"
|
||||
CACHE_DIR="/usr/share/dnscrypt-proxy"
|
||||
DIRECT_IPSETS="vpsiplist localnetwork ss_spec_wan_ac"
|
||||
|
||||
# has side effects when there is a option names the same 'addrs' in shadowsocksr config file
|
||||
# keep this uci function excuted at the bottom of scripts
|
||||
uci_filter_resolver_addrs() {
|
||||
local __PKGNAME="${NAME}"
|
||||
local __SECTIONTYPE="server_addr"
|
||||
local ret
|
||||
|
||||
filter_resolver_addrs()
|
||||
{
|
||||
local __TYPE="$1"
|
||||
local __OPTION="$2"
|
||||
set | sed -ne "s/^CONFIG_.*_addrs='\([^']*\)'$/\1/p" | sed -e "s/[, ]/\n/g" | sort | uniq
|
||||
}
|
||||
|
||||
# config_load "${__PKGNAME}"
|
||||
# tricky way first for all server_addr addrs in DNSCrypt ACL
|
||||
ret=$(filter_resolver_addrs "${__SECTIONTYPE}" "addrs")
|
||||
# or get all addrs from all resolvers configured.
|
||||
[ -z "${ret}" ] && {
|
||||
CONFIG_APPEND=1
|
||||
config_list_foreach "ns1" "resolvers" config_load
|
||||
ret=$(filter_resolver_addrs ".*" "addrs")
|
||||
}
|
||||
echo "${ret}"
|
||||
}
|
||||
|
||||
uci_get_by_name() {
|
||||
local ret=$(uci get dnscrypt-proxy.$1.$2 2>/dev/null)
|
||||
echo "${ret:=$3}"
|
||||
}
|
||||
|
||||
boot() {
|
||||
dnscrypt_boot=1
|
||||
rc_procd start_service
|
||||
}
|
||||
|
||||
dnscrypt_instance() {
|
||||
local config_path="$CONFIG_DIR/dnscrypt-proxy-$1.conf"
|
||||
|
||||
[ $(uci_get_by_name "$1" enable 0) -eq 1 ] || return 0
|
||||
create_config_file $1 "$config_path"
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command $PROG -config "$config_path" -pidfile "$SERVICE_PID_FILE"
|
||||
procd_set_param file "$config_path"
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
include_for_firewall_reload() {
|
||||
local FWI=$(uci get firewall.dnscrypt_proxy.path 2>/dev/null)
|
||||
|
||||
[ -n "$FWI" ] || return 0
|
||||
echo '#!/bin/sh' >$FWI
|
||||
cat <<-EOF >>"$FWI"
|
||||
addr_filter=\$(uci get ${NAME}.ns1.addr_filter 2>/dev/null)
|
||||
if [ "\${addr_filter:-auto}" == "auto" ]; then
|
||||
for list in ${DIRECT_IPSETS}; do
|
||||
ipset list -n "\${list}" >/dev/null 2>&1
|
||||
[ \$? -eq 0 ] && addr_filter="\${list}" && break
|
||||
done
|
||||
fi
|
||||
ipset list -n "\${addr_filter}" >/dev/null 2>&1 && {
|
||||
ipset_shell=\$(find ${CONFIG_DIR} -name "dnscrypt_filter2_*.sh" | head -n1)
|
||||
[ -z "\${ipset_shell}" ] || {
|
||||
sed -i 's/^ipset add [^ ]* \(.*\)$/ipset add '"\${addr_filter}"' \1/g' "\${ipset_shell}"
|
||||
echo "### \$(date) on firewall reload" >> "${LOG_FILE}.log"
|
||||
echo "### appending resolver addresses to ipset list \${addr_filter}..." >> "${LOG_FILE}.log"
|
||||
wc -l "\${ipset_shell}" >> "${LOG_FILE}.log" 2>&1
|
||||
date >"\${ipset_shell}.log"
|
||||
\${ipset_shell} >>"\${ipset_shell}.log" 2>&1 &
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
create_config_file() {
|
||||
local server_names listen_address query_meta max_clients bootstrap_resolvers netprobe_address
|
||||
local disabled_server_names log_file log_level timeout keepalive cert_refresh_delay netprobe_timeout
|
||||
local log_files_max_size log_files_max_age log_files_max_backups reject_ttl
|
||||
local reject_ttl cache_size cache_min_ttl cache_max_ttl cache_neg_min_ttl cache_neg_max_ttl
|
||||
local lb_strategy blocked_query_response force_defaults force_gets
|
||||
local proxy http_proxy cloaking_rules cloak_ttl
|
||||
local config_path="$2"
|
||||
local dstf two_line_header forward_resolvers
|
||||
|
||||
[ ! -d "$CONFIG_DIR" ] && mkdir -p "$CONFIG_DIR"
|
||||
[ -d "${CACHE_DIR}" ] || mkdir -p "${CACHE_DIR}"
|
||||
[ -f "$config_path" ] && rm "$config_path"
|
||||
|
||||
config_get server_names $1 'server_names' ''
|
||||
config_get listen_addresses $1 'listen_addresses' '127.0.0.1:5335'
|
||||
config_get query_meta $1 'query_meta' ''
|
||||
config_get max_clients $1 'max_clients' '250'
|
||||
config_get bootstrap_resolvers $1 'bootstrap_resolvers' '114.114.114.114:53'
|
||||
config_get netprobe_address $1 'netprobe_address' '114.114.114.114:53'
|
||||
config_get disabled_server_names $1 'disabled_server_names' ''
|
||||
|
||||
config_get log_file $1 'log_file' "${LOG_FILE}.log"
|
||||
config_get log_level $1 'log_level' '2'
|
||||
|
||||
config_get timeout $1 'timeout' '5000'
|
||||
config_get keepalive $1 'keepalive' '30'
|
||||
config_get cert_refresh_delay $1 'cert_refresh_delay' '240'
|
||||
config_get netprobe_timeout $1 'netprobe_timeout' '60'
|
||||
config_get log_files_max_size $1 'log_files_max_size' '1'
|
||||
config_get log_files_max_age $1 'log_files_max_age' '7'
|
||||
config_get log_files_max_backups $1 'log_files_max_backups' '1'
|
||||
config_get reject_ttl $1 'reject_ttl' '600'
|
||||
config_get cache_size $1 'cache_size' '512'
|
||||
config_get cache_min_ttl $1 'cache_min_ttl' '600'
|
||||
config_get cache_max_ttl $1 'cache_max_ttl' '86400'
|
||||
config_get cache_neg_min_ttl $1 'cache_neg_min_ttl' '60'
|
||||
config_get cache_neg_max_ttl $1 'cache_neg_max_ttl' '600'
|
||||
|
||||
config_get lb_strategy $1 'lb_strategy' 'p2'
|
||||
config_get blocked_query_response $1 'blocked_query_response' 'hinfo'
|
||||
|
||||
config_get proxy $1 'proxy' ''
|
||||
config_get http_proxy $1 'http_proxy' ''
|
||||
|
||||
config_get cloak_ttl $1 'cloak_ttl' '600'
|
||||
|
||||
append_str_param "user_name" "$USER" $config_path
|
||||
append_multivalue_param "server_names" "$server_names" $config_path
|
||||
append_multivalue_param "listen_addresses" "$listen_addresses" $config_path
|
||||
append_multivalue_param "query_meta" "$query_meta" $config_path
|
||||
append_param "max_clients" "$max_clients" $config_path
|
||||
append_multivalue_param "bootstrap_resolvers" "$bootstrap_resolvers" $config_path
|
||||
append_str_param "netprobe_address" "$netprobe_address" $config_path
|
||||
append_multivalue_param "disabled_server_names" "$disabled_server_names" $config_path
|
||||
|
||||
append_param "log_level" "$log_level" $config_path
|
||||
append_str_param "log_file" "$log_file" $config_path
|
||||
|
||||
append_param "timeout" "$timeout" $config_path
|
||||
append_param "cert_refresh_delay" "$cert_refresh_delay" $config_path
|
||||
append_param "netprobe_timeout" "$netprobe_timeout" $config_path
|
||||
append_param "log_files_max_size" "$log_files_max_size" $config_path
|
||||
append_param "log_files_max_age" "$log_files_max_age" $config_path
|
||||
append_param "log_files_max_backups" "$log_files_max_backups" $config_path
|
||||
append_param "reject_ttl" "$reject_ttl" $config_path
|
||||
append_param "cache_size" "$cache_size" $config_path
|
||||
append_param "cache_min_ttl" "$cache_min_ttl" $config_path
|
||||
append_param "cache_max_ttl" "$cache_max_ttl" $config_path
|
||||
append_param "cache_neg_min_ttl" "$cache_neg_min_ttl" $config_path
|
||||
append_param "cache_neg_max_ttl" "$cache_neg_max_ttl" $config_path
|
||||
|
||||
append_str_param "lb_strategy" "$lb_strategy" $config_path
|
||||
append_str_param "blocked_query_response" "$blocked_query_response" $config_path
|
||||
|
||||
append_str_param "proxy" "$proxy" $config_path
|
||||
append_str_param "http_proxy" "$http_proxy" $config_path
|
||||
|
||||
append_param "cloak_ttl" "$cloak_ttl" $config_path
|
||||
|
||||
force_defaults='
|
||||
lb_estimator,true
|
||||
ignore_system_dns,true
|
||||
block_unqualified,true
|
||||
block_undelegated,true
|
||||
ipv4_servers,true
|
||||
ipv6_servers,false
|
||||
block_ipv6,true
|
||||
dnscrypt_servers,true
|
||||
doh_servers,true
|
||||
require_dnssec,false
|
||||
force_tcp,false
|
||||
require_nolog,true
|
||||
require_nofilter,true
|
||||
cache,true
|
||||
offline_mode,false
|
||||
dnscrypt_ephemeral_keys,false
|
||||
tls_disable_session_tickets,false
|
||||
cert_ignore_timestamp,true
|
||||
'
|
||||
append_yes_no() {
|
||||
local sets=$1
|
||||
local defs=$2
|
||||
local config_path=$3
|
||||
local line param_name param_value val
|
||||
|
||||
for line in $defs; do
|
||||
param_name="${line%%,*}"; param_value="${line##*,}";
|
||||
for val in $sets; do
|
||||
[[ x$val == x$param_name ]] && param_value=true
|
||||
done
|
||||
echo "$param_name = $param_value" >> $config_path
|
||||
done
|
||||
}
|
||||
config_get force_gets $1 'force' ''
|
||||
append_yes_no "$force_gets" "$force_defaults" "$config_path"
|
||||
|
||||
handle_list_file() {
|
||||
local file
|
||||
local fwd="$2"
|
||||
if [ x"${1:0:4}" == x"http" ]; then file=$(cache_file "${1}" 0);
|
||||
elif [ x"${1:0:1}" == x"/" ]; then file="${1}";
|
||||
else file="$CACHE_DIR/${1}";
|
||||
fi
|
||||
[ x"$file" == x -o ! -f "${file}" ] && return
|
||||
local tmpf="/tmp/dnscrypt_${file##*/}"
|
||||
if [ x"${file##*.}" == xconf -o x"${file##*.}" == xadblock ]; then
|
||||
sed -ne "s/^\(address\|server\)=\/\([^/]*\)\/.*$/\2 $fwd/p" -e "s/ *$//g" "$file" > "$tmpf"
|
||||
else
|
||||
[ -z "$fwd" ] || sed -i -e "s/$/ $fwd/g" "$tmpf"
|
||||
cat "$file" > "$tmpf"
|
||||
fi
|
||||
echo "$tmpf"
|
||||
}
|
||||
|
||||
append_list_file() {
|
||||
local sec=$1
|
||||
local list=$2
|
||||
local param_name=$3
|
||||
local txtf=$4
|
||||
local log=$5
|
||||
local config_path=$6
|
||||
local line2=$7
|
||||
local fwd=$8
|
||||
|
||||
echo -e $line2 > "$txtf"
|
||||
[ -z "$log" ] || {
|
||||
append_str_param "log_file" "${LOG_FILE}_$log" $config_path
|
||||
append_str_param "log_format" "tsv" $config_path
|
||||
}
|
||||
merg_list_file() {
|
||||
local src=${1%% *}
|
||||
local list_file
|
||||
|
||||
list_file=$(handle_list_file $src "$fwd")
|
||||
[[ x"$list_file" == x ]] && return 0
|
||||
cat "$list_file" >> "$txtf"
|
||||
}
|
||||
config_list_foreach "$sec" "$list" merg_list_file $config_path
|
||||
line=$(sort "$txtf" | uniq); echo "$line" > "$txtf"
|
||||
line=$(cat "$txtf" | wc -l); [ $line -le 2 ] && rm -f "$txtf" && return
|
||||
echo "#total $((line-1)) uniq items." >> "$txtf"
|
||||
append_str_param "$param_name" "$txtf" $config_path
|
||||
}
|
||||
|
||||
dstf="$CONFIG_DIR/dnscrypt_forwarding_rules.txt"
|
||||
two_line_header='#dnscrypt forwarding rule file.\n'
|
||||
forward_resolvers="$bootstrap_resolvers"
|
||||
append_list_file $1 "forwarding_rules" "forwarding_rules" "$dstf" "" $config_path "$two_line_header" $forward_resolvers
|
||||
|
||||
dstf="$CONFIG_DIR/dnscrypt_cloaking_rules.txt"
|
||||
two_line_header='#dnscrypt cloaking rules file.\n'
|
||||
append_list_file $1 "cloaking_rules" "cloaking_rules" "$dstf" "" $config_path "$two_line_header"
|
||||
|
||||
echo "[query_log]" >> $config_path
|
||||
append_str_param "file" "${LOG_FILE}_query.log" $config_path
|
||||
append_str_param "format" "tsv" $config_path
|
||||
|
||||
echo "[nx_log]" >> $config_path
|
||||
append_str_param "file" "${LOG_FILE}_nx.log" $config_path
|
||||
append_str_param "format" "tsv" $config_path
|
||||
|
||||
echo "[blocked_names]" >> $config_path
|
||||
dstf="$CONFIG_DIR/dnscrypt_blocked_names.txt"
|
||||
two_line_header='#dnscrypt domain black list file.\n*.test\n*.onion\n*.localhost\n*.local\n*.invalid\n*.bind\n*.lan\n*.internal\n*.intranet\n*.private\n*.workgroup\n*.10.in-addr.arpa\n*.16.172.in-addr.arpa\n*.168.192.in-addr.arpa\n*.254.169.in-addr.arpa\n*.d.f.ip6.arpa'
|
||||
append_list_file $1 "blocked_names" "blocked_names_file" "$dstf" "bd.log" $config_path "$two_line_header"
|
||||
|
||||
echo "[blocked_ips]" >> $config_path
|
||||
dstf="$CONFIG_DIR/dnscrypt_blocked_ips.txt"
|
||||
two_line_header='#dnscrypt ip black list file.\n127.*\n192.168.*'
|
||||
append_list_file $1 "blocked_ips" "blocked_ips_file" "$dstf" "bi.log" $config_path "$two_line_header"
|
||||
|
||||
echo "[allowed_names]" >> $config_path
|
||||
dstf="$CONFIG_DIR/dnscrypt_allowed_names.txt"
|
||||
two_line_header='#dnscrypt white list file.\n'
|
||||
append_list_file $1 "allowed_names" "allowed_names_file" "$dstf" "wd.log" $config_path "$two_line_header"
|
||||
|
||||
echo "[static]" >> $config_path
|
||||
append_static_resolver() {
|
||||
local sdns=$1
|
||||
local config_path=$2
|
||||
local sdns
|
||||
|
||||
[[ "x$sdns" == x ]] && return 0
|
||||
echo "[static.'$sdns']" >> $config_path
|
||||
append_str_param "sdns" "$sdns" $config_path
|
||||
}
|
||||
config_list_foreach "$1" "sdns" append_static_resolver $config_path
|
||||
|
||||
echo "[sources]" >> $config_path
|
||||
append_resolvers_source() {
|
||||
local resolver=$1
|
||||
local config_path=$2
|
||||
local section="global"
|
||||
local urls cache_file minisign_key prefix selfsign details_json
|
||||
|
||||
config_unset $section "urls"
|
||||
[ -f "/etc/config/${resolver}" ] || return 0
|
||||
config_load ${resolver}
|
||||
[ $? -eq 0 ] || return 0
|
||||
config_get urls $section 'urls' ''
|
||||
[[ "x$urls" == x ]] && return 0
|
||||
echo "[sources.'${resolver}']" >> $config_path
|
||||
|
||||
config_get urls $section 'urls' ''
|
||||
config_get format $section 'format' 'v2'
|
||||
config_get cache_file $section 'cache_file' "${urls##*/}"
|
||||
config_get minisign_key $section 'minisign_key' 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
|
||||
config_get prefix $section 'prefix' ''
|
||||
|
||||
config_get details_json $section 'details_json' "${cache_file%%.md}.json"
|
||||
config_get_bool cache_mode $section 'cache_mode' '1'
|
||||
config_get_bool selfsign $section 'selfsign' '0'
|
||||
|
||||
if [ $cache_mode -eq 1 ] ; then
|
||||
local redirect_https site_addr schema port
|
||||
redirect_https="$(uci_get uhttpd main redirect_https '0')"
|
||||
site_addr="$(uci_get uhttpd main listen_https '[::]:80')"
|
||||
schema=http
|
||||
port=${site_addr##*:}
|
||||
[ x"${port}" != "x80" -a $redirect_https -eq 1 ] && opkg list-installed | grep libustream-openssl && schema=https
|
||||
[ x"${port}" == "x80" -o x"${port}" == "x443" ] && port=
|
||||
urls="${schema}://localhost${port:+:${port}}/${urls##*/}"
|
||||
fi
|
||||
|
||||
append_multivalue_param "urls" "$urls" $config_path
|
||||
append_str_param "format" "$format" $config_path
|
||||
append_str_param "cache_file" "$cache_file" $config_path
|
||||
append_str_param "minisign_key" "$minisign_key" $config_path
|
||||
append_str_param "prefix" "$prefix" $config_path
|
||||
|
||||
config_get_bool selfsign $section 'selfsign' '0'
|
||||
config_get details_json $section 'details_json' ''
|
||||
}
|
||||
config_list_foreach "$1" "resolvers" append_resolvers_source $config_path
|
||||
|
||||
}
|
||||
|
||||
multivalue_parse() {
|
||||
local param_values=$(echo $1 | sed -e 's/[, ]/\n/g' -e 's/\n\n/\n/g')
|
||||
|
||||
[[ x == "x${param_values}" ]] && echo -n "[]" && return 1
|
||||
local p
|
||||
p=$(for p in ${param_values}; do echo -n "'${p}'"; done)
|
||||
echo -n "["
|
||||
echo -n $p | sed -e "s/''/', '/g"
|
||||
echo -n "]"
|
||||
}
|
||||
|
||||
log_ignored_param() {
|
||||
local param_name=$1
|
||||
logger -t dnscrypt-proxy -p user.warn "dnscrypt-proxy plugins support not present, ignoring '$param_name' parameter."
|
||||
}
|
||||
|
||||
append_multivalue_param() {
|
||||
local param_name=$1
|
||||
local param_value=$2
|
||||
local config_path=$3
|
||||
|
||||
echo "$param_name = $(multivalue_parse $param_value)" >> $config_path
|
||||
}
|
||||
|
||||
append_str_param() {
|
||||
local param_name=$1
|
||||
local param_value=$2
|
||||
local config_path=$3
|
||||
|
||||
echo "$param_name = '$param_value'" >> $config_path
|
||||
}
|
||||
|
||||
append_param() {
|
||||
local param_name=$1
|
||||
local param_value=$2
|
||||
local config_path=$3
|
||||
|
||||
echo "$param_name = $param_value" >> $config_path
|
||||
}
|
||||
|
||||
start_service() {
|
||||
config_load dnscrypt-proxy
|
||||
|
||||
local addr_filter list
|
||||
config_get addr_filter ns1 'addr_filter' 'auto'
|
||||
if [ "${addr_filter}" == "auto" ]; then
|
||||
for list in ${DIRECT_IPSETS}; do
|
||||
ipset list -n "${list}" >/dev/null 2>&1
|
||||
[ $? -eq 0 ] && addr_filter="${list}" && break
|
||||
done
|
||||
fi
|
||||
ipset list -n "${addr_filter}" >/dev/null 2>&1 && {
|
||||
local ipset_shell="${CONFIG_DIR}/dnscrypt_filter2_${addr_filter}.sh"
|
||||
uci_filter_resolver_addrs > "${ipset_shell}"
|
||||
sed -i 's/^\(.*\)$/ipset add '"${addr_filter}"' "\1" nomatch/g' "${ipset_shell}"
|
||||
chmod +x "${ipset_shell}"
|
||||
echo "### appending resolver addresses to ipset list ${addr_filter}..." >> "${LOG_FILE}.log"
|
||||
wc -l "${ipset_shell}" >> "${LOG_FILE}.log" 2>&1
|
||||
date >"${ipset_shell}.log"
|
||||
${ipset_shell} >>"${ipset_shell}.log" 2>&1 &
|
||||
}
|
||||
include_for_firewall_reload
|
||||
|
||||
config_foreach dnscrypt_instance dnscrypt-proxy
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger 'dnscrypt-proxy'
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
cache_file() {
|
||||
local tdl=$1
|
||||
local key=$2
|
||||
local root=$3
|
||||
local mode=${4:-0}
|
||||
[ -n "$root" ] && tdl=$tdl$'\n'$tdl.minisig
|
||||
for cdl in $tdl; do
|
||||
echo "INFO: details[$cdl]" > $LUCI_STATUS && sleep 3
|
||||
local md5=$(echo $cdl | md5sum | cut -d' ' -f1)
|
||||
local fn="$CACHE_DIR/${md5}_${cdl##*/}"
|
||||
local tmpf="/tmp/dnscrypt_${cdl##*/}.dl"
|
||||
local line
|
||||
[ ! -f "$fn" ] && {
|
||||
wget -q --no-check-certificate -t 3 -T 30 -O "$tmpf" "$cdl"
|
||||
[ $? -eq 0 ] || return
|
||||
line=$(cat "$tmpf" | wc -l)
|
||||
[ $line -gt 1 ] || return
|
||||
cat /dev/null > "$fn"
|
||||
[ -z "$key" -o $mode -eq 11 ] && echo "##source[#$line]: $cdl" >> "$fn"
|
||||
cat "$tmpf" >> "$fn"
|
||||
}
|
||||
[ $mode -ge 10 ] && cat "$fn" > $root/${cdl##*/}
|
||||
done
|
||||
echo "${fn%%.minisig}"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2019 p.t. <peter-tank@github.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
EXTRA_COMMANDS="update cache_file"
|
||||
|
||||
PROG=/usr/sbin/dnscrypt-proxy
|
||||
CONFIG_DIR=/var/etc
|
||||
|
||||
LUCI_STATUS=/var/run/luci-reload-status
|
||||
LOG_FILE="/var/etc/dnscrypt"
|
||||
CACHE_DIR="/usr/share/dnscrypt-proxy"
|
||||
[ -d "${CACHE_DIR}" ] || mkdir -p "${CACHE_DIR}"
|
||||
#set -x
|
||||
|
||||
. $IPKG_INSTROOT/lib/functions.sh
|
||||
|
||||
multivalue_parse() {
|
||||
local param_values=$(echo $1 | sed -e 's/[, ]/\n/g' -e 's/\n\n/\n/g')
|
||||
|
||||
[[ x == x${param_values} ]] && echo -n "[]" && return 1
|
||||
local p
|
||||
p=$(for p in ${param_values}; do echo -n "'${p}'"; done)
|
||||
echo -n "["
|
||||
echo -n $p | sed -e "s/''/', '/g"
|
||||
echo -n "]"
|
||||
}
|
||||
|
||||
cache_file() {
|
||||
local tdl=$1
|
||||
local key=$2
|
||||
local root=$3
|
||||
local mode=${4:-0}
|
||||
[ -n "$root" ] && tdl=$tdl$'\n'$tdl.minisig
|
||||
for cdl in $tdl; do
|
||||
echo "INFO: details[$cdl]" > $LUCI_STATUS && sleep 3
|
||||
local md5=$(echo $cdl | md5sum | cut -d' ' -f1)
|
||||
local fn="$CACHE_DIR/${md5}_${cdl##*/}"
|
||||
local tmpf="/tmp/dnscrypt_${cdl##*/}.dl"
|
||||
local line
|
||||
[ ! -f "$fn" ] && {
|
||||
wget -q --no-check-certificate -t 3 -O "$tmpf" "$cdl"
|
||||
[ $? -eq 0 ] || return
|
||||
line=$(cat "$tmpf" | wc -l)
|
||||
[ $line -gt 1 ] || return
|
||||
cat /dev/null > "$fn"
|
||||
[ -z "$key" -o $mode -eq 11 ] && echo "##source[#$line]: $cdl" >> "$fn"
|
||||
cat "$tmpf" >> "$fn"
|
||||
}
|
||||
[ $mode -ge 10 ] && cat "$fn" > $root/${cdl##*/}
|
||||
done
|
||||
echo "${fn%%.minisig}"
|
||||
}
|
||||
|
||||
#update <resolvers_filename_in_configure>
|
||||
update() {
|
||||
local cfg="${1}"
|
||||
local siteroot="$(uci_get uhttpd main home ""/www"")"
|
||||
|
||||
[ -z "${cfg}" -o ! -f "/etc/config/${cfg}" ] && exit 0
|
||||
NO_CALLBACK=1 config_load "${cfg}"
|
||||
local section="global" urls minisign_key cache_file details_json cache_mode selfsign
|
||||
|
||||
config_get urls $section 'urls' ''
|
||||
[ $? -ne 0 ] && echo "ERROR: Wrong configure..." > $LUCI_STATUS && sleep 3 && exit 1
|
||||
[ -z "${urls}" ] && echo "SKIPED: None resolvers URLs..." > $LUCI_STATUS && sleep 3 && exit 2
|
||||
. "$IPKG_INSTROOT/usr/share/libubox/jshn.sh"
|
||||
|
||||
config_get minisign_key $section 'minisign_key' ''
|
||||
config_get cache_file $section 'cache_file' "${urls##*/}"
|
||||
config_get details_json $section 'details_json' "${cache_file%%.md}.json"
|
||||
config_get_bool cache_mode $section 'cache_mode' '1'
|
||||
config_get_bool selfsign $section 'selfsign' '0'
|
||||
|
||||
json_set_namespace "urls" "pre"
|
||||
json_init
|
||||
json_load "{'urls':$(multivalue_parse $urls)}"
|
||||
json_for_each_item cache_file 'urls' "$siteroot" "$cache_mode$selfsign"
|
||||
json_cleanup
|
||||
json_set_namespace "pre"
|
||||
|
||||
local url="$details_json" stype="dnscrypt" file
|
||||
[ -z "${url}" ] && return 2
|
||||
|
||||
if [ x"${url:0:4}" == x"http" ]; then file=$(cache_file "${url}" $cache_mode$selfsign);
|
||||
elif [ x"${url:0:1}" == x"/" ]; then file="${url}";
|
||||
else file="$CACHE_DIR/${url}";
|
||||
fi
|
||||
[ x"$file" == x -o ! -f "${file}" ] && { echo "ERROR: JSON file not exist!" > $LUCI_STATUS; sleep 3; return 3; }
|
||||
|
||||
json_set_namespace "resolvers" "pre"
|
||||
json_init
|
||||
echo "INFO: JSON parsing [$file]..." > $LUCI_STATUS
|
||||
echo "{'resolvers':$(cat $file)}" > "/tmp/${file##*/}.ld"
|
||||
json_load_file "/tmp/${file##*/}.ld"
|
||||
|
||||
local type resolvers resolver keys key val
|
||||
local sname name addrs ports proto stamp country description dnssec ipv6 location nofilter nolog
|
||||
json_get_type type "resolvers"
|
||||
[ x"$type" == "xarray" ] || { echo "ERROR: JSON parse error!" > $LUCI_STATUS; sleep 3; return 4; }
|
||||
|
||||
json_get_multivalue() {
|
||||
local _v_dst="$1"
|
||||
local _v_keys _v_val _select=
|
||||
local _json_no_warning=1 _sep=","
|
||||
|
||||
unset "$_v_dst"
|
||||
[ -n "$2" ] && {
|
||||
json_select "$2" || return 1
|
||||
_select=1
|
||||
}
|
||||
|
||||
json_get_keys _v_keys
|
||||
set -- $_v_keys
|
||||
while [ "$#" -gt 0 ]; do
|
||||
json_get_var _v_val "$1"
|
||||
__jshn_raw_append "$_v_dst" "$_v_val" "$_sep"
|
||||
shift
|
||||
done
|
||||
[ -n "$_select" ] && json_select ..
|
||||
|
||||
return 0
|
||||
}
|
||||
json_select "resolvers"
|
||||
json_get_keys resolvers
|
||||
local icount=${resolvers##* }
|
||||
for resolver in $resolvers; do
|
||||
json_select "$resolver"
|
||||
json_get_vars name proto stamp country description dnssec ipv6 nofilter nolog
|
||||
json_get_multivalue addrs "addrs"
|
||||
json_get_multivalue ports "ports"
|
||||
json_get_multivalue location "location"
|
||||
sname=$(echo "$name" | sed 's/[^a-zA-Z0-9_]/_/g')
|
||||
uci batch <<-EOB
|
||||
set "$cfg.$sname"="$stype"
|
||||
set "$cfg.$sname.name"="$name"
|
||||
set "$cfg.$sname.proto"="$proto"
|
||||
set "$cfg.$sname.addrs"="$addrs"
|
||||
set "$cfg.$sname.ports"="$ports"
|
||||
set "$cfg.$sname.stamp"="$stamp"
|
||||
set "$cfg.$sname.location"="$location"
|
||||
set "$cfg.$sname.country"="${country:-Unkown}"
|
||||
set "$cfg.$sname.description"="$description"
|
||||
set "$cfg.$sname.dnssec"="$dnssec"
|
||||
set "$cfg.$sname.ipv6"="$ipv6"
|
||||
set "$cfg.$sname.nofilter"="$nofilter"
|
||||
set "$cfg.$sname.nolog"="$nolog"
|
||||
EOB
|
||||
[ "${resolver:${#resolver}-1:1}" -eq 9 ] && uci_commit "$cfg" && echo "INFO: resolver[$resolver/${icount}]: $name {${proto}://$addrs|$ports}" > $LUCI_STATUS
|
||||
json_select ..
|
||||
done
|
||||
json_select ..
|
||||
uci_commit "$cfg" && echo "DONE: resolver[$resolver/${icount}]: $name {${proto}://$addrs|$ports}" > $LUCI_STATUS && sleep 3
|
||||
json_cleanup
|
||||
json_set_namespace "pre"
|
||||
return 0
|
||||
}
|
||||
[ x"$1" == x"enabled" ] && return 0
|
||||
echo "INFO: update resolvers[$1]" > $LUCI_STATUS && sleep 3
|
||||
update $1
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"luci-app-dnscrypt-proxy2": {
|
||||
"description": "Grant UCI access for luci-app-dnscrypt-proxy2",
|
||||
"read": {
|
||||
"uci": [ "*" ]
|
||||
},
|
||||
"write": {
|
||||
"uci": [ "*" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
-- Copyright (C) 2019 github.com/peter-tank
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
module("luci.controller.dnscrypt-proxy", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/dnscrypt-proxy") then
|
||||
return
|
||||
end
|
||||
|
||||
entry({"admin", "services", "dnscrypt-proxy"},alias("admin", "services", "dnscrypt-proxy", "global"),_("DNSCrypt Proxy"), 10).acl_depends = { "luci-app-dnscrypt-proxy2" }
|
||||
|
||||
entry({"admin", "services", "dnscrypt-proxy", "global"},cbi("dnscrypt-proxy/global"),_("Overview"), 10).leaf = true
|
||||
entry({"admin", "services", "dnscrypt-proxy", "dnscrypt-resolvers"},cbi("dnscrypt-proxy/dnscrypt-resolvers"),_("Resolvers"), 20).leaf = true
|
||||
entry({"admin", "services", "dnscrypt-proxy", "dnscrypt-resolvers"},arcombine(cbi("dnscrypt-proxy/dnscrypt-resolvers"), cbi("dnscrypt-proxy/dnscrypt-resolvers-config")),_("Resolvers"), 25).dependent = true
|
||||
entry({"admin", "services", "dnscrypt-proxy", "dnscrypt-proxy-acl"},cbi("dnscrypt-proxy/dnscrypt-proxy-acl"),_("Resolver ACL"), 30).leaf = true
|
||||
entry({"admin", "services", "dnscrypt-proxy", "dnscrypt-proxy"},cbi("dnscrypt-proxy/dnscrypt-proxy"),_("Proxy Setting"), 40).dependent = true
|
||||
entry({"admin", "services", "dnscrypt-proxy", "refresh_c"}, call("refresh_cmd"))
|
||||
entry({"admin", "services", "dnscrypt-proxy", "resolve_c"}, call("resolve_cmd"))
|
||||
entry({"admin", "services", "dnscrypt-proxy", "update_c"}, call("update_cmd"))
|
||||
|
||||
entry({"admin", "services", "dnscrypt-proxy", "fileread"}, call("act_read"), nil).leaf=true
|
||||
|
||||
entry({"admin", "services", "dnscrypt-proxy", "logview"}, cbi("dnscrypt-proxy/logview"), _("Log") ,80).leaf=true
|
||||
|
||||
end
|
||||
|
||||
function update_cmd()
|
||||
local dc = require "luci.tools.dnscrypt".init()
|
||||
local set = luci.http.formvalue("set")
|
||||
local surl = luci.http.formvalue("url")
|
||||
local ecount, retstring = 0, "-1"
|
||||
|
||||
if set == "dnscrypt_bin" then
|
||||
local bin_file = "/usr/sbin/dnscrypt-proxy"
|
||||
local ret = action_update(surl)
|
||||
retstring = type(ret) == "table" and table.concat(ret,", ") or ret
|
||||
ecount = nixio.fs.chmod(bin_file, 755)
|
||||
else
|
||||
ecount = -1
|
||||
retstring = "Unkown CMD: " .. set
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ err=ecount, status=retstring})
|
||||
end
|
||||
|
||||
function refresh_cmd()
|
||||
local set = luci.http.formvalue("set")
|
||||
local icount, retstring = 0, "-1"
|
||||
|
||||
if set == "remove_caches" then
|
||||
local dir = "/usr/share/dnscrypt-proxy"
|
||||
local output = { }
|
||||
exec("/bin/busybox", { "find", dir, "-type", "f" },
|
||||
function(chunk) output[#output+1] = chunk:match("%S+") end)
|
||||
exec("/bin/busybox", { "find", dir, "-type", "f", "-exec", "rm", "{}", ";" })
|
||||
icount = #output
|
||||
retstring = "[%d]<br />%s" % { icount, table.concat(output, "<br />") }
|
||||
elseif set == "dump_resolver" then
|
||||
local output = "/usr/share/dnscrypt-proxy/running.json"
|
||||
luci.sys.exec("/usr/sbin/dnscrypt-proxy -json --list-all -config /var/etc/dnscrypt-proxy-ns1.conf > %s" % output)
|
||||
local lua_data = luci.jsonc.parse(nixio.fs.readfile(output))
|
||||
icount = #lua_data
|
||||
retstring = "[%d] - %s" % { icount, output }
|
||||
else
|
||||
icount = -1
|
||||
retstring = "Unkown CMD: " .. set
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ ret=retstring ,retcount=icount})
|
||||
end
|
||||
|
||||
function resolve_cmd()
|
||||
local set = luci.http.formvalue("set")
|
||||
local retstring="<br /><br />"
|
||||
|
||||
retstring = luci.sys.exec("/usr/sbin/dnscrypt-proxy -resolve www.google.com,127.0.0.1:7915 -config /var/etc/dnscrypt-proxy-ns1.conf")
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ ret=retstring })
|
||||
end
|
||||
|
||||
-- called by XHR.get from logview.htm
|
||||
function act_read(lfile)
|
||||
local fs = require "nixio.fs"
|
||||
local http = require "luci.http"
|
||||
local lfile = http.formvalue("lfile")
|
||||
local ldata={}
|
||||
ldata[#ldata+1] = fs.readfile(lfile) or "_nofile_"
|
||||
if ldata[1] == "" then
|
||||
ldata[1] = "_nodata_"
|
||||
end
|
||||
http.prepare_content("application/json")
|
||||
http.write_json(ldata)
|
||||
end
|
||||
|
||||
function action_data()
|
||||
local http = require "luci.http"
|
||||
|
||||
local types = {
|
||||
csv = "text/csv",
|
||||
json = "application/json"
|
||||
}
|
||||
|
||||
local args = { }
|
||||
local mtype = http.formvalue("type") or "json"
|
||||
|
||||
http.prepare_content(types[mtype])
|
||||
exec("/usr/sbin/dnscrypt-proxy", args, http.write)
|
||||
end
|
||||
|
||||
function action_list()
|
||||
local http = require "luci.http"
|
||||
|
||||
local fd = io.popen("/usr/sbin/dnscrypt-proxy -c list")
|
||||
local periods = { }
|
||||
|
||||
if fd then
|
||||
while true do
|
||||
local period = fd:read("*l")
|
||||
|
||||
if not period then
|
||||
break
|
||||
end
|
||||
|
||||
periods[#periods+1] = period
|
||||
end
|
||||
|
||||
fd:close()
|
||||
end
|
||||
|
||||
http.prepare_content("application/json")
|
||||
http.write_json(periods)
|
||||
end
|
||||
|
||||
function action_update(surl)
|
||||
local tmp = "/tmp/dnscrypt-proxy_bin.tar.gz"
|
||||
local dir = "/tmp"
|
||||
local stype = luci.util.exec("uname"):lower()
|
||||
local sarch = luci.util.exec("uname -m")
|
||||
|
||||
exec("/usr/bin/wget-ssl", {"--no-check-certificate", "-O", tmp, surl})
|
||||
|
||||
exec("/usr/sbin/dnscrypt-proxy", {"-service", "stop" })
|
||||
local files = { }
|
||||
local tar = io.popen("/bin/tar -tzf %s" % tmp, "r")
|
||||
if tar then
|
||||
while true do
|
||||
local file = tar:read("*l")
|
||||
if not file then
|
||||
break
|
||||
elseif file:match("^(.*\/dnscrypt.proxy)$") then
|
||||
files[#files+1] = file
|
||||
end
|
||||
end
|
||||
tar:close()
|
||||
end
|
||||
|
||||
if #files == 0 then
|
||||
return {500, "Internal Server Error", stype, sarch}
|
||||
end
|
||||
|
||||
|
||||
local output = { }
|
||||
|
||||
exec("/usr/sbin/dnscrypt-proxy", {"-service", "stop" })
|
||||
exec("/bin/mkdir", { "-p", dir })
|
||||
|
||||
exec("/bin/tar", { "-C", dir, "-vxzf", tmp, unpack(files) },
|
||||
function(chunk) output[#output+1] = chunk:match("%S+") end)
|
||||
|
||||
exec("/bin/cp", { "-f", dir .. "/" .. files[1], "/usr/sbin/dnscrypt-proxy"})
|
||||
exec("/bin/rm", { "-f", "%s/%s-%s/dnscrypt-proxy" % {dir, stype, sarch}})
|
||||
exec("/bin/rm", { "-f", tmp })
|
||||
exec("/usr/sbin/dnscrypt-proxy", {"-service", "start" })
|
||||
return out
|
||||
end
|
||||
|
||||
function exec(cmd, args, writer)
|
||||
local os = require "os"
|
||||
local nixio = require "nixio"
|
||||
|
||||
local fdi, fdo = nixio.pipe()
|
||||
local pid = nixio.fork()
|
||||
|
||||
if pid > 0 then
|
||||
fdo:close()
|
||||
|
||||
while true do
|
||||
local buffer = fdi:read(2048)
|
||||
|
||||
if not buffer or #buffer == 0 then
|
||||
break
|
||||
end
|
||||
|
||||
if writer then
|
||||
writer(buffer)
|
||||
end
|
||||
end
|
||||
|
||||
nixio.waitpid(pid)
|
||||
elseif pid == 0 then
|
||||
nixio.dup(fdo, nixio.stdout)
|
||||
fdi:close()
|
||||
fdo:close()
|
||||
nixio.exece(cmd, args, nil)
|
||||
nixio.stdout:close()
|
||||
os.exit(1)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,454 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
||||
msgid "Enable"
|
||||
msgstr "启用"
|
||||
|
||||
msgid "Disable"
|
||||
msgstr "停用"
|
||||
|
||||
msgid "Log"
|
||||
msgstr "日志"
|
||||
|
||||
msgid "Servers Setting"
|
||||
msgstr "服务器配置"
|
||||
|
||||
msgid "Alias(optional)"
|
||||
msgstr "别名(可选)"
|
||||
|
||||
msgid "Server Address"
|
||||
msgstr "服务器地址"
|
||||
|
||||
msgid "Server Port"
|
||||
msgstr "服务器端口"
|
||||
|
||||
msgid "Local Port"
|
||||
msgstr "本地端口"
|
||||
|
||||
msgid "Protocol"
|
||||
msgstr "传输协议"
|
||||
|
||||
msgid "Access Control"
|
||||
msgstr "访问控制"
|
||||
|
||||
msgid "Enable Server"
|
||||
msgstr "启动服务端"
|
||||
|
||||
msgid "Server Setting"
|
||||
msgstr "服务端配置"
|
||||
|
||||
msgid "Edit DNSCrypt Server"
|
||||
msgstr "编辑服务器配置"
|
||||
|
||||
msgid "Alias"
|
||||
msgstr "别名"
|
||||
|
||||
msgid "Server"
|
||||
msgstr "服务器"
|
||||
|
||||
msgid "Status"
|
||||
msgstr "状态"
|
||||
|
||||
msgid "Unknown"
|
||||
msgstr "未知"
|
||||
|
||||
msgid "Running Status"
|
||||
msgstr "运行状态"
|
||||
|
||||
msgid "Not exist"
|
||||
msgstr "未安装可执行文件"
|
||||
|
||||
msgid "Not Running"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "Running"
|
||||
msgstr "运行中"
|
||||
|
||||
msgid "No Check"
|
||||
msgstr "未检查"
|
||||
|
||||
msgid "Check"
|
||||
msgstr "检查"
|
||||
|
||||
msgid "Connect OK"
|
||||
msgstr "连接正常"
|
||||
|
||||
msgid "Connect Error"
|
||||
msgstr "连接错误"
|
||||
|
||||
msgid "Check..."
|
||||
msgstr "正在检查.."
|
||||
|
||||
msgid "Proxy Check"
|
||||
msgstr "代理检查"
|
||||
|
||||
msgid "Records"
|
||||
msgstr "条记录"
|
||||
|
||||
msgid "Refresh Data"
|
||||
msgstr "更新数据库"
|
||||
|
||||
msgid "Refresh..."
|
||||
msgstr "正在更新,请稍候.."
|
||||
|
||||
msgid "Refresh OK!"
|
||||
msgstr "更新成功!"
|
||||
|
||||
msgid "Refresh Error!"
|
||||
msgstr "更新失败!"
|
||||
|
||||
msgid "No new data!"
|
||||
msgstr "你已经是最新数据,无需更新!"
|
||||
|
||||
msgid "Total Records:"
|
||||
msgstr "新的总纪录数:"
|
||||
|
||||
msgid "Check Server"
|
||||
msgstr "检查服务器"
|
||||
|
||||
msgid "Servers Manage"
|
||||
msgstr "服务器管理"
|
||||
|
||||
msgid "Update"
|
||||
msgstr "更新"
|
||||
|
||||
msgid "Server Count"
|
||||
msgstr "服务器节点数量"
|
||||
|
||||
msgid "Severs Nodes"
|
||||
msgstr "服务器节点"
|
||||
|
||||
msgid "Server Node Type"
|
||||
msgstr "服务器节点类型"
|
||||
|
||||
msgid "DNSCrypt Resolvers"
|
||||
msgstr "订阅列表"
|
||||
|
||||
msgid "DNSCrypt Proxy Settings"
|
||||
msgstr "DNSCrypt代理设置"
|
||||
|
||||
msgid "Proxy Setting"
|
||||
msgstr "代理设置"
|
||||
|
||||
msgid "DNSCrypt Proxy"
|
||||
msgstr "DNSCrypt代理"
|
||||
|
||||
msgid "DNSCrypt Proxy binary not found."
|
||||
msgstr "未发现DNSCrypt代理应用。"
|
||||
|
||||
msgid "Binary Management"
|
||||
msgstr "应用管理"
|
||||
|
||||
msgid "Binary update"
|
||||
msgstr "应用更新 "
|
||||
|
||||
msgid "Current version:"
|
||||
msgstr "当前版本:"
|
||||
|
||||
msgid "Version2 atleast:"
|
||||
msgstr "至少应为第2版:"
|
||||
|
||||
msgid "Update to final release from:"
|
||||
msgstr "更新到最新正式版本:"
|
||||
|
||||
msgid "Force Reload"
|
||||
msgstr "强制重启"
|
||||
|
||||
msgid "Proxy force reload,"
|
||||
msgstr "强制重启代理:"
|
||||
|
||||
msgid "DNS resolve test"
|
||||
msgstr "DNS解析测试"
|
||||
|
||||
msgid "Cache Management"
|
||||
msgstr "缓存文件"
|
||||
|
||||
msgid "Running resolver details and offline caches manipulating."
|
||||
msgstr "节点详情和订阅的离线缓存文件控制。"
|
||||
|
||||
msgid "Dump Details"
|
||||
msgstr "调取详情"
|
||||
|
||||
msgid "Dump DNSCrypt resolver details to cache file:"
|
||||
msgstr "从代理实例调取节点详情到文件缓存:"
|
||||
|
||||
msgid "JSON dumped"
|
||||
msgstr "详情JSON已保存 "
|
||||
|
||||
msgid "Remove cache files"
|
||||
msgstr "删除缓存文件"
|
||||
|
||||
msgid "files"
|
||||
msgstr "文件"
|
||||
|
||||
msgid "Remove cached resolvers info from:"
|
||||
msgstr "删除所有订阅的缓存:"
|
||||
|
||||
msgid "Resolver cache"
|
||||
msgstr "订阅缓存 "
|
||||
|
||||
msgid "Listening address"
|
||||
msgstr "监听地址"
|
||||
|
||||
msgid "Enabled Resolvers"
|
||||
msgstr "订阅列表"
|
||||
|
||||
msgid "Fallback resolvers"
|
||||
msgstr "备用DNS"
|
||||
|
||||
msgid "DNS resolver on query fails or for forced forwarding domain list."
|
||||
msgstr "用于解析DNSCrypt解析失败时,及强制转发名单里的域名。"
|
||||
|
||||
msgid "Resolver White List"
|
||||
msgstr "节点白名单"
|
||||
|
||||
msgid "Resolver white list by name, Allow *ALL* in default."
|
||||
msgstr "默认允许所有订阅内任意节点名的节点。"
|
||||
|
||||
msgid "Resolver Black List"
|
||||
msgstr "节点黑名单"
|
||||
|
||||
msgid "Resolver black list by name, disable specified resolver."
|
||||
msgstr "不连接节点名在此名单内的节点。"
|
||||
|
||||
msgid "Forwarding2Fallback"
|
||||
msgstr "强制转发名单"
|
||||
|
||||
msgid "Domains forced to fallback resolver, [.conf] file treat like dnsmasq configure."
|
||||
msgstr "强制由备用DNS解析的名单,可处理dnsmasq的配置文件[.conf]。"
|
||||
|
||||
msgid "Domain Black List"
|
||||
msgstr "域名黑名单"
|
||||
|
||||
msgid "Domains to blacklist, [.conf|.adblock] file treat like dnsmasq configure:"
|
||||
msgstr "拒绝解析的域名表,可处理dnsmasq及adbyby的配置文件[.conf|.adblock]:"
|
||||
|
||||
msgid "IP Address List"
|
||||
msgstr "IP黑名单"
|
||||
|
||||
msgid "IP Address to blacklist, [.conf] file treat like dnsmasq configure:"
|
||||
msgstr "拒绝解析的IP名单,可处理dnsmasq的配置文件[.conf]:"
|
||||
|
||||
msgid "Net probe address"
|
||||
msgstr "找网DNS"
|
||||
|
||||
msgid "Resolver on downloading resolver lists file."
|
||||
msgstr "用于解析订阅地址的DNS。"
|
||||
|
||||
msgid "Force Options"
|
||||
msgstr "强制选项"
|
||||
|
||||
msgid "ignore_system_dns"
|
||||
msgstr "忽略系统DNS"
|
||||
|
||||
msgid "ipv4_servers"
|
||||
msgstr "连IPv4类型"
|
||||
|
||||
msgid "ipv6_servers"
|
||||
msgstr "连IPv6类型"
|
||||
|
||||
msgid "block_ipv6"
|
||||
msgstr "立即空答IPv6"
|
||||
|
||||
msgid "dnscrypt_servers"
|
||||
msgstr "连DNSCrypt类型"
|
||||
|
||||
msgid "doh_servers"
|
||||
msgstr "连DoH类型"
|
||||
|
||||
msgid "require_dnssec"
|
||||
msgstr "DNSSEC验证"
|
||||
|
||||
msgid "force_tcp"
|
||||
msgstr "只用TCP查询"
|
||||
|
||||
msgid "require_nolog"
|
||||
msgstr "无记录验证"
|
||||
|
||||
msgid "require_nofilter"
|
||||
msgstr "无过滤验证"
|
||||
|
||||
msgid "cache"
|
||||
msgstr "缓存结果"
|
||||
|
||||
msgid "offline_mode"
|
||||
msgstr "离线模式"
|
||||
|
||||
msgid "use_syslog"
|
||||
msgstr "系统LOG"
|
||||
|
||||
msgid "dnscrypt_ephemeral_keys"
|
||||
msgstr "不停刷新钥匙"
|
||||
|
||||
msgid "cert_ignore_timestamp"
|
||||
msgstr "忽略证书时间戳"
|
||||
|
||||
msgid "tls_disable_session_tickets"
|
||||
msgstr "TLS握手不缓存"
|
||||
|
||||
msgid "lb_estimator"
|
||||
msgstr "节点监测"
|
||||
|
||||
msgid "Response for blocked queries."
|
||||
msgstr "拒绝时回应"
|
||||
|
||||
msgid "Load-balancing strategy"
|
||||
msgstr "负载均衡模式"
|
||||
|
||||
msgid "Items forced for checking, will show your the defaults when unchecked all."
|
||||
msgstr "DNSCrypt节点过滤和其它设置项,清空后会显示为默认。"
|
||||
|
||||
msgid "Static Stamp"
|
||||
msgstr "静态戳记"
|
||||
|
||||
msgid "Mostly useful for testing your own servers."
|
||||
msgstr "主要用来测试自建DNSCrypt服务器。"
|
||||
|
||||
msgid "One or more requred configure is missing!"
|
||||
msgstr "至少需要1个正确配置并更新的订阅!"
|
||||
|
||||
msgid "Address filter list(ipset)"
|
||||
msgstr "节点地址过滤(ipset)"
|
||||
|
||||
msgid "The ipset list name that DNSCrypt server addresses try appending to if any."
|
||||
msgstr "向使用中的 ipset 列表追加过滤出来的DNSCrypt 节点地址。"
|
||||
|
||||
msgid "Follwing available one (auto)"
|
||||
msgstr "检测已知 (auto)"
|
||||
|
||||
msgid "PassWall direct (vpsiplist)"
|
||||
msgstr "PassWall 直走(vpsiplist)"
|
||||
|
||||
msgid "Clash direct (localnetwork)"
|
||||
msgstr "Clash 直走(localnetwork)"
|
||||
|
||||
msgid "SSR-Plus direct (ss_spec_wan_ac)"
|
||||
msgstr "SSR+ 直走(ss_spec_wan_ac)"
|
||||
|
||||
msgid "Total %d records."
|
||||
msgstr "总计 %d 条记录。"
|
||||
|
||||
msgid "Resolvers"
|
||||
msgstr "订阅"
|
||||
|
||||
msgid "Available Resolvers:"
|
||||
msgstr "已知节点:"
|
||||
|
||||
msgid "DNSCrypt Resolver Info"
|
||||
msgstr "DNSCrypt节点信息"
|
||||
|
||||
msgid "Trash Resolver Info"
|
||||
msgstr "清空节点信息"
|
||||
|
||||
msgid "DNS Forward"
|
||||
msgstr " DNS转发"
|
||||
|
||||
msgid "DNS Forward resolve test"
|
||||
msgstr "DNS转发检查"
|
||||
|
||||
msgid "Check DNSCrypt resolver:"
|
||||
msgstr "检测DNS服务器:"
|
||||
|
||||
msgid "Resolver ACL"
|
||||
msgstr "节点流控"
|
||||
|
||||
msgid "ACL Setting"
|
||||
msgstr "流控设置"
|
||||
|
||||
msgid "DNSCrypt Resolver ACL"
|
||||
msgstr "DNSCrypt节点流控"
|
||||
|
||||
msgid "DNSCrypt will automatically pick the fastest, working servers from the list<br />All or filtered out addresses are prepared for 'Address filter list(ipset)'.<br />Resolver with detailed addresses is a must."
|
||||
msgstr "DNSCrypt 会自动选择最快的有效服务器。<br />所有已知或过滤出来的地址将用于 '节点地址过滤(ipset)' <br />只有存在详细地址的节点才能添加进来。"
|
||||
|
||||
msgid "DNS Resolver Filter"
|
||||
msgstr "节点篩选器"
|
||||
|
||||
msgid "Resolver"
|
||||
msgstr "解析服务器"
|
||||
|
||||
msgid "Stamp"
|
||||
msgstr "戳记"
|
||||
|
||||
msgid "more than 100, try filter out to show details..."
|
||||
msgstr "多于100条,请进一步篩选以显示节点详情。"
|
||||
|
||||
msgid "Choose a resolver to configure"
|
||||
msgstr "请选择一个订阅来配置"
|
||||
|
||||
msgid "Input the name to re-configure, if your resolvers not updated correctly and not showns up."
|
||||
msgstr "如果你的订阅没有出现在列表里(或未能正确更新),请手动输入订阅名字新增(或重新)订阅。"
|
||||
|
||||
msgid "Update the resolvers here by a new apply. Permently cover your modifications on specific resolve, if the source resolved successfully."
|
||||
msgstr "在此应用借以更新订阅。如订阅成功,将重建此订阅中所有节点信息。"
|
||||
|
||||
msgid "Not a typical dnscrypt-proxy resolvers configure!"
|
||||
msgstr "非典型的DNSCrypt代理订阅配置!"
|
||||
|
||||
msgid "Additional changes on apply:"
|
||||
msgstr "点应用后,将会产生如下附加配置的修改:"
|
||||
|
||||
msgid "Change this only on duplicating this resolver to another source when retrieving:"
|
||||
msgstr "修改此值并更新,借以新增自定订阅:"
|
||||
|
||||
msgid "Cache File"
|
||||
msgstr "缓存"
|
||||
|
||||
msgid "Details File URL"
|
||||
msgstr "节点详情"
|
||||
|
||||
msgid "Detailed resolvers JSON file `dnscrypt-proxy -json --list-all` or:"
|
||||
msgstr "有关节点情细情况的JSON文件,可在启动后手动执行`dnscrypt-proxy -json --list-all`来抓取,或:"
|
||||
|
||||
msgid "DNSCrypt Resolvers Manage"
|
||||
msgstr "DNSCrypt订阅管理"
|
||||
|
||||
msgid "Update the resolvers here by a new apply."
|
||||
msgstr "应用时会自动检查并更新订阅。"
|
||||
|
||||
msgid "DNSCrypt Resolver Editing -"
|
||||
msgstr "DNSCrypt节点编辑 - "
|
||||
|
||||
msgid "Source URL"
|
||||
msgstr "订阅地址"
|
||||
|
||||
msgid "Split MultiValues by a comma"
|
||||
msgstr "多个值以英文逗号分隔"
|
||||
|
||||
msgid "MiniSign Key"
|
||||
msgstr "Mini验证"
|
||||
|
||||
msgid "Resolvers singed by:"
|
||||
msgstr "订阅源签名公钥:"
|
||||
|
||||
msgid "No resolvers update."
|
||||
msgstr "离线模式"
|
||||
|
||||
msgid "Force cached resolvers only:"
|
||||
msgstr "使用缓存文件,主要用来解决在订阅源无法正常获取时,DNSCrypt代理启动失败的状况:"
|
||||
|
||||
msgid "Selfsign Resolvers"
|
||||
msgstr "自签订阅"
|
||||
|
||||
msgid "Mostly useful for build your own resolvers list on net probe fails. minisign binary needed:"
|
||||
msgstr "主要用于自定义的服务器订阅,需要安装minisign应用:"
|
||||
|
||||
msgid "Choose a file from the list to read."
|
||||
msgstr "请从列表选择文件来查看。"
|
||||
|
||||
msgid "File Viewer"
|
||||
msgstr "文件查看器"
|
||||
|
||||
msgid "Read / Reread log file"
|
||||
msgstr "读取/重新读取"
|
||||
|
||||
msgid "Please press [Read] button"
|
||||
msgstr "请点读取按钮"
|
||||
|
||||
msgid "File not found or empty"
|
||||
msgstr "文件未找到或为空"
|
||||
|
||||
msgid "No files found"
|
||||
msgstr "文件未找到"
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
-- Copyright (C) 2019 github.com/peter-tank
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local disp = require "luci.dispatcher"
|
||||
local m, _, s, o
|
||||
local cfg="dnscrypt-proxy"
|
||||
|
||||
m = Map(cfg, "%s - %s" %{translate("DNSCrypt Proxy"),
|
||||
translate("ACL Setting")})
|
||||
|
||||
-- [[ ACL Setting ]]--
|
||||
s = m:section(TypedSection, "server_addr", translate("DNSCrypt Resolver ACL"), translate("DNSCrypt will automatically pick the fastest, working servers from the list<br />All or filtered out addresses are prepared for 'Address filter list(ipset)'.<br />Resolver with detailed addresses is a must.") .. " https://dnscrypt.info/stamps/")
|
||||
s.sectionhead = translate("Alias")
|
||||
s.template = "cbi/tblsection"
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
s.sortable = false
|
||||
s.template_addremove = "dnscrypt-proxy/cbi_addserver"
|
||||
|
||||
function s.create(self, section)
|
||||
local a = m:formvalue("_newsrv.alias")
|
||||
local c = m:formvalue("_newsrv.country")
|
||||
local n = m:formvalue("_newsrv.name")
|
||||
local ad = m:formvalue("_newsrv.addrs")
|
||||
local po = m:formvalue("_newsrv.ports")
|
||||
local pr = m:formvalue("_newsrv.proto")
|
||||
local st = m:formvalue("_newsrv.stamp")
|
||||
|
||||
created = nil
|
||||
if a ~= "" and n ~= "" and ad ~= "" and st ~= "" then
|
||||
created = TypedSection.create(self, section)
|
||||
|
||||
self.map:set(created, "alias", a)
|
||||
self.map:set(created, "country", c or "Unknown")
|
||||
self.map:set(created, "name", n or "Custom")
|
||||
self.map:set(created, "addrs", ad)
|
||||
self.map:set(created, "ports", po or "ALL")
|
||||
self.map:set(created, "proto", pr or "Unknown")
|
||||
self.map:set(created, "stamp", st or "Error")
|
||||
end
|
||||
end
|
||||
|
||||
function s.parse(self, ...)
|
||||
TypedSection.parse(self, ...)
|
||||
if created then
|
||||
m.uci:save("dnscrypt-proxy")
|
||||
luci.http.redirect(disp.build_url("admin", "services", "dnscrypt-proxy", "dnscrypt-proxy-acl"))
|
||||
end
|
||||
end
|
||||
|
||||
s:option(DummyValue,"alias",translate("Alias"))
|
||||
s:option(DummyValue,"country",translate("Country"))
|
||||
s:option(DummyValue,"proto",translate("Protocol"))
|
||||
s:option(DummyValue,"name",translate("Resolver"))
|
||||
s:option(DummyValue,"addrs",translate("Address"))
|
||||
s:option(DummyValue,"ports",translate("Server Port"))
|
||||
s:option(DummyValue,"stamp",translate("Stamp"))
|
||||
|
||||
return m
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
-- Copyright (C) 2019 github.com/peter-tank
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, _, s, o
|
||||
local dc = require "luci.tools.dnscrypt".init()
|
||||
local resolvers = dc:resolvers_list(true)
|
||||
local cfg = "dnscrypt-proxy"
|
||||
|
||||
m = Map(cfg, "%s - %s" %{translate("DNSCrypt Proxy"), translate("Proxy Setting")})
|
||||
|
||||
-- [[ Proxy Setting ]]--
|
||||
local type = "dnscrypt-proxy"
|
||||
s = m:section(TypedSection, type)
|
||||
s.anonymous = false
|
||||
-- section might not exist
|
||||
function s.cfgvalue(self, section)
|
||||
if not self.map:get(section) then
|
||||
self.map:set(section, nil, self.sectiontype)
|
||||
self.map:set(section, "resolvers", {"public-resolvers", "opennic"})
|
||||
end
|
||||
return self.map:get(section)
|
||||
end
|
||||
|
||||
o = s:option(Flag, "enable", translate("Enable"))
|
||||
o.default = false
|
||||
o.optional = false
|
||||
|
||||
o = s:option(Value, "listen_addresses", translate("Listening address"), translate("Split MultiValues by a comma"))
|
||||
o.default = "127.0.0.1:5335"
|
||||
o.placeholder = o.default
|
||||
o.optional = false
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "netprobe_address", translate("Net probe address"), translate("Resolver on downloading resolver lists file."))
|
||||
o.default = "114.114.114.114:53"
|
||||
o.placeholder = o.default
|
||||
o.optional = false
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "bootstrap_resolvers", translate("Fallback resolvers"), translate("DNS resolver on query fails or for forced forwarding domain list.") .. translate("Split MultiValues by a comma"))
|
||||
o.default = "114.114.114.114:53"
|
||||
o.placeholder = o.default
|
||||
o.optional = false
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(DynamicList, "resolvers", translate("Enabled Resolvers"), translate("Available Resolvers: ") .. "https://download.dnscrypt.info/dnscrypt-resolvers/v2/{*}.md")
|
||||
local opt, val
|
||||
for _, val in ipairs(resolvers) do
|
||||
opt = luci.util.split(val, "|")[1]
|
||||
o:value(opt, translate(opt))
|
||||
end
|
||||
o.optional = false
|
||||
o.rmempty = false
|
||||
o.placeholder = "onion-services"
|
||||
|
||||
o = s:option(MultiValue, "force", translate("Force Options"), translate("Items forced for checking, will show your the defaults when unchecked all."))
|
||||
o.optional = false
|
||||
o.widget = "select"
|
||||
o.force_defaults = {
|
||||
["lb_estimator"] = "true",
|
||||
["ignore_system_dns"] = "true",
|
||||
["block_unqualified"] = "true",
|
||||
["block_undelegated"] = "true",
|
||||
["ipv4_servers"] = "true",
|
||||
["ipv6_servers"] = "false",
|
||||
["block_ipv6"] = "true",
|
||||
["dnscrypt_servers"] = "true",
|
||||
["doh_servers"] = "true",
|
||||
["require_dnssec"] = "false",
|
||||
["force_tcp"] = "false",
|
||||
["require_nolog"] = "true",
|
||||
["require_nofilter"] = "true",
|
||||
["cache"] = "true",
|
||||
["offline_mode"] = "false",
|
||||
["dnscrypt_ephemeral_keys"] = "false",
|
||||
["tls_disable_session_tickets"] = "false",
|
||||
["cert_ignore_timestamp"] = "true",
|
||||
["use_syslog"] = "false",
|
||||
}
|
||||
for k, v in pairs(o.force_defaults) do o:value(k, translate(k)) end
|
||||
o.cfgvalue = function (self, section)
|
||||
local ret, k, d
|
||||
ret = Value.cfgvalue(self, section)
|
||||
if ret then return ret end
|
||||
ret = ""
|
||||
for k, d in pairs(self.force_defaults) do
|
||||
if d == "true" then
|
||||
ret = ret .. self.delimiter .. k
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
o = s:option(ListValue, "log_level", translate("Log output level"))
|
||||
o:value(0, translate("Debug"))
|
||||
o:value(1, translate("Info"))
|
||||
o:value(2, translate("Notice"))
|
||||
o:value(3, translate("Warning"))
|
||||
o:value(4, translate("Error"))
|
||||
o:value(5, translate("Critical"))
|
||||
o:value(6, translate("Fatal"))
|
||||
o.default = 2
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(ListValue, "blocked_query_response", translate("Response for blocked queries."))
|
||||
o:value("refused", translate("refused"))
|
||||
o:value("hinfo", translate("hinfo"))
|
||||
o.default = "hinfo"
|
||||
o.placeholder = "eg: a:<IPv4>,aaaa:<IPv6>"
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(ListValue, "lb_strategy", translate("Load-balancing strategy"))
|
||||
o:value("p2", translate("p2"))
|
||||
o:value("ph", translate("ph"))
|
||||
o:value("first", translate("first"))
|
||||
o:value("random", translate("random"))
|
||||
o.default = "p2"
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(DynamicList, "forwarding_rules", translate("Forwarding2Fallback"), translate("Domains forced to fallback resolver, [.conf] file treat like dnsmasq configure."))
|
||||
o.default = "/etc/dnsmasq.oversea/oversea_list.conf"
|
||||
o.placeholder = "/etc/dnsmasq.oversea/oversea_list.conf"
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(DynamicList, "blocked_named", translate("Domain Black List"), translate("Domains to blacklist, [.conf|.adblock] file treat like dnsmasq configure: ") .. "https://download.dnscrypt.info/blacklists/domains/mybase.txt")
|
||||
o.default = "/etc/dnsmasq.ssr/ad.conf"
|
||||
o.placeholder = "/usr/share/adbyby/dnsmasq.adblock"
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(DynamicList, "blocked_ips", translate("IP Address List"), translate("IP Address to blacklist, [.conf] file treat like dnsmasq configure: ") .. "https://download.dnscrypt.info/blacklists/ips/mybase.txt")
|
||||
o.default = "https://download.dnscrypt.info/blacklists/domains/mybase.txt"
|
||||
o.placeholder = "/etc/dnsmasq.ssr/ad.conf"
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(DynamicList, "static", translate("Static Stamp"), translate("Mostly useful for testing your own servers."))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.placeholder = "eg: sdns:AQcAAAAAAAAAAAAQMi5kbnNjcnlwdC1jZXJ0Lg"
|
||||
|
||||
o = s:option(Value, "server_names", translate("Resolver White List"), "%s %s" % {translate("Resolver white list by name, Allow *ALL* in default."), translate("Split MultiValues by a comma")})
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.placeholder = "eg: goodguy1,goodguy2"
|
||||
|
||||
o = s:option(Value, "disabled_server_names", translate("Resolver Black List"), "%s %s" % {translate("Resolver black list by name, disable specified resolver."), translate("Split MultiValues by a comma")})
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.placeholder = "eg: badguy1,badguy2"
|
||||
|
||||
o = s:option(Value, "max_clients", translate("Simulaneous"), translate("Maximum number of simultaneous client connections to accept."))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.datatype = "uinteger"
|
||||
o.default = 500
|
||||
o.placeholder = o.default
|
||||
|
||||
o = s:option(Value, "keepalive", translate("Keep Alive"), translate("Keepalive for HTTP (HTTPS, HTTP/2) queries, in seconds."))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.datatype = "uinteger"
|
||||
o.default = 30
|
||||
o.placeholder = o.default
|
||||
|
||||
o = s:option(Value, "cert_refresh_delay", translate("Cert refresh delay"), translate("Delay, in minutes, after which certificates are reloaded."))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.datatype = "uinteger"
|
||||
o.default = 240
|
||||
o.placeholder = o.default
|
||||
|
||||
o = s:option(Value, "netprobe_timeout", translate("Net probe timer"), translate("Maximum time (in seconds) to wait for network connectivity before initializing the proxy."))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.datatype = "uinteger"
|
||||
o.default = 60
|
||||
o.placeholder = o.default
|
||||
|
||||
o = s:option(Value, "reject_ttl", translate("Reject TTL"), translate("TTL for synthetic responses sent when a request has been blocked (due to IPv6 or blacklists)."))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.datatype = "uinteger"
|
||||
o.default = 60
|
||||
o.placeholder = o.default
|
||||
|
||||
o = s:option(Value, "cache_size", translate("Cache size"), translate("Cache size for queries."))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.datatype = "uinteger"
|
||||
o.default = 512
|
||||
o.placeholder = o.default
|
||||
|
||||
o = s:option(Value, "query_meta", translate("Additional TXT records"), translate("Additional data to attach to outgoing queries.") .. [[<br />]] .. translate("Split MultiValues by a comma"))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.placeholder = "eg: key1:value1,key2:value2"
|
||||
|
||||
o = s:option(Value, "proxy", translate("SOCKS proxy"), translate("Tor doesn't support UDP, so set `force_tcp` to `true` as well."))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.placeholder = "eg: socks5://127.0.0.1:9050"
|
||||
|
||||
o = s:option(Value, "http_proxy", translate("HTTP/HTTPS proxy"), translate("Only for DoH servers."))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.placeholder = "eg: http://127.0.0.1:8888"
|
||||
|
||||
o = s:option(DynamicList, "cloaking_rules", translate("Cloaking rules"), translate("Cloaking returns a predefined address for a specific name."))
|
||||
o.optional = true
|
||||
o.rmempty = true
|
||||
o.placeholder = "eg: /usr/share/dnscrypt-proxy/cloaking-rules.txt"
|
||||
|
||||
o = s:option(Value, "addr_filter", translate("Address filter list(ipset)"), translate("The ipset list name that DNSCrypt server addresses try appending to if any."))
|
||||
o:value("auto", translate("Follwing available one (auto)"))
|
||||
o:value("vpsiplist", translate("PassWall direct (vpsiplist)"))
|
||||
o:value("localnetwork", translate("Clash direct (localnetwork)"))
|
||||
o:value("ss_spec_wan_ac", translate("SSR-Plus direct (ss_spec_wan_ac)"))
|
||||
o.optional = false
|
||||
o.rmempty = true
|
||||
o.default = "auto"
|
||||
o.placeholder = "e.g.: gfwlist"
|
||||
|
||||
return m
|
||||
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
-- Copyright (C) 2019 github.com/peter-tank
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, s, o, _, v, created
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
local ds = require "luci.tools.dnscrypt".init()
|
||||
local cfg, sid = arg[1], arg[2]
|
||||
|
||||
local protocol = {
|
||||
"DNSCrypt",
|
||||
"DoH",
|
||||
}
|
||||
|
||||
function typicalmsg(self)
|
||||
if not ds:typicalcfg(cfg) then
|
||||
local c, init, exec = luci.model.uci.cursor()
|
||||
c:load("ucitrack")
|
||||
init = c:get_first("ucitrack", self.config, "init", "null")
|
||||
exec = c:get_first("ucitrack", self.config, "exec", "null")
|
||||
c:unload("ucitrack")
|
||||
local error = {}
|
||||
table.insert(error, translate("Not a typical dnscrypt-proxy resolvers configure!") .. " Original for: [%s]" % init)
|
||||
table.insert(error, translate("Additional changes on apply:"))
|
||||
table.insert(error, "init script: %s --> %s" % {init, "null"})
|
||||
table.insert(error, "exec script: %s --> %s %s" % {exec, "/etc/init.d/dnscrypt-proxy_resolvers", self.config})
|
||||
self.error = self.error and self.error or {}
|
||||
self.error["global"] = self.error["global"] and table(self.error["global"], error) or error
|
||||
end
|
||||
end
|
||||
|
||||
function list_dns(m, cfg)
|
||||
-- [[ Source Setting ]]--
|
||||
s = m:section(NamedSection, "global", "source", translate("Configuration -: ") .. cfg)
|
||||
s.description = translate("Update the resolvers here by a new apply. Permently cover your modifications on specific resolve, if the source resolved successfully.")
|
||||
s.anonymous = false
|
||||
s.addremove = true
|
||||
typicalmsg(s)
|
||||
-- section might not exist
|
||||
function s.cfgvalue(self, section)
|
||||
if not self.map:get(section) then
|
||||
self.map:set(section, nil, self.sectiontype)
|
||||
end
|
||||
return self.map:get(section)
|
||||
end
|
||||
function s.remove(self, section)
|
||||
self.map:del(section)
|
||||
self.map.proceed = true
|
||||
return self.map.uci:delete_all(self.config, "dnscrypt", function(section) return true end)
|
||||
end
|
||||
|
||||
o = s:option(Value, "urls", translate("Source URL"), translate("Split MultiValues by a comma"))
|
||||
o.rmempty = true
|
||||
o.default = "https://download.dnscrypt.info/dnscrypt-resolvers/v3/public-resolvers.md"
|
||||
o.placeholder = "https://xxx.xxx.xxx/public-resolvers.md"
|
||||
|
||||
--o = s:option(Value, "cache_file", translate("Cache File"), translate("Change this only on duplicating this resolver to another source when retrieving: ") .. "/usr/share/dnscrypt-proxy/{*}.md")
|
||||
--o.default = "public-resolvers.md"
|
||||
--o.placeholder = "eg: custom.md"
|
||||
--o.rmempty = false
|
||||
|
||||
o = s:option(Value, "details_json", translate("Details File URL"), translate("Detailed resolvers JSON file `dnscrypt-proxy -json --list-all` or: ") .. "https://download.dnscrypt.info/dnscrypt-resolvers/json/{*}.json")
|
||||
o.default = "https://download.dnscrypt.info/dnscrypt-resolvers/json/public-resolvers.json"
|
||||
o.placeholder = "eg: custom.json"
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Flag, "cache_mode", translate("No resolvers update."), translate("Force cached resolvers only: ").. "/usr/share/dnscrypt-proxy/{.*}[.md|.minisig|.json]")
|
||||
o.default = true
|
||||
o.optional = false
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "selfsign", translate("Selfsign Resolvers"), translate("Mostly useful for build your own resolvers list on net probe fails. minisign binary needed: ") .. "https://github.com/peter-tank/openwrt-minisign")
|
||||
o.default = false
|
||||
o.optional = false
|
||||
o.rmempty = true
|
||||
o:depends("cache_mode", true)
|
||||
|
||||
o = s:option(Value, "minisign_key", translate("MiniSign Key"), translate("Resolvers singed by: ") .. "https://download.dnscrypt.info/dnscrypt-resolvers/v3/minisign.pub")
|
||||
o.default = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3"
|
||||
o.optional = false
|
||||
o.placeholder = o.default
|
||||
o.rmempty = false
|
||||
o:depends("selfsign", false)
|
||||
|
||||
o = s:option(Value, "prefix", translate("Prefix"), translate("Change this only on filtering the resolvers: "))
|
||||
o.optional = true
|
||||
o.placeholder = "eg: quad9-"
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "format", translate("Version"), translate("Configure file version."))
|
||||
o.optional = true
|
||||
o.default = "v3"
|
||||
o.rmempty = true
|
||||
|
||||
s = m:section(TypedSection, 'dnscrypt', translate("DNSCrypt Resolver Info"))
|
||||
s.anonymous = false
|
||||
s.addremove = true
|
||||
s.sortable = false
|
||||
s.template = "cbi/tblsection"
|
||||
s.extedit = luci.dispatcher.build_url("admin/services/dnscrypt-proxy/dnscrypt-resolvers", cfg, "%s")
|
||||
function s.create(self, name)
|
||||
AbstractSection.create(self, name)
|
||||
luci.http.redirect( self.extedit:format(name) )
|
||||
end
|
||||
|
||||
s:option(DummyValue, "country", translate("Country"))
|
||||
s:option(DummyValue, "proto", translate("Protocol"))
|
||||
s:option(DummyValue, "name", translate("Resolver"))
|
||||
s:option(DummyValue, "description", translate("Description"))
|
||||
s:option(Flag, "ipv6", translate("IPv6"))
|
||||
s:option(Flag, "dnssec", translate("DNSSec Validation"))
|
||||
s:option(Flag, "nolog", translate("NoLog"))
|
||||
s:option(Flag, "nofilter", translate("NoFilter"))
|
||||
s:option(DummyValue, "addrs", translate("Address"))
|
||||
s:option(DummyValue, "ports", translate("Port"))
|
||||
-- s:option(DummyValue, "stamp", translate("Stamp"))
|
||||
end
|
||||
|
||||
|
||||
-- [[ Servers Setting ]]--
|
||||
function edit_list(m)
|
||||
s = m:section(NamedSection, sid, "dnscrypt", translate("DNSCrypt Resolver Editing - ") .. sid)
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
|
||||
o = s:option(Value, "name", translate("Resolver"))
|
||||
o.default = sid
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "country", translate("Country"))
|
||||
o.default = "China"
|
||||
|
||||
o = s:option(Value, "proto", translate("Protocol"))
|
||||
for _, v in ipairs(protocol) do o:value(v) end
|
||||
o.default = "DNSCrypt"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "description", translate("Description"))
|
||||
o.default = "Dns-over-HTTPS protocol . Non-logging, supports DNSSEC. By https://www.google.com"
|
||||
|
||||
o = s:option(Flag, "dnssec", translate("DNSSec Validation"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "ipv6", translate("IPv6"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "nolog", translate("NoLog"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "nofilter", translate("NoFilter"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "addrs", translate("Resolver Address"), translate("Split MultiValues by a comma"))
|
||||
o.placeholder = "eg: 8.8.8.8,8.8.4.4"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "ports", translate("Port"), translate("Split MultiValues by a comma"))
|
||||
o.placeholder = "eg: 443,5353"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "location", translate("Geography Coordinates"))
|
||||
o.placeholder = "eg: 33.032501, 83.895699"
|
||||
|
||||
o = s:option(Value, "stamp", translate("Stamp"))
|
||||
o.placeholder = "eg: sdns://AgcAAAAAAAAADjExNi4yMDMuNzAuMTU2ID4aGg9sU_PpekktVwhLW5gHBZ7gV6sVBYdv2D_aPbg4EWRvaC5kbnN3YXJkZW4uY29tCy91bmNlbnNvcmVk"
|
||||
o.rmempty = false
|
||||
end
|
||||
|
||||
m = Map(cfg, translate("DNSCrypt Resolvers Manage"))
|
||||
m.on_before_commit = function (self)
|
||||
local exec = "/etc/init.d/dnscrypt-proxy_resolvers"
|
||||
local section, stype, on_remove = "global", "source", false
|
||||
local sec = "DNSCrypt_resolvers_" .. self.config:gsub("[^%w_]", "_")
|
||||
local c = luci.model.uci.cursor()
|
||||
local changes = c:changes()
|
||||
self.redirect = luci.dispatcher.build_url("admin/services/dnscrypt-proxy/dnscrypt-resolvers", self.config)
|
||||
for r, tbl in pairs(changes or next(changes)) do
|
||||
for s, os in pairs(tbl) do
|
||||
if os['.type'] and os['.type'] == "" and r == self.config and s == section then on_remove = true end
|
||||
end
|
||||
end
|
||||
c:load("ucitrack")
|
||||
if self:get(section, "urls") and not on_remove then
|
||||
if not c:get_first("ucitrack", self.config, "exec", nil) then
|
||||
c:delete_all("ucitrack", self.config, function(section) return true end)
|
||||
sec = c:section("ucitrack", self.config, sec)
|
||||
c:set("ucitrack", sec, "init", "null")
|
||||
c:set("ucitrack", sec, "test", "0")
|
||||
c:set("ucitrack", sec, "exec", "%s %s" % {exec, self.config})
|
||||
c:save("ucitrack"); c:commit("ucitrack");
|
||||
end
|
||||
else
|
||||
if c:get_first("ucitrack", self.config, "exec", nil) == ("%s %s" %{exec, self.config}) then
|
||||
c:delete_all("ucitrack", self.config, function(section) return true end)
|
||||
c:save("ucitrack"); c:commit("ucitrack");
|
||||
end
|
||||
self.redirect = luci.dispatcher.build_url("admin/services/dnscrypt-proxy/dnscrypt-resolvers")
|
||||
end
|
||||
c:unload("ucitrack")
|
||||
luci.util.exec("/etc/init.d/ucitrack reload")
|
||||
end
|
||||
|
||||
if cfg then
|
||||
if sid == nil then list_dns(m, cfg) else edit_list(m, cfg) end
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/services/dnscrypt-proxy/dnscrypt-resolvers"))
|
||||
return
|
||||
end
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,55 @@
|
||||
-- Copyright (C) 2019 github.com/peter-tank
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, _, s, o, id, cfg, src, val, k, v
|
||||
local uci = luci.model.uci.cursor()
|
||||
local dc = require "luci.tools.dnscrypt".init()
|
||||
local resolvers = dc:resolvers_list(true)
|
||||
local disp = require "luci.dispatcher"
|
||||
|
||||
cfg = "dnscrypt-proxy"
|
||||
|
||||
local dnslist_table = {}
|
||||
for _, s in pairs(dc:dns_list()) do
|
||||
if s.addrs ~= nil then
|
||||
dnslist_table[#dnslist_table+1] = "%s.%s:%s@%s://%s:%s" %{s.resolver, s.country, s.name, s.proto, s.addrs, s.ports}
|
||||
end
|
||||
end
|
||||
|
||||
-- [[ Servers Setting ]]--
|
||||
m = Map(cfg, translate("DNSCrypt Resolvers"))
|
||||
m.anonymous = true
|
||||
m.addremove = false
|
||||
m.pageaction = false
|
||||
|
||||
local type = "dnscrypt-proxy"
|
||||
s = m:section(NamedSection, 'ns1', type, translate("Choose a resolver to configure"), translate("Input the name to re-configure, if your resolvers not updated correctly and not showns up."))
|
||||
s.cfgvalue = function(self, section) return resolvers end
|
||||
s.template = "dnscrypt-proxy/cfgselection"
|
||||
s.extedit = luci.dispatcher.build_url("admin/services/dnscrypt-proxy/dnscrypt-resolvers", "%s")
|
||||
|
||||
--s = m:section(NamedSection, 'ns1', type, translate("DNSCrypt Resolvers update"))
|
||||
|
||||
o = s:option(TextValue, "_Dummy", translate("DNSCrypt Resolver Info"), translate("Total %d records.") % #dnslist_table)
|
||||
o.rows = 7
|
||||
o.readonly = true
|
||||
o.wrap = "soft"
|
||||
o.cfgvalue = function (self, sec)
|
||||
local ret = translate("Available Resolvers:")
|
||||
for k, v in pairs(dnslist_table) do ret = "%s\n%03d) %s" % {ret, k, v} end
|
||||
return ret
|
||||
end
|
||||
o.write = function (...) end
|
||||
|
||||
o = s:option(Button,"trash", translate("Trash Resolver Info"))
|
||||
o.inputstyle = "reset"
|
||||
o.write = function()
|
||||
local resolver
|
||||
for _, val in pairs(resolvers) do
|
||||
resolver = luci.util.split(val, "|")[1]
|
||||
uci:delete_all(resolver, "dnscrypt", function(s) return true end)
|
||||
uci:save(resolver)
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,86 @@
|
||||
-- Copyright (C) 2019 github.com/peter-tank
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, _, s, o, id, cfg, src, val, k, v
|
||||
local cfg="dnscrypt-proxy"
|
||||
|
||||
local sys = require "luci.sys"
|
||||
local http = require "luci.http"
|
||||
local disp = require "luci.dispatcher"
|
||||
local fs = require "nixio.fs"
|
||||
local dc = require "luci.tools.dnscrypt".init()
|
||||
local resolvers = dc:resolvers_list(true)
|
||||
|
||||
local caches_list = {}
|
||||
local caches="/usr/share/dnscrypt-proxy/*"
|
||||
for name in (fs.glob(caches) or function() end) do
|
||||
caches_list[#caches_list+1] = name
|
||||
end
|
||||
|
||||
local function has_bin(name)
|
||||
return sys.call("command -v %s >/dev/null" %{name}) == 0
|
||||
end
|
||||
local has_dnscrypt = has_bin("dnscrypt-proxy")
|
||||
|
||||
local bin_version
|
||||
local bin_file="/usr/sbin/dnscrypt-proxy"
|
||||
if not fs.access(bin_file) then
|
||||
bin_version=translate("Not exist")
|
||||
else
|
||||
if not fs.access(bin_file, "rwx", "rx", "rx") then
|
||||
fs.chmod(bin_file, 755)
|
||||
end
|
||||
bin_version=luci.util.trim(luci.sys.exec(bin_file .. " -version"))
|
||||
if not bin_version or bin_version == "" then
|
||||
bin_version = translate("Unknown")
|
||||
end
|
||||
end
|
||||
|
||||
m = Map(cfg, "%s - %s" %{translate("DNSCrypt Proxy"),
|
||||
translate("Overview")})
|
||||
m.pageaction = false
|
||||
|
||||
-- [[ Binary ]]--
|
||||
s = m:section(TypedSection, cfg, translate("Binary Management"), has_dnscrypt and "" or ('<b style="color:red">%s</b>' % translate("DNSCrypt Proxy binary not found.")))
|
||||
s.anonymous = true
|
||||
o = s:option(DummyValue,"dnscrypt_bin", translate("Binary update"))
|
||||
o.rawhtml = true
|
||||
o.template = "dnscrypt-proxy/refresh"
|
||||
o.name = translate("Update")
|
||||
o.ret = bin_version:match('^1%..*') and translate("Version2 atleast: ") or translate("Current version: ")
|
||||
o.value = o.ret .. bin_version
|
||||
o.description = translate("Update to final release from: ") .. "https://github.com/dnscrypt/dnscrypt-proxy/releases"
|
||||
o.write = function (self, ...) end
|
||||
|
||||
o = s:option(Button, "Force Reload", translate("Force Reload"), translate("Proxy force reload, ") .. "/etc/init.d/dnscrypt-proxy reload")
|
||||
o.inputstyle = "reset"
|
||||
o.write = function (self, ...)
|
||||
sys.call("/etc/init.d/dnscrypt-proxy reload >/dev/null 2>&1 &")
|
||||
http.redirect(disp.build_url("admin", "services", "dnscrypt-proxy"))
|
||||
end
|
||||
|
||||
o = s:option(Button, "dnscrypt_ck", translate("DNS resolve test"))
|
||||
o.rawhtml = true
|
||||
o.template = "dnscrypt-proxy/resolve"
|
||||
o.description = translate("Check DNSCrypt resolver: ") .. "/usr/sbin/dnscrypt-proxy -resolve www.google.com,127.0.0.1:7915 -config /var/etc/dnscrypt-proxy-ns1.conf"
|
||||
|
||||
-- [[ Caches ]]--
|
||||
s = m:section(TypedSection, cfg, translate("Cache Management"), translate("Running resolver details and offline caches manipulating."))
|
||||
s.anonymous = true
|
||||
o = s:option(Button,"dump_resolver", translate("Dump Details"))
|
||||
o.rawhtml = true
|
||||
o.template = "dnscrypt-proxy/refresh"
|
||||
o.ret = translate("JSON dumped ")
|
||||
o.value = " %d %s" % {#resolvers, translate("Records")}
|
||||
o.description = translate("Dump DNSCrypt resolver details to cache file: ") .. "dnscrypt-proxy -json --list-all > /usr/share/dnscrypt-proxy/running.json"
|
||||
|
||||
o = s:option(Button, "remove_caches", translate("Remove cache files"))
|
||||
o.rawhtml = true
|
||||
o.template = "dnscrypt-proxy/refresh"
|
||||
o.name = translate("Remove")
|
||||
o.ret = translate("Resolver cache ")
|
||||
o.value = " %d %s" % {#caches_list, translate("files")}
|
||||
o.description = translate("Remove cached resolvers info from: ") .. "/usr/share/dnscrypt-proxy/*"
|
||||
|
||||
return m
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local NXFS = require "nixio.fs"
|
||||
local DISP = require "luci.dispatcher"
|
||||
local HTTP = require "luci.http"
|
||||
local UCI = luci.model.uci.cursor()
|
||||
|
||||
local m = Map("dnscrypt-proxy")
|
||||
m.pageaction=false
|
||||
-- log directory
|
||||
log_dir = UCI:get_first(m.config, "global", "log_dir") or "/tmp"
|
||||
run_dir = UCI:get_first(m.config, "global", "run_dir") or "/var/etc"
|
||||
local logfile_list = {}
|
||||
|
||||
local logfs = {
|
||||
"%s/dnscrypt*" % run_dir,
|
||||
"%s/dnsmasq.*/*.*" % log_dir,
|
||||
"%s/*" % "/usr/share/dnscrypt-proxy",
|
||||
"%s/dnscrypt_*" % log_dir,
|
||||
"%s/*.ld" % log_dir,
|
||||
}
|
||||
local _, dir, ns, lv, lfile
|
||||
for _, dir in pairs(logfs) do
|
||||
for path in (NXFS.glob(dir) or function() end) do
|
||||
logfile_list[#logfile_list+1] = path
|
||||
end
|
||||
end
|
||||
|
||||
ns = m:section(TypedSection, "_dummy", translate("File Viewer"))
|
||||
ns.addremove = false
|
||||
ns.anonymous = true
|
||||
function ns.cfgsections()
|
||||
return{"_exrules"}
|
||||
end
|
||||
|
||||
lv = ns:option(DynamicList, "logfiles")
|
||||
lv.template = "dnscrypt-proxy/logsview"
|
||||
lv.inputtitle = translate("Read / Reread log file")
|
||||
lv.rows = 25
|
||||
lv.default = ""
|
||||
for _, lfile in ipairs(logfile_list) do lv:value(lfile, lfile) end
|
||||
function lv.cfgvalue(self, section)
|
||||
if logfile_list[1] then
|
||||
local lfile=logfile_list[1]
|
||||
if NXFS.access(lfile) then
|
||||
return lfile .. "\n" .. translate("Please press [Read] button")
|
||||
end
|
||||
return lfile .. "\n" .. translate("File not found or empty")
|
||||
else
|
||||
return log_dir .. "\/\n" .. translate("No files found")
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,126 @@
|
||||
|
||||
local type, pairs, ipairs, table, luci, math
|
||||
= type, pairs, ipairs, table, luci, math
|
||||
|
||||
local tpl = require "luci.template.parser"
|
||||
local utl = require "luci.util"
|
||||
local uci = require "luci.model.uci"
|
||||
local fs = require "nixio.fs"
|
||||
module "luci.tools.dnscrypt"
|
||||
|
||||
local uci_r, uci_s
|
||||
local dsec, dlst = "dnscrypt", "resolvers"
|
||||
local dglb, dsrc = "source", "urls"
|
||||
|
||||
function _valid_id(x)
|
||||
return (x and #x > 0 and x:match("^[a-zA-Z0-9_]+$"))
|
||||
end
|
||||
|
||||
function _get(c, s, o)
|
||||
return uci_r:get(c, s, o)
|
||||
end
|
||||
|
||||
function _set(c, s, o, v)
|
||||
if v ~= nil then
|
||||
if type(v) == "boolean" then v = v and "1" or "0" end
|
||||
return uci_r:set(c, s, o, v)
|
||||
else
|
||||
return uci_r:delete(c, s, o)
|
||||
end
|
||||
end
|
||||
|
||||
function typicalcfg(self, cfg)
|
||||
local dnscrypt_types, all_val, k, t = {"source", "dnscrypt"}, uci_r:get_all(cfg)
|
||||
if not all_val then return true end
|
||||
for k, t in pairs(all_val) do
|
||||
if not luci.util.contains(dnscrypt_types, t[".type"]) then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function resolvers_list(self, with_src)
|
||||
local _, cfg, r = nil, nil, { }
|
||||
for cfg in (fs.glob(uci_r:get_confdir() .. "/*")) do
|
||||
cfg=fs.basename(cfg)
|
||||
uci_r:foreach(cfg, dsec,
|
||||
function(s)
|
||||
if s.name and s.stamp and s.proto and s.country then
|
||||
local src = uci_r:get_first(cfg, dglb, dsrc)
|
||||
r[#r+1] = with_src and "%s|%s" %{cfg, src or "Unknown"} or cfg
|
||||
end
|
||||
return false
|
||||
end)
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
function country_list(self)
|
||||
local _, cfg, r = nil, nil, { }
|
||||
for _, cfg in pairs(self:resolvers_list(false)) do
|
||||
uci_r:foreach(cfg, dsec,
|
||||
function(s)
|
||||
if s.country then
|
||||
r[s.country] = s.country
|
||||
end
|
||||
end)
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
function proto_list(self)
|
||||
local _, cfg, r = nil, nil, { }
|
||||
for _, cfg in pairs(self:resolvers_list(false)) do
|
||||
uci_r:foreach(cfg, dsec,
|
||||
function(s)
|
||||
if s.proto then
|
||||
r[s.proto] = s.proto
|
||||
end
|
||||
end)
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
function dns_list(self, rf, cf, prf)
|
||||
local _, cfg, r = nil, nil, { }
|
||||
for _, cfg in pairs(self:resolvers_list(false)) do
|
||||
uci_r:foreach(cfg, dsec,
|
||||
function(s)
|
||||
if rf and cfg ~= rf then return false end
|
||||
if s.name and s.stamp and s.proto then
|
||||
if cf and cf ~= s.country then return true end
|
||||
if prf and prf ~= s.proto then return true end
|
||||
r[#r+1] = {
|
||||
['resolver'] = cfg,
|
||||
['proto'] = s.proto,
|
||||
['country'] = s.country,
|
||||
['name'] = s.name,
|
||||
['stamp'] = s.stamp,
|
||||
['addrs'] = s.addrs,
|
||||
['ports'] = s.ports,
|
||||
}
|
||||
end
|
||||
end)
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
function init(cursor)
|
||||
uci_r = cursor or uci_r or uci.cursor()
|
||||
uci_s = uci_r:substate()
|
||||
|
||||
return _M
|
||||
end
|
||||
|
||||
function save(self, ...)
|
||||
uci_r:save(...)
|
||||
uci_r:load(...)
|
||||
end
|
||||
|
||||
function commit(self, ...)
|
||||
uci_r:commit(...)
|
||||
uci_r:load(...)
|
||||
end
|
||||
|
||||
function get_defaults()
|
||||
return defaults()
|
||||
end
|
||||
@@ -0,0 +1,180 @@
|
||||
<%-
|
||||
local dc = require "luci.tools.dnscrypt".init()
|
||||
local rsl = dc:resolvers_list(false)
|
||||
local ctl = dc:country_list()
|
||||
local prl = dc:proto_list()
|
||||
local dnss = dc:dns_list()
|
||||
local _, z
|
||||
-%>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var dnslist = <%= luci.http.write_json(dnss) %>;
|
||||
function find_in_object(my_object, my_criteria){
|
||||
|
||||
return my_object.filter(function(obj) {
|
||||
return Object.keys(my_criteria).every(function(c) {
|
||||
return obj[c] == my_criteria[c];
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
function unique_list(data, id) {
|
||||
if (data.length > 0) {
|
||||
var result = ["ALL"];
|
||||
|
||||
data.forEach(function (elem) {
|
||||
if (result.indexOf(elem[id]) === -1) {
|
||||
result.push(elem[id]);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
function cbi_set_values(id, vals) {
|
||||
while (id.options[0])
|
||||
id.remove(0);
|
||||
|
||||
for (var i = 0; vals && i < vals.length; i += 1)
|
||||
{
|
||||
// if (!vals[i+2])
|
||||
// continue;
|
||||
var opt = document.createElement('option');
|
||||
opt.value = vals[i];
|
||||
opt.text = vals[i];
|
||||
id.add(opt);
|
||||
}
|
||||
id.vals = vals;
|
||||
}
|
||||
function cbi_init_dnslist(self, reset = false) {
|
||||
id = "_newsrv";
|
||||
var oproto = document.getElementById(id + '.proto');
|
||||
var oresolvers = document.getElementById(id + '.resolvers');
|
||||
var ocountry = document.getElementById(id + '.country');
|
||||
var oname = document.getElementById(id + '.name');
|
||||
var oaddrs = document.getElementById(id + '.addrs');
|
||||
var oports = document.getElementById(id + '.ports');
|
||||
var ohints = document.getElementById(id + '.hints');
|
||||
var oaddbt = document.getElementById("cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>");
|
||||
|
||||
filter = {};
|
||||
vproto = reset ? "ALL" : oproto.value;
|
||||
vresolvers = reset ? "ALL" : oresolvers.value;
|
||||
vcountry = reset ? "ALL" : ocountry.value;
|
||||
vname = reset ? "ALL" : oname.value;
|
||||
vaddrs = reset ? "ALL" : oaddrs.value;
|
||||
vports = reset ? "ALL" : oports.value;
|
||||
if (vproto != "ALL" && vproto != "") filter["proto"] = vproto;
|
||||
if (vresolvers != "ALL" && vresolvers != "") filter["resolver"] = vresolvers;
|
||||
if (vcountry != "ALL" && vcountry != "") filter["country"] = vcountry;
|
||||
if (vname != "ALL" && vname != "") filter["name"] = vname;
|
||||
if (vaddrs != "ALL" && vaddrs != "") filter["addrs"] = vaddrs;
|
||||
if (vports != "ALL" && vports != "") filter["ports"] = vports;
|
||||
|
||||
var dst = find_in_object(dnslist, filter);
|
||||
cbi_set_values(oproto, unique_list(dst, "proto"));
|
||||
cbi_set_values(oresolvers, unique_list(dst, "resolver"));
|
||||
cbi_set_values(ocountry, unique_list(dst, "country"));
|
||||
cbi_set_values(oname, unique_list(dst, "name"));
|
||||
cbi_set_values(oaddrs, unique_list(dst, "addrs"));
|
||||
cbi_set_values(oports, unique_list(dst, "ports"));
|
||||
|
||||
if (dst.length === 1) {
|
||||
vproto = dst[0]["proto"];
|
||||
vresolvers = dst[0]["resolver"];
|
||||
vcountry = dst[0]["country"];
|
||||
vname = dst[0]["name"];
|
||||
vaddrs = dst[0]["addrs"];
|
||||
document.getElementById(id + '.alias').value = vname + "." + vcountry + "@" + vproto;
|
||||
document.getElementById(id + '.stamp').value = dst[0]['stamp'];
|
||||
}
|
||||
oproto.value = vproto;
|
||||
oresolvers.value = vresolvers;
|
||||
ocountry.value = vcountry;
|
||||
oname.value = vname;
|
||||
oaddrs.value = vaddrs;
|
||||
oports.value = vports;
|
||||
|
||||
oaddbt.disabled = ( dst.length !== 1);
|
||||
ohints.innerHTML = "Filter: (" + String(dst.length) + ")" + JSON.stringify(filter) + '\n' + ((dst.length < 80) ? JSON.stringify(dst) : "<%:more than 100, try filter out to show details...%>");
|
||||
}
|
||||
//]]></script>
|
||||
<div class="cbi-section cbi-tblsection">
|
||||
<h3><%:DNS Resolver Filter%></h3>
|
||||
<div class="table cbi-section-table">
|
||||
<div class="tr cbi-section-table-titles">
|
||||
<div class="th cbi-section-table-cell"><%:Resolvers%></div>
|
||||
<div class="th cbi-section-table-cell"><%:Country%></div>
|
||||
<div class="th cbi-section-table-cell"><%:Protocol%></div>
|
||||
<div class="th cbi-section-table-cell"><%:Resolver%></div>
|
||||
<div class="th cbi-section-table-cell"><%:Address%></div>
|
||||
<div class="th cbi-section-table-cell"><%:Port%></div>
|
||||
<div class="th cbi-section-table-cell cbi-section-actions"></div>
|
||||
</div>
|
||||
<div class="tr cbi-section-table-row">
|
||||
<div class="td cbi-section-table-cell">
|
||||
<select class="cbi-input-select" id="_newsrv.resolvers" name="_newsrv.resolvers">
|
||||
<option value="ALL"><%:ALL%></option>
|
||||
<% for _, z in ipairs(rsl) do -%><option value="<%=z%>"><%=z%></option><%- end %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="td cbi-section-table-cell">
|
||||
<select class="cbi-input-select" id="_newsrv.country" name="_newsrv.country">
|
||||
<option value="ALL"><%:ALL%></option>
|
||||
<% for _, z in pairs(ctl) do -%><option value="<%=z%>"><%=z%></option><%- end %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="td cbi-section-table-cell">
|
||||
<select class="cbi-input-select" id="_newsrv.proto" name="_newsrv.proto">
|
||||
<option value="ALL"><%:ALL%></option>
|
||||
<% for _, z in pairs(prl) do -%><option value="<%=z%>"><%=z%></option><%- end %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="td cbi-section-table-cell">
|
||||
<select class="cbi-input-select" id="_newsrv.name" name="_newsrv.name">
|
||||
<option value="ALL"><%:ALL%></option>
|
||||
<% for _, z in pairs(dnss) do -%><option value="<%=z['name']%>"><%=z['name']%></option><%- end %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="td cbi-section-table-cell">
|
||||
<select class="cbi-input-select" id="_newsrv.addrs" name="_newsrv.addrs">
|
||||
<option value="ALL"><%:ALL%></option>
|
||||
<% for _, z in pairs(dnss) do -%><option value="<%=z['addrs']%>"><%=z['addrs']%></option><%- end %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="td cbi-section-table-cell">
|
||||
<select class="cbi-input-select" id="_newsrv.ports" name="_newsrv.ports">
|
||||
<option value="ALL"><%:ALL%></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="td cbi-section-table-cell nowrap cbi-section-actions"><div>
|
||||
<input type="reset" class="cbi-button cbi-button-reset" name="_newsrv.reset" id="_newsrv.reset" value="<%:Reset%>" />
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table cbi-section-table">
|
||||
<div class="tr cbi-section-table-row">
|
||||
<div class="td cbi-section-table-cell">
|
||||
<input type="text" class="cbi-input-text" id="_newsrv.alias" name="_newsrv.alias" placeholder="<%:Alias%>" />
|
||||
</div>
|
||||
<div class="td cbi-section-table-cell">
|
||||
<input type="text" class="cbi-input-text" id="_newsrv.stamp" name="_newsrv.stamp" data-optional="false" placeholder="<%:Stamp%>" />
|
||||
</div>
|
||||
<div class="td cbi-section-table-cell nowrap cbi-section-actions"><div>
|
||||
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<textarea class="cbi-input-textarea" style="width: 100%" id="_newsrv.hints" name="_newsrv.hints" data-update="change" rows="10" wrap="soft" readonly="true">sample</textarea>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
cbi_init_dnslist();
|
||||
document.getElementById('_newsrv.country').addEventListener('change', function() {try{cbi_init_dnslist();}catch(e){}});
|
||||
document.getElementById('_newsrv.resolvers').addEventListener('change', function() {try{cbi_init_dnslist();}catch(e){}});
|
||||
document.getElementById('_newsrv.proto').addEventListener('change', function() {try{cbi_init_dnslist();}catch(e){}});
|
||||
document.getElementById('_newsrv.name').addEventListener('change', function() {try{cbi_init_dnslist();}catch(e){}});
|
||||
document.getElementById('_newsrv.addrs').addEventListener('change', function() {try{cbi_init_dnslist();}catch(e){}});
|
||||
document.getElementById('_newsrv.ports').addEventListener('change', function() {try{cbi_init_dnslist();}catch(e){}});
|
||||
document.getElementById('_newsrv.reset').addEventListener('click', function() {try{cbi_init_dnslist(true);}catch(e){};});
|
||||
//]]></script>
|
||||
@@ -0,0 +1,61 @@
|
||||
<% if self:cfgvalue(self.section) then section = self.section; cfgs = self:cfgvalue(self.section)%>
|
||||
<fieldset class="cbi-section">
|
||||
<% if self.title and #self.title > 0 then -%>
|
||||
<legend><%=self.title%></legend>
|
||||
<%- end %>
|
||||
<div class="cbi-section-node" id="cbi-<%=self.config%>-<%=section%>">
|
||||
<% local isempty = true for i, val in ipairs(cfgs) do -%>
|
||||
<% local cfg = luci.util.split(val, "|")[1]; local src = luci.util.split(val, "|")[2] -%>
|
||||
<div class="cbi-value<% if i > #cfgs then -%> cbi-value-last<%- end%>" id="cbi-<%=cfg.."-source-urls"%>" data-index="<%=i%>" data-depends="[]">
|
||||
<label class="cbi-value-title"<%= attr("for", "source") %>>
|
||||
<a title="<%=translate('Go to relevant configuration page')%>" class="cbi-title-ref" href="<%=self.extedit % cfg%>">
|
||||
<%-='%d) %s' % {i, cfg}-%>
|
||||
</a>
|
||||
</label>
|
||||
<div class="cbi-value-field">
|
||||
<%
|
||||
write('Source: <a href="%s">%s</a>' % {src, src})
|
||||
%>
|
||||
</div>
|
||||
</div>
|
||||
<% isempty = false -%>
|
||||
<%- end %>
|
||||
<br />
|
||||
<% if isempty then i = 1 -%>
|
||||
<em><%:One or more requred configure is missing!%><br /><br /></em>
|
||||
<%- end %>
|
||||
<% if self.description and #self.description > 0 then -%>
|
||||
<div class="cbi-section-descr"><%=self.description%></div>
|
||||
<%- end %>
|
||||
<div class="cbi-section-create">
|
||||
<input type="text" class="cbi-section-create-name" id="cbi.cts.<%=self.config%>.new.source" name="cbi.cts.<%=self.config%>.new.source" data-type="uciname" data-optional="true" />
|
||||
<input type="submit" class="cbi-button cbi-button-add" onclick="window.location.href='<%=self.extedit%>'.format(document.getElementById('cbi.cts.<%=self.config%>.new.source').value); return false" value="<%:Add%>/<%:Edit%><%:Resolvers%>" />
|
||||
<% if self.invalid_cts then -%>
|
||||
<br /><%:Invalid%></div>
|
||||
<%- end %>
|
||||
</div>
|
||||
<br />
|
||||
<% self:render_children(section, scope or {}) %>
|
||||
</div>
|
||||
<br />
|
||||
<% if self.error and self.error[1] then -%>
|
||||
<div class="cbi-section-error">
|
||||
<ul><% for _, e in ipairs(self.error[1]) do -%>
|
||||
<li>
|
||||
<%- if e == "invalid" then -%>
|
||||
<%:One or more configure contain invalid values!%>
|
||||
<%- elseif e == "missing" then -%>
|
||||
<%:One or more required configure is missing!%>
|
||||
<%- else -%>
|
||||
<%=pcdata(e)%>
|
||||
<%- end -%>
|
||||
</li>
|
||||
<%- end %></ul>
|
||||
</div>
|
||||
<%- end %>
|
||||
<% if message then %>
|
||||
<div class="alert-message"><%=message%></div>
|
||||
<% end %>
|
||||
<br />
|
||||
</fieldset>
|
||||
<% end %>
|
||||
@@ -0,0 +1,107 @@
|
||||
<!-- ++ BEGIN ++ DNSCrypt Proxy ++ logsview.htm ++ -->
|
||||
<%-
|
||||
local values = self:formvalue(section)
|
||||
if not values then
|
||||
values = self:cfgvalue(section) or {self.default}
|
||||
end
|
||||
|
||||
local function serialize_json(x, cb)
|
||||
local rv, push = nil, cb
|
||||
if not push then
|
||||
rv = { }
|
||||
push = function(tok) rv[#rv+1] = tok end
|
||||
end
|
||||
|
||||
if x == nil then
|
||||
push("null")
|
||||
elseif type(x) == "table" then
|
||||
push("[")
|
||||
for k = 1, #x do
|
||||
if k > 1 then
|
||||
push(",")
|
||||
end
|
||||
serialize_json(x[k], push)
|
||||
end
|
||||
push("]")
|
||||
else
|
||||
push('"%s"' % tostring(x):gsub('["%z\1-\31\\]',
|
||||
function(c) return '\\u%04x' % c:byte(1) end))
|
||||
end
|
||||
|
||||
if not cb then
|
||||
return table.concat(rv, "")
|
||||
end
|
||||
end
|
||||
-%>
|
||||
<%+cbi/valueheader%>
|
||||
<select class="cbi-input-select" onchange="onclick_logview(this, false)"
|
||||
<%=
|
||||
attr("name", cbid) .. attr("id", cbid) .. attr("value", self.default) .. ifattr(self.size, "size")
|
||||
%>
|
||||
></select>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
(function() {
|
||||
//var values = <%=serialize_json(values)%>;
|
||||
var keylist = <%=serialize_json(self.keylist)%>;
|
||||
var vallist = <%=serialize_json(self.vallist)%>;
|
||||
var parent = document.getElementById("<%=cbid%>");
|
||||
for (var j = 0; j < keylist.length; j++) {
|
||||
var opt = document.createElement("option");
|
||||
opt.value = keylist[j];
|
||||
if (j == 0) {
|
||||
opt.selected = "selected";
|
||||
}
|
||||
opt.appendChild(document.createTextNode(vallist[j]));
|
||||
parent.appendChild(opt);
|
||||
}
|
||||
}());
|
||||
//]]></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function onclick_logview(id, bottom) {
|
||||
// get elements
|
||||
var txt = document.getElementById("<%=cbid%>.txt"); // TextArea
|
||||
if ( !txt ) { return; } // security check
|
||||
txt.value= "Reading: " + document.getElementById("<%=cbid%>").value
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "dnscrypt-proxy", "fileread")%>', {lfile: document.getElementById("<%=cbid%>").value} ,
|
||||
function(x, rv) {
|
||||
if(x.readyState === 4 ) {
|
||||
if(x.status === 200) {try{res = JSON.parse(x.responseText);}catch(e){res=null;}
|
||||
if(res !==null && typeof(res) === "object") txt.value = res[0]; if (bottom) txt.scrollTop = txt.scrollHeight; else txt.scrollTop = 0; txt.scrollLeft = 0;
|
||||
} else {
|
||||
txt.value = "XHR.get(<%=luci.dispatcher.build_url("admin", "services", "dnscrypt-proxy", "fileread")%>) Failed!";
|
||||
}}});
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
<%
|
||||
-- one button on top, one at the buttom
|
||||
%>
|
||||
<br /><br />
|
||||
<input class="cbi-button cbi-input-button" style="align: center; width: 100%" type="button" onclick='onclick_logview(this, false)'
|
||||
<%=
|
||||
attr("name", section) .. attr("id", cbid .. ".btn1") .. attr("value", self.inputtitle)
|
||||
%> />
|
||||
|
||||
<br /><br />
|
||||
|
||||
<%
|
||||
-- set a readable style taken from openwrt theme for textarea#syslog
|
||||
-- in openwrt theme there are problems with a width of 100 so we check for theme and set to lower value
|
||||
%>
|
||||
<textarea style="width: <%if media == "/luci-static/openwrt.org" then%>98.7%<%else%>100%<%end%> ; min-height: 200px; border: 3px solid #cccccc; padding: 5px; font-family: monospace; resize: none;" wrap="off" readonly="readonly"
|
||||
<%=
|
||||
attr("name", cbid .. ".txt") .. attr("id", cbid .. ".txt") .. ifattr(self.rows, "rows")
|
||||
%> >
|
||||
<%-=pcdata(self:cfgvalue(section))-%>
|
||||
</textarea>
|
||||
<br /><br />
|
||||
|
||||
<%
|
||||
-- one button on top, one at the buttom
|
||||
%>
|
||||
<input class="cbi-button cbi-input-button" style="align: center; width: 100%" type="button" onclick='onclick_logview(this, true)'
|
||||
<%= attr("name", section) .. attr("id", cbid .. ".btn2") .. attr("value", self.inputtitle) %> />
|
||||
<br /><br />
|
||||
<%+cbi/valuefooter%>
|
||||
<!-- ++ END ++ DNSCrypt Proxy ++ logsview.htm ++ -->
|
||||
@@ -0,0 +1,103 @@
|
||||
<%+cbi/valueheader%>
|
||||
<%-
|
||||
local util = require "luci.util"
|
||||
local sys = require "luci.sys"
|
||||
-%>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
<% if self.option == "dnscrypt_bin" then -%>
|
||||
function update_bin(obtn, dataname, surl)
|
||||
{
|
||||
obtn.disabled = true;
|
||||
ret = false;
|
||||
alert(dataname+":\n" + surl);
|
||||
murl = dataname;
|
||||
var osta = document.getElementById(dataname+'-status'); XHR.get('<%=luci.dispatcher.build_url("admin", "services", "dnscrypt-proxy","update_c")%>',
|
||||
{ set:"dnscrypt_bin", url:surl },
|
||||
function(x, rv) {
|
||||
if(x.readyState === 4 ) {
|
||||
if(x.status === 200) {try{res = JSON.parse(x.responseText);}catch(e){res=null;}
|
||||
if(res !==null && typeof(res) === "object") {osta.innerText = res.status; obtn.disabled = false; obtn.value = '<%= self.name or translate("Refresh Data")%>';obtn.onclick = function (){alert("<%:No new data!%>");}; return (rv.err === 0);}
|
||||
}}});
|
||||
return false;
|
||||
}
|
||||
|
||||
function parse_gittag(gtag, obtn, osta, sprefix, scver)
|
||||
{
|
||||
ret = true;
|
||||
tagv = gtag.name;
|
||||
dlfile = 'dnscrypt-proxy-%s-%s.tar.gz'.format(sprefix, tagv);
|
||||
obtn.title = "";
|
||||
osta.innerHTML = '<font color="red">%s</font><br /><div class="cbi-section-descr"><pre>%s</pre></div>'.format(dlfile, gtag.body);
|
||||
if(scver === tagv) {obtn.value = '<%:No new data!%>';}
|
||||
else if(! gtag.assets) {osta.innerText = '<%:Refresh Error!%>'; ret = false;}
|
||||
else {
|
||||
_assets = gtag.assets;
|
||||
osta.innerText = dlfile;
|
||||
for (var idx = 0; idx < _assets.length; idx++) {
|
||||
var dls=_assets[idx];
|
||||
if(dls.name === dlfile) {
|
||||
obtn.value = '<%:Update%> ' + tagv;
|
||||
obtn.title = dls.browser_download_url;
|
||||
obtn.onclick = function() { update_bin(this,'<%=self.option%>',this.title); };
|
||||
obtn.disabled = false;
|
||||
osta.innerHTML = '<a href="%s">%s</a>(%00.1fMB)<br /><div class="cbi-section-descr"><pre>%s</pre></div>'.format(dls.browser_download_url, dlfile, dls.size/1024/1024, gtag.body);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
<%- end %>
|
||||
function refresh_data_<%=self.option%>(btn,dataname)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Refresh...%> ';
|
||||
murl=dataname;
|
||||
var s = document.getElementById(dataname+'-status');
|
||||
if (dataname === "dnscrypt_bin") {
|
||||
os = '<%=util.trim(sys.exec("uname")):lower()%>';
|
||||
arch = '<%=util.trim(sys.exec("uname -m"))%>';
|
||||
prefix = '%s_%s'.format(os, arch);
|
||||
cver = '<%=util.trim(sys.exec("/usr/sbin/dnscrypt-proxy -version"))%>';
|
||||
tag_url = 'https://api.github.com/repos/dnscrypt/dnscrypt-proxy/releases/latest';
|
||||
s.innerHTML = ' current: dnscrypt-proxy %s-%s.tar.gz <a href="%s">release checking...</a>'.format(prefix, cver, tag_url);
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "dnscrypt-proxy","refresh_c")%>',null, function(x,rv) {
|
||||
s.innerText = 'Test, %s readyState: %d, status: %d'.format(x.statusText, x.readyState, x.status);
|
||||
x.open('GET', tag_url, true);
|
||||
x.onreadystatechange = function() {
|
||||
if(x.readyState === 4 && x.status === 200) {
|
||||
try{res = JSON.parse(x.responseText);}catch(e){res=null;}
|
||||
if(res !==null && typeof(res) === "object") {parse_gittag(res, btn, s, prefix, cver);}
|
||||
} else {
|
||||
s.innerHTML = '<font color="red">ReleaseTag, %s readyState: %d, status: %d</font>'.format(x.statusText, x.readyState, x.status);
|
||||
btn.disabled = false;
|
||||
btn.value = '<%= self.name or translate("Refresh Data")%>';
|
||||
}};
|
||||
x.send(null);
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "dnscrypt-proxy","refresh_c")%>',
|
||||
{ set:murl },
|
||||
function(x, rv) {
|
||||
if(x.readyState === 4 ) {
|
||||
if(x.status === 200) {try{res = JSON.parse(x.responseText);}catch(e){res=null;}
|
||||
if(res !==null && typeof(res) === "object") {
|
||||
var s = document.getElementById(dataname+'-status');
|
||||
if (s) {
|
||||
if (res.ret=="0") s.innerHTML ="<font color='green'>"+"<%:No new data!%> "+"</font>";
|
||||
else if(res.ret=="-1") s.innerHTML ="<font color='red'>"+"<%:Refresh Error!%> "+"</font>";
|
||||
else s.innerHTML ="<font color='green'>"+"<%:Refresh OK!%> "+"<%= self.ret or translate('Total Records:')%>"+res.ret+"</font>";
|
||||
btn.disabled = false;
|
||||
btn.value = '<%= self.name or translate('Refresh Data')%>';}}
|
||||
}}});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
|
||||
<input type="button" class="cbi-button cbi-input-reload" value="<%= self.name or translate('Refresh Data')%> " onclick="return refresh_data_<%=self.option%>(this,'<%=self.option%>')" />
|
||||
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
@@ -0,0 +1,22 @@
|
||||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
function check_port(btn, func)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Check...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "dnscrypt-proxy","resolve_c")%>',
|
||||
{ set:func },
|
||||
function(x, rv) {
|
||||
if(x.readyState === 4 ) {
|
||||
if(x.status === 200) {try{res = JSON.parse(x.responseText);}catch(e){res=null;}
|
||||
if(res !==null && typeof(res) === "object") {var s = document.getElementById(func + '-status'); if (s) s.innerHTML =res.ret; btn.disabled = false; btn.value = '<%:Check Server%>';}
|
||||
}}});
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Check Server%>" onclick="return check_port(this,'<%=self.option%>')" />
|
||||
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
config source 'global'
|
||||
option urls 'https://github.com/DNSCrypt/dnscrypt-resolvers/raw/master/v3/public-resolvers.md'
|
||||
option details_json 'https://download.dnscrypt.info/dnscrypt-resolvers/json/public-resolvers.json'
|
||||
option minisign_key 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
|
||||
option cache_mode '1'
|
||||
option selfsign '0'
|
||||
|
||||
config dnscrypt 'quad9_dnscrypt_ip6_filter_pri'
|
||||
option name 'quad9-dnscrypt-ip6-filter-pri'
|
||||
option proto 'DNSCrypt'
|
||||
option addrs '[2620:fe::fe:9]'
|
||||
option ports '8443'
|
||||
option stamp 'sdns://AQMAAAAAAAAAFFsyNjIwOmZlOjpmZTo5XTo4NDQzIGfIR7jIdYzRICRVQ751Z0bfNN8dhMALjEcDaN-CHYY-GTIuZG5zY3J5cHQtY2VydC5xdWFkOS5uZXQ'
|
||||
option description 'Quad9 (anycast) dnssec/no-log/filter 2620:fe::fe:9'
|
||||
option location '37.751000,-97.822000'
|
||||
option country 'United States'
|
||||
option dnssec '1'
|
||||
option ipv6 '1'
|
||||
option nolog '1'
|
||||
option nofilter '0'
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
[ ! -f "/usr/share/ucitrack/luci-app-dnscrypt_proxy.json" ] && {
|
||||
cat > /usr/share/ucitrack/luci-app-dnscrypt_proxy.json << EEOF
|
||||
{
|
||||
"config": "dnscrypt_proxy",
|
||||
"init": "dnscrypt_proxy"
|
||||
}
|
||||
EEOF
|
||||
}
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@dnscrypt_proxy[-1]
|
||||
add ucitrack dnscrypt_proxy
|
||||
set ucitrack.@dnscrypt_proxy[-1].init=dnscrypt-proxy
|
||||
commit ucitrack
|
||||
delete firewall.dnscrypt_proxy
|
||||
set firewall.dnscrypt_proxy=include
|
||||
set firewall.dnscrypt_proxy.type=script
|
||||
set firewall.dnscrypt_proxy.path=/var/etc/dnscrypt-proxy.include
|
||||
set firewall.dnscrypt_proxy.reload=1
|
||||
commit firewall
|
||||
EOF
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
||||
Reference in new issue
Block a user