diff --git a/nikki/Makefile b/nikki/Makefile index cd8ccabdb..85587c826 100644 --- a/nikki/Makefile +++ b/nikki/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/MetaCubeX/mihomo.git -PKG_SOURCE_DATE:=2025-04-06 -PKG_SOURCE_VERSION:=9e8f4ada4754ae95b002535acbeb457e40b06731 -PKG_MIRROR_HASH:=1c8a7d70de0cb903b58eca1937b6561003cae7e76f9f021fd3eb9007b6a1f65f +PKG_SOURCE_DATE:=2025-04-12 +PKG_SOURCE_VERSION:=cedb36df5fe58d5d972b1507c1ab656aca5f046d +PKG_MIRROR_HASH:=b2f9fe4e2ebd38036eac0f2c5af79362cb2afbb780c36c236259ecace9db11da PKG_LICENSE:=GPL3.0+ PKG_MAINTAINER:=Joseph Mory @@ -16,7 +16,7 @@ PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_PARALLEL:=1 PKG_BUILD_FLAGS:=no-mips16 -PKG_BUILD_VERSION:=alpha-9e8f4ad +PKG_BUILD_VERSION:=alpha-cedb36d PKG_BUILD_TIME:=$(shell date -u -Iseconds) GO_PKG:=github.com/metacubex/mihomo diff --git a/nikki/files/nikki.conf b/nikki/files/nikki.conf index f323e6bd0..1f59b736d 100644 --- a/nikki/files/nikki.conf +++ b/nikki/files/nikki.conf @@ -10,9 +10,9 @@ config config 'config' option 'test_profile' '1' config proxy 'proxy' - option 'transparent_proxy' '1' - option 'tcp_transparent_proxy_mode' 'redirect' - option 'udp_transparent_proxy_mode' 'tun' + option 'enabled' '1' + option 'tcp_mode' 'redirect' + option 'udp_mode' 'tun' option 'ipv4_dns_hijack' '1' option 'ipv6_dns_hijack' '1' option 'ipv4_proxy' '1' @@ -20,30 +20,7 @@ config proxy 'proxy' option 'fake_ip_ping_hijack' '1' option 'router_proxy' '1' option 'lan_proxy' '1' - option 'access_control_mode' 'all' - option 'acl_ip' '' - option 'acl_ip6' '' - option 'acl_mac' '' - option 'acl_interface' '' - 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' 'dnsmasq' - list 'bypass_group' 'ftp' - list 'bypass_group' 'logd' - list 'bypass_group' 'nogroup' - list 'bypass_group' 'ntp' - list 'bypass_group' 'ubus' - list 'bypass_cgroup' 'adguardhome' - list 'bypass_cgroup' 'aria2' - list 'bypass_cgroup' 'dnsmasq' - list 'bypass_cgroup' 'netbird' - list 'bypass_cgroup' 'qbittorrent' - list 'bypass_cgroup' 'tailscale' - list 'bypass_cgroup' 'zerotier' + list 'lan_inbound_interface' 'lan' list 'bypass_dscp' '4' option 'bypass_china_mainland_ip' '0' option 'proxy_tcp_dport' '0-65535' @@ -100,6 +77,38 @@ config env 'env' option 'disable_quic_go_gso' '0' option 'disable_quic_go_ecn' '0' +config router_access_control + option 'enabled' '1' + list 'user' 'dnsmasq' + list 'user' 'ftp' + list 'user' 'logd' + list 'user' 'nobody' + list 'user' 'ntp' + list 'user' 'ubus' + list 'group' 'dnsmasq' + list 'group' 'ftp' + list 'group' 'logd' + list 'group' 'nogroup' + list 'group' 'ntp' + list 'group' 'ubus' + list 'cgroup' 'adguardhome' + list 'cgroup' 'aria2' + list 'cgroup' 'dnsmasq' + list 'cgroup' 'netbird' + list 'cgroup' 'qbittorrent' + list 'cgroup' 'sysntpd' + list 'cgroup' 'tailscale' + list 'cgroup' 'zerotier' + option 'proxy' '0' + +config router_access_control + option 'enabled' '1' + option 'proxy' '1' + +config lan_access_control + option 'enabled' '1' + option 'proxy' '1' + config authentication option 'enabled' '1' option 'username' 'nikki' diff --git a/nikki/files/nikki.init b/nikki/files/nikki.init index c492399ec..4428ddc67 100644 --- a/nikki/files/nikki.init +++ b/nikki/files/nikki.init @@ -143,11 +143,11 @@ service_started() { fi # load config config_load nikki - # check if transparent proxy enabled - local transparent_proxy - config_get_bool transparent_proxy "proxy" "transparent_proxy" 0 - if [ "$transparent_proxy" == 0 ]; then - log "Transparent Proxy" "Disabled." + # check if proxy enabled + local enabled + config_get_bool enabled "proxy" "enabled" 0 + if [ "$enabled" == 0 ]; then + log "Proxy" "Disabled." return fi # get config @@ -156,19 +156,19 @@ service_started() { local tun_device config_get tun_device "mixin" "tun_device" "nikki" ## proxy config - ### transparent proxy - local tcp_transparent_proxy_mode udp_transparent_proxy_mode ipv4_proxy ipv6_proxy - config_get tcp_transparent_proxy_mode "proxy" "tcp_transparent_proxy_mode" - config_get udp_transparent_proxy_mode "proxy" "udp_transparent_proxy_mode" + ### general + local tcp_mode udp_mode ipv4_proxy ipv6_proxy + config_get tcp_mode "proxy" "tcp_mode" + config_get udp_mode "proxy" "udp_mode" config_get_bool ipv4_proxy "proxy" "ipv4_proxy" 0 config_get_bool ipv6_proxy "proxy" "ipv6_proxy" 0 # prepare config local tproxy_enable; tproxy_enable=0 - if [[ "$tcp_transparent_proxy_mode" == "tproxy" || "$udp_transparent_proxy_mode" == "tproxy" ]]; then + if [[ "$tcp_mode" == "tproxy" || "$udp_mode" == "tproxy" ]]; then tproxy_enable=1 fi local tun_enable; tun_enable=0 - if [[ "$tcp_transparent_proxy_mode" == "tun" || "$udp_transparent_proxy_mode" == "tun" ]]; then + if [[ "$tcp_mode" == "tun" || "$udp_mode" == "tun" ]]; then tun_enable=1 fi # fix compatible with dockerd @@ -197,17 +197,17 @@ service_started() { fi fi fi - # transparent proxy - log "Transparent Proxy" "Enabled." + # proxy + log "Proxy" "Enabled." # wait for tun device online if [ "$tun_enable" == 1 ]; then - log "Transparent Proxy" "Waiting for tun device online..." + log "Proxy" "Waiting for tun device online..." local tun_timeout; tun_timeout=15 local tun_interval; tun_interval=1 while [ "$tun_timeout" -gt 0 ]; do if (ip link show dev "$tun_device" > /dev/null 2>&1); then if [ $(ip -json addr show dev "$tun_device" | tun_device="$tun_device" yq -M '.[] | select(.ifname = strenv(tun_device)) | .addr_info | length') -gt 0 ]; then - log "Transparent Proxy" "Tun device is online." + log "Proxy" "Tun device is online." break fi fi @@ -215,7 +215,7 @@ service_started() { sleep "$tun_interval" done if [ "$tun_timeout" -le 0 ]; then - log "Transparent Proxy" "Waiting timeout, tun device is not online." + log "Proxy" "Waiting timeout, tun device is not online." log "App" "Exit." return fi @@ -246,9 +246,9 @@ service_started() { utpl -D cgroup_name="$CGROUP_NAME" -D cgroup_id="$CGROUP_ID" -D tproxy_fw_mark="$TPROXY_FW_MARK" -D tun_fw_mark="$TUN_FW_MARK" -S "$HIJACK_UT" | nft -f - # check hijack if (nft list tables | grep -q nikki); then - log "Transparent Proxy" "Hijack successful." + log "Proxy" "Hijack successful." else - log "Transparent Proxy" "Hijack failed." + log "Proxy" "Hijack failed." log "App" "Exit." fi } diff --git a/nikki/files/scripts/firewall_include.sh b/nikki/files/scripts/firewall_include.sh index c655ae168..fde110d46 100644 --- a/nikki/files/scripts/firewall_include.sh +++ b/nikki/files/scripts/firewall_include.sh @@ -5,11 +5,11 @@ config_load nikki config_get enabled "config" "enabled" 0 -config_get tcp_transparent_proxy_mode "proxy" "tcp_transparent_proxy_mode" -config_get udp_transparent_proxy_mode "proxy" "udp_transparent_proxy_mode" +config_get tcp_mode "proxy" "tcp_mode" +config_get udp_mode "proxy" "udp_mode" config_get tun_device "mixin" "tun_device" -if [ "$enabled" == 1 ] && [[ "$tcp_transparent_proxy_mode" == "tun" || "$udp_transparent_proxy_mode" == "tun" ]]; then +if [ "$enabled" == 1 ] && [[ "$tcp_mode" == "tun" || "$udp_mode" == "tun" ]]; then nft insert rule inet fw4 input iifname "$tun_device" counter accept comment "nikki" nft insert rule inet fw4 forward oifname "$tun_device" counter accept comment "nikki" nft insert rule inet fw4 forward iifname "$tun_device" counter accept comment "nikki" diff --git a/nikki/files/uci-defaults/migrate.sh b/nikki/files/uci-defaults/migrate.sh index ba07d1b61..1326cb9f2 100644 --- a/nikki/files/uci-defaults/migrate.sh +++ b/nikki/files/uci-defaults/migrate.sh @@ -30,6 +30,82 @@ mixin_dns_port=$(uci -q get nikki.mixin.dns_port); [ -n "$mixin_dns_port" ] && { uci set nikki.mixin.dns_listen=[::]:$mixin_dns_port } +# since v1.22.0 + +proxy_transparent_proxy=$(uci -q get nikki.proxy.transparent_proxy); [ -n "$proxy_transparent_proxy" ] && { + uci rename nikki.proxy.transparent_proxy=enabled + uci rename nikki.proxy.tcp_transparent_proxy_mode=tcp_mode + uci rename nikki.proxy.udp_transparent_proxy_mode=udp_mode + + uci add nikki router_access_control + uci set nikki.@router_access_control[-1].enabled=1 + proxy_bypass_user=$(uci -q get nikki.proxy.bypass_user); [ -n "$proxy_bypass_user" ] && { + for user in $proxy_bypass_user; do + uci add_list nikki.@router_access_control[-1].user="$user" + done + } + proxy_bypass_group=$(uci -q get nikki.proxy.bypass_group); [ -n "$proxy_bypass_group" ] && { + for group in $proxy_bypass_group; do + uci add_list nikki.@router_access_control[-1].group="$group" + done + } + proxy_bypass_cgroup=$(uci -q get nikki.proxy.bypass_cgroup); [ -n "$proxy_bypass_cgroup" ] && { + for cgroup in $proxy_bypass_cgroup; do + uci add_list nikki.@router_access_control[-1].cgroup="$cgroup" + done + } + uci set nikki.@router_access_control[-1].proxy=0 + + uci add nikki router_access_control + uci set nikki.@router_access_control[-1].enabled=1 + uci set nikki.@router_access_control[-1].proxy=1 + + uci add_list nikki.proxy.lan_inbound_interface=lan + + proxy_access_control_mode=$(uci -q get nikki.proxy.access_control_mode); [ "$proxy_access_control_mode" != "all" ] && { + proxy_acl_ip=$(uci -q get nikki.proxy.acl_ip); [ -n "$proxy_acl_ip" ] && { + for ip in $proxy_acl_ip; do + uci add nikki lan_access_control + uci set nikki.@lan_access_control[-1].enabled=1 + uci add_list nikki.@lan_access_control[-1].ip="$ip" + [ "$proxy_access_control_mode" == "allow" ] && uci set nikki.@lan_access_control[-1].proxy=1 + [ "$proxy_access_control_mode" == "block" ] && uci set nikki.@lan_access_control[-1].proxy=0 + done + } + proxy_acl_ip6=$(uci -q get nikki.proxy.acl_ip6); [ -n "$proxy_acl_ip6" ] && { + for ip6 in $proxy_acl_ip6; do + uci add nikki lan_access_control + uci set nikki.@lan_access_control[-1].enabled=1 + uci add_list nikki.@lan_access_control[-1].ip6="$ip6" + [ "$proxy_access_control_mode" == "allow" ] && uci set nikki.@lan_access_control[-1].proxy=1 + [ "$proxy_access_control_mode" == "block" ] && uci set nikki.@lan_access_control[-1].proxy=0 + done + } + proxy_acl_mac=$(uci -q get nikki.proxy.acl_mac); [ -n "$proxy_acl_mac" ] && { + for mac in $proxy_acl_mac; do + uci add nikki lan_access_control + uci set nikki.@lan_access_control[-1].enabled=1 + uci add_list nikki.@lan_access_control[-1].mac="$mac" + [ "$proxy_access_control_mode" == "allow" ] && uci set nikki.@lan_access_control[-1].proxy=1 + [ "$proxy_access_control_mode" == "block" ] && uci set nikki.@lan_access_control[-1].proxy=0 + done + } + [ "$proxy_access_control_mode" == "block" ] && { + uci add nikki lan_access_control + uci set nikki.@lan_access_control[-1].enabled=1 + uci set nikki.@lan_access_control[-1].proxy=1 + } + } + + uci del nikki.proxy.access_control_mode + uci del nikki.proxy.acl_ip + uci del nikki.proxy.acl_ip6 + uci del nikki.proxy.acl_mac + uci del nikki.proxy.acl_interface + uci del nikki.proxy.bypass_user + uci del nikki.proxy.bypass_group + uci del nikki.proxy.bypass_cgroup +} # commit uci commit nikki diff --git a/nikki/files/ucode/hijack.ut b/nikki/files/ucode/hijack.ut index 3fae069c6..e69faac1f 100644 --- a/nikki/files/ucode/hijack.ut +++ b/nikki/files/ucode/hijack.ut @@ -27,32 +27,43 @@ const tun_device = uci.get('nikki', 'mixin', 'tun_device'); - const tcp_transparent_proxy_mode = uci.get('nikki', 'proxy', 'tcp_transparent_proxy_mode'); - const udp_transparent_proxy_mode = uci.get('nikki', 'proxy', 'udp_transparent_proxy_mode'); + const tcp_mode = uci.get('nikki', 'proxy', 'tcp_mode'); + const udp_mode = uci.get('nikki', 'proxy', 'udp_mode'); const ipv4_dns_hijack = uci_bool(uci.get('nikki', 'proxy', 'ipv4_dns_hijack')); const ipv6_dns_hijack = uci_bool(uci.get('nikki', 'proxy', 'ipv6_dns_hijack')); const ipv4_proxy = uci_bool(uci.get('nikki', 'proxy', 'ipv4_proxy')); const ipv6_proxy = uci_bool(uci.get('nikki', 'proxy', 'ipv6_proxy')); const fake_ip_ping_hijack = uci_bool(uci.get('nikki', 'proxy', 'fake_ip_ping_hijack')); + const router_proxy = uci_bool(uci.get('nikki', 'proxy', 'router_proxy')); + const router_access_control = []; + uci.foreach('nikki', 'router_access_control', (access_control) => { + access_control['enabled'] = uci_bool(access_control['enabled']); + access_control['user'] = filter(uci_array(access_control['user']), (x) => index(users, x) >= 0); + access_control['group'] = filter(uci_array(access_control['group']), (x) => index(groups, x) >= 0); + access_control['cgroup'] = filter(uci_array(access_control['cgroup']), (x) => index(cgroups, x) >= 0); + access_control['proxy'] = uci_bool(access_control['proxy']); + push(router_access_control, access_control); + }); + const lan_proxy = uci_bool(uci.get('nikki', 'proxy', 'lan_proxy')); - - const access_control_mode = uci.get('nikki', 'proxy', 'access_control_mode'); - const acl_ip = uci_array(uci.get('nikki', 'proxy', 'acl_ip')); - const acl_ip6 = uci_array(uci.get('nikki', 'proxy', 'acl_ip6')); - const acl_mac = uci_array(uci.get('nikki', 'proxy', 'acl_mac')); - const acl_interface = uci_array(uci.get('nikki', 'proxy', 'acl_interface')); - - const bypass_user = filter(uci_array(uci.get('nikki', 'proxy', 'bypass_user')), (x) => x != 'root' && index(users, x) >= 0); - const bypass_group = filter(uci_array(uci.get('nikki', 'proxy', 'bypass_group')), (x) => x != 'root' && index(groups, x) >= 0); - - let bypass_cgroup = []; - if (cgroups_version == 1) { - push(bypass_cgroup, cgroup_id); - } else if (cgroups_version == 2) { - bypass_cgroup = filter(uci_array(uci.get('nikki', 'proxy', 'bypass_cgroup')), (x) => x != 'nikki' && index(cgroups, x) >= 0); - push(bypass_cgroup, cgroup_name); + const lan_inbound_interface = uci_array(uci.get('nikki', 'proxy', 'lan_inbound_interface')); + const lan_inbound_device = []; + for (let interface in lan_inbound_interface) { + const device = ubus.call('network.interface', 'status', {'interface': interface})?.l3_device ?? ''; + if (device != '') { + push(lan_inbound_device, device); + } } + const lan_access_control = []; + uci.foreach('nikki', 'lan_access_control', (access_control) => { + access_control['enabled'] = uci_bool(access_control['enabled']); + access_control['ip'] = uci_array(access_control['ip']); + access_control['ip6'] = uci_array(access_control['ip6']); + access_control['mac'] = uci_array(access_control['mac']); + access_control['proxy'] = uci_bool(access_control['proxy']); + push(lan_access_control, access_control); + }); const bypass_dscp = uci_array(uci.get('nikki', 'proxy', 'bypass_dscp')); const bypass_china_mainland_ip = uci_bool(uci.get('nikki', 'proxy', 'bypass_china_mainland_ip')); @@ -67,14 +78,6 @@ push(dns_hijack_nfproto, 'ipv6'); } - const acl_device = []; - for (let i = 0; i < length(acl_interface); i++) { - const device = ubus.call('network.interface', 'status', {'interface': acl_interface[i]})?.l3_device ?? ''; - if (device != '') { - push(acl_device, device); - } - } - const proxy_nfproto = []; if (ipv4_proxy) { push(proxy_nfproto, 'ipv4'); @@ -98,8 +101,8 @@ table inet nikki { flags interval {% if (length(dns_hijack_nfproto) > 0): %} elements = { - {% for (let x in dns_hijack_nfproto): %} - {{ x }}, + {% for (let nfproto in dns_hijack_nfproto): %} + {{ nfproto }}, {% endfor %} } {% endif %} @@ -110,67 +113,13 @@ table inet nikki { flags interval {% if (length(proxy_nfproto) > 0): %} elements = { - {% for (let x in proxy_nfproto): %} - {{ x }}, + {% for (let nfproto in proxy_nfproto): %} + {{ nfproto }}, {% endfor %} } {% endif %} } - set bypass_user { - type uid - flags interval - auto-merge - {% if (length(bypass_user) > 0): %} - elements = { - {% for (let x in bypass_user): %} - {{ x }}, - {% endfor %} - } - {% endif %} - } - - set bypass_group { - type gid - flags interval - auto-merge - {% if (length(bypass_group) > 0): %} - elements = { - {% for (let x in bypass_group): %} - {{ x }}, - {% endfor %} - } - {% endif %} - } - - {% if (cgroups_version == 1): %} - set bypass_cgroup { - typeof meta cgroup - flags interval - auto-merge - {% if (length(bypass_cgroup) > 0): %} - elements = { - {% for (let x in bypass_cgroup): %} - {{ x }}, - {% endfor %} - } - {% endif %} - } - {% elif (cgroups_version == 2): %} - set bypass_cgroup { - type cgroupsv2 - flags interval - auto-merge - {% if (length(bypass_cgroup) > 0): %} - elements = { - {% for (let x in bypass_cgroup): %} - services/{{ x }}, - {% endfor %} - } - {% endif %} - } - {% endif %} - set reserved_ip { type ipv4_addr flags interval @@ -183,6 +132,19 @@ table inet nikki { auto-merge } + set lan_inbound_device { + type ifname + flags interval + auto-merge + {% if (length(lan_inbound_device) > 0): %} + elements = { + {% for (let device in lan_inbound_device): %} + {{ device }}, + {% endfor %} + } + {% endif %} + } + set china_ip { type ipv4_addr flags interval @@ -199,8 +161,8 @@ table inet nikki { auto-merge {% if (length(proxy_dport) > 0): %} elements = { - {% for (let x in proxy_dport): %} - {{ x }}, + {% for (let dport in proxy_dport): %} + {{ dport }}, {% endfor %} } {% endif %} @@ -212,145 +174,215 @@ table inet nikki { auto-merge {% if (length(bypass_dscp) > 0): %} elements = { - {% for (let x in bypass_dscp): %} - {{ x }}, + {% for (let dscp in bypass_dscp): %} + {{ dscp }}, {% endfor %} } {% endif %} } - set acl_ip { - type ipv4_addr - flags interval - auto-merge - {% if (length(acl_ip) > 0): %} - elements = { - {% for (let x in acl_ip): %} - {{ x }}, - {% endfor %} - } + chain router_dns_hijack { + {% for (let access_control in router_access_control): %} + {% if (access_control['enabled']): %} + {% if (length(access_control['user']) == 0 && length(access_control['group']) == 0 && length(access_control['cgroup']) == 0): %} + meta l4proto { tcp, udp } th dport 53 counter {% if (access_control.proxy == '1'): %} redirect to :{{ dns_port }} {% else %} return {% endif %} + + {% else %} + {% if (length(access_control['user']) > 0): %} + meta l4proto { tcp, udp } meta skuid { {% for (let user in access_control['user']): %} {{ user }}, {% endfor %} } th dport 53 counter {% if (access_control.proxy == '1'): %} redirect to :{{ dns_port }} {% else %} return {% endif %} + {% endif %} + {% if (length(access_control['group']) > 0): %} + meta l4proto { tcp, udp } meta skgid { {% for (let group in access_control['group']): %} {{ group }}, {% endfor %} } th dport 53 counter {% if (access_control.proxy == '1'): %} redirect to :{{ dns_port }} {% else %} return {% endif %} + + {% endif %} + {% if (cgroups_version == 2 && length(access_control['cgroup']) > 0): %} + meta l4proto { tcp, udp } socket cgroupv2 level 2 { {% for (let cgroup in access_control['cgroup']): %} services/{{ cgroup }}, {% endfor %} } th dport 53 counter {% if (access_control.proxy == '1'): %} redirect to :{{ dns_port }} {% else %} return {% endif %} + + {% endif %} + {% endif %} + {% endif %} + {% endfor %} } - set acl_ip6 { - type ipv6_addr - flags interval - auto-merge - {% if (length(acl_ip6) > 0): %} - elements = { - {% for (let x in acl_ip6): %} - {{ x }}, - {% endfor %} - } + chain router_redirect { + {% for (let access_control in router_access_control): %} + {% if (access_control['enabled']): %} + {% if (length(access_control['user']) == 0 && length(access_control['group']) == 0 && length(access_control['cgroup']) == 0): %} + meta l4proto tcp counter {% if (access_control.proxy == '1'): %} redirect to :{{ redir_port }} {% else %} return {% endif %} + + {% else %} + {% if (length(access_control['user']) > 0): %} + meta l4proto tcp meta skuid { {% for (let user in access_control['user']): %} {{ user }}, {% endfor %} } counter {% if (access_control.proxy == '1'): %} redirect to :{{ redir_port }} {% else %} return {% endif %} + {% endif %} + {% if (length(access_control['group']) > 0): %} + meta l4proto tcp meta skgid { {% for (let group in access_control['group']): %} {{ group }}, {% endfor %} } counter {% if (access_control.proxy == '1'): %} redirect to :{{ redir_port }} {% else %} return {% endif %} + + {% endif %} + {% if (cgroups_version == 2 && length(access_control['cgroup']) > 0): %} + meta l4proto tcp socket cgroupv2 level 2 { {% for (let cgroup in access_control['cgroup']): %} services/{{ cgroup }}, {% endfor %} } counter {% if (access_control.proxy == '1'): %} redirect to :{{ redir_port }} {% else %} return {% endif %} + + {% endif %} + {% endif %} + {% endif %} + {% endfor %} } - set acl_mac { - type ether_addr - flags interval - auto-merge - {% if (length(acl_mac) > 0): %} - elements = { - {% for (let x in acl_mac): %} - {{ x }}, - {% endfor %} - } + chain router_tproxy { + {% for (let access_control in router_access_control): %} + {% if (access_control['enabled']): %} + {% if (length(access_control['user']) == 0 && length(access_control['group']) == 0 && length(access_control['cgroup']) == 0): %} + meta l4proto { tcp, udp } {% if (access_control.proxy == '1'): %} meta mark set {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept {% else %} counter return {% endif %} + + {% else %} + {% if (length(access_control['user']) > 0): %} + meta l4proto { tcp, udp } meta skuid { {% for (let user in access_control['user']): %} {{ user }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept {% else %} counter return {% endif %} + {% endif %} + {% if (length(access_control['group']) > 0): %} + meta l4proto { tcp, udp } meta skgid { {% for (let group in access_control['group']): %} {{ group }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept {% else %} counter return {% endif %} + + {% endif %} + {% if (cgroups_version == 2 && length(access_control['cgroup']) > 0): %} + meta l4proto { tcp, udp } socket cgroupv2 level 2 { {% for (let cgroup in access_control['cgroup']): %} services/{{ cgroup }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept {% else %} counter return {% endif %} + + {% endif %} + {% endif %} + {% endif %} + {% endfor %} } - set acl_device { - type ifname - flags interval - auto-merge - {% if (length(acl_device) > 0): %} - elements = { - {% for (let x in acl_device): %} - {{ x }}, - {% endfor %} - } + chain router_tun { + {% for (let access_control in router_access_control): %} + {% if (access_control['enabled']): %} + {% if (length(access_control['user']) == 0 && length(access_control['group']) == 0 && length(access_control['cgroup']) == 0): %} + meta l4proto { tcp, udp } {% if (access_control.proxy == '1'): %} meta mark set {{ tun_fw_mark }} counter accept {% else %} counter return {% endif %} + + {% else %} + {% if (length(access_control['user']) > 0): %} + meta l4proto { tcp, udp } meta skuid { {% for (let user in access_control['user']): %} {{ user }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tun_fw_mark }} counter accept {% else %} counter return {% endif %} + {% endif %} + {% if (length(access_control['group']) > 0): %} + meta l4proto { tcp, udp } meta skgid { {% for (let group in access_control['group']): %} {{ group }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tun_fw_mark }} counter accept {% else %} counter return {% endif %} + + {% endif %} + {% if (cgroups_version == 2 && length(access_control['cgroup']) > 0): %} + meta l4proto { tcp, udp } socket cgroupv2 level 2 { {% for (let cgroup in access_control['cgroup']): %} services/{{ cgroup }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tun_fw_mark }} counter accept {% else %} counter return {% endif %} + + {% endif %} + {% endif %} + {% endif %} + {% endfor %} } chain lan_dns_hijack { - {% if (access_control_mode == 'all'): %} - meta l4proto { tcp, udp } th dport 53 counter redirect to :{{ dns_port }} - {% elif (access_control_mode == 'allow'): %} - meta l4proto { tcp, udp } th dport 53 ip saddr @acl_ip counter redirect to :{{ dns_port }} - meta l4proto { tcp, udp } th dport 53 ip6 saddr @acl_ip6 counter redirect to :{{ dns_port }} - meta l4proto { tcp, udp } th dport 53 ether saddr @acl_mac counter redirect to :{{ dns_port }} - meta l4proto { tcp, udp } th dport 53 iifname @acl_device counter redirect to :{{ dns_port }} - {% elif (access_control_mode == 'block'): %} - meta l4proto { tcp, udp } th dport 53 ip saddr @acl_ip counter return - meta l4proto { tcp, udp } th dport 53 ip6 saddr @acl_ip6 counter return - meta l4proto { tcp, udp } th dport 53 ether saddr @acl_mac counter return - meta l4proto { tcp, udp } th dport 53 iifname @acl_device counter return - meta l4proto { tcp, udp } th dport 53 counter redirect to :{{ dns_port }} + {% for (let access_control in lan_access_control): %} + {% if (access_control['enabled']): %} + {% if (length(access_control['ip']) == 0 && length(access_control['ip6']) == 0 && length(access_control['mac']) == 0): %} + meta l4proto { tcp, udp } th dport 53 counter {% if (access_control.proxy == '1'): %} redirect to :{{ dns_port }} {% else %} return {% endif %} + + {% else %} + {% if (length(access_control['ip']) > 0): %} + meta l4proto { tcp, udp } ip saddr { {% for (let ip in access_control['ip']): %} {{ ip }}, {% endfor %} } th dport 53 counter {% if (access_control.proxy == '1'): %} redirect to :{{ dns_port }} {% else %} return {% endif %} + {% endif %} + {% if (length(access_control['ip6']) > 0): %} + meta l4proto { tcp, udp } ip6 saddr { {% for (let ip6 in access_control['ip6']): %} {{ ip6 }}, {% endfor %} } th dport 53 counter {% if (access_control.proxy == '1'): %} redirect to :{{ dns_port }} {% else %} return {% endif %} + + {% endif %} + {% if (length(access_control['mac']) > 0): %} + meta l4proto { tcp, udp } ether saddr { {% for (let mac in access_control['mac']): %} {{ mac }}, {% endfor %} } th dport 53 counter {% if (access_control.proxy == '1'): %} redirect to :{{ dns_port }} {% else %} return {% endif %} + + {% endif %} + {% endif %} + {% endif %} + {% endfor %} } chain lan_redirect { - {% if (access_control_mode == 'all'): %} - meta l4proto tcp counter redirect to :{{ redir_port }} - {% elif (access_control_mode == 'allow'): %} - meta l4proto tcp ip saddr @acl_ip counter redirect to :{{ redir_port }} - meta l4proto tcp ip6 saddr @acl_ip6 counter redirect to :{{ redir_port }} - meta l4proto tcp ether saddr @acl_mac counter redirect to :{{ redir_port }} - meta l4proto tcp iifname @acl_device counter redirect to :{{ redir_port }} - {% elif (access_control_mode == 'block'): %} - meta l4proto tcp ip saddr @acl_ip counter return - meta l4proto tcp ip6 saddr @acl_ip6 counter return - meta l4proto tcp ether saddr @acl_mac counter return - meta l4proto tcp iifname @acl_device counter return - meta l4proto tcp counter redirect to :{{ redir_port }} + {% for (let access_control in lan_access_control): %} + {% if (access_control['enabled']): %} + {% if (length(access_control['ip']) == 0 && length(access_control['ip6']) == 0 && length(access_control['mac']) == 0): %} + meta l4proto tcp tcp counter {% if (access_control.proxy == '1'): %} redirect to :{{ redir_port }} {% else %} counter return {% endif %} + + {% else %} + {% if (length(access_control['ip']) > 0): %} + meta l4proto tcp ip saddr { {% for (let ip in access_control['ip']): %} {{ ip }}, {% endfor %} } counter {% if (access_control.proxy == '1'): %} redirect to :{{ redir_port }} {% else %} return {% endif %} + {% endif %} + {% if (length(access_control['ip6']) > 0): %} + meta l4proto tcp ip6 saddr { {% for (let ip6 in access_control['ip6']): %} {{ ip6 }}, {% endfor %} } counter {% if (access_control.proxy == '1'): %} redirect to :{{ redir_port }} {% else %} return {% endif %} + + {% endif %} + {% if (length(access_control['mac']) > 0): %} + meta l4proto tcp ether saddr { {% for (let mac in access_control['mac']): %} {{ mac }}, {% endfor %} } counter {% if (access_control.proxy == '1'): %} redirect to :{{ redir_port }} {% else %} return {% endif %} + + {% endif %} + {% endif %} + {% endif %} + {% endfor %} } chain lan_tproxy { - {% if (access_control_mode == 'all'): %} - meta l4proto { tcp, udp } meta mark set {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept - {% elif (access_control_mode == 'allow'): %} - meta l4proto { tcp, udp } ip saddr @acl_ip meta mark set {{ tproxy_fw_mark }} tproxy ip to :{{ tproxy_port }} counter accept - meta l4proto { tcp, udp } ip6 saddr @acl_ip6 meta mark set {{ tproxy_fw_mark }} tproxy ip6 to :{{ tproxy_port }} counter accept - meta l4proto { tcp, udp } ether saddr @acl_mac meta mark set {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept - meta l4proto { tcp, udp } iifname @acl_device meta mark set {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept - {% elif (access_control_mode == 'block'): %} - meta l4proto { tcp, udp } ip saddr @acl_ip counter return - meta l4proto { tcp, udp } ip6 saddr @acl_ip6 counter return - meta l4proto { tcp, udp } ether saddr @acl_mac counter return - meta l4proto { tcp, udp } iifname @acl_device counter return - meta l4proto { tcp, udp } meta mark set {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept + {% for (let access_control in lan_access_control): %} + {% if (access_control['enabled']): %} + {% if (length(access_control['ip']) == 0 && length(access_control['ip6']) == 0 && length(access_control['mac']) == 0): %} + meta l4proto { tcp, udp } {% if (access_control.proxy == '1'): %} meta mark set {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept {% else %} counter return {% endif %} + + {% else %} + {% if (length(access_control['ip']) > 0): %} + meta l4proto { tcp, udp } ip saddr { {% for (let ip in access_control['ip']): %} {{ ip }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tproxy_fw_mark }} tproxy ip to :{{ tproxy_port }} counter accept {% else %} counter return {% endif %} + {% endif %} + {% if (length(access_control['ip6']) > 0): %} + meta l4proto { tcp, udp } ip6 saddr { {% for (let ip6 in access_control['ip6']): %} {{ ip6 }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tproxy_fw_mark }} tproxy ip6 to :{{ tproxy_port }} counter accept {% else %} counter return {% endif %} + + {% endif %} + {% if (length(access_control['mac']) > 0): %} + meta l4proto { tcp, udp } ether saddr { {% for (let mac in access_control['mac']): %} {{ mac }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept {% else %} counter return {% endif %} + + {% endif %} + {% endif %} + {% endif %} + {% endfor %} } chain lan_tun { - {% if (access_control_mode == 'all'): %} - meta l4proto { tcp, udp } meta mark set {{ tun_fw_mark }} counter - {% elif (access_control_mode == 'allow'): %} - meta l4proto { tcp, udp } ip saddr @acl_ip meta mark set {{ tun_fw_mark }} counter - meta l4proto { tcp, udp } ip6 saddr @acl_ip6 meta mark set {{ tun_fw_mark }} counter - meta l4proto { tcp, udp } ether saddr @acl_mac meta mark set {{ tun_fw_mark }} counter - meta l4proto { tcp, udp } iifname @acl_device meta mark set {{ tun_fw_mark }} counter - {% elif (access_control_mode == 'block'): %} - meta l4proto { tcp, udp } ip saddr @acl_ip counter return - meta l4proto { tcp, udp } ip6 saddr @acl_ip6 counter return - meta l4proto { tcp, udp } ether saddr @acl_mac counter return - meta l4proto { tcp, udp } iifname @acl_device counter return - meta l4proto { tcp, udp } meta mark set {{ tun_fw_mark }} counter + {% for (let access_control in lan_access_control): %} + {% if (access_control['enabled']): %} + {% if (length(access_control['ip']) == 0 && length(access_control['ip6']) == 0 && length(access_control['mac']) == 0): %} + meta l4proto { tcp, udp } {% if (access_control.proxy == '1'): %} meta mark set {{ tun_fw_mark }} counter accept {% else %}counter return {% endif %} + + {% else %} + {% if (length(access_control['ip']) > 0): %} + meta l4proto { tcp, udp } ip saddr { {% for (let ip in access_control['ip']): %} {{ ip }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tun_fw_mark }} counter accept {% else %}counter return {% endif %} + {% endif %} + {% if (length(access_control['ip6']) > 0): %} + meta l4proto { tcp, udp } ip6 saddr { {% for (let ip6 in access_control['ip6']): %} {{ ip6 }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tun_fw_mark }} counter accept {% else %}counter return {% endif %} + + {% endif %} + {% if (length(access_control['mac']) > 0): %} + meta l4proto { tcp, udp } ether saddr { {% for (let mac in access_control['mac']): %} {{ mac }}, {% endfor %} } {% if (access_control.proxy == '1'): %} meta mark set {{ tun_fw_mark }} counter accept {% else %}counter return {% endif %} + + {% endif %} + {% endif %} + {% endif %} + {% endfor %} } {% if (router_proxy): %} chain nat_output { type nat hook output priority filter; policy accept; {% if (cgroups_version == 1): %} - meta cgroup @bypass_cgroup counter return + meta cgroup {{ cgroup_id }} counter return {% elif (cgroups_version == 2): %} - socket cgroupv2 level 2 @bypass_cgroup counter return + socket cgroupv2 level 2 services/{{ cgroup_name }} counter return {% endif %} - meta skuid @bypass_user counter return - meta skgid @bypass_group counter return - meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 counter redirect to :{{ dns_port }} - {% if (tcp_transparent_proxy_mode == 'redirect'): %} + meta nfproto @dns_hijack_nfproto jump router_dns_hijack + {% if (tcp_mode == 'redirect'): %} fib daddr type { local, multicast, broadcast, anycast } counter return ct direction reply counter return ip daddr @reserved_ip counter return @@ -361,7 +393,7 @@ table inet nikki { meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return meta l4proto { tcp, udp } ip dscp @bypass_dscp ip daddr != {{ fake_ip_range }} counter return meta l4proto { tcp, udp } ip6 dscp @bypass_dscp counter return - meta nfproto @proxy_nfproto meta l4proto tcp counter redirect to :{{ redir_port }} + meta nfproto @proxy_nfproto jump router_redirect {% endif %} {% if (fake_ip_ping_hijack): %} ip protocol icmp icmp type echo-request ip daddr {{ fake_ip_range }} counter redirect @@ -371,12 +403,10 @@ table inet nikki { chain mangle_output { type route hook output priority mangle; policy accept; {% if (cgroups_version == 1): %} - meta cgroup @bypass_cgroup counter return + meta cgroup {{ cgroup_id }} counter return {% elif (cgroups_version == 2): %} - socket cgroupv2 level 2 @bypass_cgroup counter return + socket cgroupv2 level 2 services/{{ cgroup_name }} counter return {% endif %} - meta skuid @bypass_user counter return - meta skgid @bypass_group counter return fib daddr type { local, multicast, broadcast, anycast } counter return ct direction reply counter return ip daddr @reserved_ip counter return @@ -388,25 +418,25 @@ table inet nikki { meta l4proto { tcp, udp } ip dscp @bypass_dscp ip daddr != {{ fake_ip_range }} counter return meta l4proto { tcp, udp } ip6 dscp @bypass_dscp counter return meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 counter return - {% if (tcp_transparent_proxy_mode == 'tproxy'): %} - meta nfproto @proxy_nfproto meta l4proto tcp meta mark set {{ tproxy_fw_mark }} counter - {% elif (tcp_transparent_proxy_mode == 'tun'): %} - meta nfproto @proxy_nfproto meta l4proto tcp meta mark set {{ tun_fw_mark }} counter + {% if (tcp_mode == 'tproxy'): %} + meta nfproto @proxy_nfproto meta l4proto tcp jump router_tproxy + {% elif (tcp_mode == 'tun'): %} + meta nfproto @proxy_nfproto meta l4proto tcp jump router_tun {% endif %} - {% if (udp_transparent_proxy_mode == 'tproxy'): %} - meta nfproto @proxy_nfproto meta l4proto udp meta mark set {{ tproxy_fw_mark }} counter - {% elif (udp_transparent_proxy_mode == 'tun'): %} - meta nfproto @proxy_nfproto meta l4proto udp meta mark set {{ tun_fw_mark }} counter + {% if (udp_mode == 'tproxy'): %} + meta nfproto @proxy_nfproto meta l4proto udp jump router_tproxy + {% elif (udp_mode == 'tun'): %} + meta nfproto @proxy_nfproto meta l4proto udp jump router_tun {% endif %} } chain mangle_prerouting_router { type filter hook prerouting priority mangle - 1; policy accept; - {% if (tcp_transparent_proxy_mode == 'tproxy' || udp_transparent_proxy_mode == 'tproxy'): %} - meta l4proto { tcp, udp } iifname lo meta mark {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept + {% if (tcp_mode == 'tproxy' || udp_mode == 'tproxy'): %} + iifname lo meta l4proto { tcp, udp } meta mark {{ tproxy_fw_mark }} tproxy to :{{ tproxy_port }} counter accept {% endif %} - {% if (tcp_transparent_proxy_mode == 'tun' || udp_transparent_proxy_mode == 'tun'): %} - meta l4proto { tcp, udp } iifname {{ tun_device }} counter accept + {% if (tcp_mode == 'tun' || udp_mode == 'tun'): %} + iifname {{ tun_device }} meta l4proto { icmp, tcp, udp } counter accept {% endif %} } {% endif %} @@ -414,8 +444,8 @@ table inet nikki { {% if (lan_proxy): %} chain dstnat { type nat hook prerouting priority dstnat + 1; policy accept; - meta nfproto @dns_hijack_nfproto jump lan_dns_hijack - {% if (tcp_transparent_proxy_mode == 'redirect'): %} + iifname @lan_inbound_device meta nfproto @dns_hijack_nfproto jump lan_dns_hijack + {% if (tcp_mode == 'redirect'): %} fib daddr type { local, multicast, broadcast, anycast } counter return ct direction reply counter return ip daddr @reserved_ip counter return @@ -426,7 +456,7 @@ table inet nikki { meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return meta l4proto { tcp, udp } ip dscp @bypass_dscp ip daddr != {{ fake_ip_range }} counter return meta l4proto { tcp, udp } ip6 dscp @bypass_dscp counter return - meta nfproto @proxy_nfproto jump lan_redirect + iifname @lan_inbound_device meta nfproto @proxy_nfproto jump lan_redirect {% endif %} {% if (fake_ip_ping_hijack): %} ip protocol icmp icmp type echo-request ip daddr {{ fake_ip_range }} counter redirect @@ -446,15 +476,15 @@ table inet nikki { meta l4proto { tcp, udp } ip dscp @bypass_dscp ip daddr != {{ fake_ip_range }} counter return meta l4proto { tcp, udp } ip6 dscp @bypass_dscp counter return meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 counter return - {% if (tcp_transparent_proxy_mode == 'tproxy'): %} - meta nfproto @proxy_nfproto meta l4proto tcp jump lan_tproxy - {% elif (tcp_transparent_proxy_mode == 'tun'): %} - meta nfproto @proxy_nfproto meta l4proto tcp jump lan_tun + {% if (tcp_mode == 'tproxy'): %} + iifname @lan_inbound_device meta nfproto @proxy_nfproto meta l4proto tcp jump lan_tproxy + {% elif (tcp_mode == 'tun'): %} + iifname @lan_inbound_device meta nfproto @proxy_nfproto meta l4proto tcp jump lan_tun {% endif %} - {% if (udp_transparent_proxy_mode == 'tproxy'): %} - meta nfproto @proxy_nfproto meta l4proto udp jump lan_tproxy - {% elif (udp_transparent_proxy_mode == 'tun'): %} - meta nfproto @proxy_nfproto meta l4proto udp jump lan_tun + {% if (udp_mode == 'tproxy'): %} + iifname @lan_inbound_device meta nfproto @proxy_nfproto meta l4proto udp jump lan_tproxy + {% elif (udp_mode == 'tun'): %} + iifname @lan_inbound_device meta nfproto @proxy_nfproto meta l4proto udp jump lan_tun {% endif %} } {% endif %} diff --git a/nikki/files/ucode/mixin.uc b/nikki/files/ucode/mixin.uc index 427a24467..5484cf257 100644 --- a/nikki/files/ucode/mixin.uc +++ b/nikki/files/ucode/mixin.uc @@ -47,7 +47,7 @@ if (uci_bool(uci.get('nikki', 'mixin', 'authentication'))) { } config['tun'] = {}; -if (uci.get('nikki', 'proxy', 'tcp_transparent_proxy_mode') == 'tun' || uci.get('nikki', 'proxy', 'udp_transparent_proxy_mode') == 'tun') { +if (uci.get('nikki', 'proxy', 'tcp_mode') == 'tun' || uci.get('nikki', 'proxy', 'udp_mode') == 'tun') { config['tun']['enable'] = true; config['tun']['auto-route'] = false; config['tun']['auto-redirect'] = false;