diff --git a/.github/build-ipk.sh b/.github/build-ipk.sh index a4f4798a..61ef4d75 100755 --- a/.github/build-ipk.sh +++ b/.github/build-ipk.sh @@ -43,7 +43,7 @@ EOF cat > "$TEMP_PKG_DIR/CONTROL/control" <<-EOF Package: $PKG_NAME Version: $PKG_VERSION - Depends: libc, sing-box, chinadns-ng, firewall4, kmod-nft-tproxy + Depends: libc, sing-box, firewall4, kmod-nft-tproxy Source: https://github.com/immortalwrt/homeproxy SourceName: $PKG_NAME Section: luci diff --git a/Makefile b/Makefile index 536f3d2a..ad13e02a 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,6 @@ LUCI_TITLE:=The modern ImmortalWrt proxy platform for ARM64/AMD64 LUCI_PKGARCH:=all LUCI_DEPENDS:= \ +sing-box \ - +chinadns-ng \ +firewall4 \ +kmod-nft-tproxy diff --git a/htdocs/luci-static/resources/view/homeproxy/client.js b/htdocs/luci-static/resources/view/homeproxy/client.js index 356e832d..96870898 100644 --- a/htdocs/luci-static/resources/view/homeproxy/client.js +++ b/htdocs/luci-static/resources/view/homeproxy/client.js @@ -181,42 +181,26 @@ return view.extend({ return true; } - if (features.hp_has_chinadns_ng) { - o = s.taboption('routing', form.DynamicList, 'china_dns_server', _('China DNS server')); - o.value('wan', _('WAN DNS (read from interface)')); - o.value('223.5.5.5', _('Aliyun Public DNS (223.5.5.5)')); - o.value('210.2.4.8', _('CNNIC Public DNS (210.2.4.8)')); - o.value('119.29.29.29', _('Tencent Public DNS (119.29.29.29)')); - o.value('117.50.10.10', _('ThreatBook Public DNS (117.50.10.10)')); - o.depends('routing_mode', 'bypass_mainland_china'); - o.validate = function(section_id) { - if (section_id) { - var value = this.map.lookupOption('china_dns_server', section_id)[0].formvalue(section_id); - if (value.length < 1) - return true; - - if (!features.hp_has_chinadns_ng_v2 && value.length > 2) - return _('You can only have two servers set at maximum.'); - - for (var dns of value) { - var ipv6_support = this.map.lookupOption('ipv6_support', section_id)[0].formvalue(section_id); - if (dns === 'wan') { - continue; - } else { - var err = _('Expecting: %s').format(_('valid address#port')); - dns = dns.split('#'); - if (dns.length > 2) - return err; - if (!stubValidator.apply((ipv6_support === '1') ? 'ipaddr' : 'ip4addr', dns[0])) - return err; - if (dns[1] && !stubValidator.apply('port', dns[1])) - return err; - } - } - } + o = s.taboption('routing', form.Value, 'china_dns_server', _('China DNS server')); + o.value('wan', _('WAN DNS (read from interface)')); + o.value('223.5.5.5', _('Aliyun Public DNS (223.5.5.5)')); + o.value('210.2.4.8', _('CNNIC Public DNS (210.2.4.8)')); + o.value('119.29.29.29', _('Tencent Public DNS (119.29.29.29)')); + o.value('117.50.10.10', _('ThreatBook Public DNS (117.50.10.10)')); + o.depends('routing_mode', 'bypass_mainland_china'); + o.default = '223.5.5.5'; + o.rmempty = false; + o.validate = function(section_id, value) { + if (section_id && !['wan'].includes(value)) { + var ipv6_support = this.map.lookupOption('ipv6_support', section_id)[0].formvalue(section_id); - return true; + if (!value) + return _('Expecting: %s').format(_('non-empty value')); + else if (!stubValidator.apply((ipv6_support === '1') ? 'ipaddr' : 'ip4addr', value)) + return _('Expecting: %s').format(_('valid IP address')); } + + return true; } o = s.taboption('routing', form.ListValue, 'routing_mode', _('Routing mode')); @@ -1070,7 +1054,7 @@ return view.extend({ /* Custom routing settings end */ /* Rule set settings start */ - s.tab('ruleset', _('Rule set')); + s.tab('ruleset', _('Rule Set')); o = s.taboption('ruleset', form.SectionValue, '_ruleset', form.GridSection, 'ruleset'); o.depends('routing_mode', 'custom'); diff --git a/root/etc/config/homeproxy b/root/etc/config/homeproxy index 19549eaf..03323534 100644 --- a/root/etc/config/homeproxy +++ b/root/etc/config/homeproxy @@ -6,7 +6,6 @@ config homeproxy 'infra' option redirect_port '5331' option tproxy_port '5332' option dns_port '5333' - option china_dns_port '5334' option udp_timeout '' option tun_name 'singtun0' option tun_addr4 '172.19.0.1/30' diff --git a/root/etc/homeproxy/scripts/generate_client.uc b/root/etc/homeproxy/scripts/generate_client.uc index 3716a0d8..aa3f17ee 100755 --- a/root/etc/homeproxy/scripts/generate_client.uc +++ b/root/etc/homeproxy/scripts/generate_client.uc @@ -53,8 +53,8 @@ if (!wan_dns) const dns_port = uci.get(uciconfig, uciinfra, 'dns_port') || '5333'; let main_node, main_udp_node, dedicated_udp_node, default_outbound, domain_strategy, sniff_override = '1', - dns_server, dns_default_strategy, dns_default_server, dns_disable_cache, dns_disable_cache_expire, - dns_independent_cache, dns_client_subnet, direct_domain_list, proxy_domain_list; + dns_server, china_dns_server, dns_default_strategy, dns_default_server, dns_disable_cache, + dns_disable_cache_expire, dns_independent_cache, dns_client_subnet, direct_domain_list, proxy_domain_list; if (routing_mode !== 'custom') { main_node = uci.get(uciconfig, ucimain, 'main_node') || 'nil'; @@ -65,6 +65,12 @@ if (routing_mode !== 'custom') { if (isEmpty(dns_server) || dns_server === 'wan') dns_server = wan_dns; + if (routing_mode === 'bypass_mainland_china') { + china_dns_server = uci.get(uciconfig, ucimain, 'china_dns_server'); + if (isEmpty(china_dns_server) || type(china_dns_server) !== 'string' || china_dns_server === 'wan') + china_dns_server = wan_dns; + } + direct_domain_list = trim(readfile(HP_DIR + '/resources/direct_list.txt')); if (direct_domain_list) direct_domain_list = split(direct_domain_list, /[\r\n]/); @@ -367,22 +373,25 @@ config.dns = { }; if (!isEmpty(main_node)) { - /* Avoid DNS loop */ - const main_node_addr = uci.get(uciconfig, main_node, 'address'); - if (validateHostname(main_node_addr)) - push(config.dns.rules, { - domain: main_node_addr, - server: 'default-dns' + /* Main DNS */ + let default_final_dns = 'default-dns'; + if (dns_server !== wan_dns) { + push(config.dns.servers, { + tag: 'main-dns', + address: 'tcp://' + (validation('ip6addr', dns_server) ? `[${dns_server}]` : dns_server), + strategy: (ipv6_support !== '1') ? 'ipv4_only' : null, + detour: 'main-out' }); - if (dedicated_udp_node) { - const main_udp_node_addr = uci.get(uciconfig, main_udp_node, 'address'); - if (validateHostname(main_udp_node_addr)) - push(config.dns.rules, { - domain: main_udp_node_addr, - server: 'default-dns' - }); + default_final_dns = 'main-dns'; } + config.dns.final = default_final_dns; + + /* Avoid DNS loop */ + push(config.dns.rules, { + outbound: 'any', + server: 'default-dns' + }); if (direct_domain_list) push(config.dns.rules, { @@ -398,23 +407,38 @@ if (!isEmpty(main_node)) { server: 'block-dns' }); - if (isEmpty(config.dns.rules)) - config.dns.rules = null; - - let default_final_dns = 'default-dns'; - /* Main DNS */ - if (dns_server !== wan_dns) { + if (routing_mode === 'bypass_mainland_china') { push(config.dns.servers, { - tag: 'main-dns', - address: 'tcp://' + (validation('ip6addr', dns_server) ? `[${dns_server}]` : dns_server), - strategy: (ipv6_support !== '1') ? 'ipv4_only' : null, - detour: 'main-out' + tag: 'china-dns', + address: china_dns_server, + detour: 'direct-out' }); - default_final_dns = 'main-dns'; - } + if (proxy_domain_list) + push(config.dns.rules, { + domain_keyword: proxy_domain_list, + server: default_final_dns + }); - config.dns.final = default_final_dns; + push(config.dns.rules, { + rule_set: 'geosite-cn', + server: 'china-dns' + }); + push(config.dns.rules, { + type: 'logical', + mode: 'and', + rules: [ + { + rule_set: 'geosite-noncn', + invert: true + }, + { + rule_set: 'geoip-cn' + } + ], + server: 'china-dns' + }); + } } else if (!isEmpty(default_outbound)) { /* DNS servers */ uci.foreach(uciconfig, ucidnsserver, (cfg) => { @@ -460,7 +484,6 @@ if (!isEmpty(main_node)) { process_path_regex: cfg.process_path_regex, user: cfg.user, rule_set: get_ruleset(cfg.rule_set), - /* rule_set_ipcidr_match_source is deprecated in sing-box 1.10.0 */ rule_set_ip_cidr_match_source: (cfg.rule_set_ip_cidr_match_source === '1') || null, invert: (cfg.invert === '1') || null, outbound: get_outbound(cfg.outbound), @@ -617,6 +640,7 @@ config.route = { outbound: 'dns-out' } ], + rule_set: [], auto_detect_interface: isEmpty(default_interface) ? true : null, default_interface: default_interface }; @@ -638,6 +662,31 @@ if (!isEmpty(main_node)) { }); config.route.final = 'main-out'; + + /* Rule set */ + if (routing_mode === 'bypass_mainland_china') { + push(config.route.rule_set, { + type: 'remote', + tag: 'geoip-cn', + format: 'binary', + url: 'https://github.com/1715173329/IPCIDR-CHINA/raw/rule-set/cn.srs', + download_detour: 'main-out' + }); + push(config.route.rule_set, { + type: 'remote', + tag: 'geosite-cn', + format: 'binary', + url: 'https://github.com/1715173329/sing-geosite/raw/rule-set-unstable/geosite-geolocation-cn.srs', + download_detour: 'main-out' + }); + push(config.route.rule_set, { + type: 'remote', + tag: 'geosite-noncn', + format: 'binary', + url: 'https://github.com/1715173329/sing-geosite/raw/rule-set-unstable/geosite-geolocation-!cn.srs', + download_detour: 'main-out' + }); + } } else if (!isEmpty(default_outbound)) { uci.foreach(uciconfig, uciroutingrule, (cfg) => { if (cfg.enabled !== '1') @@ -673,11 +722,8 @@ if (!isEmpty(main_node)) { }); config.route.final = get_outbound(default_outbound); -}; -/* Rule set */ -if (routing_mode === 'custom') { - config.route.rule_set = []; + /* Rule set */ uci.foreach(uciconfig, uciruleset, (cfg) => { if (cfg.enabled !== '1') return null; @@ -696,7 +742,7 @@ if (routing_mode === 'custom') { /* Routing rules end */ /* Experimental start */ -if (routing_mode === 'custom') { +if (routing_mode in ['bypass_mainland_china', 'custom']) { config.experimental = { cache_file: { enabled: true, diff --git a/root/etc/init.d/homeproxy b/root/etc/init.d/homeproxy index d25a12e2..d71b30ba 100755 --- a/root/etc/init.d/homeproxy +++ b/root/etc/init.d/homeproxy @@ -72,45 +72,28 @@ start_service() { fi # DNSMasq rules - local ipv6_support + local ipv6_support dns_port config_get_bool ipv6_support "config" "ipv6_support" "0" - local dns_port china_dns_server china_dns_port config_get dns_port "infra" "dns_port" "5333" mkdir -p "$DNSMASQ_DIR" echo -e "conf-dir=$DNSMASQ_DIR" > "$DNSMASQ_DIR/../dnsmasq-homeproxy.conf" case "$routing_mode" in + "bypass_mainland_china"|"custom"|"global") + cat <<-EOF >> "$DNSMASQ_DIR/redirect-dns.conf" + no-poll + no-resolv + server=127.0.0.1#$dns_port + EOF + ;; "gfwlist") [ "$ipv6_support" -eq "0" ] || local gfw_nftset_v6=",6#inet#fw4#homeproxy_gfw_list_v6" sed -r -e "s/(.*)/server=\/\1\/127.0.0.1#$dns_port\nnftset=\/\1\\/4#inet#fw4#homeproxy_gfw_list_v4$gfw_nftset_v6/g" \ "$HP_DIR/resources/gfw_list.txt" > "$DNSMASQ_DIR/gfw_list.conf" ;; - "bypass_mainland_china") - config_get china_dns_server "config" "china_dns_server" - config_get china_dns_port "infra" "china_dns_port" "5334" - - if [ -e "/usr/bin/chinadns-ng" ] && [ -n "$china_dns_server" ]; then - cat <<-EOF >> "$DNSMASQ_DIR/redirect-dns.conf" - no-poll - no-resolv - server=127.0.0.1#$china_dns_port - EOF - else - china_dns_server="" - sed -r -e "s/(.*)/server=\/\1\/127.0.0.1#$dns_port/g" \ - "$HP_DIR/resources/gfw_list.txt" > "$DNSMASQ_DIR/gfw_list.conf" - fi - ;; "proxy_mainland_china") sed -r -e "s/(.*)/server=\/\1\/127.0.0.1#$dns_port/g" \ "$HP_DIR/resources/china_list.txt" > "$DNSMASQ_DIR/china_list.conf" ;; - "custom"|"global") - cat <<-EOF >> "$DNSMASQ_DIR/redirect-dns.conf" - no-poll - no-resolv - server=127.0.0.1#$dns_port - EOF - ;; esac if [ "$routing_mode" != "custom" ] && [ -s "$HP_DIR/resources/proxy_list.txt" ]; then @@ -183,53 +166,6 @@ start_service() { procd_set_param respawn procd_close_instance - - # chinadns-ng - if [ -n "$china_dns_server" ]; then - local wandns="$(ifstatus wan | jsonfilter -e '@["dns-server"][0]' || echo "119.29.29.29")" - china_dns_server="${china_dns_server/wan/$wandns}" - china_dns_server="${china_dns_server// /,}" - - for i in $(seq 1 "$(grep -c "processor" "/proc/cpuinfo")"); do - procd_open_instance "chinadns-ng-$i" - - procd_set_param command "/usr/bin/chinadns-ng" - procd_append_param command --bind-port "$china_dns_port" - procd_append_param command --china-dns "$china_dns_server" - procd_append_param command --trust-dns "127.0.0.1#$dns_port" - procd_append_param command --ipset-name4 "inet@fw4@homeproxy_mainland_addr_v4" - procd_append_param command --ipset-name6 "inet@fw4@homeproxy_mainland_addr_v6" - procd_append_param command --chnlist-file "$HP_DIR/resources/china_list.txt" - procd_append_param command --gfwlist-file "$HP_DIR/resources/gfw_list.txt" - procd_append_param command --reuse-port - - if chinadns-ng --version | grep -q "target:"; then - procd_append_param command --cache 10000 - procd_append_param command --cache-stale 3600 - procd_append_param command --verdict-cache 10000 - [ "$ipv6_support" -eq "1" ] || procd_append_param command --no-ipv6=ip:non_china - else - [ "$ipv6_support" -eq "1" ] || procd_append_param command --no-ipv6=tC - fi - - if [ -x "/sbin/ujail" ]; then - procd_add_jail "chinadns-ng" log - procd_add_jail_mount "$HP_DIR/resources/china_list.txt" - procd_add_jail_mount "$HP_DIR/resources/gfw_list.txt" - procd_set_param capabilities "/etc/capabilities/homeproxy.json" - procd_set_param no_new_privs 1 - procd_set_param user sing-box - procd_set_param group sing-box - fi - - procd_set_param limits core="unlimited" - procd_set_param limits nofile="1000000 1000000" - procd_set_param stderr 1 - procd_set_param respawn - - procd_close_instance - done - fi fi if [ "$server_enabled" = "1" ]; then diff --git a/root/etc/uci-defaults/luci-homeproxy-migration b/root/etc/uci-defaults/luci-homeproxy-migration index 7b2d3f74..bf1ab835 100644 --- a/root/etc/uci-defaults/luci-homeproxy-migration +++ b/root/etc/uci-defaults/luci-homeproxy-migration @@ -3,13 +3,13 @@ china_dns_server="$(uci -q get "homeproxy.config.china_dns_server")" if [ "$china_dns_server" = "wan_114" ]; then uci -q delete "homeproxy.config.china_dns_server" - uci -q add_list "homeproxy.config.china_dns_server"="wan" - uci -q add_list "homeproxy.config.china_dns_server"="114.114.114.114" + uci -q set "homeproxy.config.china_dns_server"="114.114.114.114" elif echo "$china_dns_server" | grep -q ","; then uci -q delete "homeproxy.config.china_dns_server" - for dns in ${china_dns_server//,/ }; do - uci -q add_list "homeproxy.config.china_dns_server"="$dns" - done + uci -q set "homeproxy.config.china_dns_server"="${china_dns_server%%,*}" +elif echo "$china_dns_server" | grep -q " "; then + uci -q delete "homeproxy.config.china_dns_server" + uci -q set "homeproxy.config.china_dns_server"="${china_dns_server%% *}" fi if [ "$(uci -q get homeproxy.config.routing_port)" = "all" ]; then @@ -19,5 +19,6 @@ fi [ -z "$(uci -q changes "homeproxy")" ] || uci -q commit "homeproxy" sed -i "s/rule_set_ipcidr_match_source/rule_set_ip_cidr_match_source/g" "/etc/config/homeproxy" +sed -i "/china_dns_port/d" "/etc/config/homeproxy" exit 0 diff --git a/root/usr/share/rpcd/ucode/luci.homeproxy b/root/usr/share/rpcd/ucode/luci.homeproxy index 28b94a6d..10a96896 100644 --- a/root/usr/share/rpcd/ucode/luci.homeproxy +++ b/root/usr/share/rpcd/ucode/luci.homeproxy @@ -173,9 +173,6 @@ const methods = { fd.close(); } - features.hp_has_chinadns_ng = access('/usr/bin/chinadns-ng'); - if (features.hp_has_chinadns_ng) - features.hp_has_chinadns_ng_v2 = (system('/usr/bin/chinadns-ng --version | grep -q "target:"') === 0); features.hp_has_ip_full = access('/usr/libexec/ip-full'); features.hp_has_tcp_brutal = hasKernelModule('brutal.ko'); features.hp_has_tproxy = hasKernelModule('nft_tproxy.ko') || access('/etc/modules.d/nft-tproxy');