diff --git a/mihomo/Makefile b/mihomo/Makefile index bbb503e59..79f513fe7 100644 --- a/mihomo/Makefile +++ b/mihomo/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mihomo -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/MetaCubeX/mihomo.git diff --git a/mihomo/files/mihomo.conf b/mihomo/files/mihomo.conf index ef265ccc7..61e8c8564 100644 --- a/mihomo/files/mihomo.conf +++ b/mihomo/files/mihomo.conf @@ -24,9 +24,24 @@ config proxy 'proxy' option 'acl_ip' '' option 'acl_ip6' '' option 'acl_mac' '' + option 'acl_interface' '' + list 'bypass_user' 'aria2' + list 'bypass_user' 'dnsmasq' + list 'bypass_user' 'ftp' + list 'bypass_user' 'logd' + list 'bypass_user' 'nobody' + list 'bypass_user' 'ntp' + list 'bypass_user' 'ubus' + list 'bypass_group' 'aria2' + list 'bypass_group' 'dnsmasq' + list 'bypass_group' 'ftp' + list 'bypass_group' 'logd' + list 'bypass_group' 'nogroup' + list 'bypass_group' 'ntp' + list 'bypass_group' 'ubus' option 'bypass_china_mainland_ip' '0' - option 'acl_tcp_dport' '0-65535' - option 'acl_udp_dport' '0-65535' + option 'proxy_tcp_dport' '0-65535' + option 'proxy_udp_dport' '0-65535' config subscription 'subscription' option 'name' 'default' diff --git a/mihomo/files/mihomo.init b/mihomo/files/mihomo.init index 1d0ee102f..9e05a1c6d 100644 --- a/mihomo/files/mihomo.init +++ b/mihomo/files/mihomo.init @@ -64,11 +64,11 @@ start_service() { config_get_bool router_proxy "proxy" "router_proxy" 0 config_get_bool lan_proxy "proxy" "lan_proxy" 0 ### access control - local access_control_mode bypass_china_mainland_ip acl_tcp_dport acl_udp_dport + local access_control_mode bypass_china_mainland_ip proxy_tcp_dport proxy_udp_dport config_get access_control_mode "proxy" "access_control_mode" config_get_bool bypass_china_mainland_ip "proxy" "bypass_china_mainland_ip" 0 - config_get acl_tcp_dport "proxy" "acl_tcp_dport" "0-65535" - config_get acl_udp_dport "proxy" "acl_udp_dport" "0-65535" + config_get proxy_tcp_dport "proxy" "proxy_tcp_dport" "0-65535" + config_get proxy_udp_dport "proxy" "proxy_udp_dport" "0-65535" ## mixin config ### general local mode match_process outbound_interface ipv6 tcp_keep_alive_idle tcp_keep_alive_interval log_level @@ -336,11 +336,9 @@ start_service() { ip -6 rule add pref "$UDP_RULE_PREF" fwmark "$FW_MARK/$FW_MARK_MASK" ipproto udp table "$udp_route_table" fi fi - nft -f "$HIJACK_NFT" -D FW_MARK="$FW_MARK" -D FW_MARK_MASK="$FW_MARK_MASK" -D TUN_DEVICE="$TUN_DEVICE" -D DNS_PORT="$dns_port" -D REDIR_PORT="$redir_port" -D TPROXY_PORT="$tproxy_port" + nft -f "$HIJACK_NFT" -D MIHOMO_GROUP="$MIHOMO_GROUP" -D FW_MARK="$FW_MARK" -D FW_MARK_MASK="$FW_MARK_MASK" -D TUN_DEVICE="$TUN_DEVICE" -D FAKE_IP="$fake_ip_range" -D DNS_PORT="$dns_port" -D REDIR_PORT="$redir_port" -D TPROXY_PORT="$tproxy_port" nft -f "$RESERVED_IP_NFT" nft -f "$RESERVED_IP6_NFT" - nft add element inet "$FW_TABLE" bypass_group \{ "$MIHOMO_GROUP" \} - nft add element inet "$FW_TABLE" fake_ip \{ "$fake_ip_range" \} # dns hijack if [ "$ipv4_dns_hijack" == 1 ]; then log "Transparent Proxy: IPv4 DNS Hijack is enabled, IPv4 dns request will redirect to the core." @@ -359,7 +357,9 @@ start_service() { log "Transparent Proxy: IPv6 Proxy is enabled, set proxy for IPv6 traffic." nft add element inet "$FW_TABLE" proxy_nfproto \{ ipv6 \} fi - # bypass china mainland ip + # bypass + config_list_foreach "proxy" "bypass_user" add_bypass_user + config_list_foreach "proxy" "bypass_group" add_bypass_group if [ "$bypass_china_mainland_ip" == 1 ]; then log "Transparent Proxy: Bypass china mainland ip is enabled." if [ "$ipv4_proxy" == 1 ]; then @@ -369,15 +369,14 @@ start_service() { nft -f "$GEOIP6_CN_NFT" fi fi - # destination port to proxy - log "Transparent Proxy: Destination TCP Port to Proxy: $acl_tcp_dport." - log "Transparent Proxy: Destination UDP Port to Proxy: $acl_udp_dport." - local acl_dport - for acl_dport in $acl_tcp_dport; do - nft add element inet "$FW_TABLE" acl_dport \{ "tcp" . "$acl_dport" \} + log "Transparent Proxy: Destination TCP Port to Proxy: $proxy_tcp_dport." + log "Transparent Proxy: Destination UDP Port to Proxy: $proxy_udp_dport." + local proxy_dport + for proxy_dport in $proxy_tcp_dport; do + nft add element inet "$FW_TABLE" proxy_dport \{ "tcp" . "$proxy_dport" \} done - for acl_dport in $acl_udp_dport; do - nft add element inet "$FW_TABLE" acl_dport \{ "udp" . "$acl_dport" \} + for proxy_dport in $proxy_udp_dport; do + nft add element inet "$FW_TABLE" proxy_dport \{ "udp" . "$proxy_dport" \} done # router proxy if [ "$router_proxy" == 1 ]; then @@ -406,6 +405,7 @@ start_service() { config_list_foreach "proxy" "acl_ip" add_acl_ip config_list_foreach "proxy" "acl_ip6" add_acl_ip6 config_list_foreach "proxy" "acl_mac" add_acl_mac + config_list_foreach "proxy" "acl_interface" add_acl_interface if [ "$tcp_transparent_proxy_mode" == "redirect" ]; then nft insert rule inet "$FW_TABLE" dstnat jump "${access_control_mode}_dns_hijack" nft add rule inet "$FW_TABLE" dstnat meta l4proto tcp jump "${access_control_mode}_${tcp_transparent_proxy_mode}" @@ -592,6 +592,20 @@ mixin_nameserver_policy() { nameserver="$1" matcher="$2" yq -M -i '.dns.nameserver-policy.[env(matcher)] += [env(nameserver)]' "$RUN_PROFILE_PATH" } +add_bypass_user() { + local user; user="$1" + if [ "$user" != "root" ] && (cut -d ':' -f 1 < /etc/passwd | grep -q "$user"); then + nft add element inet "$FW_TABLE" bypass_user \{ "$user" \} + fi +} + +add_bypass_group() { + local group; group="$1" + if [ "$group" != "root" ] && (cut -d ':' -f 1 < /etc/group | grep -q "$group"); then + nft add element inet "$FW_TABLE" bypass_group \{ "$group" \} + fi +} + add_acl_ip() { nft add element inet "$FW_TABLE" acl_ip \{ "$1" \} } @@ -604,6 +618,14 @@ add_acl_mac() { nft add element inet "$FW_TABLE" acl_mac \{ "$1" \} } +add_acl_interface() { + local interface; interface="$1" + local device; network_get_device device "$interface" + if [ -n "$device" ]; then + nft add element inet "$FW_TABLE" acl_interface \{ "$device" \} + fi +} + update_subscription() { local subscription_section; subscription_section="$1" if [ -n "$subscription_section" ]; then diff --git a/mihomo/files/nftables/hijack.nft b/mihomo/files/nftables/hijack.nft index e3fad6e76..a2940151a 100644 --- a/mihomo/files/nftables/hijack.nft +++ b/mihomo/files/nftables/hijack.nft @@ -1,14 +1,18 @@ #!/usr/sbin/nft -f table inet mihomo { + set bypass_user { + type uid + flags interval + auto-merge + } + set bypass_group { type gid flags interval auto-merge elements = { - ntp, - dnsmasq, - logd + $MIHOMO_GROUP } } @@ -44,12 +48,7 @@ table inet mihomo { auto-merge } - set fake_ip { - type ipv4_addr - flags interval - } - - set acl_dport { + set proxy_dport { type inet_proto . inet_service flags interval auto-merge @@ -73,7 +72,14 @@ table inet mihomo { auto-merge } + set acl_interface { + type ifname + flags interval + auto-merge + } + chain router_dns_hijack { + meta skuid @bypass_user counter return meta skgid @bypass_group counter return meta nfproto @dns_hijack_nfproto meta l4proto udp th dport 53 counter redirect to :$DNS_PORT } @@ -86,12 +92,14 @@ table inet mihomo { meta nfproto @dns_hijack_nfproto meta l4proto udp th dport 53 ip saddr @acl_ip counter redirect to :$DNS_PORT meta nfproto @dns_hijack_nfproto meta l4proto udp th dport 53 ip6 saddr @acl_ip6 counter redirect to :$DNS_PORT meta nfproto @dns_hijack_nfproto meta l4proto udp th dport 53 ether saddr @acl_mac counter redirect to :$DNS_PORT + meta nfproto @dns_hijack_nfproto meta l4proto udp th dport 53 iifname @acl_interface counter redirect to :$DNS_PORT } chain block_dns_hijack { meta nfproto @dns_hijack_nfproto meta l4proto udp th dport 53 ip saddr @acl_ip counter return meta nfproto @dns_hijack_nfproto meta l4proto udp th dport 53 ip6 saddr @acl_ip6 counter return meta nfproto @dns_hijack_nfproto meta l4proto udp th dport 53 ether saddr @acl_mac counter return + meta nfproto @dns_hijack_nfproto meta l4proto udp th dport 53 iifname @acl_interface counter return meta nfproto @dns_hijack_nfproto meta l4proto udp th dport 53 counter redirect to :$DNS_PORT } @@ -103,12 +111,14 @@ table inet mihomo { meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip saddr @acl_ip counter redirect to :$REDIR_PORT meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip6 saddr @acl_ip6 counter redirect to :$REDIR_PORT meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ether saddr @acl_mac counter redirect to :$REDIR_PORT + meta nfproto @proxy_nfproto meta l4proto { tcp, udp } iifname @acl_interface counter redirect to :$REDIR_PORT } chain block_redirect { meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip saddr @acl_ip counter return meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip6 saddr @acl_ip6 counter return meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ether saddr @acl_mac counter return + meta nfproto @proxy_nfproto meta l4proto { tcp, udp } iifname @acl_interface counter return meta nfproto @proxy_nfproto meta l4proto { tcp, udp } counter redirect to :$REDIR_PORT } @@ -120,12 +130,14 @@ table inet mihomo { meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip saddr @acl_ip meta mark set mark ^ $FW_MARK tproxy ip to :$TPROXY_PORT counter accept meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip6 saddr @acl_ip6 meta mark set mark ^ $FW_MARK tproxy ip6 to :$TPROXY_PORT counter accept meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ether saddr @acl_mac meta mark set mark ^ $FW_MARK tproxy to :$TPROXY_PORT counter accept + meta nfproto @proxy_nfproto meta l4proto { tcp, udp } iifname @acl_interface meta mark set mark ^ $FW_MARK tproxy to :$TPROXY_PORT counter accept } chain block_tproxy { meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip saddr @acl_ip counter return meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip6 saddr @acl_ip6 counter return meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ether saddr @acl_mac counter return + meta nfproto @proxy_nfproto meta l4proto { tcp, udp } iifname @acl_interface counter return meta nfproto @proxy_nfproto meta l4proto { tcp, udp } meta mark set mark ^ $FW_MARK tproxy to :$TPROXY_PORT counter accept } @@ -137,12 +149,14 @@ table inet mihomo { meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip saddr @acl_ip meta mark set mark ^ $FW_MARK counter meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip6 saddr @acl_ip6 meta mark set mark ^ $FW_MARK counter meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ether saddr @acl_mac meta mark set mark ^ $FW_MARK counter + meta nfproto @proxy_nfproto meta l4proto { tcp, udp } iifname @acl_interface meta mark set mark ^ $FW_MARK counter } chain block_tun { meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip saddr @acl_ip counter return meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip6 saddr @acl_ip6 counter return meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ether saddr @acl_mac counter return + meta nfproto @proxy_nfproto meta l4proto { tcp, udp } iifname @acl_interface counter return meta nfproto @proxy_nfproto meta l4proto { tcp, udp } meta mark set mark ^ $FW_MARK counter } @@ -162,12 +176,13 @@ table inet mihomo { ip6 daddr @reserved_ip6 counter return ip daddr @china_ip counter return ip6 daddr @china_ip6 counter return - meta l4proto . th dport != @acl_dport ip daddr != @fake_ip counter return - meta nfproto ipv6 meta l4proto . th dport != @acl_dport counter return + meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return + meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return } chain nat_output { type nat hook output priority filter; policy accept; + meta skuid @bypass_user counter return meta skgid @bypass_group counter return fib daddr type local counter return ct direction reply counter return @@ -175,8 +190,8 @@ table inet mihomo { ip6 daddr @reserved_ip6 counter return ip daddr @china_ip counter return ip6 daddr @china_ip6 counter return - meta l4proto . th dport != @acl_dport ip daddr != @fake_ip counter return - meta nfproto ipv6 meta l4proto . th dport != @acl_dport counter return + meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return + meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return } chain mangle_prerouting { @@ -189,13 +204,14 @@ table inet mihomo { ip6 daddr @reserved_ip6 counter return ip daddr @china_ip counter return ip6 daddr @china_ip6 counter return - meta l4proto . th dport != @acl_dport ip daddr != @fake_ip counter return - meta nfproto ipv6 meta l4proto . th dport != @acl_dport counter return + meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return + meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return meta l4proto udp th dport 53 counter return } chain mangle_output { type route hook output priority mangle; policy accept; + meta skuid @bypass_user counter return meta skgid @bypass_group counter return fib daddr type local counter return ct direction reply counter return @@ -203,8 +219,8 @@ table inet mihomo { ip6 daddr @reserved_ip6 counter return ip daddr @china_ip counter return ip6 daddr @china_ip6 counter return - meta l4proto . th dport != @acl_dport ip daddr != @fake_ip counter return - meta nfproto ipv6 meta l4proto . th dport != @acl_dport counter return + meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return + meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return meta l4proto udp th dport 53 counter return } } diff --git a/mihomo/files/uci-defaults/migrate.sh b/mihomo/files/uci-defaults/migrate.sh index a993228b4..515f3f785 100644 --- a/mihomo/files/uci-defaults/migrate.sh +++ b/mihomo/files/uci-defaults/migrate.sh @@ -14,6 +14,32 @@ mixin_file_content=$(uci -q get mihomo.mixin.mixin_file_content); [ -z "$mixin_f start_delay=$(uci -q get mihomo.config.start_delay); [ -z "$start_delay" ] && uci set mihomo.config.start_delay=0 +# since v1.11.0 + +acl_tcp_dport=$(uci -q get mihomo.proxy.acl_tcp_dport); [ -n "$acl_tcp_dport" ] && uci rename mihomo.proxy.acl_tcp_dport=proxy_tcp_dport + +acl_udp_dport=$(uci -q get mihomo.proxy.acl_udp_dport); [ -n "$acl_udp_dport" ] && uci rename mihomo.proxy.acl_udp_dport=proxy_udp_dport + +bypass_user=$(uci -q get mihomo.proxy.bypass_user); [ -z "$bypass_user" ] && { + uci add_list mihomo.proxy.bypass_user="aria2" + uci add_list mihomo.proxy.bypass_user="dnsmasq" + uci add_list mihomo.proxy.bypass_user="ftp" + uci add_list mihomo.proxy.bypass_user="logd" + uci add_list mihomo.proxy.bypass_user="nobody" + uci add_list mihomo.proxy.bypass_user="ntp" + uci add_list mihomo.proxy.bypass_user="ubus" +} + +bypass_group=$(uci -q get mihomo.proxy.bypass_group); [ -z "$bypass_group" ] && { + uci add_list mihomo.proxy.bypass_group="aria2" + uci add_list mihomo.proxy.bypass_group="dnsmasq" + uci add_list mihomo.proxy.bypass_group="ftp" + uci add_list mihomo.proxy.bypass_group="logd" + uci add_list mihomo.proxy.bypass_group="nogroup" + uci add_list mihomo.proxy.bypass_group="ntp" + uci add_list mihomo.proxy.bypass_group="ubus" +} + # commit uci commit mihomo