update 2026-05-10 09:48:30

This commit is contained in:
action committed 2026-05-10 09:48:30 +08:00
1 parent 95ac96413e
commit 0b362674f1
6244 files changed
+2992248

No files matched your search

+32
View File
@@ -0,0 +1,32 @@
config mosdns 'config'
option enabled '0'
option listen_port '5335'
option listen_address '0.0.0.0'
option geo_auto_update '0'
option geo_update_week_time '*'
option geo_update_day_time '2'
option geoip_type 'geoip-only-cn-private'
option configfile '/var/etc/mosdns.json'
option log_level 'info'
option log_file '/var/log/mosdns.log'
option cache '1'
option concurrent '2'
option idle_timeout '30'
option minimal_ttl '0'
option maximum_ttl '0'
option enable_pipeline '1'
option insecure_skip_verify '0'
option dns_leak '0'
option cloudflare '0'
option listen_port_api '9091'
option bootstrap_dns '119.29.29.29'
list remote_dns 'tls://8.8.8.8'
option redirect '1'
option prefer_ipv4 '1'
option enable_ecs_remote '0'
option cache_size '8000'
option lazy_cache_ttl '86400'
option dump_file '0'
option reject_type65 '1'
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
[ "$ACTION" = ifup ] && /etc/init.d/mosdns restart
+836
View File
@@ -0,0 +1,836 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2020-2022, IrineSistiana
# Copyright (C) 2023-2026, sbwml <admin@cooluc.com>
START=75
USE_PROCD=1
PROG=/usr/bin/mosdns
CONF=$(uci -q get mosdns.config.configfile)
CRON_FILE=/etc/crontabs/root
DUMP_FILE=/etc/mosdns/cache.dump
DUMP_FILE_DEFAULT=/usr/share/mosdns/cache.dump
MOSDNS_SCRIPT=/usr/share/mosdns/mosdns.uc
REDIRECT_LOCK_FILE=/etc/mosdns/redirect.lock
get_config() {
config_get enabled $1 enabled 0
config_get adblock $1 adblock 0
config_get ad_source $1 ad_source ""
config_get cache $1 cache 0
config_get cache_size $1 cache_size 8000
config_get lazy_cache_ttl $1 lazy_cache_ttl 86400
config_get dump_file $1 dump_file 0
config_get dump_interval $1 dump_interval 3600
config_get enable_pipeline $1 enable_pipeline 0
config_get geo_auto_update $1 geo_auto_update 0
config_get geo_update_day_time $1 geo_update_day_time 2
config_get geo_update_week_time $1 geo_update_week_time "*"
config_get listen_port $1 listen_port 5335
config_get listen_address $1 listen_address "0.0.0.0"
config_get log_file $1 log_file "/var/log/mosdns.log"
config_get log_level $1 log_level "info"
config_get minimal_ttl $1 minimal_ttl 0
config_get maximum_ttl $1 maximum_ttl 0
config_get redirect $1 redirect 0
config_get local_dns_redirect $1 local_dns_redirect 0
config_get prefer_ipv4_cn $1 prefer_ipv4_cn 0
config_get prefer_ipv4 $1 prefer_ipv4 0
config_get remote_dns $1 remote_dns "tls://8.8.8.8 tls://1.1.1.1"
config_get custom_local_dns $1 custom_local_dns 0
config_get apple_optimization $1 apple_optimization 0
config_get custom_stream_media_dns $1 custom_stream_media_dns 0
config_get stream_media_dns $1 stream_media_dns "tls://8.8.8.8"
config_get bootstrap_dns $1 bootstrap_dns "119.29.29.29"
config_get listen_port_api $1 listen_port_api 52001
config_get concurrent $1 concurrent 1
config_get insecure_skip_verify $1 insecure_skip_verify 0
config_get idle_timeout $1 idle_timeout 30
config_get enable_ecs_remote $1 enable_ecs_remote 0
config_get remote_ecs_ip $1 remote_ecs_ip "110.34.181.1"
config_get dns_leak $1 dns_leak 0
config_get cloudflare $1 cloudflare 0
config_get cloudflare_ip $1 cloudflare_ip ""
config_get reject_type65 $1 reject_type65 "0"
}
generate_config() {
# jshn shell library
. /usr/share/libubox/jshn.sh
# json data
json_init
# log
json_add_object 'log'
json_add_string "level" "$log_level"
json_add_string "file" "$log_file"
json_close_object
# api
json_add_object 'api'
json_add_string "http" "127.0.0.1:$listen_port_api"
json_close_object
# include
json_add_array "include"
json_close_array
# plugins
json_add_array "plugins"
# plugin: geosite_cn
json_add_object
json_add_string "tag" "geosite_cn"
json_add_string "type" "domain_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/var/mosdns/geosite_cn.txt"
json_close_array
json_close_object
json_close_object
# plugin: geoip_cn
json_add_object
json_add_string "tag" "geoip_cn"
json_add_string "type" "ip_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/var/mosdns/geoip_cn.txt"
json_close_array
json_close_object
json_close_object
# plugin: geosite_apple
json_add_object
json_add_string "tag" "geosite_apple"
json_add_string "type" "domain_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/var/mosdns/geosite_apple.txt"
json_close_array
json_close_object
json_close_object
# plugin: geosite_no_cn
json_add_object
json_add_string "tag" "geosite_no_cn"
json_add_string "type" "domain_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/var/mosdns/geosite_geolocation-!cn.txt"
json_close_array
json_close_object
json_close_object
# plugin: whitelist
json_add_object
json_add_string "tag" "whitelist"
json_add_string "type" "domain_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/etc/mosdns/rule/whitelist.txt"
json_close_array
json_close_object
json_close_object
# plugin: blocklist
json_add_object
json_add_string "tag" "blocklist"
json_add_string "type" "adblock_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/etc/mosdns/rule/blocklist.txt"
json_close_array
json_close_object
json_close_object
# plugin: greylist
json_add_object
json_add_string "tag" "greylist"
json_add_string "type" "domain_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/etc/mosdns/rule/greylist.txt"
json_close_array
json_close_object
json_close_object
# plugin: ddnslist
json_add_object
json_add_string "tag" "ddnslist"
json_add_string "type" "domain_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/etc/mosdns/rule/ddnslist.txt"
json_close_array
json_close_object
json_close_object
# plugin: hosts
json_add_object
json_add_string "tag" "hosts"
json_add_string "type" "hosts"
json_add_object "args"
json_add_array "files"
json_add_string "" "/etc/mosdns/rule/hosts.txt"
json_close_array
json_close_object
json_close_object
# plugin: redirect
json_add_object
json_add_string "tag" "redirect"
json_add_string "type" "redirect"
json_add_object "args"
json_add_array "files"
json_add_string "" "/etc/mosdns/rule/redirect.txt"
json_close_array
json_close_object
json_close_object
# plugin: adlist
json_add_object
json_add_string "tag" "adlist"
json_add_string "type" "adblock_set"
json_add_object "args"
json_add_array "files"
adlist=$($MOSDNS_SCRIPT get_adlist)
[ -z "$adlist" ] && adlist="/var/mosdns/disable-ads.txt" # fail-safe
for list in $adlist; do
json_add_string "" "$list"
done
json_close_array
json_close_object
json_close_object
# plugin: local_ptr
json_add_object
json_add_string "tag" "local_ptr"
json_add_string "type" "domain_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/etc/mosdns/rule/local-ptr.txt"
json_close_array
json_close_object
json_close_object
# plugin: stream_media
json_add_object
json_add_string "tag" "stream_media"
json_add_string "type" "domain_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/var/mosdns/geosite_disney.txt"
json_add_string "" "/var/mosdns/geosite_netflix.txt"
json_add_string "" "/var/mosdns/geosite_hulu.txt"
json_add_string "" "/etc/mosdns/rule/streaming.txt"
json_close_array
json_close_object
json_close_object
# plugin: cloudflare_cidr
json_add_object
json_add_string "tag" "cloudflare_cidr"
json_add_string "type" "ip_set"
json_add_object "args"
json_add_array "files"
json_add_string "" "/etc/mosdns/rule/cloudflare-cidr.txt"
json_close_array
json_close_object
json_close_object
# plugin: lazy_cache
[ "$cache" -eq 1 ] && {
json_add_object
json_add_string "tag" "lazy_cache"
json_add_string "type" "cache"
json_add_object "args"
json_add_int "size" "$cache_size"
json_add_int "lazy_cache_ttl" "$lazy_cache_ttl"
[ "$dump_file" -eq 1 ] && {
json_add_string "dump_file" "/etc/mosdns/cache.dump"
json_add_int "dump_interval" "$dump_interval"
}
json_close_object
json_close_object
}
# plugin: forward_xinfeng_udp
json_add_object
json_add_string "tag" "forward_xinfeng_udp"
json_add_string "type" "forward"
json_add_object "args"
json_add_int "concurrent" 2
json_add_array "upstreams"
json_add_object
json_add_string "addr" "114.114.114.114"
json_close_object
json_add_object
json_add_string "addr" "114.114.115.115"
json_close_object
json_close_array
json_close_object
json_close_object
# plugin: forward_local
json_add_object
json_add_string "tag" "forward_local"
json_add_string "type" "forward"
json_add_object "args"
json_add_int "concurrent" "$concurrent"
json_add_array "upstreams"
local_dns=$($MOSDNS_SCRIPT interface_dns)
[ -z "$local_dns" ] && local_dns="119.29.29.29 223.5.5.5" # fail-safe
for addr in $local_dns; do
enable_http3=0
if echo "$addr" | grep -q "^h3://"; then
enable_http3=1
addr=$(echo $addr | sed 's/h3:\/\//https:\/\//g')
fi
json_add_object
json_add_string "addr" "$addr"
json_add_string "bootstrap" "$bootstrap_dns"
json_add_boolean "enable_pipeline" "$enable_pipeline"
json_add_boolean "insecure_skip_verify" "$insecure_skip_verify"
json_add_int "idle_timeout" "$idle_timeout"
[ "$enable_http3" -eq 1 ] && json_add_boolean "enable_http3" "1"
json_close_object
done
json_close_array
json_close_object
json_close_object
# plugin: forward_remote
json_add_object
json_add_string "tag" "forward_remote"
json_add_string "type" "forward"
json_add_object "args"
json_add_int "concurrent" "$concurrent"
json_add_array "upstreams"
for addr in $remote_dns; do
enable_http3=0
if echo "$addr" | grep -q "^h3://"; then
enable_http3=1
addr=$(echo $addr | sed 's/h3:\/\//https:\/\//g')
fi
json_add_object
json_add_string "addr" "$addr"
json_add_string "bootstrap" "$bootstrap_dns"
json_add_boolean "enable_pipeline" "$enable_pipeline"
json_add_boolean "insecure_skip_verify" "$insecure_skip_verify"
json_add_int "idle_timeout" "$idle_timeout"
[ "$enable_http3" -eq 1 ] && json_add_boolean "enable_http3" "1"
json_close_object
done
json_close_array
json_close_object
json_close_object
# plugin: forward_remote_upstream
json_add_object
json_add_string "tag" "forward_remote_upstream"
json_add_string "type" "sequence"
json_add_array "args"
[ "$prefer_ipv4" -eq 1 ] && {
json_add_object
json_add_string "exec" "prefer_ipv4"
json_close_object
}
[ "$enable_ecs_remote" -eq 1 ] && {
json_add_object
json_add_string "exec" "ecs $remote_ecs_ip"
json_close_object
}
json_add_object
json_add_string "exec" "\$forward_remote"
json_close_object
json_close_array
json_close_object
# plugin: forward_stream_media
json_add_object
json_add_string "tag" "forward_stream_media"
json_add_string "type" "forward"
json_add_object "args"
json_add_int "concurrent" "$concurrent"
json_add_array "upstreams"
for addr in $stream_media_dns; do
enable_http3=0
if echo "$addr" | grep -q "^h3://"; then
enable_http3=1
addr=$(echo $addr | sed 's/h3:\/\//https:\/\//g')
fi
json_add_object
json_add_string "addr" "$addr"
json_add_string "bootstrap" "$bootstrap_dns"
json_add_boolean "enable_pipeline" "$enable_pipeline"
json_add_boolean "insecure_skip_verify" "$insecure_skip_verify"
json_add_int "idle_timeout" "$idle_timeout"
[ "$enable_http3" -eq 1 ] && json_add_boolean "enable_http3" "1"
json_close_object
done
json_close_array
json_close_object
json_close_object
# plugin: forward_stream_media_upstream
json_add_object
json_add_string "tag" "forward_stream_media_upstream"
json_add_string "type" "sequence"
json_add_array "args"
[ "$prefer_ipv4" -eq 1 ] && {
json_add_object
json_add_string "exec" "prefer_ipv4"
json_close_object
}
[ "$enable_ecs_remote" -eq 1 ] && {
json_add_object
json_add_string "exec" "ecs $remote_ecs_ip"
json_close_object
}
json_add_object
json_add_string "exec" "\$forward_stream_media"
json_close_object
json_close_array
json_close_object
# plugin: modify_ttl
json_add_object
json_add_string "tag" "modify_ttl"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "exec" "ttl $minimal_ttl-$maximum_ttl"
json_close_object
json_close_array
json_close_object
# plugin: modify_ddns_ttl
json_add_object
json_add_string "tag" "modify_ddns_ttl"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "exec" "ttl 5-5"
json_close_object
json_close_array
json_close_object
# plugin: has_resp_sequence
json_add_object
json_add_string "tag" "has_resp_sequence"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "matches" "qname \$ddnslist"
json_add_string "exec" "\$modify_ddns_ttl"
json_close_object
json_add_object
json_add_string "matches" "!qname \$ddnslist"
json_add_string "exec" "\$modify_ttl"
json_close_object
[ "$cloudflare" -eq 1 ] && {
json_add_object
json_add_array "matches"
json_add_string "" "!qname \$whitelist"
json_add_string "" "!qname \$greylist"
json_add_string "" "!qname \$stream_media"
json_add_string "" "resp_ip \$cloudflare_cidr"
json_close_array
json_add_string "exec" "black_hole $cloudflare_ip"
json_close_object
}
json_add_object
json_add_string "matches" "has_resp"
json_add_string "exec" "accept"
json_close_object
json_close_array
json_close_object
# plugin: query_is_non_local_ip
json_add_object
json_add_string "tag" "query_is_non_local_ip"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "exec" "\$forward_local"
json_close_object
json_add_object
json_add_string "matches" "!resp_ip \$geoip_cn"
json_add_string "exec" "drop_resp"
json_close_object
json_close_array
json_close_object
# plugin: fallback
json_add_object
json_add_string "tag" "fallback"
json_add_string "type" "fallback"
json_add_object "args"
[ "$dns_leak" -eq 1 ] && json_add_string "primary" "forward_remote_upstream" || json_add_string "primary" "query_is_non_local_ip"
json_add_string "secondary" "forward_remote_upstream"
json_add_int "threshold" 500
json_add_boolean "always_standby" 1
json_close_object
json_close_object
# plugin: apple_domain_fallback
json_add_object
json_add_string "tag" "apple_domain_fallback"
json_add_string "type" "fallback"
json_add_object "args"
json_add_string "primary" "query_is_non_local_ip"
json_add_string "secondary" "forward_xinfeng_udp"
json_add_int "threshold" 100
json_add_boolean "always_standby" 1
json_close_object
json_close_object
# plugin: query_is_apple_domain
json_add_object
json_add_string "tag" "query_is_apple_domain"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "matches" "!qname \$geosite_apple"
json_add_string "exec" "return"
json_close_object
json_add_object
json_add_string "exec" "\$apple_domain_fallback"
json_close_object
json_close_array
json_close_object
# plugin: query_is_ddns_domain
json_add_object
json_add_string "tag" "query_is_ddns_domain"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "matches" "qname \$ddnslist"
json_add_string "exec" "\$forward_local"
json_close_object
json_close_array
json_close_object
# plugin: query_is_local_domain
json_add_object
json_add_string "tag" "query_is_local_domain"
json_add_string "type" "sequence"
json_add_array "args"
[ "$prefer_ipv4_cn" -eq 1 ] && {
json_add_object
json_add_string "exec" "prefer_ipv4"
json_close_object
}
json_add_object
json_add_string "matches" "qname \$geosite_cn"
json_add_string "exec" "\$forward_local"
json_close_object
json_close_array
json_close_object
# plugin: query_is_no_local_domain
json_add_object
json_add_string "tag" "query_is_no_local_domain"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "matches" "qname \$geosite_no_cn"
json_add_string "exec" "\$forward_remote_upstream"
json_close_object
json_close_array
json_close_object
# plugin: query_is_whitelist_domain
json_add_object
json_add_string "tag" "query_is_whitelist_domain"
json_add_string "type" "sequence"
json_add_array "args"
[ "$prefer_ipv4_cn" -eq 1 ] && {
json_add_object
json_add_string "exec" "prefer_ipv4"
json_close_object
}
json_add_object
json_add_string "matches" "qname \$whitelist"
json_add_string "exec" "\$forward_local"
json_close_object
json_close_array
json_close_object
# plugin: query_is_greylist_domain
json_add_object
json_add_string "tag" "query_is_greylist_domain"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "matches" "qname \$greylist"
json_add_string "exec" "\$forward_remote_upstream"
json_close_object
json_close_array
json_close_object
# plugin: query_is_reject_domain
json_add_object
json_add_string "tag" "query_is_reject_domain"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "matches" "qname \$blocklist"
json_add_string "exec" "reject 3"
json_close_object
json_add_object
json_add_string "matches" "qname \$adlist"
json_add_string "exec" "reject 3"
json_close_object
json_add_object
json_add_array "matches"
json_add_string "" "qtype 12"
json_add_string "" "qname \$local_ptr"
json_close_array
json_add_string "exec" "reject 3"
json_close_object
[ "$reject_type65" -eq 1 ] && {
json_add_object
json_add_string "matches" "qtype 65"
json_add_string "exec" "reject 3"
json_close_object
}
json_close_array
json_close_object
# plugin: query_is_stream_media_domain
json_add_object
json_add_string "tag" "query_is_stream_media_domain"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "matches" "qname \$stream_media"
json_add_string "exec" "\$forward_stream_media_upstream"
json_close_object
json_close_array
json_close_object
# plugin: main_sequence
json_add_object
json_add_string "tag" "main_sequence"
json_add_string "type" "sequence"
json_add_array "args"
json_add_object
json_add_string "exec" "\$hosts"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
[ "$cache" -eq 1 ] && {
json_add_object
json_add_array "matches"
json_add_string "" "!qname \$ddnslist"
json_add_string "" "!qname \$blocklist"
json_add_string "" "!qname \$adlist"
json_add_string "" "!qname \$local_ptr"
json_close_array
json_add_string "exec" "\$lazy_cache"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
}
json_add_object
json_add_string "exec" "\$redirect"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
json_add_object
[ "$apple_optimization" -eq 1 ] && {
json_add_string "exec" "\$query_is_apple_domain"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
json_add_object
}
json_add_string "exec" "\$query_is_ddns_domain"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
json_add_object
json_add_string "exec" "\$query_is_whitelist_domain"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
json_add_object
json_add_string "exec" "\$query_is_reject_domain"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
json_add_object
json_add_string "exec" "\$query_is_greylist_domain"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
[ "$custom_stream_media_dns" -eq 1 ] && {
json_add_object
json_add_string "exec" "\$query_is_stream_media_domain"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
}
json_add_object
json_add_string "exec" "\$query_is_local_domain"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
json_add_object
json_add_string "exec" "\$query_is_no_local_domain"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
json_add_object
json_add_string "exec" "\$fallback"
json_close_object
json_add_object
json_add_string "exec" "jump has_resp_sequence"
json_close_object
json_close_array
json_close_object
# plugin: udp_server
json_add_object
json_add_string "tag" "udp_server"
json_add_string "type" "udp_server"
json_add_object "args"
json_add_string "entry" "main_sequence"
json_add_string "listen" "$listen_address:$listen_port"
json_close_object
json_close_object
# plugin: tcp_server
json_add_object
json_add_string "tag" "tcp_server"
json_add_string "type" "tcp_server"
json_add_object "args"
json_add_string "entry" "main_sequence"
json_add_string "listen" "$listen_address:$listen_port"
json_close_object
json_close_object
# close plugins array
json_close_array
# print json
json_dump > /var/etc/mosdns.json
# init dump_file
[ "$dump_file" -eq 1 ] && [ ! -f $DUMP_FILE ] && cp -a $DUMP_FILE_DEFAULT $DUMP_FILE
[ "$dump_file" -eq 0 ] && \cp -a $DUMP_FILE_DEFAULT $DUMP_FILE
}
service_triggers() {
procd_add_reload_trigger "mosdns"
}
dhcp_setting() {
[ ! -f "$REDIRECT_LOCK_FILE" ] && {
printf "rebind_protection=$(uci -q get dhcp.@dnsmasq[0].rebind_protection)\n"
printf "rebind_localhost=$(uci -q get dhcp.@dnsmasq[0].rebind_localhost)\n"
printf "noresolv=$(uci -q get dhcp.@dnsmasq[0].noresolv)\n"
printf "resolvfile=$(uci -q get dhcp.@dnsmasq[0].resolvfile)\n"
printf "cachesize=$(uci -q get dhcp.@dnsmasq[0].cachesize)\n"
} > $REDIRECT_LOCK_FILE
if [ "${CONF}" = "/var/etc/mosdns.json" ]; then
sed -i "/list server/d" /etc/config/dhcp
uci add_list dhcp.@dnsmasq[0].server="127.0.0.1#$listen_port"
uci set dhcp.@dnsmasq[0].rebind_protection='0'
uci set dhcp.@dnsmasq[0].noresolv="1"
uci set dhcp.@dnsmasq[0].cachesize='0'
uci commit dhcp
else
sed -i "/list server/d" /etc/config/dhcp
uci add_list dhcp.@dnsmasq[0].server="127.0.0.1#$(awk -F'[:" ]+' '/^\s+listen:/{for(i=1;i<=NF;i++){if($i~/^[0-9]+$/){print $i;exit}}}' $CONF)"
uci set dhcp.@dnsmasq[0].rebind_protection='0'
uci set dhcp.@dnsmasq[0].noresolv="1"
uci set dhcp.@dnsmasq[0].cachesize='0'
uci commit dhcp
fi
}
uci_set_or_del() {
local key="$1"
local val="$2"
if [ -n "$val" ]; then
uci set "$key=$val"
else
uci del "$key"
fi
}
restore_dhcp_setting() {
if [ -f "$REDIRECT_LOCK_FILE" ]; then
sed -i "/list server/d" /etc/config/dhcp
source "$REDIRECT_LOCK_FILE"
uci_set_or_del dhcp.@dnsmasq[0].rebind_protection "$rebind_protection"
uci_set_or_del dhcp.@dnsmasq[0].resolvfile "$resolvfile"
uci_set_or_del dhcp.@dnsmasq[0].rebind_localhost "$rebind_localhost"
uci_set_or_del dhcp.@dnsmasq[0].noresolv "$noresolv"
uci_set_or_del dhcp.@dnsmasq[0].cachesize "$cachesize"
uci commit dhcp
rm -f "$REDIRECT_LOCK_FILE"
fi
}
reload_dnsmasq() {
[ "$(/etc/init.d/dnsmasq status)" = "running" ] && /etc/init.d/dnsmasq reload
}
reload_service() {
stop
sleep 1
start
}
setcron() {
sed -i '/mosdns.uc/d' $CRON_FILE 2>/dev/null
[ "$geo_auto_update" -eq 1 ] && echo "0 $geo_update_day_time * * $geo_update_week_time /usr/share/mosdns/mosdns.uc update" >> $CRON_FILE
crontab $CRON_FILE
}
delcron() {
sed -i '/mosdns.uc/d' $CRON_FILE 2>/dev/null
crontab $CRON_FILE
}
start_service() {
config_load "mosdns"
config_foreach get_config "mosdns"
[ $enabled -ne 1 ] && return 1
delcron ; setcron
rm -rf /tmp/log/mosdns*
$MOSDNS_SCRIPT v2dat_dump
[ "${CONF}" = "/var/etc/mosdns.json" ] && generate_config
procd_open_instance mosdns
procd_set_param env QUIC_GO_DISABLE_RECEIVE_BUFFER_WARNING=true
procd_set_param command $PROG start
procd_append_param command -c "$CONF"
procd_append_param command -d "/etc/mosdns"
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param respawn
procd_close_instance mosdns
[ "$redirect" -ne 1 ] && restore_dhcp_setting
[ "$redirect" -eq 1 ] && dhcp_setting
reload_dnsmasq
# dns hijack
if [ "$local_dns_redirect" -eq 1 ] && [ -f "/sbin/fw4" ]; then
! nft --check list table inet mosdns > "/dev/null" 2>&1 || \
nft delete table inet mosdns
nft add table inet mosdns
nft add chain inet mosdns prerouting "{ type nat hook prerouting priority -95; policy accept; }"
nft add rule inet mosdns prerouting "meta nfproto { ipv4, ipv6 } udp dport 53 counter redirect to :$listen_port comment \"DNS HIJACK\""
fi
# Update Adlist
update_list=0
if [ "$adblock" -eq 1 ]; then
if [ -f "/etc/mosdns/rule/.ad_source" ]; then
for url in $ad_source; do
if [ "$url" = "geosite.dat" ] ||[ $(echo "$url" | grep -c -E "^file://") -eq 1 ]; then
continue
fi
if [ $(grep -c "$url" "/etc/mosdns/rule/.ad_source") -eq 0 ]; then
update_list=1
break
fi
done
else
update_list=1
fi
fi
[ "$update_list" -eq 1 ] && $MOSDNS_SCRIPT update_adlist &
}
stop_service() {
config_load "mosdns"
config_foreach get_config "mosdns"
[ "$enabled" -eq "0" ] && restore_dhcp_setting
! nft --check list table inet mosdns > "/dev/null" 2>&1 || \
nft delete table inet mosdns
reload_dnsmasq
delcron
}
@@ -0,0 +1,143 @@
log:
level: info
file: "/var/log/mosdns.log"
# API 入口设置
api:
http: "0.0.0.0:9091"
include: []
plugins:
# 国内域名
- tag: geosite_cn
type: domain_set
args:
files:
- "/var/mosdns/geosite_cn.txt"
# 国内 IP
- tag: geoip_cn
type: ip_set
args:
files:
- "/var/mosdns/geoip_cn.txt"
# 国外域名
- tag: geosite_no_cn
type: domain_set
args:
files:
- "/var/mosdns/geosite_geolocation-!cn.txt"
# 缓存
- tag: lazy_cache
type: cache
args:
size: 20000
lazy_cache_ttl: 86400
dump_file: "/etc/mosdns/cache.dump"
dump_interval: 600
# 转发至本地服务器
- tag: forward_local
type: forward
args:
upstreams:
- addr: "https://doh.pub/dns-query"
bootstrap: 180.76.76.76
- addr: 119.29.29.29
# 转发至远程服务器
- tag: forward_remote
type: forward
args:
upstreams:
- addr: tls://8.8.8.8
enable_pipeline: false
# 国内解析
- tag: local_sequence
type: sequence
args:
- exec: $forward_local
# 国外解析
- tag: remote_sequence
type: sequence
args:
- exec: prefer_ipv4
- exec: $forward_remote
# 有响应终止返回
- tag: has_resp_sequence
type: sequence
args:
- matches: has_resp
exec: accept
# fallback 用本地服务器 sequence
# 返回非国内 ip 则 drop_resp
- tag: query_is_local_ip
type: sequence
args:
- exec: $local_sequence
- matches: "!resp_ip $geoip_cn"
exec: drop_resp
# fallback 用远程服务器 sequence
- tag: query_is_remote
type: sequence
args:
- exec: $remote_sequence
# fallback 用远程服务器 sequence
- tag: fallback
type: fallback
args:
primary: query_is_local_ip
secondary: query_is_remote
threshold: 500
always_standby: true
# 查询国内域名
- tag: query_is_local_domain
type: sequence
args:
- matches: qname $geosite_cn
exec: $local_sequence
# 查询国外域名
- tag: query_is_no_local_domain
type: sequence
args:
- matches: qname $geosite_no_cn
exec: $remote_sequence
# 主要的运行逻辑插件
# sequence 插件中调用的插件 tag 必须在 sequence 前定义,
# 否则 sequence 找不到对应插件。
- tag: main_sequence
type: sequence
args:
- exec: $lazy_cache
- exec: jump has_resp_sequence
- exec: $query_is_local_domain
- exec: jump has_resp_sequence
- exec: $query_is_no_local_domain
- exec: jump has_resp_sequence
- exec: $fallback
# 启动 udp 服务器。
- tag: udp_server
type: udp_server
args:
entry: main_sequence
listen: ":5335"
# 启动 tcp 服务器。
- tag: tcp_server
type: tcp_server
args:
entry: main_sequence
listen: ":5335"
@@ -0,0 +1,2 @@
# MosDNS Rules
@@ -0,0 +1,22 @@
173.245.48.0/20
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
141.101.64.0/18
108.162.192.0/18
190.93.240.0/20
188.114.96.0/20
197.234.240.0/22
198.41.128.0/17
162.158.0.0/15
104.16.0.0/13
104.24.0.0/14
172.64.0.0/13
131.0.72.0/22
2400:cb00::/32
2606:4700::/32
2803:f800::/32
2405:b500::/32
2405:8100::/32
2a06:98c0::/29
2c0f:f248::/32
@@ -0,0 +1,2 @@
# MosDNS Rules
@@ -0,0 +1,2 @@
# MosDNS Rules
@@ -0,0 +1,2 @@
# MosDNS Rules
@@ -0,0 +1,87 @@
0.in-addr.arpa
10.in-addr.arpa
127.in-addr.arpa
16.172.in-addr.arpa
17.172.in-addr.arpa
18.172.in-addr.arpa
19.172.in-addr.arpa
20.172.in-addr.arpa
21.172.in-addr.arpa
22.172.in-addr.arpa
23.172.in-addr.arpa
24.172.in-addr.arpa
25.172.in-addr.arpa
26.172.in-addr.arpa
27.172.in-addr.arpa
28.172.in-addr.arpa
29.172.in-addr.arpa
30.172.in-addr.arpa
31.172.in-addr.arpa
64.100.in-addr.arpa
65.100.in-addr.arpa
66.100.in-addr.arpa
67.100.in-addr.arpa
68.100.in-addr.arpa
69.100.in-addr.arpa
70.100.in-addr.arpa
71.100.in-addr.arpa
72.100.in-addr.arpa
73.100.in-addr.arpa
74.100.in-addr.arpa
75.100.in-addr.arpa
76.100.in-addr.arpa
77.100.in-addr.arpa
78.100.in-addr.arpa
79.100.in-addr.arpa
80.100.in-addr.arpa
81.100.in-addr.arpa
82.100.in-addr.arpa
83.100.in-addr.arpa
84.100.in-addr.arpa
85.100.in-addr.arpa
86.100.in-addr.arpa
87.100.in-addr.arpa
88.100.in-addr.arpa
89.100.in-addr.arpa
90.100.in-addr.arpa
91.100.in-addr.arpa
92.100.in-addr.arpa
93.100.in-addr.arpa
94.100.in-addr.arpa
95.100.in-addr.arpa
96.100.in-addr.arpa
97.100.in-addr.arpa
98.100.in-addr.arpa
99.100.in-addr.arpa
100.100.in-addr.arpa
101.100.in-addr.arpa
102.100.in-addr.arpa
103.100.in-addr.arpa
104.100.in-addr.arpa
105.100.in-addr.arpa
106.100.in-addr.arpa
107.100.in-addr.arpa
108.100.in-addr.arpa
109.100.in-addr.arpa
110.100.in-addr.arpa
111.100.in-addr.arpa
112.100.in-addr.arpa
113.100.in-addr.arpa
114.100.in-addr.arpa
115.100.in-addr.arpa
116.100.in-addr.arpa
117.100.in-addr.arpa
118.100.in-addr.arpa
119.100.in-addr.arpa
120.100.in-addr.arpa
121.100.in-addr.arpa
122.100.in-addr.arpa
123.100.in-addr.arpa
124.100.in-addr.arpa
125.100.in-addr.arpa
126.100.in-addr.arpa
127.100.in-addr.arpa
2.0.192.in-addr.arpa
168.192.in-addr.arpa
255.255.255.255.in-addr.arpa
domain:ip6.arpa
@@ -0,0 +1,2 @@
# MosDNS Rules
@@ -0,0 +1,2 @@
# MosDNS Rules
@@ -0,0 +1,2 @@
# MosDNS Rules
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
[ -f "/etc/config/ucitrack" ] && {
uci -q batch <<-EOF >/dev/null
delete ucitrack.@mosdns[-1]
add ucitrack mosdns
set ucitrack.@mosdns[-1].init=mosdns
commit ucitrack
EOF
}
rm -rf /tmp/luci-*
exit 0
@@ -0,0 +1,45 @@
{
"admin/services/mosdns": {
"title": "MosDNS",
"order": 30,
"action": {
"type": "firstchild"
},
"depends": {
"acl": [ "luci-app-mosdns" ],
"uci": { "mosdns": true }
}
},
"admin/services/mosdns/basic": {
"title": "Basic Setting",
"order": 10,
"action": {
"type": "view",
"path": "mosdns/basic"
}
},
"admin/services/mosdns/rules": {
"title": "Rules",
"order": 15,
"action": {
"type": "view",
"path": "mosdns/rules"
}
},
"admin/services/mosdns/update": {
"title": "Geodata Update",
"order": 20,
"action": {
"type": "view",
"path": "mosdns/update"
}
},
"admin/services/mosdns/logs": {
"title": "Logs",
"order": 25,
"action": {
"type": "view",
"path": "mosdns/logs"
}
}
}
Binary file not shown.
+349
View File
@@ -0,0 +1,349 @@
#!/usr/bin/env ucode
'use strict';
import { popen, mkdir, unlink, writefile, open, stat, stdout } from 'fs';
import { cursor } from 'uci';
import { connect } from 'ubus';
function to_array(val) {
let res =[];
if (type(val) == 'array') {
for (let i = 0; i < length(val); i++) {
if (type(val[i]) == 'string') {
let s = replace(val[i], /^\s+|\s+$/g, '');
if (s != "") push(res, s);
}
}
} else if (type(val) == 'string') {
let parts = split(val, /[ \t\n]+/);
for (let i = 0; i < length(parts); i++) {
if (parts[i] != "") push(res, parts[i]);
}
}
return res;
}
function exec_sys(cmd) {
let p = popen(cmd + " 2>&1", "r");
if (!p) return { code: -1, stdout: "" };
let stdout = p.read("all");
let code = p.close();
if (type(stdout) == 'string') {
stdout = replace(stdout, /^\s+|\s+$/g, '');
}
return { code: code, stdout: stdout || "" };
}
function interface_dns() {
let uci_cursor = cursor();
uci_cursor.load('mosdns');
let dns_list =[];
if (uci_cursor.get('mosdns', 'config', 'custom_local_dns') === '1') {
dns_list = to_array(uci_cursor.get('mosdns', 'config', 'local_dns'));
} else {
uci_cursor.load('network');
let peerdns = uci_cursor.get('network', 'wan', 'peerdns');
let proto = uci_cursor.get('network', 'wan', 'proto');
if (peerdns === '0' || proto === 'static') {
dns_list = to_array(uci_cursor.get('network', 'wan', 'dns'));
} else {
let ubus_conn = connect();
if (ubus_conn) {
let status = ubus_conn.call('network.interface.wan', 'status');
if (status && type(status['dns-server']) == 'array' && length(status['dns-server']) > 0) {
dns_list = status['dns-server'];
}
}
}
}
if (length(dns_list) === 0) {
dns_list =['119.29.29.29', '223.5.5.5'];
}
print(join(" ", dns_list) + "\n");
}
function get_adlist() {
let uci_cursor = cursor();
uci_cursor.load('mosdns');
let adblock = uci_cursor.get('mosdns', 'config', 'adblock');
if (adblock !== '1') {
mkdir('/etc/mosdns/rule', 0755);
exec_sys('rm -rf /etc/mosdns/rule/adlist /etc/mosdns/rule/.ad_source');
writefile('/var/mosdns/disable-ads.txt', '');
print("/var/mosdns/disable-ads.txt\n");
return;
}
mkdir('/etc/mosdns/rule/adlist', 0755);
let ad_source = to_array(uci_cursor.get('mosdns', 'config', 'ad_source'));
let adlist =[];
for (let i = 0; i < length(ad_source); i++) {
let url = ad_source[i];
if (!url) continue;
if (url === 'geosite.dat') {
push(adlist, '/var/mosdns/geosite_category-ads-all.txt');
} else if (index(url, 'file://') === 0) {
push(adlist, substr(url, 7));
} else {
let parts = split(url, '/');
let filename = parts[length(parts) - 1];
let local_path = `/etc/mosdns/rule/adlist/${filename}`;
if (!stat(local_path)) {
writefile(local_path, '');
}
push(adlist, local_path);
}
}
print(join("\n", adlist) + "\n");
}
function update_adlist() {
let uci_cursor = cursor();
uci_cursor.load('mosdns');
if (uci_cursor.get('mosdns', 'config', 'adblock') !== '1') {
return false;
}
let lock_file = '/var/lock/mosdns_ad_update.lock';
let ad_source = to_array(uci_cursor.get('mosdns', 'config', 'ad_source'));
let github_proxy = uci_cursor.get('mosdns', 'config', 'github_proxy') || '';
mkdir('/etc/mosdns/rule', 0755);
writefile('/etc/mosdns/rule/.ad_source', '');
if (stat(lock_file)) return false;
writefile(lock_file, '');
let tmp_res = exec_sys('mktemp -d');
if (tmp_res.code !== 0) {
unlink(lock_file);
die("Failed to create temp directory for adlist.");
}
let ad_tmpdir = tmp_res.stdout;
let has_update = false;
let download_failed = false;
for (let i = 0; i < length(ad_source); i++) {
let url = ad_source[i];
if (!url) continue;
if (url !== 'geosite.dat' && index(url, 'file://') !== 0) {
has_update = true;
exec_sys(`echo "${url}" >> /etc/mosdns/rule/.ad_source`);
let parts = split(url, '/');
let filename = parts[length(parts) - 1];
let mirror = "";
if (match(url, /^https:\/\/raw\.githubusercontent\.com/)) {
mirror = github_proxy ? github_proxy + '/' : '';
}
print(`Downloading ${mirror}${url}\n`);
stdout.flush();
let curl_res = exec_sys(`curl --connect-timeout 5 -m 90 --ipv4 -kfSLo "${ad_tmpdir}/${filename}" "${mirror}${url}"`);
if (curl_res.code !== 0) download_failed = true;
}
}
if (download_failed) {
print("\x1b[1;31mRules download failed.\n");
exec_sys(`rm -rf "${ad_tmpdir}"`);
unlink(lock_file);
exit(1);
} else {
if (has_update) {
mkdir('/etc/mosdns/rule/adlist', 0755);
exec_sys('rm -rf /etc/mosdns/rule/adlist/*');
exec_sys(`cp "${ad_tmpdir}"/* /etc/mosdns/rule/adlist/`);
}
}
exec_sys(`rm -rf "${ad_tmpdir}"`);
unlink(lock_file);
return has_update;
}
function update_geodat() {
let uci_cursor = cursor();
uci_cursor.load('mosdns');
let github_proxy = uci_cursor.get('mosdns', 'config', 'github_proxy') || '';
let mirror = github_proxy ? github_proxy + '/' : '';
let geoip_type = uci_cursor.get('mosdns', 'config', 'geoip_type') || 'geoip-only-cn-private';
let v2dat_dir = '/usr/share/v2ray';
let tmp_res = exec_sys('mktemp -d');
if (tmp_res.code !== 0) exit(1);
let tmpdir = tmp_res.stdout;
exec_sys(`mkdir -p "${v2dat_dir}"`);
let geoip_updated = false;
let geoip_url = mirror + "https://github.com/Loyalsoldier/geoip/releases/latest/download/" + geoip_type + ".dat";
print(`Downloading ${geoip_url}.sha256sum\n`);
stdout.flush();
if (exec_sys(`curl --connect-timeout 5 -m 20 --ipv4 -kfSLo "${tmpdir}/geoip.dat.sha256sum" "${geoip_url}.sha256sum"`).code !== 0) {
exec_sys(`rm -rf "${tmpdir}"`); exit(1);
}
let geoip_sum_remote = split(exec_sys(`cat "${tmpdir}/geoip.dat.sha256sum"`).stdout, /[ \t\n]+/)[0];
let geoip_sum_local = "";
if (stat(`${v2dat_dir}/geoip.dat`)) {
geoip_sum_local = split(exec_sys(`sha256sum "${v2dat_dir}/geoip.dat"`).stdout, /[ \t\n]+/)[0];
}
if (geoip_sum_local === geoip_sum_remote) {
print("geoip.dat is up to date.\n");
stdout.flush();
} else {
print(`Downloading ${geoip_url}\n`);
stdout.flush();
if (exec_sys(`curl --connect-timeout 5 -m 120 --ipv4 -kfSLo "${tmpdir}/geoip.dat" "${geoip_url}"`).code !== 0) {
exec_sys(`rm -rf "${tmpdir}"`); exit(1);
}
let sum_downloaded = split(exec_sys(`sha256sum "${tmpdir}/geoip.dat"`).stdout, /[ \t\n]+/)[0];
if (sum_downloaded !== geoip_sum_remote) {
print("\x1b[1;31mgeoip.dat checksum error\n");
exec_sys(`rm -rf "${tmpdir}"`); exit(1);
}
geoip_updated = true;
}
let geosite_updated = false;
let geosite_url = mirror + "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat";
print(`Downloading ${geosite_url}.sha256sum\n`);
stdout.flush();
if (exec_sys(`curl --connect-timeout 5 -m 20 --ipv4 -kfSLo "${tmpdir}/geosite.dat.sha256sum" "${geosite_url}.sha256sum"`).code !== 0) {
exec_sys(`rm -rf "${tmpdir}"`); exit(1);
}
let geosite_sum_remote = split(exec_sys(`cat "${tmpdir}/geosite.dat.sha256sum"`).stdout, /[ \t\n]+/)[0];
let geosite_sum_local = "";
if (stat(`${v2dat_dir}/geosite.dat`)) {
geosite_sum_local = split(exec_sys(`sha256sum "${v2dat_dir}/geosite.dat"`).stdout, /[ \t\n]+/)[0];
}
if (geosite_sum_local === geosite_sum_remote) {
print("geosite.dat is up to date.\n");
stdout.flush();
} else {
print(`Downloading ${geosite_url}\n`);
stdout.flush();
if (exec_sys(`curl --connect-timeout 5 -m 120 --ipv4 -kfSLo "${tmpdir}/geosite.dat" "${geosite_url}"`).code !== 0) {
exec_sys(`rm -rf "${tmpdir}"`); exit(1);
}
let sum_downloaded = split(exec_sys(`sha256sum "${tmpdir}/geosite.dat"`).stdout, /[ \t\n]+/)[0];
if (sum_downloaded !== geosite_sum_remote) {
print("\x1b[1;31mgeosite.dat checksum error\n");
exec_sys(`rm -rf "${tmpdir}"`); exit(1);
}
geosite_updated = true;
}
if (geoip_updated) {
exec_sys(`cp -a "${tmpdir}/geoip.dat" "${v2dat_dir}/"`);
}
if (geosite_updated) {
exec_sys(`cp -a "${tmpdir}/geosite.dat" "${v2dat_dir}/"`);
}
exec_sys(`rm -rf "${tmpdir}"`);
}
function v2dat_dump() {
let uci_cursor = cursor();
uci_cursor.load('mosdns');
let v2dat_dir = '/usr/share/v2ray';
let configfile = uci_cursor.get('mosdns', 'config', 'configfile') || '/var/etc/mosdns.json';
let adblock = uci_cursor.get('mosdns', 'config', 'adblock');
let ad_source = uci_cursor.get('mosdns', 'config', 'ad_source') || "";
let streaming_media = uci_cursor.get('mosdns', 'config', 'custom_stream_media_dns');
mkdir('/var/mosdns', 0755);
exec_sys('rm -f /var/mosdns/geo*.txt');
if (configfile === "/var/etc/mosdns.json") {
exec_sys(`v2dat unpack geoip -o /var/mosdns -f cn ${v2dat_dir}/geoip.dat`);
exec_sys(`v2dat unpack geosite -o /var/mosdns -f cn -f apple -f 'geolocation-!cn' ${v2dat_dir}/geosite.dat`);
if (adblock === '1' && index(ad_source, 'geosite.dat') !== -1) {
exec_sys(`v2dat unpack geosite -o /var/mosdns -f category-ads-all ${v2dat_dir}/geosite.dat`);
}
if (streaming_media === '1') {
exec_sys(`v2dat unpack geosite -o /var/mosdns -f netflix -f disney -f hulu ${v2dat_dir}/geosite.dat`);
} else {
writefile('/var/mosdns/geosite_disney.txt', '');
writefile('/var/mosdns/geosite_netflix.txt', '');
writefile('/var/mosdns/geosite_hulu.txt', '');
}
} else {
exec_sys(`v2dat unpack geoip -o /var/mosdns -f cn ${v2dat_dir}/geoip.dat`);
exec_sys(`v2dat unpack geosite -o /var/mosdns -f cn -f 'geolocation-!cn' ${v2dat_dir}/geosite.dat`);
let geoip_tags = to_array(uci_cursor.get('mosdns', 'config', 'geoip_tags'));
if (length(geoip_tags) > 0) {
let tags_str = "-f '" + join("' -f '", geoip_tags) + "'";
exec_sys(`v2dat unpack geoip -o /var/mosdns ${tags_str} ${v2dat_dir}/geoip.dat`);
}
let geosite_tags = to_array(uci_cursor.get('mosdns', 'config', 'geosite_tags'));
if (length(geosite_tags) > 0) {
let tags_str = "-f '" + join("' -f '", geosite_tags) + "'";
exec_sys(`v2dat unpack geosite -o /var/mosdns ${tags_str} ${v2dat_dir}/geosite.dat`);
}
}
}
let action = ARGV[0];
switch (action) {
case "interface_dns":
interface_dns();
break;
case "get_adlist":
get_adlist();
break;
case "update":
if (stat('/var/lock/mosdns_update.lock')) {
print("Another update is already in progress.\n");
exit(1);
}
writefile('/var/lock/mosdns_update.lock', '');
try {
update_geodat();
update_adlist();
v2dat_dump();
print("UPDATE_FINISHED\n");
stdout.flush();
} catch (e) {
print("Update failed: " + e + "\n");
print("UPDATE_FINISHED\n");
stdout.flush();
}
unlink('/var/lock/mosdns_update.lock');
break;
case "update_adlist":
update_adlist();
break;
case "v2dat_dump":
v2dat_dump();
break;
default:
exit(0);
}
@@ -0,0 +1,43 @@
{
"luci-app-mosdns": {
"description": "Grant UCI access for luci-app-mosdns",
"read": {
"file": {
"/etc/init.d/mosdns": [ "exec" ],
"/etc/mosdns/config_custom.yaml": [ "read" ],
"/etc/mosdns/rule/*": [ "read" ],
"/usr/bin/mosdns": [ "exec" ],
"/usr/share/mosdns/mosdns.uc": [ "exec" ],
"/var/log/*": [ "read" ],
"/var/mosdns/*": [ "read" ]
},
"ubus": {
"file": [ "read" ],
"service": [ "list" ],
"luci.mosdns": [
"clean_log",
"flush_cache",
"get_version",
"print_log",
"get_update_log",
"start_update"
]
},
"uci": [ "mosdns" ]
},
"write": {
"file": {
"/etc/mosdns/config_custom.yaml": [ "write" ],
"/etc/mosdns/rule/*": [ "write" ],
"/usr/share/mosdns/*": [ "write" ],
"/usr/share/v2ray/*": [ "write" ],
"/var/log/*": [ "write" ],
"/var/mosdns/*": [ "write" ]
},
"ubus": {
"file": [ "write" ]
},
"uci": [ "mosdns" ]
}
}
}
@@ -0,0 +1,154 @@
#!/usr/bin/env ucode
'use strict';
import { popen, writefile, stat, readfile } from 'fs';
import { cursor } from 'uci';
function to_array(val) {
let res =[];
if (type(val) == 'array') {
for (let i = 0; i < length(val); i++) {
if (type(val[i]) == 'string') {
let s = replace(val[i], /^\s+|\s+$/g, '');
if (s != "") push(res, s);
}
}
} else if (type(val) == 'string') {
let parts = split(val, /[ \t\n]+/);
for (let i = 0; i < length(parts); i++) {
if (parts[i] != "") push(res, parts[i]);
}
}
return res;
}
function exec_sys(cmd) {
let p = popen(cmd + " 2>&1", "r");
if (!p) return { code: -1, stdout: "" };
let stdout = p.read("all");
let code = p.close();
if (type(stdout) == 'string') {
stdout = replace(stdout, /^\s+|\s+$/g, '');
}
return { code: code, stdout: stdout || "" };
}
function get_logfile_path_internal() {
let uci_cursor = cursor();
uci_cursor.load('mosdns');
let configfile = uci_cursor.get('mosdns', 'config', 'configfile');
if (configfile === '/var/etc/mosdns.json' || !configfile) {
return uci_cursor.get('mosdns', 'config', 'log_file');
} else {
let content = readfile(configfile);
if (content) {
let m = match(content, /file:\s*([^\r\n]+)/);
if (m && m[1]) {
let log_path = m[1];
log_path = replace(log_path, /^\s+|\s+$/g, '');
log_path = replace(log_path, /^["']|["']$/g, '');
if (log_path != "") {
return log_path;
}
}
}
return '/var/log/mosdns.log';
}
}
const methods = {
flush_cache: {
call: function() {
try {
let uci_cursor = cursor();
uci_cursor.load('mosdns');
let port = uci_cursor.get('mosdns', 'config', 'listen_port_api');
if (!port) return { error: "API listen port not configured." };
let res = exec_sys(`curl -s 127.0.0.1:${port}/plugins/lazy_cache/flush`);
if (res.code === 0) {
return { success: true };
} else {
return { success: false, error: res.stdout };
}
} catch (e) {
return { error: String(e) };
}
}
},
print_log: {
call: function() {
try {
let path = get_logfile_path_internal();
if (path && stat(path)) {
return { log: readfile(path) };
} else {
return { error: 'Log file not accessible or does not exist.' };
}
} catch (e) {
return { error: String(e) };
}
}
},
clean_log: {
call: function() {
try {
let path = get_logfile_path_internal();
if (path) {
writefile(path, '');
return { success: true };
} else {
return { error: 'Log file path could not be determined.' };
}
} catch (e) {
return { error: String(e) };
}
}
},
get_version: {
call: function() {
let res = exec_sys('mosdns version');
if (res.code === 0) {
return { version: res.stdout };
} else {
return { error: res.stdout };
}
}
},
start_update: {
call: function() {
try {
if (stat('/var/lock/mosdns_update.lock')) {
return { success: false, error: 'Another update is already in progress.' };
}
exec_sys('echo "" > /var/log/mosdns_update.log');
exec_sys('{ /usr/share/mosdns/mosdns.uc update; rm -f /var/lock/mosdns_update.lock; echo "UPDATE_FINISHED"; } > /var/log/mosdns_update.log 2>&1 &');
return { success: true };
} catch (e) {
return { success: false, error: String(e) };
}
}
},
get_update_log: {
call: function() {
try {
if (stat('/var/log/mosdns_update.log')) {
return { log: readfile('/var/log/mosdns_update.log') };
} else {
return { log: '' };
}
} catch (e) {
return { error: String(e) };
}
}
}
};
return { "luci.mosdns": methods };
@@ -0,0 +1,4 @@
{
"config": "mosdns",
"init": "mosdns"
}