From 0386731fe034bfc50d765243c6fa2695bb9bc108 Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Thu, 12 Dec 2024 19:38:28 +0100 Subject: [PATCH] Update On Thu Dec 12 19:38:28 CET 2024 --- .github/update.log | 1 + clash-meta/component/sniffer/dispatcher.go | 26 +- clash-meta/component/sniffer/tls_sniffer.go | 19 +- clash-nyanpasu/frontend/nyanpasu/package.json | 4 +- clash-nyanpasu/pnpm-lock.yaml | 20 +- filebrowser/tools/yarn.lock | 6 +- .../dts/mt7622-xiaomi-redmi-router-ax6s.dts | 6 +- lede/target/linux/mediatek/image/mt7622.mk | 2 +- mihomo/component/sniffer/dispatcher.go | 26 +- mihomo/component/sniffer/tls_sniffer.go | 19 +- nekobox-android/.github/workflows/release.yml | 8 +- .../sagernet/database/ProfileManager.kt | 2 +- .../nekohasekai/sagernet/fmt/ConfigBuilder.kt | 88 +++--- .../sagernet/fmt/v2ray/V2RayFmt.kt | 12 +- .../nekohasekai/sagernet/group/RawUpdater.kt | 6 +- .../nekohasekai/sagernet/ui/AssetsActivity.kt | 3 +- .../nekohasekai/sagernet/ui/MainActivity.kt | 2 +- .../nekohasekai/sagernet/utils/Cloudflare.kt | 6 +- .../moe/matsuri/nb4a/SingBoxOptionsUtil.kt | 3 +- .../main/java/moe/matsuri/nb4a/utils/Util.kt | 56 +++- nekobox-android/libcore/build.sh | 1 + nekobox-android/libcore/fix.go | 12 + nekobox-android/libcore/http.go | 20 +- nekobox-android/nb4a.properties | 4 +- openwrt-packages/alist/Makefile | 8 +- .../luasrc/controller/passwall.lua | 21 ++ .../model/cbi/passwall/client/global.lua | 3 - .../model/cbi/passwall/client/rule_list.lua | 84 ++--- .../luasrc/view/passwall/rule_list/js.htm | 49 ++- .../luci-app-passwall/po/zh-cn/passwall.po | 10 +- .../root/usr/share/passwall/app.sh | 102 +++--- .../root/usr/share/passwall/helper_dnsmasq.sh | 92 +----- .../usr/share/passwall/helper_dnsmasq_add.lua | 2 - .../root/usr/share/passwall/iptables.sh | 143 +++++---- .../root/usr/share/passwall/nftables.sh | 139 ++++---- .../Auto compile with openwrt sdk.yml | 7 +- openwrt-passwall2/luci-app-passwall2/Makefile | 12 +- .../model/cbi/passwall2/client/other.lua | 1 + .../luasrc/passwall2/util_sing-box.lua | 12 + .../luasrc/passwall2/util_xray.lua | 12 + .../root/usr/share/passwall2/0_default_config | 1 + .../root/usr/share/passwall2/app.sh | 23 ++ .../root/usr/share/passwall2/iptables.sh | 208 +++++++----- .../root/usr/share/passwall2/nftables.sh | 209 +++++++----- sing-box/.github/workflows/build.yml | 104 ++---- sing-box/Makefile | 20 +- sing-box/clients/android/app/build.gradle | 31 +- .../sfa/bg/DefaultNetworkMonitor.kt | 23 +- .../nekohasekai/sfa/bg/UpdateProfileWork.kt | 16 +- .../java/io/nekohasekai/sfa/ktx/Wrappers.kt | 7 + .../io/nekohasekai/sfa/ui/MainActivity.kt | 20 -- .../sfa/ui/main/SettingsFragment.kt | 5 +- .../sfa/ui/main/SettingsFragment0.kt | 9 - .../sfa/ui/profile/EditProfileActivity.kt | 15 +- .../ui/profile/EditProfileContentActivity.kt | 3 +- .../ui/settings/AbstractSettingsFragment.kt | 27 -- .../sfa/ui/settings/CoreFragment.kt | 6 - .../nekohasekai/sfa/ui/settings/Preference.kt | 45 --- .../io/nekohasekai/sfa/utils/HTTPClient.kt | 3 +- .../res/layout/fragment_settings_core.xml | 6 - .../main/res/navigation/mobile_navigation.xml | 5 - .../app/src/main/res/values/strings.xml | 1 - .../src/main/res/xml/preferences_settings.xml | 9 - sing-box/clients/android/build.gradle | 8 +- sing-box/clients/android/gradle.properties | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 4 +- sing-box/clients/android/version.properties | 6 +- .../Views/Dashboard/DashboardView.swift | 2 +- .../Views/Profile/EditProfileView.swift | 1 + .../Library/Database/Profile+Update.swift | 19 +- .../Library/Network/ExtensionProvider.swift | 3 +- .../apple/Library/Network/HTTPClient.swift | 8 +- .../apple/sing-box.xcodeproj/project.pbxproj | 24 +- .../cmd/internal/app_store_connect/main.go | 299 ++++++++++++++++++ sing-box/cmd/internal/build_libbox/main.go | 18 +- sing-box/cmd/internal/build_shared/tag.go | 8 - sing-box/cmd/internal/read_tag/main.go | 18 +- sing-box/docs/changelog.md | 10 +- sing-box/go.mod | 4 + sing-box/go.sum | 10 + .../model/cbi/passwall/client/global.lua | 3 - small/luci-app-passwall/po/zh-cn/passwall.po | 3 - .../root/usr/share/passwall/app.sh | 102 +++--- .../root/usr/share/passwall/helper_dnsmasq.sh | 92 +----- .../usr/share/passwall/helper_dnsmasq_add.lua | 2 - .../root/usr/share/passwall/iptables.sh | 143 +++++---- .../root/usr/share/passwall/nftables.sh | 139 ++++---- small/luci-app-passwall2/Makefile | 12 +- .../model/cbi/passwall2/client/other.lua | 1 + .../luasrc/passwall2/util_sing-box.lua | 12 + .../luasrc/passwall2/util_xray.lua | 12 + .../root/usr/share/passwall2/0_default_config | 1 + .../root/usr/share/passwall2/app.sh | 23 ++ .../root/usr/share/passwall2/iptables.sh | 208 +++++++----- .../root/usr/share/passwall2/nftables.sh | 209 +++++++----- .../transport/internet/splithttp/client.go | 5 +- .../transport/internet/splithttp/dialer.go | 62 ++-- yt-dlp/yt_dlp/extractor/patreon.py | 22 +- yt-dlp/yt_dlp/extractor/soundcloud.py | 2 + yt-dlp/yt_dlp/extractor/youtube.py | 3 +- 100 files changed, 1931 insertions(+), 1414 deletions(-) create mode 100644 nekobox-android/libcore/fix.go delete mode 100644 sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/SettingsFragment0.kt delete mode 100644 sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/AbstractSettingsFragment.kt delete mode 100644 sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/CoreFragment.kt delete mode 100644 sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/Preference.kt delete mode 100644 sing-box/clients/android/app/src/main/res/layout/fragment_settings_core.xml delete mode 100644 sing-box/clients/android/app/src/main/res/xml/preferences_settings.xml create mode 100644 sing-box/cmd/internal/app_store_connect/main.go diff --git a/.github/update.log b/.github/update.log index 8f1d38f2b9..1e0371fb69 100644 --- a/.github/update.log +++ b/.github/update.log @@ -849,3 +849,4 @@ Update On Thu Dec 5 19:36:56 CET 2024 Update On Fri Dec 6 19:37:02 CET 2024 Update On Sat Dec 7 19:36:20 CET 2024 Update On Thu Dec 12 11:40:54 CET 2024 +Update On Thu Dec 12 19:38:19 CET 2024 diff --git a/clash-meta/component/sniffer/dispatcher.go b/clash-meta/component/sniffer/dispatcher.go index f198c4aebb..ada4317686 100644 --- a/clash-meta/component/sniffer/dispatcher.go +++ b/clash-meta/component/sniffer/dispatcher.go @@ -145,6 +145,10 @@ func (sd *Dispatcher) Enable() bool { } func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (string, error) { + //defer func(start time.Time) { + // log.Debugln("[Sniffer] [%s] Sniffing took %s", metadata.DstIP, time.Since(start)) + //}(time.Now()) + for s := range sd.sniffers { if s.SupportNetwork() == C.TCP && s.SupportPort(metadata.DstPort) { _ = conn.SetReadDeadline(time.Now().Add(1 * time.Second)) @@ -154,7 +158,7 @@ func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (s _, ok := err.(*net.OpError) if ok { sd.cacheSniffFailed(metadata) - log.Errorln("[Sniffer] [%s] may not have any sent data, Consider adding skip", metadata.DstIP.String()) + log.Errorln("[Sniffer] [%s] [%s] may not have any sent data, Consider adding skip", metadata.DstIP, s.Protocol()) _ = conn.Close() } @@ -164,22 +168,36 @@ func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (s bufferedLen := conn.Buffered() bytes, err := conn.Peek(bufferedLen) if err != nil { - log.Debugln("[Sniffer] the data length not enough") + log.Debugln("[Sniffer] [%s] [%s] the data length not enough, error: %v", metadata.DstIP, s.Protocol(), err) continue } host, err := s.SniffData(bytes) + var e *errNeedAtLeastData + if errors.As(err, &e) { + //log.Debugln("[Sniffer] [%s] [%s] %v, got length: %d", metadata.DstIP, s.Protocol(), e, len(bytes)) + _ = conn.SetReadDeadline(time.Now().Add(1 * time.Second)) + bytes, err = conn.Peek(e.length) + _ = conn.SetReadDeadline(time.Time{}) + //log.Debugln("[Sniffer] [%s] [%s] try again, got length: %d", metadata.DstIP, s.Protocol(), len(bytes)) + if err != nil { + log.Debugln("[Sniffer] [%s] [%s] the data length not enough, error: %v", metadata.DstIP, s.Protocol(), err) + continue + } + host, err = s.SniffData(bytes) + } if err != nil { - //log.Debugln("[Sniffer] [%s] Sniff data failed %s", s.Protocol(), metadata.DstIP) + //log.Debugln("[Sniffer] [%s] [%s] Sniff data failed, error: %v", metadata.DstIP, s.Protocol(), err) continue } _, err = netip.ParseAddr(host) if err == nil { - //log.Debugln("[Sniffer] [%s] Sniff data failed %s", s.Protocol(), metadata.DstIP) + //log.Debugln("[Sniffer] [%s] [%s] Sniff data failed, got host [%s]", metadata.DstIP, s.Protocol(), host) continue } + //log.Debugln("[Sniffer] [%s] [%s] Sniffed [%s]", metadata.DstIP, s.Protocol(), host) return host, nil } } diff --git a/clash-meta/component/sniffer/tls_sniffer.go b/clash-meta/component/sniffer/tls_sniffer.go index 974df79a5b..b57f36ec88 100644 --- a/clash-meta/component/sniffer/tls_sniffer.go +++ b/clash-meta/component/sniffer/tls_sniffer.go @@ -3,6 +3,7 @@ package sniffer import ( "encoding/binary" "errors" + "fmt" "strings" "github.com/metacubex/mihomo/common/utils" @@ -15,6 +16,19 @@ var ( errNotClientHello = errors.New("not client hello") ) +type errNeedAtLeastData struct { + length int + err error +} + +func (e *errNeedAtLeastData) Error() string { + return fmt.Sprintf("%v, need at least length: %d", e.err, e.length) +} + +func (e *errNeedAtLeastData) Unwrap() error { + return e.err +} + var _ sniffer.Sniffer = (*TLSSniffer)(nil) type TLSSniffer struct { @@ -160,7 +174,10 @@ func SniffTLS(b []byte) (*string, error) { } headerLen := int(binary.BigEndian.Uint16(b[3:5])) if 5+headerLen > len(b) { - return nil, ErrNoClue + return nil, &errNeedAtLeastData{ + length: 5 + headerLen, + err: ErrNoClue, + } } domain, err := ReadClientHello(b[5 : 5+headerLen]) diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index d2727bdb70..d7e1cf6a24 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -52,11 +52,11 @@ "@csstools/normalize.css": "12.1.1", "@emotion/babel-plugin": "11.13.5", "@emotion/react": "11.13.5", - "@iconify/json": "2.2.281", + "@iconify/json": "2.2.282", "@monaco-editor/react": "4.6.0", "@tanstack/react-router": "1.87.9", "@tanstack/router-devtools": "1.87.9", - "@tanstack/router-plugin": "1.87.7", + "@tanstack/router-plugin": "1.87.11", "@tauri-apps/plugin-clipboard-manager": "2.2.0", "@tauri-apps/plugin-dialog": "2.2.0", "@tauri-apps/plugin-fs": "2.2.0", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 81e402066e..e8c4c6d8a6 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -305,8 +305,8 @@ importers: specifier: 11.13.5 version: 11.13.5(react@19.0.0-rc.1)(types-react@19.0.0-rc.1) '@iconify/json': - specifier: 2.2.281 - version: 2.2.281 + specifier: 2.2.282 + version: 2.2.282 '@monaco-editor/react': specifier: 4.6.0 version: 4.6.0(monaco-editor@0.52.2)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) @@ -317,8 +317,8 @@ importers: specifier: 1.87.9 version: 1.87.9(@tanstack/react-router@1.87.9(@tanstack/router-generator@1.87.7)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1))(csstype@3.1.3)(react-dom@19.0.0-rc.1(react@19.0.0-rc.1))(react@19.0.0-rc.1) '@tanstack/router-plugin': - specifier: 1.87.7 - version: 1.87.7(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)) + specifier: 1.87.11 + version: 1.87.11(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1)) '@tauri-apps/plugin-clipboard-manager': specifier: 2.2.0 version: 2.2.0 @@ -1716,8 +1716,8 @@ packages: '@vue/compiler-sfc': optional: true - '@iconify/json@2.2.281': - resolution: {integrity: sha512-4AjvOQzMHiKa4n4MxQ3IxwWBRF564TMFQwYYP+OY83afINJttbD4rZvSA/wACgZL7jntsd3NDZ9CwJOVkFRaFQ==} + '@iconify/json@2.2.282': + resolution: {integrity: sha512-G3PMvBEziGL8sbf6I2etaS7C0BFk+8swLhvzas3CBEubFmd8CSkbYbV6AwChgDRCcTTVgZ/ls7UALh69ohsGGQ==} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -2707,8 +2707,8 @@ packages: resolution: {integrity: sha512-w9Px1C6DM0YNVXvu1VjUuZ5el0ykOeofEmEZBW83VUTzvCXFpcjPCHncU9FO9uXup8NFIxNfGz+xpwf93GoFnQ==} engines: {node: '>=12'} - '@tanstack/router-plugin@1.87.7': - resolution: {integrity: sha512-3QdDyanjZkGW9yqqiDbjrFIEnrDpJGydNB5pawTbv2UsWO3vXQfzFY6wYuUZGjbXjXxXZ+C0H2f/igIP0dDDqg==} + '@tanstack/router-plugin@1.87.11': + resolution: {integrity: sha512-mg8Ci9IT2H5aDBM6DippwKr1AHTBc6eudgpvHRMelGxLl4VY7vlKNx5Ds5yZeqE9Jp6VNr2z7E0xx70e8cFoBg==} engines: {node: '>=12'} peerDependencies: '@rsbuild/core': '>=1.0.2' @@ -9069,7 +9069,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@iconify/json@2.2.281': + '@iconify/json@2.2.282': dependencies: '@iconify/types': 2.0.0 pathe: 1.1.2 @@ -10037,7 +10037,7 @@ snapshots: tsx: 4.19.2 zod: 3.23.8 - '@tanstack/router-plugin@1.87.7(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))': + '@tanstack/router-plugin@1.87.11(vite@6.0.3(@types/node@22.10.2)(jiti@2.4.0)(less@4.2.0)(sass-embedded@1.78.0)(sass@1.82.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.2)(yaml@2.5.1))': dependencies: '@babel/core': 7.26.0 '@babel/generator': 7.26.3 diff --git a/filebrowser/tools/yarn.lock b/filebrowser/tools/yarn.lock index 1802db10d1..4ac3bd1626 100644 --- a/filebrowser/tools/yarn.lock +++ b/filebrowser/tools/yarn.lock @@ -535,9 +535,9 @@ create-require@^1.1.0: integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" diff --git a/lede/target/linux/mediatek/dts/mt7622-xiaomi-redmi-router-ax6s.dts b/lede/target/linux/mediatek/dts/mt7622-xiaomi-redmi-router-ax6s.dts index fccf8348c7..035393e28e 100644 --- a/lede/target/linux/mediatek/dts/mt7622-xiaomi-redmi-router-ax6s.dts +++ b/lede/target/linux/mediatek/dts/mt7622-xiaomi-redmi-router-ax6s.dts @@ -298,7 +298,7 @@ */ partition@2c0000 { label = "kernel"; - reg = <0x2c0000 0x400000>; + reg = <0x2c0000 0x600000>; }; /* ubi partition is the result of squashing @@ -308,9 +308,9 @@ * - overlay * - obr */ - partition@6c0000 { + partition@8c0000 { label = "ubi"; - reg = <0x6C0000 0x6f00000>; + reg = <0x8c0000 0x6d00000>; }; }; }; diff --git a/lede/target/linux/mediatek/image/mt7622.mk b/lede/target/linux/mediatek/image/mt7622.mk index 3bd8bcb158..2196f57436 100644 --- a/lede/target/linux/mediatek/image/mt7622.mk +++ b/lede/target/linux/mediatek/image/mt7622.mk @@ -345,7 +345,7 @@ define Device/xiaomi_redmi-router-ax6s IMAGES += factory.bin BLOCKSIZE := 128k PAGESIZE := 2048 - KERNEL_SIZE := 4096k + KERNEL_SIZE := 6144k KERNEL_INITRAMFS_SUFFIX := -recovery.itb IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata diff --git a/mihomo/component/sniffer/dispatcher.go b/mihomo/component/sniffer/dispatcher.go index f198c4aebb..ada4317686 100644 --- a/mihomo/component/sniffer/dispatcher.go +++ b/mihomo/component/sniffer/dispatcher.go @@ -145,6 +145,10 @@ func (sd *Dispatcher) Enable() bool { } func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (string, error) { + //defer func(start time.Time) { + // log.Debugln("[Sniffer] [%s] Sniffing took %s", metadata.DstIP, time.Since(start)) + //}(time.Now()) + for s := range sd.sniffers { if s.SupportNetwork() == C.TCP && s.SupportPort(metadata.DstPort) { _ = conn.SetReadDeadline(time.Now().Add(1 * time.Second)) @@ -154,7 +158,7 @@ func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (s _, ok := err.(*net.OpError) if ok { sd.cacheSniffFailed(metadata) - log.Errorln("[Sniffer] [%s] may not have any sent data, Consider adding skip", metadata.DstIP.String()) + log.Errorln("[Sniffer] [%s] [%s] may not have any sent data, Consider adding skip", metadata.DstIP, s.Protocol()) _ = conn.Close() } @@ -164,22 +168,36 @@ func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (s bufferedLen := conn.Buffered() bytes, err := conn.Peek(bufferedLen) if err != nil { - log.Debugln("[Sniffer] the data length not enough") + log.Debugln("[Sniffer] [%s] [%s] the data length not enough, error: %v", metadata.DstIP, s.Protocol(), err) continue } host, err := s.SniffData(bytes) + var e *errNeedAtLeastData + if errors.As(err, &e) { + //log.Debugln("[Sniffer] [%s] [%s] %v, got length: %d", metadata.DstIP, s.Protocol(), e, len(bytes)) + _ = conn.SetReadDeadline(time.Now().Add(1 * time.Second)) + bytes, err = conn.Peek(e.length) + _ = conn.SetReadDeadline(time.Time{}) + //log.Debugln("[Sniffer] [%s] [%s] try again, got length: %d", metadata.DstIP, s.Protocol(), len(bytes)) + if err != nil { + log.Debugln("[Sniffer] [%s] [%s] the data length not enough, error: %v", metadata.DstIP, s.Protocol(), err) + continue + } + host, err = s.SniffData(bytes) + } if err != nil { - //log.Debugln("[Sniffer] [%s] Sniff data failed %s", s.Protocol(), metadata.DstIP) + //log.Debugln("[Sniffer] [%s] [%s] Sniff data failed, error: %v", metadata.DstIP, s.Protocol(), err) continue } _, err = netip.ParseAddr(host) if err == nil { - //log.Debugln("[Sniffer] [%s] Sniff data failed %s", s.Protocol(), metadata.DstIP) + //log.Debugln("[Sniffer] [%s] [%s] Sniff data failed, got host [%s]", metadata.DstIP, s.Protocol(), host) continue } + //log.Debugln("[Sniffer] [%s] [%s] Sniffed [%s]", metadata.DstIP, s.Protocol(), host) return host, nil } } diff --git a/mihomo/component/sniffer/tls_sniffer.go b/mihomo/component/sniffer/tls_sniffer.go index 974df79a5b..b57f36ec88 100644 --- a/mihomo/component/sniffer/tls_sniffer.go +++ b/mihomo/component/sniffer/tls_sniffer.go @@ -3,6 +3,7 @@ package sniffer import ( "encoding/binary" "errors" + "fmt" "strings" "github.com/metacubex/mihomo/common/utils" @@ -15,6 +16,19 @@ var ( errNotClientHello = errors.New("not client hello") ) +type errNeedAtLeastData struct { + length int + err error +} + +func (e *errNeedAtLeastData) Error() string { + return fmt.Sprintf("%v, need at least length: %d", e.err, e.length) +} + +func (e *errNeedAtLeastData) Unwrap() error { + return e.err +} + var _ sniffer.Sniffer = (*TLSSniffer)(nil) type TLSSniffer struct { @@ -160,7 +174,10 @@ func SniffTLS(b []byte) (*string, error) { } headerLen := int(binary.BigEndian.Uint16(b[3:5])) if 5+headerLen > len(b) { - return nil, ErrNoClue + return nil, &errNeedAtLeastData{ + length: 5 + headerLen, + err: ErrNoClue, + } } domain, err := ReadClientHello(b[5 : 5+headerLen]) diff --git a/nekobox-android/.github/workflows/release.yml b/nekobox-android/.github/workflows/release.yml index 8edda11ce7..709494de97 100644 --- a/nekobox-android/.github/workflows/release.yml +++ b/nekobox-android/.github/workflows/release.yml @@ -3,13 +3,13 @@ on: workflow_dispatch: inputs: tag: - description: 'Release Tag' + description: "Release Tag" required: true publish: - description: 'Publish: If want ignore' + description: "Publish: If want ignore" required: false play: - description: 'Play: If want ignore' + description: "Play: If want ignore" required: false jobs: libcore: @@ -33,7 +33,7 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' uses: actions/setup-go@v5 with: - go-version: ^1.21 + go-version: "1.22.10" - name: Native Build if: steps.cache.outputs.cache-hit != 'true' run: ./run lib core diff --git a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/database/ProfileManager.kt b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/database/ProfileManager.kt index bf924156d3..8049cf89ad 100644 --- a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/database/ProfileManager.kt +++ b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/database/ProfileManager.kt @@ -225,7 +225,7 @@ object ProfileManager { if (country == "cn") createRule( RuleEntity( name = app.getString(R.string.route_play_store, displayCountry), - domains = "domain:googleapis.cn", + domains = "googleapis.cn", ), false ) createRule( diff --git a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt index 8137c6d391..c4b59fde47 100644 --- a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt +++ b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt @@ -1,7 +1,11 @@ package io.nekohasekai.sagernet.fmt import android.widget.Toast -import io.nekohasekai.sagernet.* +import io.nekohasekai.sagernet.IPv6Mode +import io.nekohasekai.sagernet.Key +import io.nekohasekai.sagernet.R +import io.nekohasekai.sagernet.SagerNet +import io.nekohasekai.sagernet.TunImplementation import io.nekohasekai.sagernet.bg.VpnService import io.nekohasekai.sagernet.database.DataStore import io.nekohasekai.sagernet.database.ProxyEntity @@ -23,11 +27,32 @@ import io.nekohasekai.sagernet.fmt.v2ray.StandardV2RayBean import io.nekohasekai.sagernet.fmt.v2ray.buildSingBoxOutboundStandardV2RayBean import io.nekohasekai.sagernet.fmt.wireguard.WireGuardBean import io.nekohasekai.sagernet.fmt.wireguard.buildSingBoxOutboundWireguardBean -import io.nekohasekai.sagernet.ktx.isIpAddress import io.nekohasekai.sagernet.ktx.mkPort import io.nekohasekai.sagernet.utils.PackageCache -import moe.matsuri.nb4a.* -import moe.matsuri.nb4a.SingBoxOptions.* +import moe.matsuri.nb4a.Protocols +import moe.matsuri.nb4a.SingBoxOptions.CacheFile +import moe.matsuri.nb4a.SingBoxOptions.ClashAPIOptions +import moe.matsuri.nb4a.SingBoxOptions.DNSFakeIPOptions +import moe.matsuri.nb4a.SingBoxOptions.DNSOptions +import moe.matsuri.nb4a.SingBoxOptions.DNSRule_DefaultOptions +import moe.matsuri.nb4a.SingBoxOptions.DNSServerOptions +import moe.matsuri.nb4a.SingBoxOptions.ExperimentalOptions +import moe.matsuri.nb4a.SingBoxOptions.Inbound_DirectOptions +import moe.matsuri.nb4a.SingBoxOptions.Inbound_MixedOptions +import moe.matsuri.nb4a.SingBoxOptions.Inbound_TunOptions +import moe.matsuri.nb4a.SingBoxOptions.LogOptions +import moe.matsuri.nb4a.SingBoxOptions.MultiplexOptions +import moe.matsuri.nb4a.SingBoxOptions.MyOptions +import moe.matsuri.nb4a.SingBoxOptions.Outbound +import moe.matsuri.nb4a.SingBoxOptions.Outbound_SelectorOptions +import moe.matsuri.nb4a.SingBoxOptions.Outbound_SocksOptions +import moe.matsuri.nb4a.SingBoxOptions.RouteOptions +import moe.matsuri.nb4a.SingBoxOptions.RuleSet +import moe.matsuri.nb4a.SingBoxOptions.Rule_DefaultOptions +import moe.matsuri.nb4a.SingBoxOptionsUtil +import moe.matsuri.nb4a.checkEmpty +import moe.matsuri.nb4a.generateRuleSet +import moe.matsuri.nb4a.makeSingBoxRule import moe.matsuri.nb4a.plugin.Plugins import moe.matsuri.nb4a.proxy.config.ConfigBean import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSBean @@ -35,7 +60,6 @@ import moe.matsuri.nb4a.proxy.shadowtls.buildSingBoxOutboundShadowTLSBean import moe.matsuri.nb4a.utils.JavaUtil.gson import moe.matsuri.nb4a.utils.Util import moe.matsuri.nb4a.utils.listByLineOrComma -import okhttp3.HttpUrl.Companion.toHttpUrlOrNull const val TAG_MIXED = "mixed-in" @@ -132,7 +156,6 @@ fun buildConfig( }.toHashSet().toList()).associateBy { it.id } val buildSelector = !forTest && group?.isSelector == true && !forExport val userDNSRuleList = mutableListOf() - val domainListDNSDirectForce = mutableListOf() val bypassDNSBeans = hashSetOf() val isVPN = DataStore.serviceMode == Key.MODE_VPN val bind = if (!forTest && DataStore.allowAccess) "0.0.0.0" else LOCALHOST @@ -411,18 +434,16 @@ fun buildConfig( } // domain_strategy - pastEntity?.requireBean()?.apply { - // don't loopback - if (defaultServerDomainStrategy != "" && !serverAddress.isIpAddress()) { - domainListDNSDirectForce.add("full:$serverAddress") - } - } + currentOutbound["domain_strategy"] = if (forTest) "" else defaultServerDomainStrategy // custom JSON merge if (bean.customOutboundJson.isNotBlank()) { - Util.mergeJSON(bean.customOutboundJson, currentOutbound) + Util.mergeJSON( + bean.customOutboundJson, + currentOutbound as MutableMap + ) } } @@ -646,35 +667,6 @@ fun buildConfig( }.asMap()) } - // Bypass Lookup for the first profile - bypassDNSBeans.forEach { - var serverAddr = it.serverAddress - - if (it is ConfigBean) { - var config = mutableMapOf() - config = gson.fromJson(it.config, config.javaClass) - config["server"]?.apply { - serverAddr = toString() - } - } - - if (!serverAddr.isIpAddress()) { - domainListDNSDirectForce.add("full:${serverAddr}") - } - } - - remoteDns.forEach { - var address = it - if (address.contains("://")) { - address = address.substringAfter("://") - } - "https://$address".toHttpUrlOrNull()?.apply { - if (!host.isIpAddress()) { - domainListDNSDirectForce.add("full:$host") - } - } - } - // remote dns obj remoteDns.firstOrNull().let { dns.servers.add(DNSServerOptions().apply { @@ -756,13 +748,11 @@ fun buildConfig( disable_cache = true }) } - // force bypass (always top DNS rule) - if (domainListDNSDirectForce.isNotEmpty()) { - dns.rules.add(0, DNSRule_DefaultOptions().apply { - makeSingBoxRule(domainListDNSDirectForce.toHashSet().toList()) - server = "dns-direct" - }) - } + // avoid loopback (always top DNS rule) + dns.rules.add(0, DNSRule_DefaultOptions().apply { + outbound = mutableListOf("any") + server = "dns-direct" + }) } }.let { ConfigBuildResult( diff --git a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/V2RayFmt.kt b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/V2RayFmt.kt index 1007258a10..eea3698491 100644 --- a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/V2RayFmt.kt +++ b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/V2RayFmt.kt @@ -620,10 +620,14 @@ fun buildSingBoxOutboundTLS(bean: StandardV2RayBean): OutboundTLSOptions? { } } if (bean.enableECH) { - ech.enabled = true - ech.pq_signature_schemes_enabled = bean.enablePqSignature - ech.dynamic_record_sizing_disabled = bean.disabledDRS - ech.config = bean.echConfig.lines() + ech = OutboundECHOptions().apply { + enabled = true + pq_signature_schemes_enabled = bean.enablePqSignature + dynamic_record_sizing_disabled = bean.disabledDRS + if (bean.echConfig.isNotBlank()) { + config = bean.echConfig.lines() + } + } } } } diff --git a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt index c1a034a238..fc70e58c0a 100644 --- a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt +++ b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt @@ -23,6 +23,7 @@ import io.nekohasekai.sagernet.ktx.* import libcore.Libcore import moe.matsuri.nb4a.Protocols import moe.matsuri.nb4a.proxy.config.ConfigBean +import moe.matsuri.nb4a.utils.Util import org.ini4j.Ini import org.json.JSONArray import org.json.JSONObject @@ -66,10 +67,11 @@ object RawUpdater : GroupUpdater() { setURL(subscription.link) setUserAgent(subscription.customUserAgent.takeIf { it.isNotBlank() } ?: USER_AGENT) }.execute() - proxies = parseRaw(response.contentString) + proxies = parseRaw(Util.getStringBox(response.contentString)) ?: error(app.getString(R.string.no_proxies_found)) - subscription.subscriptionUserinfo = response.getHeader("Subscription-Userinfo") + subscription.subscriptionUserinfo = + Util.getStringBox(response.getHeader("Subscription-Userinfo")) } val proxiesMap = LinkedHashMap() diff --git a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/ui/AssetsActivity.kt b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/ui/AssetsActivity.kt index 0679a1e45c..d63848289b 100644 --- a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/ui/AssetsActivity.kt +++ b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/ui/AssetsActivity.kt @@ -18,6 +18,7 @@ import io.nekohasekai.sagernet.databinding.LayoutAssetsBinding import io.nekohasekai.sagernet.ktx.* import io.nekohasekai.sagernet.widget.UndoSnackbarManager import libcore.Libcore +import moe.matsuri.nb4a.utils.Util import org.json.JSONObject import java.io.File import java.io.FileWriter @@ -283,7 +284,7 @@ class AssetsActivity : ThemedActivity() { setURL("https://api.github.com/repos/$repo/releases/latest") }.execute() - val release = JSONObject(response.contentString) + val release = JSONObject(Util.getStringBox(response.contentString)) val tagName = release.optString("tag_name") if (tagName == localVersion) { diff --git a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/ui/MainActivity.kt b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/ui/MainActivity.kt index 56b31840d4..0040889a04 100644 --- a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/ui/MainActivity.kt +++ b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/ui/MainActivity.kt @@ -333,7 +333,7 @@ class MainActivity : ThemedActivity(), R.id.nav_about -> displayFragment(AboutFragment()) R.id.nav_tuiguang -> { - launchCustomTab("https://matsuricom.pages.dev/") + launchCustomTab("https://neko-box.pages.dev/喵") return false } diff --git a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/utils/Cloudflare.kt b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/utils/Cloudflare.kt index eee031f881..b70d854a06 100644 --- a/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/utils/Cloudflare.kt +++ b/nekobox-android/app/src/main/java/io/nekohasekai/sagernet/utils/Cloudflare.kt @@ -9,6 +9,7 @@ import io.nekohasekai.sagernet.utils.cf.RegisterRequest import io.nekohasekai.sagernet.utils.cf.UpdateDeviceRequest import libcore.Libcore import moe.matsuri.nb4a.utils.JavaUtil.gson +import moe.matsuri.nb4a.utils.Util // kang from wgcf object Cloudflare { @@ -37,8 +38,9 @@ object Cloudflare { setUserAgent("okhttp/3.12.1") }.execute() - Logs.d(response.contentString) - val device = gson.fromJson(response.contentString, DeviceResponse::class.java) + Logs.d(Util.getStringBox(response.contentString)) + val device = + gson.fromJson(Util.getStringBox(response.contentString), DeviceResponse::class.java) val accessToken = device.token client.newRequest().apply { diff --git a/nekobox-android/app/src/main/java/moe/matsuri/nb4a/SingBoxOptionsUtil.kt b/nekobox-android/app/src/main/java/moe/matsuri/nb4a/SingBoxOptionsUtil.kt index 97fb814ad0..90ae83a862 100644 --- a/nekobox-android/app/src/main/java/moe/matsuri/nb4a/SingBoxOptionsUtil.kt +++ b/nekobox-android/app/src/main/java/moe/matsuri/nb4a/SingBoxOptionsUtil.kt @@ -47,8 +47,7 @@ fun SingBoxOptions.DNSRule_DefaultOptions.makeSingBoxRule(list: List) { } else if (it.startsWith("keyword:")) { domain_keyword.plusAssign(it.removePrefix("keyword:").lowercase()) } else { - // https://github.com/SagerNet/sing-box/commit/5d41e328d4a9f7549dd27f11b4ccc43710a73664 - domain.plusAssign(it.lowercase()) + domain_suffix.plusAssign(it.lowercase()) } } rule_set?.removeIf { it.isNullOrBlank() } diff --git a/nekobox-android/app/src/main/java/moe/matsuri/nb4a/utils/Util.kt b/nekobox-android/app/src/main/java/moe/matsuri/nb4a/utils/Util.kt index 1f8f10731f..35df4ee61b 100644 --- a/nekobox-android/app/src/main/java/moe/matsuri/nb4a/utils/Util.kt +++ b/nekobox-android/app/src/main/java/moe/matsuri/nb4a/utils/Util.kt @@ -3,6 +3,7 @@ package moe.matsuri.nb4a.utils import android.annotation.SuppressLint import android.content.Context import android.util.Base64 +import libcore.StringBox import java.io.ByteArrayOutputStream import java.text.SimpleDateFormat import java.util.* @@ -113,19 +114,46 @@ object Util { } } - - fun mergeJSON(j: String, to: MutableMap) { - if (j.isBlank()) return - val m = JavaUtil.gson.fromJson(j, to.javaClass) - m.forEach { (k, v) -> - if (v is Map<*, *> && to[k] is Map<*, *>) { - val currentMap = (to[k] as Map<*, *>).toMutableMap() - currentMap += v - to[k] = currentMap - } else { - to[k] = v + fun map2StringMap(m: Map<*, *>): MutableMap { + val o = mutableMapOf() + m.forEach { + if (it.key is String) { + o[it.key as String] = it.value as Any } } + return o + } + + fun mergeMap(dst: MutableMap, src: Map): MutableMap { + src.forEach { (k, v) -> + if (v is Map<*, *> && dst[k] is Map<*, *>) { + val currentMap = (dst[k] as Map<*, *>).toMutableMap() + dst[k] = mergeMap(map2StringMap(currentMap), map2StringMap(v)) + } else if (v is List<*>) { + if (k.startsWith("+")) { // prepend + val dstKey = k.removePrefix("+") + var currentList = (dst[dstKey] as List<*>).toMutableList() + currentList = (v + currentList).toMutableList() + dst[dstKey] = currentList + } else if (k.endsWith("+")) { // append + val dstKey = k.removeSuffix("+") + var currentList = (dst[dstKey] as List<*>).toMutableList() + currentList = (currentList + v).toMutableList() + dst[dstKey] = currentList + } else { + dst[k] = v + } + } else { + dst[k] = v + } + } + return dst + } + + fun mergeJSON(j: String, dst: MutableMap) { + if (j.isBlank()) return + val src = JavaUtil.gson.fromJson(j, dst.javaClass) + mergeMap(dst, src) } // Format Time @@ -154,4 +182,10 @@ object Util { } } + fun getStringBox(b: StringBox?): String { + if (b != null && b.value != null) { + return b.value + } + return "" + } } diff --git a/nekobox-android/libcore/build.sh b/nekobox-android/libcore/build.sh index 22b9a7b0c7..202ef26dfe 100755 --- a/nekobox-android/libcore/build.sh +++ b/nekobox-android/libcore/build.sh @@ -1,5 +1,6 @@ #!/bin/bash +source ../../env_go.sh || true source ../buildScript/init/env_ndk.sh BUILD=".build" diff --git a/nekobox-android/libcore/fix.go b/nekobox-android/libcore/fix.go new file mode 100644 index 0000000000..ccc41c487e --- /dev/null +++ b/nekobox-android/libcore/fix.go @@ -0,0 +1,12 @@ +package libcore + +// https://github.com/golang/go/issues/46893 +// TODO: remove after `bulkBarrierPreWrite: unaligned arguments` fixed + +type StringBox struct { + Value string +} + +func wrapString(value string) *StringBox { + return &StringBox{Value: value} +} diff --git a/nekobox-android/libcore/http.go b/nekobox-android/libcore/http.go index 609faddc27..db15a9af71 100644 --- a/nekobox-android/libcore/http.go +++ b/nekobox-android/libcore/http.go @@ -45,9 +45,9 @@ type HTTPRequest interface { } type HTTPResponse interface { - GetHeader(string) string + GetHeader(string) *StringBox GetContent() ([]byte, error) - GetContentString() (string, error) + GetContentString() (*StringBox, error) WriteTo(path string) error } @@ -204,7 +204,7 @@ type httpResponse struct { } func (h *httpResponse) errorString() string { - content, err := h.GetContentString() + content, err := h.getContentString() if err != nil { return fmt.Sprint("HTTP ", h.Status) } @@ -214,8 +214,8 @@ func (h *httpResponse) errorString() string { return fmt.Sprint("HTTP ", h.Status, ": ", content) } -func (h *httpResponse) GetHeader(key string) string { - return h.Header.Get(key) +func (h *httpResponse) GetHeader(key string) *StringBox { + return wrapString(h.Header.Get(key)) } func (h *httpResponse) GetContent() ([]byte, error) { @@ -226,7 +226,15 @@ func (h *httpResponse) GetContent() ([]byte, error) { return h.content, h.contentError } -func (h *httpResponse) GetContentString() (string, error) { +func (h *httpResponse) GetContentString() (*StringBox, error) { + content, err := h.getContentString() + if err != nil { + return nil, err + } + return wrapString(content), nil +} + +func (h *httpResponse) getContentString() (string, error) { content, err := h.GetContent() if err != nil { return "", err diff --git a/nekobox-android/nb4a.properties b/nekobox-android/nb4a.properties index 44a3b8d889..86b85932ce 100644 --- a/nekobox-android/nb4a.properties +++ b/nekobox-android/nb4a.properties @@ -1,3 +1,3 @@ PACKAGE_NAME=moe.nb4a -VERSION_NAME=1.3.2 -VERSION_CODE=36 +VERSION_NAME=1.3.3 +VERSION_CODE=37 diff --git a/openwrt-packages/alist/Makefile b/openwrt-packages/alist/Makefile index 3a7f775a9e..066e79cfeb 100644 --- a/openwrt-packages/alist/Makefile +++ b/openwrt-packages/alist/Makefile @@ -7,13 +7,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=alist -PKG_VERSION:=3.40.0 -PKG_WEB_VERSION:=3.39.2 +PKG_VERSION:=3.41.0 +PKG_WEB_VERSION:=3.41.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/AlistGo/alist/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=350f6d0610cebb70c645e52a87aaf0e8cb5bb275593ee22778ed8348da48b005 +PKG_HASH:=0336a1c0089d558e7e3efd0337e51e9c45bc80f22ee8a71103e12417a7d647a2 PKG_LICENSE:=GPL-3.0 PKG_LICENSE_FILE:=LICENSE @@ -23,7 +23,7 @@ define Download/$(PKG_NAME)-web FILE:=$(PKG_NAME)-web-$(PKG_WEB_VERSION).tar.gz URL_FILE:=dist.tar.gz URL:=https://github.com/AlistGo/alist-web/releases/download/$(PKG_WEB_VERSION)/ - HASH:=d998315aff5544e7d7248214d02a3b04a92366bf0ac50fb4791b23833e8b543a + HASH:=7fbc3e83874fca15eb6590aad2c09cd6eb4f15aa7febe2b25a961ea56ba5265b endef PKG_BUILD_DEPENDS:=golang/host diff --git a/openwrt-passwall/luci-app-passwall/luasrc/controller/passwall.lua b/openwrt-passwall/luci-app-passwall/luasrc/controller/passwall.lua index ce89a3749d..02ce26cae9 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/controller/passwall.lua +++ b/openwrt-passwall/luci-app-passwall/luasrc/controller/passwall.lua @@ -77,6 +77,11 @@ function index() entry({"admin", "services", appname, "delete_select_nodes"}, call("delete_select_nodes")).leaf = true entry({"admin", "services", appname, "update_rules"}, call("update_rules")).leaf = true + --[[rule_list]] + entry({"admin", "services", appname, "read_gfwlist"}, call("read_rulelist", "gfw")).leaf = true + entry({"admin", "services", appname, "read_chnlist"}, call("read_rulelist", "chn")).leaf = true + entry({"admin", "services", appname, "read_chnroute"}, call("read_rulelist", "chnroute")).leaf = true + --[[Components update]] entry({"admin", "services", appname, "check_passwall"}, call("app_check")).leaf = true local coms = require "luci.passwall.com" @@ -475,3 +480,19 @@ function com_update(comname) http_write_json(json) end + +function read_rulelist(list) + local rule_path + if list == "gfw" then + rule_path = "/usr/share/passwall/rules/gfwlist" + elseif list == "chn" then + rule_path = "/usr/share/passwall/rules/chnlist" + else + rule_path = "/usr/share/passwall/rules/chnroute" + end + if api.fs.access(rule_path) then + luci.http.prepare_content("text/plain") + luci.http.write(api.fs.readfile(rule_path)) + end +end + diff --git a/openwrt-passwall/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/openwrt-passwall/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua index a63c1afc79..d766646af4 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/openwrt-passwall/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -557,9 +557,6 @@ if api.is_finded("smartdns") then o:depends({dns_shunt = "smartdns", tcp_proxy_mode = "proxy", chn_list = "direct"}) end -o = s:taboption("DNS", Flag, "dns_redirect", "DNS " .. translate("Redirect"), translate("Force Router DNS server to all local devices.")) -o.default = "0" - if (uci:get(appname, "@global_forwarding[0]", "use_nft") or "0") == "1" then o = s:taboption("DNS", Button, "clear_ipset", translate("Clear NFTSET"), translate("Try this feature if the rule modification does not take effect.")) else diff --git a/openwrt-passwall/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua b/openwrt-passwall/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua index 27e863a158..5c9abb15b5 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua +++ b/openwrt-passwall/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua @@ -273,71 +273,41 @@ end if api.fs.access(gfwlist_path) then s:tab("gfw_list", translate("GFW List")) - o = s:taboption("gfw_list", TextValue, "gfw_list", "") - o.readonly = true - o.rows = 45 - o.wrap = "off" - o.cfgvalue = function(self, section) - local limit = 100 -- 限制行数 - local cmd = string.format("head -n %d %s", limit, gfwlist_path) - return api.sys.exec(cmd) or "" - -- return fs.readfile(gfwlist_path) or "" - end - local total_lines_cmd = string.format("wc -l < %s", gfwlist_path) - local total_lines = tonumber(api.sys.exec(total_lines_cmd)) or 0 - local displayed_lines = 100 - - local total_lines_label = s:taboption("gfw_list", DummyValue, "total_lines", translate("Total Lines")) - total_lines_label.value = translatef("%d lines", total_lines) - - local displayed_lines_label = s:taboption("gfw_list", DummyValue, "displayed_lines", translate("Displayed Lines")) - displayed_lines_label.value = translatef("%d lines", displayed_lines) + o = s:taboption("gfw_list", DummyValue, "_gfw_fieldset") + o.rawhtml = true + o.default = string.format([[ +
+ + +
+ + ]], translate("Read List")) end if api.fs.access(chnlist_path) then s:tab("chn_list", translate("China List") .. "(" .. translate("Domain") .. ")") - o = s:taboption("chn_list", TextValue, "chn_list", "") - o.readonly = true - o.rows = 45 - o.wrap = "off" - o.cfgvalue = function(self, section) - local limit = 100 -- 限制行数 - local cmd = string.format("head -n %d %s", limit, chnlist_path) - return api.sys.exec(cmd) or "" - -- return fs.readfile(chnlist_path) or "" - end - local total_lines_cmd = string.format("wc -l < %s", chnlist_path) - local total_lines = tonumber(api.sys.exec(total_lines_cmd)) or 0 - local displayed_lines = 100 - - local total_lines_label = s:taboption("chn_list", DummyValue, "total_lines", translate("Total Lines")) - total_lines_label.value = translatef("%d lines", total_lines) - - local displayed_lines_label = s:taboption("chn_list", DummyValue, "displayed_lines", translate("Displayed Lines")) - displayed_lines_label.value = translatef("%d lines", displayed_lines) + o = s:taboption("chn_list", DummyValue, "_chn_fieldset") + o.rawhtml = true + o.default = string.format([[ +
+ + +
+ + ]], translate("Read List")) end if api.fs.access(chnroute_path) then s:tab("chnroute_list", translate("China List") .. "(IP)") - o = s:taboption("chnroute_list", TextValue, "chnroute_list", "") - o.readonly = true - o.rows = 45 - o.wrap = "off" - o.cfgvalue = function(self, section) - local limit = 100 -- 限制行数 - local cmd = string.format("head -n %d %s", limit, chnroute_path) - return api.sys.exec(cmd) or "" - -- return fs.readfile(chnroute_path) or "" - end - local total_lines_cmd = string.format("wc -l < %s", chnroute_path) - local total_lines = tonumber(api.sys.exec(total_lines_cmd)) or 0 - local displayed_lines = 100 - - local total_lines_label = s:taboption("chnroute_list", DummyValue, "total_lines", translate("Total Lines")) - total_lines_label.value = translatef("%d lines", total_lines) - - local displayed_lines_label = s:taboption("chnroute_list", DummyValue, "displayed_lines", translate("Displayed Lines")) - displayed_lines_label.value = translatef("%d lines", displayed_lines) + o = s:taboption("chnroute_list", DummyValue, "_chnroute_fieldset") + o.rawhtml = true + o.default = string.format([[ +
+ + +
+ + ]], translate("Read List")) end m:append(Template(appname .. "/rule_list/js")) diff --git a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/rule_list/js.htm b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/rule_list/js.htm index 096fe8635b..0797d8d5dc 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/rule_list/js.htm +++ b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/rule_list/js.htm @@ -1,18 +1,47 @@ <% local api = require "luci.passwall.api" +local translate = luci.i18n.translate +local total_lines_text = translate("Total Lines") -%> diff --git a/openwrt-passwall/luci-app-passwall/po/zh-cn/passwall.po b/openwrt-passwall/luci-app-passwall/po/zh-cn/passwall.po index 610fe9bcad..28fbc6854f 100644 --- a/openwrt-passwall/luci-app-passwall/po/zh-cn/passwall.po +++ b/openwrt-passwall/luci-app-passwall/po/zh-cn/passwall.po @@ -223,9 +223,6 @@ msgstr "需要代理的分流规则域名使用 FakeDNS。" msgid "Redirect" msgstr "重定向" -msgid "Force Router DNS server to all local devices." -msgstr "强制所有本地设备使用路由器 DNS。" - msgid "Clear IPSET" msgstr "清空 IPSET" @@ -1732,8 +1729,5 @@ msgstr "为 sing-box 节点设置默认的域名解析策略。" msgid "Total Lines" msgstr "总行数:" -msgid "Displayed Lines" -msgstr "展示行数:" - -msgid "%d lines" -msgstr "%d 行" +msgid "Read List" +msgstr "读取列表" diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/app.sh b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/app.sh index 4e1968a1f7..56a46c00aa 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/app.sh @@ -14,13 +14,10 @@ TMP_ROUTE_PATH=$TMP_PATH/route TMP_ACL_PATH=$TMP_PATH/acl TMP_IFACE_PATH=$TMP_PATH/iface TMP_PATH2=/tmp/etc/${CONFIG}_tmp -DNSMASQ_PATH=/etc/dnsmasq.d -DNSMASQ_CONF_DIR=/tmp/dnsmasq.d -TMP_DNSMASQ_PATH=${DNSMASQ_CONF_DIR}/${CONFIG} +GLOBAL_ACL_PATH=${TMP_ACL_PATH}/default LOG_FILE=/tmp/log/$CONFIG.log APP_PATH=/usr/share/$CONFIG RULES_PATH=/usr/share/${CONFIG}/rules -DNS_N=dnsmasq DNS_PORT=15353 TUN_DNS="127.0.0.1#${DNS_PORT}" LOCAL_DNS=119.29.29.29,223.5.5.5 @@ -359,6 +356,23 @@ parse_doh() { eval "${__url_var}='${__url}' ${__host_var}='${__host}' ${__port_var}='${__port}' ${__bootstrap_var}='${__bootstrap}'" } +get_geoip() { + local geoip_code="$1" + local geoip_type_flag="" + local geoip_path="$(config_t_get global_rules v2ray_location_asset)" + geoip_path="${geoip_path%*/}/geoip.dat" + [ -e "$geoip_path" ] || { echo ""; return; } + case "$2" in + "ipv4") geoip_type_flag="-ipv6=false" ;; + "ipv6") geoip_type_flag="-ipv4=false" ;; + esac + if type geoview &> /dev/null; then + geoview -input "$geoip_path" -list "$geoip_code" $geoip_type_flag -lowmem=true + else + echo "" + fi +} + run_ipt2socks() { local flag proto tcp_tproxy local_port socks_address socks_port socks_username socks_password log_file local _extra_param="" @@ -704,9 +718,9 @@ run_redir() { local node proto bind local_port config_file log_file eval_set_val $@ local tcp_node_socks_flag tcp_node_http_flag - [ -n "$config_file" ] && [ -z "$(echo ${config_file} | grep $TMP_PATH)" ] && config_file=${TMP_ACL_PATH}/default/${config_file} + [ -n "$config_file" ] && [ -z "$(echo ${config_file} | grep $TMP_PATH)" ] && config_file=${GLOBAL_ACL_PATH}/${config_file} if [ -n "$log_file" ] && [ -z "$(echo ${log_file} | grep $TMP_PATH)" ]; then - log_file=${TMP_ACL_PATH}/default/${log_file} + log_file=${GLOBAL_ACL_PATH}/${log_file} else log_file="/dev/null" fi @@ -1050,7 +1064,7 @@ run_redir() { [ "$tcp_node_socks" = "1" ] && { TCP_SOCKS_server="127.0.0.1:$tcp_node_socks_port" - echo "${TCP_SOCKS_server}" > $TMP_ACL_PATH/default/TCP_SOCKS_server + echo "${TCP_SOCKS_server}" > ${GLOBAL_ACL_PATH}/TCP_SOCKS_server } ;; esac @@ -1069,7 +1083,7 @@ start_redir() { local port=$(echo $(get_new_port $current_port $proto)) eval ${proto}_REDIR=$port run_redir node=$node proto=${proto} bind=0.0.0.0 local_port=$port config_file=$config_file log_file=$log_file - echo $node > $TMP_ACL_PATH/default/${proto}.id + echo $node > ${GLOBAL_ACL_PATH}/${proto}.id else [ "${proto}" = "UDP" ] && [ "$TCP_UDP" = "1" ] && return echolog "${proto}节点没有选择或为空,不代理${proto}。" @@ -1533,13 +1547,20 @@ start_dns() { dnsmasq_version=$(dnsmasq -v | grep -i "Dnsmasq version " | awk '{print $3}') [ "$(expr $dnsmasq_version \>= 2.87)" == 0 ] && echolog "Dnsmasq版本低于2.87,有可能无法正常使用!!!" } - source $APP_PATH/helper_dnsmasq.sh stretch - lua $APP_PATH/helper_dnsmasq_add.lua -FLAG "default" -TMP_DNSMASQ_PATH ${TMP_DNSMASQ_PATH} -DNSMASQ_CONF_DIR ${DNSMASQ_CONF_DIR} \ - -DNSMASQ_CONF_FILE "${DNSMASQ_CONF_DIR}/dnsmasq-${CONFIG}.conf" -DEFAULT_DNS ${DEFAULT_DNS} -LOCAL_DNS ${LOCAL_DNS} \ + + GLOBAL_DNSMASQ_PORT=$(get_new_port 11400) + local GLOBAL_DNSMASQ_CONF=${GLOBAL_ACL_PATH}/dnsmasq.conf + local GLOBAL_DNSMASQ_CONF_PATH=${GLOBAL_ACL_PATH}/dnsmasq.d + source $APP_PATH/helper_dnsmasq.sh copy_instance listen_port=$GLOBAL_DNSMASQ_PORT dnsmasq_conf="${GLOBAL_DNSMASQ_CONF}" dnsmasq_conf_path="${GLOBAL_DNSMASQ_CONF_PATH}" + lua $APP_PATH/helper_dnsmasq_add.lua -FLAG "default" -TMP_DNSMASQ_PATH ${GLOBAL_DNSMASQ_CONF_PATH} \ + -DNSMASQ_CONF_FILE ${GLOBAL_DNSMASQ_CONF} -DEFAULT_DNS ${DEFAULT_DNS} -LOCAL_DNS ${LOCAL_DNS} \ -TUN_DNS ${TUN_DNS} -REMOTE_FAKEDNS ${fakedns:-0} -USE_DEFAULT_DNS "${USE_DEFAULT_DNS:-direct}" -CHINADNS_DNS ${china_ng_listen:-0} \ -USE_DIRECT_LIST "${USE_DIRECT_LIST}" -USE_PROXY_LIST "${USE_PROXY_LIST}" -USE_BLOCK_LIST "${USE_BLOCK_LIST}" -USE_GFW_LIST "${USE_GFW_LIST}" -CHN_LIST "${CHN_LIST}" \ -TCP_NODE ${TCP_NODE} -DEFAULT_PROXY_MODE ${TCP_PROXY_MODE} -NO_PROXY_IPV6 ${DNSMASQ_FILTER_PROXY_IPV6:-0} -NFTFLAG ${nftflag:-0} \ -NO_LOGIC_LOG ${NO_LOGIC_LOG:-0} + ln_run "$(first_type dnsmasq)" "dnsmasq_default" "/dev/null" -C ${GLOBAL_DNSMASQ_CONF} -x ${GLOBAL_ACL_PATH}/dnsmasq.pid + echo "${GLOBAL_DNSMASQ_PORT}" > ${GLOBAL_ACL_PATH}/var_redirect_dns_port + DNS_REDIRECT_PORT=${GLOBAL_DNSMASQ_PORT} } add_ip2route() { @@ -1599,6 +1620,7 @@ acl_app() { redir_port=11200 dns_port=11300 dnsmasq_port=11400 + [ -n "${GLOBAL_DNSMASQ_PORT}" ] && dnsmasq_port=$(get_new_port $GLOBAL_DNSMASQ_PORT) chinadns_port=11500 for item in $items; do sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}') @@ -1625,9 +1647,10 @@ acl_app() { unset s2 done - mkdir -p $TMP_ACL_PATH/$sid + local acl_path=${TMP_ACL_PATH}/$sid + mkdir -p ${acl_path} - [ ! -z "${source_list}" ] && echo -e "${source_list}" | sed '/^$/d' > $TMP_ACL_PATH/$sid/source_list + [ ! -z "${source_list}" ] && echo -e "${source_list}" | sed '/^$/d' > ${acl_path}/source_list use_global_config=${use_global_config:-0} tcp_node=${tcp_node:-nil} @@ -1726,28 +1749,17 @@ acl_app() { } dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1)) - redirect_dns_port=$dnsmasq_port - mkdir -p $TMP_ACL_PATH/$sid/dnsmasq.d - [ -s "/tmp/etc/dnsmasq.conf.${DEFAULT_DNSMASQ_CFGID}" ] && { - cp -r /tmp/etc/dnsmasq.conf.${DEFAULT_DNSMASQ_CFGID} $TMP_ACL_PATH/$sid/dnsmasq.conf - sed -i "/ubus/d" $TMP_ACL_PATH/$sid/dnsmasq.conf - sed -i "/dhcp/d" $TMP_ACL_PATH/$sid/dnsmasq.conf - sed -i "/port=/d" $TMP_ACL_PATH/$sid/dnsmasq.conf - sed -i "/conf-dir/d" $TMP_ACL_PATH/$sid/dnsmasq.conf - sed -i "/server/d" $TMP_ACL_PATH/$sid/dnsmasq.conf - } - echo "port=${dnsmasq_port}" >> $TMP_ACL_PATH/$sid/dnsmasq.conf - [ "$use_default_dns" = "remote" ] && { - dnsmasq_version=$(dnsmasq -v | grep -i "Dnsmasq version " | awk '{print $3}') - [ "$(expr $dnsmasq_version \>= 2.87)" == 0 ] && echolog "Dnsmasq版本低于2.87,有可能无法正常使用!!!" - } - lua $APP_PATH/helper_dnsmasq_add.lua -FLAG ${sid} -TMP_DNSMASQ_PATH $TMP_ACL_PATH/$sid/dnsmasq.d -DNSMASQ_CONF_DIR ${DNSMASQ_CONF_DIR} \ - -DNSMASQ_CONF_FILE $TMP_ACL_PATH/$sid/dnsmasq.conf -DEFAULT_DNS $DEFAULT_DNS -LOCAL_DNS $LOCAL_DNS \ + local dnsmasq_conf=${acl_path}/dnsmasq.conf + local dnsmasq_conf_path=${acl_path}/dnsmasq.d + source $APP_PATH/helper_dnsmasq.sh copy_instance listen_port=$dnsmasq_port dnsmasq_conf="${dnsmasq_conf}" dnsmasq_conf_path="${dnsmasq_conf_path}" + lua $APP_PATH/helper_dnsmasq_add.lua -FLAG ${sid} -TMP_DNSMASQ_PATH ${dnsmasq_conf_path} \ + -DNSMASQ_CONF_FILE ${dnsmasq_conf} -DEFAULT_DNS $DEFAULT_DNS -LOCAL_DNS $LOCAL_DNS \ -USE_DIRECT_LIST "${use_direct_list}" -USE_PROXY_LIST "${use_proxy_list}" -USE_BLOCK_LIST "${use_block_list}" -USE_GFW_LIST "${use_gfw_list}" -CHN_LIST "${chn_list}" \ -TUN_DNS "127.0.0.1#${_dns_port}" -REMOTE_FAKEDNS 0 -USE_DEFAULT_DNS "${use_default_dns:-direct}" -CHINADNS_DNS ${_china_ng_listen:-0} \ -TCP_NODE $tcp_node -DEFAULT_PROXY_MODE ${tcp_proxy_mode} -NO_PROXY_IPV6 ${dnsmasq_filter_proxy_ipv6:-0} -NFTFLAG ${nftflag:-0} \ -NO_LOGIC_LOG 1 - ln_run "$(first_type dnsmasq)" "dnsmasq_${sid}" "/dev/null" -C $TMP_ACL_PATH/$sid/dnsmasq.conf -x $TMP_ACL_PATH/$sid/dnsmasq.pid + ln_run "$(first_type dnsmasq)" "dnsmasq_${sid}" "/dev/null" -C ${dnsmasq_conf} -x ${acl_path}/dnsmasq.pid + echo "${dnsmasq_port}" > ${acl_path}/var_redirect_dns_port eval node_${tcp_node}_$(echo -n "${tcp_proxy_mode}${remote_dns}" | md5sum | cut -d " " -f1)=${dnsmasq_port} } _redir_port=$(eval echo \${node_${tcp_node}_redir_port}) @@ -1760,7 +1772,7 @@ acl_app() { _dns_port=$(eval echo \${node_${tcp_node}_$(echo -n "${remote_dns}" | md5sum | cut -d " " -f1)}) run_dns ${_dns_port} else - redirect_dns_port=${_dnsmasq_port} + [ -n "${_dnsmasq_port}" ] && echo "${_dnsmasq_port}" > ${acl_path}/var_redirect_dns_port fi else socks_port=$(get_new_port $(expr $socks_port + 1)) @@ -1798,10 +1810,10 @@ acl_app() { fi run_dns ${_dns_port} fi - echo "${tcp_node}" > $TMP_ACL_PATH/$sid/var_tcp_node + echo "${tcp_node}" > ${acl_path}/var_tcp_node } fi - echo "${tcp_port}" > $TMP_ACL_PATH/$sid/var_tcp_port + echo "${tcp_port}" > ${acl_path}/var_tcp_port } [ "$udp_node" != "nil" ] && { [ "$udp_node" = "tcp" ] && udp_node=$tcp_node @@ -1850,18 +1862,16 @@ acl_app() { run_ipt2socks flag=acl_${udp_node} local_port=$redir_port socks_address=127.0.0.1 socks_port=$socks_port log_file=$log_file fi fi - echo "${udp_node}" > $TMP_ACL_PATH/$sid/var_udp_node + echo "${udp_node}" > ${acl_path}/var_udp_node fi } fi - echo "${udp_port}" > $TMP_ACL_PATH/$sid/var_udp_port + echo "${udp_port}" > ${acl_path}/var_udp_port udp_flag=1 } - [ -n "$redirect_dns_port" ] && echo "${redirect_dns_port}" > $TMP_ACL_PATH/$sid/var_redirect_dns_port unset enabled sid remarks sources interface use_global_config tcp_node udp_node use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode filter_proxy_ipv6 dns_mode remote_dns v2ray_dns_mode remote_dns_doh dns_client_ip unset _ip _mac _iprange _ipset _ip_or_mac source_list tcp_port udp_port config_file _extra_param unset _china_ng_listen _chinadns_local_dns _direct_dns_mode chinadns_ng_default_tag dnsmasq_filter_proxy_ipv6 - unset redirect_dns_port done unset socks_port redir_port dns_port dnsmasq_port chinadns_port } @@ -1904,13 +1914,12 @@ start() { } [ "$ENABLED_DEFAULT_ACL" == 1 ] && { - mkdir -p $TMP_ACL_PATH/default + mkdir -p ${GLOBAL_ACL_PATH} start_redir TCP start_redir UDP start_dns } [ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start - [ "$ENABLED_DEFAULT_ACL" == 1 ] && source $APP_PATH/helper_${DNS_N}.sh logic_restart start_crontab echolog "运行完成!\n" } @@ -1927,8 +1936,6 @@ stop() { unset XRAY_LOCATION_ASSET stop_crontab source $APP_PATH/helper_smartdns.sh del - source $APP_PATH/helper_dnsmasq.sh del - source $APP_PATH/helper_dnsmasq.sh restart no_log=1 [ -s "$TMP_PATH/bridge_nf_ipt" ] && sysctl -w net.bridge.bridge-nf-call-iptables=$(cat $TMP_PATH/bridge_nf_ipt) >/dev/null 2>&1 [ -s "$TMP_PATH/bridge_nf_ip6t" ] && sysctl -w net.bridge.bridge-nf-call-ip6tables=$(cat $TMP_PATH/bridge_nf_ip6t) >/dev/null 2>&1 rm -rf ${TMP_PATH} @@ -1999,17 +2006,6 @@ RESOLVFILE=/tmp/resolv.conf.d/resolv.conf.auto ISP_DNS=$(cat $RESOLVFILE 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u | grep -v 0.0.0.0 | grep -v 127.0.0.1) ISP_DNS6=$(cat $RESOLVFILE 2>/dev/null | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | awk -F % '{print $1}' | awk -F " " '{print $2}'| sort -u | grep -v -Fx ::1 | grep -v -Fx ::) -DEFAULT_DNSMASQ_CFGID="$(uci -q show "dhcp.@dnsmasq[0]" | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')" -if [ -f "/tmp/etc/dnsmasq.conf.$DEFAULT_DNSMASQ_CFGID" ]; then - DNSMASQ_CONF_DIR="$(awk -F '=' '/^conf-dir=/ {print $2}' "/tmp/etc/dnsmasq.conf.$DEFAULT_DNSMASQ_CFGID")" - if [ -n "$DNSMASQ_CONF_DIR" ]; then - DNSMASQ_CONF_DIR=${DNSMASQ_CONF_DIR%*/} - TMP_DNSMASQ_PATH=${DNSMASQ_CONF_DIR}/${CONFIG} - else - DNSMASQ_CONF_DIR="/tmp/dnsmasq.d" - fi -fi - DEFAULT_DNS=$(uci show dhcp.@dnsmasq[0] | grep "\.server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' '\n' | grep -v "\/" | head -2 | sed ':label;N;s/\n/,/;b label') [ -z "${DEFAULT_DNS}" ] && [ "$(echo $ISP_DNS | tr ' ' '\n' | wc -l)" -le 2 ] && DEFAULT_DNS=$(echo -n $ISP_DNS | tr ' ' '\n' | head -2 | tr '\n' ',') LOCAL_DNS="${DEFAULT_DNS:-119.29.29.29,223.5.5.5}" diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.sh b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.sh index d3d4bbd05c..746726084a 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.sh +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.sh @@ -1,89 +1,27 @@ #!/bin/sh -stretch() { - #zhenduiluanshezhiDNSderen - local dnsmasq_server=$(uci -q get dhcp.@dnsmasq[0].server) - local dnsmasq_noresolv=$(uci -q get dhcp.@dnsmasq[0].noresolv) - local _flag - for server in $dnsmasq_server; do - [ -z "$(echo $server | grep '\/')" ] && _flag=1 - done - [ -z "$_flag" ] && [ "$dnsmasq_noresolv" = "1" ] && { - uci -q delete dhcp.@dnsmasq[0].noresolv - uci -q set dhcp.@dnsmasq[0].resolvfile="$RESOLVFILE" - uci commit dhcp +copy_instance() { + local listen_port dnsmasq_conf + eval_set_val $@ + [ -s "/tmp/etc/dnsmasq.conf.${DEFAULT_DNSMASQ_CFGID}" ] && { + cp -r /tmp/etc/dnsmasq.conf.${DEFAULT_DNSMASQ_CFGID} $dnsmasq_conf + sed -i "/ubus/d" $dnsmasq_conf + sed -i "/dhcp/d" $dnsmasq_conf + sed -i "/port=/d" $dnsmasq_conf + sed -i "/conf-dir/d" $dnsmasq_conf + sed -i "/no-poll/d" $dnsmasq_conf + sed -i "/no-resolv/d" $dnsmasq_conf } + echo "port=${listen_port}" >> $dnsmasq_conf } -backup_servers() { - DNSMASQ_DNS=$(uci show dhcp.@dnsmasq[0] | grep ".server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' ',') - if [ -n "${DNSMASQ_DNS}" ]; then - uci -q set $CONFIG.@global[0].dnsmasq_servers="${DNSMASQ_DNS}" - uci commit $CONFIG - fi -} - -restore_servers() { - OLD_SERVER=$(uci -q get $CONFIG.@global[0].dnsmasq_servers | tr "," " ") - for server in $OLD_SERVER; do - uci -q del_list dhcp.@dnsmasq[0].server=$server - uci -q add_list dhcp.@dnsmasq[0].server=$server - done - uci commit dhcp - uci -q delete $CONFIG.@global[0].dnsmasq_servers - uci commit $CONFIG -} - -logic_restart() { - local no_log - eval_set_val $@ - _LOG_FILE=$LOG_FILE - [ -n "$no_log" ] && LOG_FILE="/dev/null" - if [ -f "$TMP_PATH/default_DNS" ]; then - backup_servers - #sed -i "/list server/d" /etc/config/dhcp >/dev/null 2>&1 - for server in $(uci -q get dhcp.@dnsmasq[0].server); do - [ -n "$(echo $server | grep '\/')" ] || uci -q del_list dhcp.@dnsmasq[0].server="$server" - done - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - restore_servers - else - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - fi - echolog "重启 dnsmasq 服务" - LOG_FILE=${_LOG_FILE} -} - -restart() { - local no_log - eval_set_val $@ - _LOG_FILE=$LOG_FILE - [ -n "$no_log" ] && LOG_FILE="/dev/null" - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - echolog "重启 dnsmasq 服务" - LOG_FILE=${_LOG_FILE} -} - -del() { - rm -rf $DNSMASQ_CONF_DIR/dnsmasq-$CONFIG.conf - rm -rf $DNSMASQ_PATH/dnsmasq-$CONFIG.conf - rm -rf $TMP_DNSMASQ_PATH -} +DEFAULT_DNSMASQ_CFGID="$(uci -q show "dhcp.@dnsmasq[0]" | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')" arg1=$1 shift case $arg1 in -stretch) - stretch $@ - ;; -del) - del $@ - ;; -restart) - restart $@ - ;; -logic_restart) - logic_restart $@ +copy_instance) + copy_instance $@ ;; *) ;; esac diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua index fbb3e29785..6c01766076 100644 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua @@ -4,7 +4,6 @@ local appname = "passwall" local var = api.get_args(arg) local FLAG = var["-FLAG"] -local DNSMASQ_CONF_DIR = var["-DNSMASQ_CONF_DIR"] local TMP_DNSMASQ_PATH = var["-TMP_DNSMASQ_PATH"] local DNSMASQ_CONF_FILE = var["-DNSMASQ_CONF_FILE"] local DEFAULT_DNS = var["-DEFAULT_DNS"] @@ -192,7 +191,6 @@ local setflag_4= (NFTFLAG == "1") and "4#inet#passwall#" or "" local setflag_6= (NFTFLAG == "1") and "6#inet#passwall#" or "" if not fs.access(CACHE_DNS_PATH) then - fs.mkdir(DNSMASQ_CONF_DIR) fs.mkdir(CACHE_DNS_PATH) --屏蔽列表 diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/iptables.sh b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/iptables.sh index 6015672616..ac28955666 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/iptables.sh +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/iptables.sh @@ -182,23 +182,6 @@ get_wan6_ip() { echo $NET_ADDR } -get_geoip() { - local geoip_code="$1" - local geoip_type_flag="" - local geoip_path="$(config_t_get global_rules v2ray_location_asset)" - geoip_path="${geoip_path%*/}/geoip.dat" - [ -e "$geoip_path" ] || { echo ""; return; } - case "$2" in - "ipv4") geoip_type_flag="-ipv6=false" ;; - "ipv6") geoip_type_flag="-ipv4=false" ;; - esac - if type geoview &> /dev/null; then - geoview -input "$geoip_path" -list "$geoip_code" $geoip_type_flag -lowmem=true - else - echo "" - fi -} - load_acl() { ([ "$ENABLED_ACLS" == 1 ] || ([ "$ENABLED_DEFAULT_ACL" == 1 ] && [ "$CLIENT_PROXY" == 1 ])) && echolog " - 访问控制:" [ "$ENABLED_ACLS" == 1 ] && { @@ -233,6 +216,7 @@ load_acl() { [ -s "${TMP_ACL_PATH}/${sid}/var_udp_node" ] && udp_node=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_node) [ -s "${TMP_ACL_PATH}/${sid}/var_tcp_port" ] && tcp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_tcp_port) [ -s "${TMP_ACL_PATH}/${sid}/var_udp_port" ] && udp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_port) + [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) use_shunt_tcp=0 use_shunt_udp=0 @@ -259,6 +243,9 @@ load_acl() { chn_list=${CHN_LIST} tcp_proxy_mode=${TCP_PROXY_MODE} udp_proxy_mode=${UDP_PROXY_MODE} + use_shunt_tcp=${USE_SHUNT_TCP} + use_shunt_udp=${USE_SHUNT_UDP} + dns_redirect_port=${DNS_REDIRECT_PORT} } _acl_list=${TMP_ACL_PATH}/${sid}/source_list @@ -333,7 +320,25 @@ load_acl() { echolog " - ${msg}不代理所有 UDP 端口" fi } - + + if ([ -n "$tcp_port" ] && [ -n "${tcp_proxy_mode}" ]) || ([ -n "$udp_port" ] && [ -n "${udp_proxy_mode}" ]); then + [ -n "$dns_redirect_port" ] && { + $ipt_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN + $ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null + $ipt_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN + $ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null + $ipt_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port + $ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null + $ipt_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port + $ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null + } + else + $ipt_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN + $ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null + $ipt_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN + $ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null + fi + [ -n "$tcp_port" -o -n "$udp_port" ] && { [ "${use_direct_list}" = "1" ] && $ipt_n -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_WHITELIST) -j RETURN [ "${use_direct_list}" = "1" ] && $ipt_m -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_WHITELIST) -j RETURN @@ -380,7 +385,6 @@ load_acl() { [ -n "$tcp_port" ] && { if [ -n "${tcp_proxy_mode}" ]; then - [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && $ipt_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) msg2="${msg}使用 TCP 节点[$tcp_node_remark]" if [ -n "${is_tproxy}" ]; then msg2="${msg2}(TPROXY:${tcp_port})" @@ -463,7 +467,7 @@ load_acl() { $ipt_m -A PSW $(comment "$remarks") ${_ipt_source} -p udp -j RETURN unset ipt_tmp ipt_j _ipt_source msg msg2 done - unset enabled sid remarks sources use_global_config use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode tcp_no_redir_ports udp_no_redir_ports tcp_proxy_drop_ports udp_proxy_drop_ports tcp_redir_ports udp_redir_ports tcp_node udp_node interface + unset enabled sid remarks sources use_global_config use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode dns_redirect_port tcp_no_redir_ports udp_no_redir_ports tcp_proxy_drop_ports udp_proxy_drop_ports tcp_redir_ports udp_redir_ports tcp_node udp_node interface unset tcp_port udp_port tcp_node_remark udp_node_remark _acl_list use_shunt_tcp use_shunt_udp done } @@ -495,6 +499,19 @@ load_acl() { fi } + if ([ "$TCP_NODE" != "nil" ] && [ -n "${TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${UDP_PROXY_MODE}" ]); then + [ -n "$DNS_REDIRECT_PORT" ] && { + $ipt_m -A PSW $(comment "默认") -p udp --dport 53 -j RETURN + $ip6t_m -A PSW $(comment "默认") -p udp --dport 53 -j RETURN 2>/dev/null + $ipt_m -A PSW $(comment "默认") -p tcp --dport 53 -j RETURN + $ip6t_m -A PSW $(comment "默认") -p tcp --dport 53 -j RETURN 2>/dev/null + $ipt_n -A PSW_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A PSW_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + $ipt_n -A PSW_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A PSW_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + } + fi + [ -n "${TCP_PROXY_MODE}" -o -n "${UDP_PROXY_MODE}" ] && { [ "${USE_DIRECT_LIST}" = "1" ] && $ipt_n -A PSW $(comment "默认") $(dst $IPSET_WHITELIST) -j RETURN [ "${USE_DIRECT_LIST}" = "1" ] && $ipt_m -A PSW $(comment "默认") $(dst $IPSET_WHITELIST) -j RETURN @@ -654,6 +671,10 @@ filter_node() { local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') local address=$(config_n_get $node address) local port=$(config_n_get $node port) + [ -z "$address" ] && [ -z "$port" ] && { + echolog " - 节点配置不正常,略过" + return 1 + } ipt_tmp=$ipt_n _is_tproxy=${is_tproxy} [ "$stream" == "udp" ] && _is_tproxy="TPROXY" @@ -665,7 +686,7 @@ filter_node() { fi else echolog " - 节点配置不正常,略过" - return 0 + return 1 fi local ADD_INDEX=$FORCE_INDEX @@ -674,7 +695,6 @@ filter_node() { [ "$_ipt" == "6" ] && _ipt=$ip6t_m && _set_name=$IPSET_VPSLIST6 $_ipt -n -L PSW_OUTPUT | grep -q "${address}:${port}" if [ $? -ne 0 ]; then - unset dst_rule local dst_rule="-j PSW_RULE" msg2="按规则路由(${msg})" [ "$_ipt" == "$ipt_m" -o "$_ipt" == "$ip6t_m" ] || { @@ -697,7 +717,7 @@ filter_node() { local proxy_protocol=$(config_n_get $proxy_node protocol) local proxy_type=$(echo $(config_n_get $proxy_node type nil) | tr 'A-Z' 'a-z') - [ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 0 + [ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 1 if [ "$proxy_protocol" == "_balancing" ]; then #echolog " - 多节点负载均衡(${proxy_type})..." proxy_node=$(config_n_get $proxy_node balancing_node) @@ -706,56 +726,40 @@ filter_node() { done elif [ "$proxy_protocol" == "_shunt" ]; then #echolog " - 按请求目的地址分流(${proxy_type})..." + local preproxy_enabled=$(config_n_get $proxy_node preproxy_enabled 0) + [ "$preproxy_enabled" == "1" ] && { + local preproxy_node=$(config_n_get $proxy_node main_node nil) + [ "$preproxy_node" != "nil" ] && { + local preproxy_node_address=$(config_n_get $preproxy_node address) + if [ -n "$preproxy_node_address" ]; then + filter_rules $preproxy_node $stream + else + preproxy_enabled=0 + fi + } + } local default_node=$(config_n_get $proxy_node default_node _direct) - local main_node=$(config_n_get $proxy_node main_node nil) - if [ "$main_node" != "nil" ]; then - filter_rules $main_node $stream - else - if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then - filter_rules $default_node $stream - fi + if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then + local default_proxy_tag=$(config_n_get $proxy_node default_proxy_tag nil) + [ "$default_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && default_proxy_tag="nil" + [ "$default_proxy_tag" == "nil" ] && filter_rules $default_node $stream fi -:</dev/null - $ipt_n -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "PSW_DNS_Hijack" 2>/dev/null - $ip6t_n -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "PSW_DNS_Hijack" 2>/dev/null - $ip6t_n -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "PSW_DNS_Hijack" 2>/dev/null - echolog " - 开启 DNS 重定向" - } -} - add_firewall_rule() { echolog "开始加载防火墙规则..." ipset -! create $IPSET_LANLIST nethash maxelem 1048576 @@ -1007,6 +1011,9 @@ add_firewall_rule() { $ip6t_n -A PSW_OUTPUT -m mark --mark 0xff -j RETURN } + $ip6t_n -N PSW_REDIRECT + $ip6t_n -I PREROUTING 1 -j PSW_REDIRECT + $ip6t_m -N PSW_DIVERT $ip6t_m -A PSW_DIVERT -j MARK --set-mark 1 $ip6t_m -A PSW_DIVERT -j ACCEPT @@ -1108,7 +1115,16 @@ add_firewall_rule() { echolog " - ${msg}不代理所有 UDP 端口" fi } - + + if ([ "$TCP_NODE" != "nil" ] && [ -n "${LOCALHOST_TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then + [ -n "$DNS_REDIRECT_PORT" ] && { + $ipt_n -A OUTPUT $(comment "PSW") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A OUTPUT $(comment "PSW") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + $ipt_n -A OUTPUT $(comment "PSW") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A OUTPUT $(comment "PSW") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + } + fi + [ -n "${LOCALHOST_TCP_PROXY_MODE}" -o -n "${LOCALHOST_UDP_PROXY_MODE}" ] && { [ "$TCP_PROXY_DROP_PORTS" != "disable" ] && { $ipt_m -A PSW_OUTPUT -p tcp $(factor $TCP_PROXY_DROP_PORTS "-m multiport --dport") -d $FAKE_IP -j DROP @@ -1266,9 +1282,6 @@ add_firewall_rule() { $ip6t_m -I OUTPUT $(comment "mangle-OUTPUT-PSW") -o lo -j RETURN insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW) -m mark --mark 1 -j RETURN" - - dns_hijack - } # 加载ACLS diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/nftables.sh b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/nftables.sh index 53affc84e2..eca8b922d8 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/nftables.sh +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/nftables.sh @@ -242,23 +242,6 @@ get_wan6_ip() { echo $NET_ADDR } -get_geoip() { - local geoip_code="$1" - local geoip_type_flag="" - local geoip_path="$(config_t_get global_rules v2ray_location_asset)" - geoip_path="${geoip_path%*/}/geoip.dat" - [ -e "$geoip_path" ] || { echo ""; return; } - case "$2" in - "ipv4") geoip_type_flag="-ipv6=false" ;; - "ipv6") geoip_type_flag="-ipv4=false" ;; - esac - if type geoview &> /dev/null; then - geoview -input "$geoip_path" -list "$geoip_code" $geoip_type_flag -lowmem=true - else - echo "" - fi -} - load_acl() { ([ "$ENABLED_ACLS" == 1 ] || ([ "$ENABLED_DEFAULT_ACL" == 1 ] && [ "$CLIENT_PROXY" == 1 ])) && echolog " - 访问控制:" [ "$ENABLED_ACLS" == 1 ] && { @@ -293,6 +276,7 @@ load_acl() { [ -s "${TMP_ACL_PATH}/${sid}/var_udp_node" ] && udp_node=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_node) [ -s "${TMP_ACL_PATH}/${sid}/var_tcp_port" ] && tcp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_tcp_port) [ -s "${TMP_ACL_PATH}/${sid}/var_udp_port" ] && udp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_port) + [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) use_shunt_tcp=0 use_shunt_udp=0 @@ -321,6 +305,7 @@ load_acl() { udp_proxy_mode=${UDP_PROXY_MODE} use_shunt_tcp=${USE_SHUNT_TCP} use_shunt_udp=${USE_SHUNT_UDP} + dns_redirect_port=${DNS_REDIRECT_PORT} } _acl_list=${TMP_ACL_PATH}/${sid}/source_list @@ -385,7 +370,25 @@ load_acl() { echolog " - ${msg}不代理所有 UDP 端口" fi } - + + if ([ -n "$tcp_port" ] && [ -n "${tcp_proxy_mode}" ]) || ([ -n "$udp_port" ] && [ -n "${udp_proxy_mode}" ]); then + [ -n "$dns_redirect_port" ] && { + nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + } + else + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\"" + fi + [ -n "$tcp_port" -o -n "$udp_port" ] && { [ "${use_direct_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ${_ipt_source} ip daddr @$NFTSET_WHITELIST counter return comment \"$remarks\"" [ "${use_direct_list}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ${_ipt_source} ip daddr @$NFTSET_WHITELIST counter return comment \"$remarks\"" @@ -433,7 +436,6 @@ load_acl() { [ -n "$tcp_port" ] && { if [ -n "${tcp_proxy_mode}" ]; then - [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter redirect to $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) comment \"$remarks\"" msg2="${msg}使用 TCP 节点[$tcp_node_remark]" if [ -n "${is_tproxy}" ]; then msg2="${msg2}(TPROXY:${tcp_port})" @@ -521,7 +523,7 @@ load_acl() { nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} counter return comment \"$remarks\"" 2>/dev/null unset nft_chain nft_j _ipt_source msg msg2 done - unset enabled sid remarks sources use_global_config use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode tcp_no_redir_ports udp_no_redir_ports tcp_proxy_drop_ports udp_proxy_drop_ports tcp_redir_ports udp_redir_ports tcp_node udp_node interface + unset enabled sid remarks sources use_global_config use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode dns_redirect_port tcp_no_redir_ports udp_no_redir_ports tcp_proxy_drop_ports udp_proxy_drop_ports tcp_redir_ports udp_redir_ports tcp_node udp_node interface unset tcp_port udp_port tcp_node_remark udp_node_remark _acl_list use_shunt_tcp use_shunt_udp done } @@ -550,6 +552,19 @@ load_acl() { fi } + if ([ "$TCP_NODE" != "nil" ] && [ -n "${TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${UDP_PROXY_MODE}" ]); then + [ -n "$DNS_REDIRECT_PORT" ] && { + nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp udp dport 53 counter return comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp udp dport 53 counter return comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp tcp dport 53 counter return comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp tcp dport 53 counter return comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + } + fi + [ -n "${TCP_PROXY_MODE}" -o -n "${UDP_PROXY_MODE}" ] && { [ "${USE_DIRECT_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ip daddr @$NFTSET_WHITELIST counter return comment \"默认\"" [ "${USE_DIRECT_LIST}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ip daddr @$NFTSET_WHITELIST counter return comment \"默认\"" @@ -725,6 +740,10 @@ filter_node() { local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') local address=$(config_n_get $node address) local port=$(config_n_get $node port) + [ -z "$address" ] && [ -z "$port" ] && { + echolog " - 节点配置不正常,略过" + return 1 + } _is_tproxy=${is_tproxy} [ "$stream" == "udp" ] && _is_tproxy="TPROXY" if [ -n "${_is_tproxy}" ]; then @@ -734,7 +753,7 @@ filter_node() { fi else echolog " - 节点配置不正常,略过" - return 0 + return 1 fi local ADD_INDEX=$FORCE_INDEX @@ -743,7 +762,6 @@ filter_node() { [ "$_ipt" == "6" ] && _ip_type=ip6 && _set_name=$NFTSET_VPSLIST6 nft "list chain $NFTABLE_NAME $nft_output_chain" 2>/dev/null | grep -q "${address}:${port}" if [ $? -ne 0 ]; then - unset dst_rule local dst_rule="jump PSW_RULE" msg2="按规则路由(${msg})" [ -n "${is_tproxy}" ] || { @@ -766,7 +784,7 @@ filter_node() { local proxy_protocol=$(config_n_get $proxy_node protocol) local proxy_type=$(echo $(config_n_get $proxy_node type nil) | tr 'A-Z' 'a-z') - [ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 0 + [ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 1 if [ "$proxy_protocol" == "_balancing" ]; then #echolog " - 多节点负载均衡(${proxy_type})..." proxy_node=$(config_n_get $proxy_node balancing_node) @@ -775,58 +793,40 @@ filter_node() { done elif [ "$proxy_protocol" == "_shunt" ]; then #echolog " - 按请求目的地址分流(${proxy_type})..." + local preproxy_enabled=$(config_n_get $proxy_node preproxy_enabled 0) + [ "$preproxy_enabled" == "1" ] && { + local preproxy_node=$(config_n_get $proxy_node main_node nil) + [ "$preproxy_node" != "nil" ] && { + local preproxy_node_address=$(config_n_get $preproxy_node address) + if [ -n "$preproxy_node_address" ]; then + filter_rules $preproxy_node $stream + else + preproxy_enabled=0 + fi + } + } local default_node=$(config_n_get $proxy_node default_node _direct) - local main_node=$(config_n_get $proxy_node main_node nil) - if [ "$main_node" != "nil" ]; then - filter_rules $main_node $stream - else - if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then - filter_rules $default_node $stream - fi + if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then + local default_proxy_tag=$(config_n_get $proxy_node default_proxy_tag nil) + [ "$default_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && default_proxy_tag="nil" + [ "$default_proxy_tag" == "nil" ] && filter_rules $default_node $stream fi -:</dev/null - nft insert rule $NFTABLE_NAME dstnat position 0 udp dport 53 counter redirect to :53 comment \"PSW_DNS_Hijack\" 2>/dev/null - nft insert rule $NFTABLE_NAME dstnat position 0 meta nfproto {ipv6} tcp dport 53 counter redirect to :53 comment \"PSW_DNS_Hijack\" 2>/dev/null - nft insert rule $NFTABLE_NAME dstnat position 0 meta nfproto {ipv6} udp dport 53 counter redirect to :53 comment \"PSW_DNS_Hijack\" 2>/dev/null - uci -q set dhcp.@dnsmasq[0].dns_redirect='0' 2>/dev/null - uci commit dhcp 2>/dev/null - echolog " - 开启 DNS 重定向" - } -} - add_firewall_rule() { echolog "开始加载防火墙规则..." gen_nft_tables @@ -1182,7 +1182,16 @@ add_firewall_rule() { echolog " - ${msg}不代理所有 UDP 端口" fi } - + + if ([ "$TCP_NODE" != "nil" ] && [ -n "${LOCALHOST_TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then + [ -n "$DNS_REDIRECT_PORT" ] && { + nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW\"" + nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW\"" + nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW\"" + nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW\"" + } + fi + [ -n "${LOCALHOST_TCP_PROXY_MODE}" -o -n "${LOCALHOST_UDP_PROXY_MODE}" ] && { [ "$TCP_PROXY_DROP_PORTS" != "disable" ] && { nft add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp ip daddr $FAKE_IP $(factor $TCP_PROXY_DROP_PORTS "tcp dport") counter drop @@ -1340,8 +1349,6 @@ add_firewall_rule() { nft "add rule $NFTABLE_NAME mangle_output oif lo counter return comment \"PSW_OUTPUT_MANGLE\"" nft "add rule $NFTABLE_NAME mangle_output meta mark 1 counter return comment \"PSW_OUTPUT_MANGLE\"" - - dns_hijack } # 加载ACLS diff --git a/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml b/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml index 355ac894a2..13d0fdd8ff 100644 --- a/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml +++ b/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml @@ -59,7 +59,7 @@ jobs: - name: Generate new tag & release if: steps.check_version.outputs.has_update == 'true' - uses: softprops/action-gh-release@master + uses: softprops/action-gh-release@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -154,7 +154,7 @@ jobs: echo "FIRMWARE=$PWD" >> $GITHUB_ENV - name: Upload passwall2 ipks to release - uses: softprops/action-gh-release@master + uses: softprops/action-gh-release@v2 if: steps.compile.outputs.status == 'success' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -283,7 +283,6 @@ jobs: echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_Simple_Obfs=y" >> .config echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_SingBox=y" >> .config echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_tuic_client=y" >> .config - echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_V2ray_Geoview=y" >> .config echo "CONFIG_PACKAGE_luci-app-passwall2_INCLUDE_V2ray_Plugin=y" >> .config make defconfig @@ -355,7 +354,7 @@ jobs: echo "status=success" >> $GITHUB_OUTPUT - name: Upload firmware to release - uses: softprops/action-gh-release@master + uses: softprops/action-gh-release@v2 if: steps.info.outputs.status == 'success' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/openwrt-passwall2/luci-app-passwall2/Makefile b/openwrt-passwall2/luci-app-passwall2/Makefile index 08f79b5f39..bfc2ab4f66 100644 --- a/openwrt-passwall2/luci-app-passwall2/Makefile +++ b/openwrt-passwall2/luci-app-passwall2/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=24.12.11 -PKG_RELEASE:=3 +PKG_VERSION:=24.12.12 +PKG_RELEASE:=2 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ @@ -24,14 +24,13 @@ PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_SingBox \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client \ - CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Geoview \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin LUCI_TITLE:=LuCI support for PassWall 2 LUCI_PKGARCH:=all LUCI_DEPENDS:=+coreutils +coreutils-base64 +coreutils-nohup +curl \ +ip-full +libuci-lua +lua +luci-compat +luci-lib-jsonc +resolveip +tcping \ - +xray-core +v2ray-geoip +v2ray-geosite \ + +xray-core +geoview +v2ray-geoip +v2ray-geosite \ +unzip \ +PACKAGE_$(PKG_NAME)_INCLUDE_IPv6_Nat:ip6tables-mod-nat @@ -138,11 +137,6 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client select PACKAGE_tuic-client default n -config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Geoview - bool "Include V2ray_Geoview" - select PACKAGE_geoview - default y if aarch64||arm||i386||x86_64 - config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin bool "Include V2ray-Plugin (Shadowsocks Plugin)" select PACKAGE_v2ray-plugin diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua index c8b9693d6b..314e992186 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua @@ -259,6 +259,7 @@ if has_singbox then local geoip_path = s.fields["geoip_path"] and s.fields["geoip_path"]:formvalue(section) or nil if geoip_path then os.remove(geoip_path) + luci.sys.call("rm -f /tmp/etc/passwall2_tmp/geoip-*.json") end local geosite_path = s.fields["geosite_path"] and s.fields["geosite_path"]:formvalue(section) or nil if geosite_path then diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index 20650ff6d8..254485783a 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -1386,6 +1386,11 @@ function gen_config(var) string.gsub(direct_ipset, '[^' .. "," .. ']+', function(w) sys.call("ipset -q -F " .. w) end) + local ipset_prefix_name = "passwall2_" .. node_id .. "_" + local ipset_list = sys.exec("ipset list | grep 'Name: ' | grep '" .. ipset_prefix_name .. "' | awk '{print $2}'") + string.gsub(ipset_list, '[^' .. "\r\n" .. ']+', function(w) + sys.call("ipset -q -F " .. w) + end) end if direct_nftset then string.gsub(direct_nftset, '[^' .. "," .. ']+', function(w) @@ -1398,6 +1403,13 @@ function gen_config(var) sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, set_name)) end end) + local family = "inet" + local table_name = "passwall2" + local nftset_prefix_name = "passwall2_" .. node_id .. "_" + local nftset_list = sys.exec("nft -a list sets | grep -E '" .. nftset_prefix_name .. "' | awk -F 'set ' '{print $2}' | awk '{print $1}'") + string.gsub(nftset_list, '[^' .. "\r\n" .. ']+', function(w) + sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, w)) + end) end end end diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua index a179e34524..c4d1ddb551 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -1405,6 +1405,11 @@ function gen_config(var) string.gsub(direct_ipset, '[^' .. "," .. ']+', function(w) sys.call("ipset -q -F " .. w) end) + local ipset_prefix_name = "passwall2_" .. node_id .. "_" + local ipset_list = sys.exec("ipset list | grep 'Name: ' | grep '" .. ipset_prefix_name .. "' | awk '{print $2}'") + string.gsub(ipset_list, '[^' .. "\r\n" .. ']+', function(w) + sys.call("ipset -q -F " .. w) + end) end if direct_nftset then string.gsub(direct_nftset, '[^' .. "," .. ']+', function(w) @@ -1417,6 +1422,13 @@ function gen_config(var) sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, set_name)) end end) + local family = "inet" + local table_name = "passwall2" + local nftset_prefix_name = "passwall2_" .. node_id .. "_" + local nftset_list = sys.exec("nft -a list sets | grep -E '" .. nftset_prefix_name .. "' | awk -F 'set ' '{print $2}' | awk '{print $1}'") + string.gsub(nftset_list, '[^' .. "\r\n" .. ']+', function(w) + sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, w)) + end) end end end diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/0_default_config b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/0_default_config index 5f5b8d0494..87b588d988 100644 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/0_default_config +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/0_default_config @@ -47,6 +47,7 @@ config global_rules option geosite_update '1' option geoip_update '1' option v2ray_location_asset '/usr/share/v2ray/' + option enable_geoview '1' config global_app option xray_file '/usr/bin/xray' diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh index 991ee546d0..c3ee5d6a32 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -302,6 +302,28 @@ get_geoip() { fi } +get_singbox_geoip() { + local geoip_code="$1" + local geoip_path=$(config_t_get global_singbox geoip_path) + [ -e "$geoip_path" ] || { echo ""; return; } + local has_geoip_tools=$($(first_type $(config_t_get global_app singbox_file) sing-box) geoip | grep "GeoIP tools") + if [ -n "${has_geoip_tools}" ]; then + [ -f "${geoip_path}" ] && local geoip_md5=$(md5sum ${geoip_path} | awk '{print $1}') + local output_file="${TMP_PATH2}/geoip-${geoip_md5}-${geoip_code}.json" + [ ! -f ${output_file} ] && $(first_type $(config_t_get global_app singbox_file) sing-box) geoip -f "${geoip_path}" export "${geoip_code}" -o "${output_file}" + case "$2" in + ipv4) + cat ${output_file} | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | awk -F '"' '{print $2}' | sed -e "/^$/d" + ;; + ipv6) + cat ${output_file} | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | awk -F '"' '{print $2}' | sed -e "/^$/d" + ;; + esac + else + echo "" + fi +} + run_xray() { local flag node redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy dns_cache write_ipset_direct @@ -735,6 +757,7 @@ run_global() { GLOBAL_DNSMASQ_PORT=$(get_new_port 11400) run_copy_dnsmasq flag="default" listen_port=$GLOBAL_DNSMASQ_PORT tun_dns="${TUN_DNS}" + DNS_REDIRECT_PORT=${GLOBAL_DNSMASQ_PORT} } start_socks() { diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/iptables.sh b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/iptables.sh index ae79608f8c..d9095a59c7 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/iptables.sh +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/iptables.sh @@ -187,6 +187,91 @@ get_wan6_ip() { echo $NET_ADDR } +gen_shunt_list() { + local node=${1} + local shunt_list4_var_name=${2} + local shunt_list6_var_name=${3} + local _write_ipset_direct=${4} + local _set_name4=${5} + local _set_name6=${6} + [ -z "$node" ] && continue + unset ${shunt_list4_var_name} + unset ${shunt_list6_var_name} + local _SHUNT_LIST4 _SHUNT_LIST6 + local USE_SHUNT_NODE=0 + NODE_PROTOCOL=$(config_n_get $node protocol) + [ "$NODE_PROTOCOL" = "_shunt" ] && USE_SHUNT_NODE=1 + [ "$USE_SHUNT_NODE" = "1" ] && { + local default_node=$(config_n_get ${node} default_node _direct) + local default_outbound="redirect" + [ "$default_node" = "_direct" ] && default_outbound="direct" + local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') + for shunt_id in $shunt_ids; do + local shunt_node=$(config_n_get ${node} "${shunt_id}" nil) + [ "$shunt_node" != "nil" ] && { + local ipset_v4="passwall2_${node}_${shunt_id}" + local ipset_v6="passwall2_${node}_${shunt_id}6" + ipset -! create $ipset_v4 nethash maxelem 1048576 + ipset -! create $ipset_v6 nethash family inet6 maxelem 1048576 + local outbound="redirect" + [ "$shunt_node" = "_direct" ] && outbound="direct" + [ "$shunt_node" = "_default" ] && outbound="${default_outbound}" + _SHUNT_LIST4="${_SHUNT_LIST4} ${ipset_v4}:${outbound}" + _SHUNT_LIST6="${_SHUNT_LIST6} ${ipset_v6}:${outbound}" + + config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_v4 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_v6 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { + local _geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') + [ -n "$_geoip_code" ] && { + if [ "$(config_n_get $node type)" = "sing-box" ]; then + get_singbox_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_v4 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + get_singbox_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_v6 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + else + if type geoview &> /dev/null; then + get_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_v4 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + get_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_v6 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + fi + fi + echolog " - [$?]解析分流规则[$shunt_id]-[geoip:${_geoip_code}]加入到 IPSET 完成" + } + } + } + done + [ "${_write_ipset_direct}" = "1" ] && { + _SHUNT_LIST4="${_SHUNT_LIST4} ${_set_name4}:direct" + _SHUNT_LIST6="${_SHUNT_LIST6} ${_set_name6}:direct" + } + [ "$default_node" != "nil" ] && { + local ipset_v4="passwall2_${node}_default" + local ipset_v6="passwall2_${node}_default6" + ipset -! create $ipset_v4 nethash maxelem 1048576 + ipset -! create $ipset_v6 nethash family inet6 maxelem 1048576 + _SHUNT_LIST4="${_SHUNT_LIST4} ${ipset_v4}:${default_outbound}" + _SHUNT_LIST6="${_SHUNT_LIST6} ${ipset_v6}:${default_outbound}" + } + } + [ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\" + [ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\" +} + +add_shunt_t_rule() { + local shunt_args=${1} + local t_args=${2} + local t_jump_args=${3} + [ -n "${shunt_args}" ] && { + for j in ${shunt_args}; do + local _set_name=$(echo ${j} | awk -F ':' '{print $1}') + local _outbound=$(echo ${j} | awk -F ':' '{print $2}') + [ -n "${_set_name}" ] && [ -n "${_outbound}" ] && { + local _t_arg="${t_jump_args}" + [ "${_outbound}" = "direct" ] && _t_arg="-j RETURN" + ${t_args} $(dst ${_set_name}) ${_t_arg} + } + done + } +} + load_acl() { [ "$ENABLED_ACLS" == 1 ] && { acl_app @@ -207,6 +292,8 @@ load_acl() { node_remark=$(config_n_get $NODE remarks) [ -s "${TMP_ACL_PATH}/${sid}/var_node" ] && node=$(cat ${TMP_ACL_PATH}/${sid}/var_node) [ -s "${TMP_ACL_PATH}/${sid}/var_port" ] && redir_port=$(cat ${TMP_ACL_PATH}/${sid}/var_port) + [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) + [ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT} [ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks) write_ipset_direct=${write_ipset_direct:-1} @@ -221,32 +308,7 @@ load_acl() { ipset -! create $ipset_whitelist6 nethash family inet6 maxelem 1048576 #分流规则的IP列表(使用分流节点时导入) - local _USE_SHUNT_NODE=0 - _NODE_PROTOCOL=$(config_n_get $node protocol) - [ "$_NODE_PROTOCOL" = "_shunt" ] && _USE_SHUNT_NODE=1 - [ "$_USE_SHUNT_NODE" = "1" ] && { - local _SHUNT_DEFAULT_NODE=$(config_n_get $NODE default_node _direct) - local _GEOIP_CODE="" - local _shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for _shunt_id in $_shunt_ids; do - local _SHUNT_RULE_NODE=$(config_n_get $NODE ${_shunt_id} nil) - [ "${_SHUNT_RULE_NODE}" == "_default" ] && _SHUNT_RULE_NODE=${_SHUNT_DEFAULT_NODE} - [ "${_SHUNT_RULE_NODE}" == "_direct" ] && { - config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_whitelist &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_whitelist6 &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { - local _geoip_code=$(config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') - [ -n "$_geoip_code" ] && _GEOIP_CODE="${_GEOIP_CODE:+$_GEOIP_CODE,}$_geoip_code" - } - } - done - } - - if [ -n "$_GEOIP_CODE" ] && type geoview &> /dev/null; then - get_geoip $_GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_whitelist &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - get_geoip $_GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_whitelist6 &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - echolog " - [$?]解析并加入分流节点 GeoIP 到 IPSET 完成" - fi + gen_shunt_list ${node} shunt_list4 shunt_list6 ${write_ipset_direct} ${ipset_whitelist} ${ipset_whitelist6} fi } @@ -324,11 +386,11 @@ load_acl() { } if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$redir_port" ]; then - [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && { - $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) - $ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) 2>/dev/null - $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) - $ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) 2>/dev/null + [ -n "$dns_redirect_port" ] && { + $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port + $ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null + $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port + $ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null } else $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN @@ -349,24 +411,24 @@ load_acl() { [ "$accept_icmp" = "1" ] && { $ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} -d $FAKE_IP $(REDIRECT) - [ "${write_ipset_direct}" = "1" ] && $ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} $(dst $ipset_whitelist) -j RETURN + add_shunt_t_rule "${shunt_list4}" "$ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source}" "$(REDIRECT)" $ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} $(REDIRECT) } [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { $ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source} -d $FAKE_IP_6 $(REDIRECT) 2>/dev/null - [ "${write_ipset_direct}" = "1" ] && $ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source} $(dst $ipset_whitelist6) -j RETURN 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "$ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source}" "$(REDIRECT)" 2>/dev/null $ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source} $(REDIRECT) 2>/dev/null } $ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} -d $FAKE_IP ${ipt_j} - [ "${write_ipset_direct}" = "1" ] && $ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(dst $ipset_whitelist) -j RETURN + add_shunt_t_rule "${shunt_list4}" "$ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(factor $tcp_redir_ports "-m multiport --dport")" "${ipt_j}" $ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(factor $tcp_redir_ports "-m multiport --dport") ${ipt_j} [ -n "${is_tproxy}" ] && $ipt_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY) [ "$PROXY_IPV6" == "1" ] && { $ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} -d $FAKE_IP_6 -j PSW2_RULE 2>/dev/null - [ "${write_ipset_direct}" = "1" ] && $ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(dst $ipset_whitelist6) -j RETURN 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(factor $tcp_redir_ports "-m multiport --dport")" "${ipt_j}" 2>/dev/null $ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(factor $tcp_redir_ports "-m multiport --dport") -j PSW2_RULE 2>/dev/null $ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY) 2>/dev/null } @@ -379,13 +441,13 @@ load_acl() { msg2="${msg}使用 UDP 节点[$node_remark](TPROXY:${redir_port})" $ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP -j PSW2_RULE - [ "${write_ipset_direct}" = "1" ] && $ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(dst $ipset_whitelist) -j RETURN + add_shunt_t_rule "${shunt_list4}" "$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(factor $udp_redir_ports "-m multiport --dport")" "-j PSW2_RULE" $ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(factor $udp_redir_ports "-m multiport --dport") -j PSW2_RULE $ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(REDIRECT $redir_port TPROXY) [ "$PROXY_IPV6" == "1" ] && [ "$PROXY_IPV6_UDP" == "1" ] && { $ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP_6 -j PSW2_RULE 2>/dev/null - [ "${write_ipset_direct}" = "1" ] && $ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(dst $ipset_whitelist6) -j RETURN 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(factor $udp_redir_ports "-m multiport --dport")" "-j PSW2_RULE" 2>/dev/null $ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(factor $udp_redir_ports "-m multiport --dport") -j PSW2_RULE 2>/dev/null $ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(REDIRECT $redir_port TPROXY) 2>/dev/null } @@ -429,11 +491,11 @@ load_acl() { } if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ "$NODE" != "nil" ]; then - [ -s "${TMP_ACL_PATH}/default/var_redirect_dns_port" ] && { - $ipt_n -A PSW2_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) - $ip6t_n -A PSW2_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) 2>/dev/null - $ipt_n -A PSW2_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) - $ip6t_n -A PSW2_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) 2>/dev/null + [ -n "$DNS_REDIRECT_PORT" ] && { + $ipt_n -A PSW2_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A PSW2_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + $ipt_n -A PSW2_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A PSW2_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null } fi @@ -449,24 +511,24 @@ load_acl() { [ "$accept_icmp" = "1" ] && { $ipt_n -A PSW2 $(comment "默认") -p icmp -d $FAKE_IP $(REDIRECT) - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_n -A PSW2 $(comment "默认") -p icmp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_n -A PSW2 $(comment "默认") -p icmp" "$(REDIRECT)" $ipt_n -A PSW2 $(comment "默认") -p icmp $(REDIRECT) } [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { $ip6t_n -A PSW2 $(comment "默认") -p ipv6-icmp -d $FAKE_IP_6 $(REDIRECT) - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_n -A PSW2 $(comment "默认") -p ipv6-icmp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_n -A PSW2 $(comment "默认") -p ipv6-icmp" "$(REDIRECT)" $ip6t_n -A PSW2 $(comment "默认") -p ipv6-icmp $(REDIRECT) } $ipt_tmp -A PSW2 $(comment "默认") -p tcp -d $FAKE_IP ${ipt_j} - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_tmp -A PSW2 $(comment "默认") -p tcp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_tmp -A PSW2 $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport")" "${ipt_j}" $ipt_tmp -A PSW2 $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") ${ipt_j} [ -n "${is_tproxy}" ] && $ipt_m -A PSW2 $(comment "默认") -p tcp $(REDIRECT $REDIR_PORT TPROXY) [ "$PROXY_IPV6" == "1" ] && { $ip6t_m -A PSW2 $(comment "默认") -p tcp -d $FAKE_IP_6 -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_m -A PSW2 $(comment "默认") -p tcp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2 $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ip6t_m -A PSW2 $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ip6t_m -A PSW2 $(comment "默认") -p tcp $(REDIRECT $REDIR_PORT TPROXY) } @@ -478,13 +540,13 @@ load_acl() { msg2="${msg}使用 UDP 节点[$(config_n_get $NODE remarks)](TPROXY:${REDIR_PORT})" $ipt_m -A PSW2 $(comment "默认") -p udp -d $FAKE_IP -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_m -A PSW2 $(comment "默认") -p udp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_m -A PSW2 $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ipt_m -A PSW2 $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ipt_m -A PSW2 $(comment "默认") -p udp $(REDIRECT $REDIR_PORT TPROXY) if [ "$PROXY_IPV6_UDP" == "1" ]; then $ip6t_m -A PSW2 $(comment "默认") -p udp -d $FAKE_IP_6 -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_m -A PSW2 $(comment "默认") -p udp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2 $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ip6t_m -A PSW2 $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ip6t_m -A PSW2 $(comment "默认") -p udp $(REDIRECT $REDIR_PORT TPROXY) fi @@ -670,32 +732,7 @@ add_firewall_rule() { ipset -! create $ipset_global_whitelist6 nethash family inet6 maxelem 1048576 timeout 259200 #分流规则的IP列表(使用分流节点时导入) - local USE_SHUNT_NODE=0 - NODE_PROTOCOL=$(config_n_get $NODE protocol) - [ "$NODE_PROTOCOL" = "_shunt" ] && USE_SHUNT_NODE=1 - [ "$USE_SHUNT_NODE" = "1" ] && { - local SHUNT_DEFAULT_NODE=$(config_n_get $NODE default_node _direct) - local GEOIP_CODE="" - local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for shunt_id in $shunt_ids; do - local SHUNT_RULE_NODE=$(config_n_get $NODE ${shunt_id} nil) - [ "${SHUNT_RULE_NODE}" == "_default" ] && SHUNT_RULE_NODE=${SHUNT_DEFAULT_NODE} - [ "${SHUNT_RULE_NODE}" == "_direct" ] && { - config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_global_whitelist &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_global_whitelist6 &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { - local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') - [ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code" - } - } - done - } - - if [ -n "$GEOIP_CODE" ] && type geoview &> /dev/null; then - get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_global_whitelist &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_global_whitelist6 &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - echolog " - [$?]解析并加入分流节点 GeoIP 到 IPSET 完成" - fi + gen_shunt_list ${NODE} SHUNT_LIST4 SHUNT_LIST6 ${WRITE_IPSET_DIRECT} ${ipset_global_whitelist} ${ipset_global_whitelist6} # 过滤所有节点IP filter_vpsip > /dev/null 2>&1 & @@ -867,11 +904,11 @@ add_firewall_rule() { } if [ "$NODE" != "nil" ] && ([ "$TCP_LOCALHOST_PROXY" = "1" ] || [ "$UDP_LOCALHOST_PROXY" = "1" ]); then - [ -s "${TMP_ACL_PATH}/default/var_redirect_dns_port" ] && { - $ipt_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) - $ip6t_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) 2>/dev/null - $ipt_n -A OUTPUT $(comment "PSW2") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) - $ip6t_n -A OUTPUT $(comment "PSW2") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) 2>/dev/null + [ -n "$DNS_REDIRECT_PORT" ] && { + $ipt_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + $ipt_n -A OUTPUT $(comment "PSW2") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A OUTPUT $(comment "PSW2") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null } fi @@ -880,14 +917,14 @@ add_firewall_rule() { [ "$accept_icmp" = "1" ] && { $ipt_n -A OUTPUT -p icmp -j PSW2_OUTPUT $ipt_n -A PSW2_OUTPUT -p icmp -d $FAKE_IP $(REDIRECT) - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_n -A PSW2_OUTPUT -p icmp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_n -A PSW2_OUTPUT -p icmp" "$(REDIRECT)" $ipt_n -A PSW2_OUTPUT -p icmp $(REDIRECT) } [ "$accept_icmpv6" = "1" ] && { $ip6t_n -A OUTPUT -p ipv6-icmp -j PSW2_OUTPUT $ip6t_n -A PSW2_OUTPUT -p ipv6-icmp -d $FAKE_IP_6 $(REDIRECT) - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_n -A PSW2_OUTPUT -p ipv6-icmp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp" "$(REDIRECT)" $ip6t_n -A PSW2_OUTPUT -p ipv6-icmp $(REDIRECT) } @@ -898,7 +935,7 @@ add_firewall_rule() { fi $ipt_tmp -A PSW2_OUTPUT -p tcp -d $FAKE_IP ${ipt_j} - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_tmp -A PSW2_OUTPUT -p tcp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_tmp -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport")" "${ipt_j}" $ipt_tmp -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") ${ipt_j} [ -z "${is_tproxy}" ] && $ipt_n -A OUTPUT -p tcp -j PSW2_OUTPUT [ -n "${is_tproxy}" ] && { @@ -909,7 +946,7 @@ add_firewall_rule() { if [ "$PROXY_IPV6" == "1" ]; then $ip6t_m -A PSW2_OUTPUT -p tcp -d $FAKE_IP_6 -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_m -A PSW2_OUTPUT -p tcp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ip6t_m -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ip6t_m -A PSW2 $(comment "本机") -p tcp -i lo $(REDIRECT $REDIR_PORT TPROXY) $ip6t_m -A PSW2 $(comment "本机") -p tcp -i lo -j RETURN @@ -925,7 +962,7 @@ add_firewall_rule() { # 加载路由器自身代理 UDP if [ "$NODE" != "nil" ] && [ "$UDP_LOCALHOST_PROXY" = "1" ]; then $ipt_m -A PSW2_OUTPUT -p udp -d $FAKE_IP -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_m -A PSW2_OUTPUT -p udp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ipt_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ipt_m -A PSW2 $(comment "本机") -p udp -i lo $(REDIRECT $REDIR_PORT TPROXY) $ipt_m -A PSW2 $(comment "本机") -p udp -i lo -j RETURN @@ -933,7 +970,7 @@ add_firewall_rule() { if [ "$PROXY_IPV6_UDP" == "1" ]; then $ip6t_m -A PSW2_OUTPUT -p udp -d $FAKE_IP_6 -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_m -A PSW2_OUTPUT -p udp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ip6t_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ip6t_m -A PSW2 $(comment "本机") -p udp -i lo $(REDIRECT $REDIR_PORT TPROXY) $ip6t_m -A PSW2 $(comment "本机") -p udp -i lo -j RETURN @@ -996,6 +1033,7 @@ flush_ipset_reload() { del_firewall_rule flush_ipset rm -rf /tmp/singbox_passwall2_* + rm -f /tmp/etc/passwall2_tmp/geoip-*.json /etc/init.d/passwall2 reload } diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/nftables.sh b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/nftables.sh index fb0112ec21..303431cb0c 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/nftables.sh +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/nftables.sh @@ -241,6 +241,92 @@ get_wan6_ip() { echo $NET_ADDR } +gen_shunt_list() { + local node=${1} + local shunt_list4_var_name=${2} + local shunt_list6_var_name=${3} + local _write_ipset_direct=${4} + local _set_name4=${5} + local _set_name6=${6} + [ -z "$node" ] && continue + unset ${shunt_list4_var_name} + unset ${shunt_list6_var_name} + local _SHUNT_LIST4 _SHUNT_LIST6 + local USE_SHUNT_NODE=0 + NODE_PROTOCOL=$(config_n_get $node protocol) + [ "$NODE_PROTOCOL" = "_shunt" ] && USE_SHUNT_NODE=1 + [ "$USE_SHUNT_NODE" = "1" ] && { + local default_node=$(config_n_get ${node} default_node _direct) + local default_outbound="redirect" + [ "$default_node" = "_direct" ] && default_outbound="direct" + local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') + for shunt_id in $shunt_ids; do + local shunt_node=$(config_n_get ${node} "${shunt_id}" nil) + [ "$shunt_node" != "nil" ] && { + local nftset_v4="passwall2_${node}_${shunt_id}" + local nftset_v6="passwall2_${node}_${shunt_id}6" + gen_nftset $nftset_v4 ipv4_addr 0 0 + gen_nftset $nftset_v6 ipv6_addr 0 0 + local outbound="redirect" + [ "$shunt_node" = "_direct" ] && outbound="direct" + [ "$shunt_node" = "_default" ] && outbound="${default_outbound}" + _SHUNT_LIST4="${_SHUNT_LIST4} ${nftset_v4}:${outbound}" + _SHUNT_LIST6="${_SHUNT_LIST6} ${nftset_v6}:${outbound}" + insert_nftset $nftset_v4 "0" $(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") + insert_nftset $nftset_v6 "0" $(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") + [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { + local _geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') + [ -n "$_geoip_code" ] && { + if [ "$(config_n_get $node type)" = "sing-box" ]; then + insert_nftset $nftset_v4 "0" $(get_singbox_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") + insert_nftset $nftset_v6 "0" $(get_singbox_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") + else + if type geoview &> /dev/null; then + insert_nftset $nftset_v4 "0" $(get_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") + insert_nftset $nftset_v6 "0" $(get_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") + fi + fi + echolog " - [$?]解析分流规则[$shunt_id]-[geoip:${_geoip_code}]加入到 NFTSET 完成" + } + } + } + done + [ "${_write_ipset_direct}" = "1" ] && { + _SHUNT_LIST4="${_SHUNT_LIST4} ${_set_name4}:direct" + _SHUNT_LIST6="${_SHUNT_LIST6} ${_set_name6}:direct" + } + [ "$default_node" != "nil" ] && { + local nftset_v4="passwall2_${node}_default" + local nftset_v6="passwall2_${node}_default6" + gen_nftset $nftset_v4 ipv4_addr 0 0 + gen_nftset $nftset_v6 ipv6_addr 0 0 + _SHUNT_LIST4="${_SHUNT_LIST4} ${nftset_v4}:${default_outbound}" + _SHUNT_LIST6="${_SHUNT_LIST6} ${nftset_v6}:${default_outbound}" + } + } + [ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\" + [ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\" +} + +add_shunt_t_rule() { + local shunt_args=${1} + local t_args=${2} + local t_jump_args=${3} + local t_comment=${4} + [ -n "${shunt_args}" ] && { + [ -n "${t_comment}" ] && t_comment="comment \"$t_comment\"" + for j in ${shunt_args}; do + local _set_name=$(echo ${j} | awk -F ':' '{print $1}') + local _outbound=$(echo ${j} | awk -F ':' '{print $2}') + [ -n "${_set_name}" ] && [ -n "${_outbound}" ] && { + local _t_arg="${t_jump_args}" + [ "${_outbound}" = "direct" ] && _t_arg="counter return" + ${t_args} @${_set_name} ${_t_arg} ${t_comment} + } + done + } +} + load_acl() { [ "$ENABLED_ACLS" == 1 ] && { acl_app @@ -261,6 +347,8 @@ load_acl() { node_remark=$(config_n_get $NODE remarks) [ -s "${TMP_ACL_PATH}/${sid}/var_node" ] && node=$(cat ${TMP_ACL_PATH}/${sid}/var_node) [ -s "${TMP_ACL_PATH}/${sid}/var_port" ] && redir_port=$(cat ${TMP_ACL_PATH}/${sid}/var_port) + [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) + [ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT} [ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks) write_ipset_direct=${write_ipset_direct:-1} @@ -275,32 +363,7 @@ load_acl() { gen_nftset $nftset_whitelist6 ipv6_addr 3d 3d #分流规则的IP列表(使用分流节点时导入) - local _USE_SHUNT_NODE=0 - _NODE_PROTOCOL=$(config_n_get $node protocol) - [ "$_NODE_PROTOCOL" = "_shunt" ] && _USE_SHUNT_NODE=1 - [ "$_USE_SHUNT_NODE" = "1" ] && { - local _SHUNT_DEFAULT_NODE=$(config_n_get $NODE default_node _direct) - local _GEOIP_CODE="" - local _shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for _shunt_id in $_shunt_ids; do - local _SHUNT_RULE_NODE=$(config_n_get $NODE ${_shunt_id} nil) - [ "${_SHUNT_RULE_NODE}" == "_default" ] && _SHUNT_RULE_NODE=${_SHUNT_DEFAULT_NODE} - [ "${_SHUNT_RULE_NODE}" == "_direct" ] && { - insert_nftset $nftset_whitelist "0" $(config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") - insert_nftset $nftset_whitelist6 "0" $(config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") - [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { - local _geoip_code=$(config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') - [ -n "$_geoip_code" ] && _GEOIP_CODE="${_GEOIP_CODE:+$_GEOIP_CODE,}$_geoip_code" - } - } - done - } - - if [ -n "$_GEOIP_CODE" ] && type geoview &> /dev/null; then - insert_nftset $nftset_whitelist "0" $(get_geoip $_GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") - insert_nftset $nftset_whitelist6 "0" $(get_geoip $_GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") - echolog " - [$?]解析并加入分流节点 GeoIP 到 IPSET 完成" - fi + gen_shunt_list ${node} shunt_list4 shunt_list6 ${write_ipset_direct} ${nftset_whitelist} ${nftset_whitelist6} fi } @@ -368,11 +431,11 @@ load_acl() { } if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$redir_port" ]; then - [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && { - nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) comment \"$remarks\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) comment \"$remarks\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) comment \"$remarks\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) comment \"$remarks\"" + [ -n "$dns_redirect_port" ] && { + nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" } else nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" @@ -395,26 +458,26 @@ load_acl() { [ "$accept_icmp" = "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} ip daddr $FAKE_IP $(REDIRECT) comment \"$remarks\"" - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} ip daddr @$nftset_whitelist counter return comment \"$remarks\"" + add_shunt_t_rule "${shunt_list4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} ip daddr" "$(REDIRECT)" "$remarks" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} $(REDIRECT) comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} return comment \"$remarks\"" } [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr $FAKE_IP_6 $(REDIRECT) comment \"$remarks\"" 2>/dev/null - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr @$nftset_whitelist6 counter return comment \"$remarks\"" 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr" "$(REDIRECT)" "$remarks" 2>/dev/null nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} $(REDIRECT) comment \"$remarks\"" 2>/dev/null nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} return comment \"$remarks\"" 2>/dev/null } nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} ip daddr $FAKE_IP ${nft_j} comment \"$remarks\"" - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} ip daddr @$nftset_whitelist counter return comment \"$remarks\"" + add_shunt_t_rule "${shunt_list4}" "nft add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ip daddr" "${nft_j}" "$remarks" nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ${nft_j} comment \"$remarks\"" [ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY4) comment \"$remarks\"" [ "$PROXY_IPV6" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} ip6 daddr $FAKE_IP_6 counter jump PSW2_RULE comment \"$remarks\"" - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} ip6 daddr @$nftset_whitelist6 counter return comment \"$remarks\"" 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "nft add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ip6 daddr" "counter jump PSW2_RULE" "$remarks" 2>/dev/null nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") counter jump PSW2_RULE comment \"$remarks\"" 2>/dev/null nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY) comment \"$remarks\"" 2>/dev/null } @@ -427,13 +490,13 @@ load_acl() { msg2="${msg}使用 UDP 节点[$node_remark](TPROXY:${redir_port})" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} ip daddr $FAKE_IP counter jump PSW2_RULE comment \"$remarks\"" - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} ip daddr @$nftset_whitelist counter return comment \"$remarks\"" + add_shunt_t_rule "${shunt_list4}" "nft add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") ip daddr" "counter jump PSW2_RULE" "$remarks" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") counter jump PSW2_RULE comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(REDIRECT $redir_port TPROXY4) comment \"$remarks\"" [ "$PROXY_IPV6" == "1" ] && [ "$PROXY_IPV6_UDP" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} ip6 daddr $FAKE_IP_6 counter jump PSW2_RULE comment \"$remarks\"" - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} ip6 daddr @$nftset_whitelist6 counter return comment \"$remarks\"" 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "nft add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") ip6 daddr" "counter jump PSW2_RULE" "$remarks" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") counter jump PSW2_RULE comment \"$remarks\"" 2>/dev/null nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(REDIRECT $redir_port TPROXY) comment \"$remarks\"" 2>/dev/null } @@ -475,11 +538,11 @@ load_acl() { } if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ "$NODE" != "nil" ]; then - [ -s "${TMP_ACL_PATH}/default/var_redirect_dns_port" ] && { - nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"默认\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"默认\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"默认\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"默认\"" + [ -n "$DNS_REDIRECT_PORT" ] && { + nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" } fi @@ -497,26 +560,26 @@ load_acl() { [ "$accept_icmp" = "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ip daddr $FAKE_IP $(REDIRECT) comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ip daddr @$nftset_global_whitelist counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ip daddr" "$(REDIRECT)" "默认" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp $(REDIRECT) comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp return comment \"默认\"" } [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr $FAKE_IP_6 $(REDIRECT) comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr @$nftset_global_whitelist6 counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr" "$(REDIRECT)" "默认" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 $(REDIRECT) comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 return comment \"默认\"" } nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr $FAKE_IP ${nft_j} comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr @$nftset_global_whitelist counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip daddr" "${nft_j}" "默认" nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ${nft_j} comment \"默认\"" [ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp $(REDIRECT $REDIR_PORT TPROXY4) comment \"默认\"" [ "$PROXY_IPV6" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 jump PSW2_RULE comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ip6 daddr @$nftset_global_whitelist6 counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip6 daddr" "${nft_j}" "默认" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") counter jump PSW2_RULE comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(REDIRECT $REDIR_PORT TPROXY) comment \"默认\"" } @@ -528,13 +591,13 @@ load_acl() { msg2="${msg}使用 UDP 节点[$(config_n_get $NODE remarks)](TPROXY:${REDIR_PORT})" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ip daddr @$nftset_global_whitelist counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") ip daddr" "counter jump PSW2_RULE" "默认" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(REDIRECT $REDIR_PORT TPROXY4) comment \"默认\"" [ "$PROXY_IPV6" == "1" ] && [ "$PROXY_IPV6_UDP" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 jump PSW2_RULE comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ip6 daddr @$nftset_global_whitelist6 counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") ip6 daddr" "counter jump PSW2_RULE" "默认" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp $(REDIRECT $REDIR_PORT TPROXY) comment \"默认\"" } @@ -716,32 +779,7 @@ add_firewall_rule() { gen_nftset $nftset_global_whitelist6 ipv6_addr 0 0 #分流规则的IP列表(使用分流节点时导入) - local USE_SHUNT_NODE=0 - NODE_PROTOCOL=$(config_n_get $NODE protocol) - [ "$NODE_PROTOCOL" = "_shunt" ] && USE_SHUNT_NODE=1 - [ "$USE_SHUNT_NODE" = "1" ] && { - local SHUNT_DEFAULT_NODE=$(config_n_get $NODE default_node _direct) - local GEOIP_CODE="" - local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for shunt_id in $shunt_ids; do - local SHUNT_RULE_NODE=$(config_n_get $NODE ${shunt_id} nil) - [ "${SHUNT_RULE_NODE}" == "_default" ] && SHUNT_RULE_NODE=${SHUNT_DEFAULT_NODE} - [ "${SHUNT_RULE_NODE}" == "_direct" ] && { - insert_nftset $nftset_global_whitelist "0" $(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") - insert_nftset $nftset_global_whitelist6 "0" $(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") - [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { - local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') - [ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code" - } - } - done - } - - if [ -n "$GEOIP_CODE" ] && type geoview &> /dev/null; then - insert_nftset $nftset_global_whitelist "0" $(get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") - insert_nftset $nftset_global_whitelist6 "0" $(get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") - echolog " - [$?]解析并加入分流节点 GeoIP 到 IPSET 完成" - fi + gen_shunt_list ${NODE} SHUNT_LIST4 SHUNT_LIST6 ${WRITE_IPSET_DIRECT} ${nftset_global_whitelist} ${nftset_global_whitelist6} # 过滤所有节点IP filter_vpsip > /dev/null 2>&1 & @@ -925,11 +963,11 @@ add_firewall_rule() { } if [ "$NODE" != "nil" ] && ([ "$TCP_LOCALHOST_PROXY" = "1" ] || [ "$UDP_LOCALHOST_PROXY" = "1" ]); then - [ -s "${TMP_ACL_PATH}/default/var_redirect_dns_port" ] && { - nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"PSW2\"" - nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"PSW2\"" - nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"PSW2\"" - nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"PSW2\"" + [ -n "$DNS_REDIRECT_PORT" ] && { + nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\"" + nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\"" + nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\"" + nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\"" } fi @@ -937,14 +975,14 @@ add_firewall_rule() { if [ "$NODE" != "nil" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then [ "$accept_icmp" = "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr $FAKE_IP counter redirect" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr @$nftset_global_whitelist counter return" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr" "counter redirect" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp counter redirect" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp counter return" } [ "$accept_icmpv6" = "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 ip6 daddr $FAKE_IP_6 counter redirect" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 ip6 daddr @$nftset_global_whitelist6 counter return" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 ip6 daddr" "counter redirect" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 counter redirect" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 counter return" } @@ -958,7 +996,7 @@ add_firewall_rule() { fi nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr $FAKE_IP ${nft_j}" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr @$nftset_global_whitelist counter return" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip daddr" "${nft_j}" nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ${nft_j}" [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME nat_output ip protocol tcp counter jump PSW2_OUTPUT_NAT" [ -n "${is_tproxy}" ] && { @@ -969,7 +1007,7 @@ add_firewall_rule() { [ "$PROXY_IPV6" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 jump PSW2_RULE" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp ip6 daddr @$nftset_global_whitelist6 counter return" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip6 daddr" "counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp iif lo $(REDIRECT $REDIR_PORT TPROXY) comment \"本机\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp iif lo counter return comment \"本机\"" @@ -984,7 +1022,7 @@ add_firewall_rule() { # 加载路由器自身代理 UDP if [ "$NODE" != "nil" ] && [ "$UDP_LOCALHOST_PROXY" = "1" ]; then nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp ip daddr @$nftset_global_whitelist counter return" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") ip daddr" "counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp iif lo $(REDIRECT $REDIR_PORT TPROXY4) comment \"本机\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp iif lo counter return comment \"本机\"" @@ -992,7 +1030,7 @@ add_firewall_rule() { if [ "$PROXY_IPV6_UDP" == "1" ]; then nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 jump PSW2_RULE" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr @$nftset_global_whitelist6 counter return" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") ip6 daddr" "counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo $(REDIRECT $REDIR_PORT TPROXY) comment \"本机\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo counter return comment \"本机\"" @@ -1073,6 +1111,7 @@ flush_nftset_reload() { del_firewall_rule flush_table rm -rf /tmp/singbox_passwall2_* + rm -f /tmp/etc/passwall2_tmp/geoip-*.json /etc/init.d/passwall2 reload } diff --git a/sing-box/.github/workflows/build.yml b/sing-box/.github/workflows/build.yml index b55a331a83..2a61e463db 100644 --- a/sing-box/.github/workflows/build.yml +++ b/sing-box/.github/workflows/build.yml @@ -7,11 +7,6 @@ on: description: "Version name" required: true type: string - prerelease: - description: "Is prerelease" - required: true - type: boolean - default: true build: description: "Build type" required: true @@ -28,10 +23,6 @@ on: - tvOS - macOS-standalone - publish-android - macos_project_version: - description: "macOS project version" - required: false - type: string push: branches: - main-next @@ -47,7 +38,6 @@ jobs: runs-on: ubuntu-latest outputs: version: ${{ steps.outputs.outputs.version }} - prerelease: ${{ steps.outputs.outputs.prerelease }} steps: - name: Checkout uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4 @@ -61,9 +51,7 @@ jobs: if: github.event_name == 'workflow_dispatch' run: |- echo "version=${{ inputs.version }}" - echo "prerelease=${{ inputs.prerelease }}" echo "version=${{ inputs.version }}" >> "$GITHUB_ENV" - echo "prerelease=${{ inputs.prerelease }}" >> "$GITHUB_ENV" - name: Calculate version if: github.event_name != 'workflow_dispatch' run: |- @@ -72,7 +60,6 @@ jobs: id: outputs run: |- echo "version=$version" >> "$GITHUB_OUTPUT" - echo "prerelease=$prerelease" >> "$GITHUB_OUTPUT" build: name: Build binary if: github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Binary' @@ -253,12 +240,12 @@ jobs: JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} - name: Checkout main branch - if: needs.calculate_version.outputs.prerelease == 'false' + if: github.ref == 'refs/heads/main-next' && github.event_name != 'workflow_dispatch' run: |- cd clients/android git checkout main - name: Checkout dev branch - if: needs.calculate_version.outputs.prerelease == 'true' + if: github.ref == 'refs/heads/dev-next' && github.event_name != 'workflow_dispatch' run: |- cd clients/android git checkout dev @@ -327,12 +314,12 @@ jobs: JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} - name: Checkout main branch - if: needs.calculate_version.outputs.prerelease == 'false' + if: github.ref == 'refs/heads/main-next' && github.event_name != 'workflow_dispatch' run: |- cd clients/android git checkout main - name: Checkout dev branch - if: needs.calculate_version.outputs.prerelease == 'true' + if: github.ref == 'refs/heads/dev-next' && github.event_name != 'workflow_dispatch' run: |- cd clients/android git checkout dev @@ -354,67 +341,38 @@ jobs: ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }} SERVICE_ACCOUNT_CREDENTIALS: ${{ secrets.SERVICE_ACCOUNT_CREDENTIALS }} - build_apple_library: - name: Build Apple library - if: github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Apple' || inputs.build == 'app-store' || inputs.build == 'iOS' || inputs.build == 'macOS' || inputs.build == 'tvOS' || inputs.build == 'macOS-standalone' - runs-on: macos-15 - needs: - - calculate_version - steps: - - name: Checkout - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4 - with: - fetch-depth: 0 - submodules: 'recursive' - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: ^1.23 - - name: Setup Xcode - run: |- - sudo xcode-select -s /Applications/Xcode_16.2_beta_3.app - - name: Set tag - run: |- - git tag v${{ needs.calculate_version.outputs.version }} - - name: Build library - run: |- - make lib_install - export PATH="$PATH:$(go env GOPATH)/bin" - make lib_ios - - name: Upload library - uses: actions/upload-artifact@v4 - with: - name: library-apple - path: 'Libbox.xcframework' build_apple: name: Build Apple clients runs-on: macos-15 needs: - calculate_version - - build_apple_library strategy: matrix: include: - name: iOS if: ${{ github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Apple' || inputs.build == 'app-store'|| inputs.build == 'iOS' }} + platform: ios scheme: SFI destination: 'generic/platform=iOS' archive: build/SFI.xcarchive upload: SFI/Upload.plist - name: macOS if: ${{ github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Apple' || inputs.build == 'app-store'|| inputs.build == 'macOS' }} + platform: macos scheme: SFM destination: 'generic/platform=macOS' archive: build/SFM.xcarchive upload: SFI/Upload.plist - name: tvOS if: ${{ github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Apple' || inputs.build == 'app-store'|| inputs.build == 'tvOS' }} + platform: tvos scheme: SFT destination: 'generic/platform=tvOS' archive: build/SFT.xcarchive upload: SFI/Upload.plist - name: macOS-standalone if: ${{ github.event_name != 'workflow_dispatch' || inputs.build == 'All' || inputs.build == 'Apple' || inputs.build == 'macOS-standalone' }} + platform: macos scheme: SFM.System destination: 'generic/platform=macOS' archive: build/SFM.System.xcarchive @@ -432,22 +390,26 @@ jobs: uses: actions/setup-go@v5 with: go-version: ^1.23 - - name: Setup Xcode - if: matrix.if + - name: Setup Xcode stable + if: matrix.if && github.ref == 'refs/heads/main-next' run: |- - sudo xcode-select -s /Applications/Xcode_16.2_beta_3.app + sudo xcode-select -s /Applications/Xcode_16.1.app + - name: Setup Xcode beta + if: matrix.if && github.ref == 'refs/heads/dev-next' + run: |- + sudo xcode-select -s /Applications/Xcode_16.2.app - name: Set tag if: matrix.if run: |- git tag v${{ needs.calculate_version.outputs.version }} echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV" - name: Checkout main branch - if: matrix.if && needs.calculate_version.outputs.prerelease == 'false' + if: matrix.if && github.ref == 'refs/heads/main-next' && github.event_name != 'workflow_dispatch' run: |- cd clients/apple git checkout main - name: Checkout dev branch - if: matrix.if && needs.calculate_version.outputs.prerelease == 'true' + if: matrix.if && github.ref == 'refs/heads/dev-next' && github.event_name != 'workflow_dispatch' run: |- cd clients/apple git checkout dev @@ -478,6 +440,10 @@ jobs: --key $ASC_KEY_PATH \ --key-id $ASC_KEY_ID \ --issuer $ASC_KEY_ISSUER_ID + + echo "ASC_KEY_PATH=$ASC_KEY_PATH" >> "$GITHUB_ENV" + echo "ASC_KEY_ID=$ASC_KEY_ID" >> "$GITHUB_ENV" + echo "ASC_KEY_ISSUER_ID=$ASC_KEY_ISSUER_ID" >> "$GITHUB_ENV" env: CERTIFICATES_P12: ${{ secrets.CERTIFICATES_P12 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} @@ -486,12 +452,19 @@ jobs: ASC_KEY: ${{ secrets.ASC_KEY }} ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }} ASC_KEY_ISSUER_ID: ${{ secrets.ASC_KEY_ISSUER_ID }} - - name: Download library + - name: Build library if: matrix.if - uses: actions/download-artifact@v4 - with: - name: library-apple - path: clients/apple/Libbox.xcframework + run: |- + make lib_install + export PATH="$PATH:$(go env GOPATH)/bin" + go run ./cmd/internal/build_libbox -target apple -platform ${{ matrix.platform }} + mv Libbox.xcframework clients/apple + - name: Update macOS version + if: matrix.if && matrix.name == 'macOS' && github.event_name == 'workflow_dispatch' + run: |- + MACOS_PROJECT_VERSION=$(go run -v ./cmd/internal/app_store_connect next_macos_project_version) + echo "MACOS_PROJECT_VERSION=$MACOS_PROJECT_VERSION" + echo "MACOS_PROJECT_VERSION=$MACOS_PROJECT_VERSION" >> "$GITHUB_ENV" - name: Build if: matrix.if run: |- @@ -503,13 +476,9 @@ jobs: -destination "${{ matrix.destination }}" \ -archivePath "${{ matrix.archive }}" \ -allowProvisioningUpdates \ - -authenticationKeyPath $RUNNER_TEMP/Key.p12 \ + -authenticationKeyPath $ASC_KEY_PATH \ -authenticationKeyID $ASC_KEY_ID \ -authenticationKeyIssuerID $ASC_KEY_ISSUER_ID - env: - MACOS_PROJECT_VERSION: ${{ inputs.macos_project_version }} - ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }} - ASC_KEY_ISSUER_ID: ${{ secrets.ASC_KEY_ISSUER_ID }} - name: Upload to App Store Connect if: matrix.if && matrix.name != 'macOS-standalone' && github.event_name == 'workflow_dispatch' run: |- @@ -518,12 +487,9 @@ jobs: -archivePath "${{ matrix.archive }}" \ -exportOptionsPlist ${{ matrix.upload }} \ -allowProvisioningUpdates \ - -authenticationKeyPath $RUNNER_TEMP/Key.p12 \ + -authenticationKeyPath $ASC_KEY_PATH \ -authenticationKeyID $ASC_KEY_ID \ -authenticationKeyIssuerID $ASC_KEY_ISSUER_ID - env: - ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }} - ASC_KEY_ISSUER_ID: ${{ secrets.ASC_KEY_ISSUER_ID }} - name: Build image if: matrix.if && matrix.name == 'macOS-standalone' && github.event_name == 'workflow_dispatch' run: |- diff --git a/sing-box/Makefile b/sing-box/Makefile index 2bc149892a..11cecd17f6 100644 --- a/sing-box/Makefile +++ b/sing-box/Makefile @@ -182,10 +182,22 @@ release_tvos: build_tvos upload_tvos_app_store update_apple_version: go run ./cmd/internal/update_apple_version +update_macos_version: + MACOS_PROJECT_VERSION=$(shell go run -v ./cmd/internal/app_store_connect next_macos_project_version) go run ./cmd/internal/update_apple_version + release_apple: lib_ios update_apple_version release_ios release_macos release_tvos release_macos_standalone release_apple_beta: update_apple_version release_ios release_macos release_tvos +publish_testflight: + go run -v ./cmd/internal/app_store_connect publish_testflight + +prepare_app_store: + go run -v ./cmd/internal/app_store_connect prepare_app_store + +publish_app_store: + go run -v ./cmd/internal/app_store_connect publish_app_store + test: @go test -v ./... && \ cd test && \ @@ -204,11 +216,11 @@ lib_android: lib_android_debug: go run ./cmd/internal/build_libbox -target android -debug -lib_ios: - go run ./cmd/internal/build_libbox -target ios +lib_apple: + go run ./cmd/internal/build_libbox -target apple -lib_ios_debug: - go run ./cmd/internal/build_libbox -target ios -debug +lib_ios: + go run ./cmd/internal/build_libbox -target apple -platform ios -debug lib: go run ./cmd/internal/build_libbox -target android diff --git a/sing-box/clients/android/app/build.gradle b/sing-box/clients/android/app/build.gradle index 01661cc58d..acfa36b5d6 100644 --- a/sing-box/clients/android/app/build.gradle +++ b/sing-box/clients/android/app/build.gradle @@ -12,7 +12,7 @@ android { namespace "io.nekohasekai.sfa" compileSdk 35 - ndkVersion "26.2.11394342" + ndkVersion "28.0.12674087" ksp { arg("room.incremental", "true") @@ -51,6 +51,10 @@ android { } } + dependenciesInfo { + includeInApk = false + } + flavorDimensions "vendor" productFlavors { play { @@ -143,18 +147,25 @@ tasks.withType(KotlinCompile.class).configureEach { } def getProps(String propName) { + def propsInEnv = System.getenv("LOCAL_PROPERTIES") + if (propsInEnv != null) { + def props = new Properties() + props.load(new ByteArrayInputStream(Base64.decoder.decode(propsInEnv))) + String value = props[propName] + if (value != null) { + return value + } + } def propsFile = rootProject.file("local.properties") if (propsFile.exists()) { def props = new Properties() props.load(new FileInputStream(propsFile)) String value = props[propName] - if (value == null) { - return "" + if (value != null) { + return value } - return value - } else { - return "" } + return "" } def getVersionProps(String propName) { @@ -163,11 +174,9 @@ def getVersionProps(String propName) { def props = new Properties() props.load(new FileInputStream(propsFile)) String value = props[propName] - if (value == null) { - return "" + if (value != null) { + return value } - return value - } else { - return "" } + return "" } \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/DefaultNetworkMonitor.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/DefaultNetworkMonitor.kt index 3d116b825b..7ca51e4d03 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/DefaultNetworkMonitor.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/DefaultNetworkMonitor.kt @@ -4,6 +4,10 @@ import android.net.Network import android.os.Build import io.nekohasekai.libbox.InterfaceUpdateListener import io.nekohasekai.sfa.Application +import io.nekohasekai.sfa.BuildConfig +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import java.net.NetworkInterface object DefaultNetworkMonitor { @@ -55,12 +59,25 @@ object DefaultNetworkMonitor { Thread.sleep(100) continue } - listener.updateDefaultInterface(interfaceName, interfaceIndex) + // TODO: remove launch after fixed + // https://github.com/golang/go/issues/68760 + if (BuildConfig.DEBUG) { + GlobalScope.launch(Dispatchers.IO) { + listener.updateDefaultInterface(interfaceName, interfaceIndex) + } + } else { + listener.updateDefaultInterface(interfaceName, interfaceIndex) + } } } else { - listener.updateDefaultInterface("", -1) + if (BuildConfig.DEBUG) { + GlobalScope.launch(Dispatchers.IO) { + listener.updateDefaultInterface("", -1) + } + } else { + listener.updateDefaultInterface("", -1) + } } } - } \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/UpdateProfileWork.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/UpdateProfileWork.kt index 2e833b568c..9dee852fdb 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/UpdateProfileWork.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/bg/UpdateProfileWork.kt @@ -11,6 +11,7 @@ import androidx.work.WorkerParameters import io.nekohasekai.libbox.Libbox import io.nekohasekai.sfa.Application import io.nekohasekai.sfa.database.ProfileManager +import io.nekohasekai.sfa.database.Settings import io.nekohasekai.sfa.database.TypedProfile import io.nekohasekai.sfa.utils.HTTPClient import java.io.File @@ -63,10 +64,12 @@ class UpdateProfileWork { appContext: Context, params: WorkerParameters ) : CoroutineWorker(appContext, params) { override suspend fun doWork(): Result { + var selectedProfileUpdated = false val remoteProfiles = ProfileManager.list() .filter { it.typed.type == TypedProfile.Type.Remote && it.typed.autoUpdate } if (remoteProfiles.isEmpty()) return Result.success() var success = true + val selectedProfile = Settings.selectedProfile for (profile in remoteProfiles) { val lastSeconds = (System.currentTimeMillis() - profile.typed.lastUpdated.time) / 1000L @@ -76,7 +79,13 @@ class UpdateProfileWork { try { val content = HTTPClient().use { it.getString(profile.typed.remoteURL) } Libbox.checkConfig(content) - File(profile.typed.path).writeText(content) + val file = File(profile.typed.path) + if (file.readText() != content) { + File(profile.typed.path).writeText(content) + if (profile.id == selectedProfile) { + selectedProfileUpdated = true + } + } profile.typed.lastUpdated = Date() ProfileManager.update(profile) } catch (e: Exception) { @@ -84,6 +93,11 @@ class UpdateProfileWork { success = false } } + if (selectedProfileUpdated) { + runCatching { + Libbox.newStandaloneCommandClient().serviceReload() + } + } return if (success) { Result.success() } else { diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ktx/Wrappers.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ktx/Wrappers.kt index 1fc7ad1826..bd8b2f6d50 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ktx/Wrappers.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ktx/Wrappers.kt @@ -4,9 +4,16 @@ import android.net.IpPrefix import android.os.Build import androidx.annotation.RequiresApi import io.nekohasekai.libbox.RoutePrefix +import io.nekohasekai.libbox.StringBox import io.nekohasekai.libbox.StringIterator import java.net.InetAddress +val StringBox?.unwrap: String + get() { + if (this == null) return "" + return value + } + fun Iterable.toStringIterator(): StringIterator { return object : StringIterator { val iterator = iterator() diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt index d3986a24f1..0cfb338644 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/MainActivity.kt @@ -18,14 +18,11 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController import androidx.navigation.NavDestination -import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.navigateUp import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController -import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat import com.google.android.material.dialog.MaterialAlertDialogBuilder import io.nekohasekai.libbox.Libbox import io.nekohasekai.libbox.ProfileContent @@ -46,7 +43,6 @@ import io.nekohasekai.sfa.ktx.errorDialogBuilder import io.nekohasekai.sfa.ktx.hasPermission import io.nekohasekai.sfa.ktx.launchCustomTab import io.nekohasekai.sfa.ui.profile.NewProfileActivity -import io.nekohasekai.sfa.ui.settings.CoreFragment import io.nekohasekai.sfa.ui.shared.AbstractActivity import io.nekohasekai.sfa.utils.MIUIUtils import io.nekohasekai.sfa.vendor.Vendor @@ -57,7 +53,6 @@ import java.io.File import java.util.Date class MainActivity : AbstractActivity(), - PreferenceFragmentCompat.OnPreferenceStartFragmentCallback, ServiceConnection.Callback { companion object { @@ -111,21 +106,6 @@ class MainActivity : AbstractActivity(), binding.dashboardTabContainer.isVisible = destinationId == R.id.navigation_dashboard } - override fun onPreferenceStartFragment( - caller: PreferenceFragmentCompat, - pref: Preference - ): Boolean { - val navController = findNavController(R.id.nav_host_fragment_activity_my) - when (pref.fragment) { - CoreFragment::class.java.name -> { - navController.navigate(R.id.navigation_settings_core) - return true - } - - else -> return false - } - } - override public fun onNewIntent(intent: Intent) { super.onNewIntent(intent) val uri = intent.data ?: return diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/SettingsFragment.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/SettingsFragment.kt index 564d69d07a..ae6ff697bb 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/SettingsFragment.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/SettingsFragment.kt @@ -1,7 +1,6 @@ package io.nekohasekai.sfa.ui.main import android.annotation.SuppressLint -import android.app.Activity import android.content.Intent import android.net.Uri import android.os.Build @@ -48,8 +47,8 @@ class SettingsFragment : Fragment() { private val requestIgnoreBatteryOptimizations = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { result -> - if (result.resultCode == Activity.RESULT_OK) { - binding.backgroundPermissionCard.isVisible = false + if (Application.powerManager.isIgnoringBatteryOptimizations(Application.application.packageName)) { + binding.backgroundPermissionCard.isGone = true } } diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/SettingsFragment0.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/SettingsFragment0.kt deleted file mode 100644 index 9c3dfb1a43..0000000000 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/main/SettingsFragment0.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.nekohasekai.sfa.ui.main - -import io.nekohasekai.sfa.R -import io.nekohasekai.sfa.ui.settings.AbstractSettingsFragment - -class SettingsFragment0 : AbstractSettingsFragment(R.xml.preferences_settings) { - - -} \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileActivity.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileActivity.kt index 9935a1daf2..29924c80b8 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileActivity.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileActivity.kt @@ -11,6 +11,7 @@ import io.nekohasekai.sfa.bg.UpdateProfileWork import io.nekohasekai.sfa.constant.EnabledType import io.nekohasekai.sfa.database.Profile import io.nekohasekai.sfa.database.ProfileManager +import io.nekohasekai.sfa.database.Settings import io.nekohasekai.sfa.database.TypedProfile import io.nekohasekai.sfa.databinding.ActivityEditProfileBinding import io.nekohasekai.sfa.ktx.addTextChangedListener @@ -166,10 +167,17 @@ class EditProfileActivity : AbstractActivity() { private fun updateProfile(view: View) { binding.progressView.isVisible = true lifecycleScope.launch(Dispatchers.IO) { + var selectedProfileUpdated = false try { val content = HTTPClient().use { it.getString(profile.typed.remoteURL) } Libbox.checkConfig(content) - File(profile.typed.path).writeText(content) + val file = File(profile.typed.path) + if (file.readText() != content) { + File(profile.typed.path).writeText(content) + if (profile.id == Settings.selectedProfile) { + selectedProfileUpdated = true + } + } profile.typed.lastUpdated = Date() ProfileManager.update(profile) } catch (e: Exception) { @@ -182,6 +190,11 @@ class EditProfileActivity : AbstractActivity() { DateFormat.getDateTimeInstance().format(profile.typed.lastUpdated) binding.progressView.isVisible = false } + if (selectedProfileUpdated) { + runCatching { + Libbox.newStandaloneCommandClient().serviceReload() + } + } } } diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileContentActivity.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileContentActivity.kt index 7beacdfdcd..df762eb6e2 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileContentActivity.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/profile/EditProfileContentActivity.kt @@ -14,6 +14,7 @@ import io.nekohasekai.sfa.database.Profile import io.nekohasekai.sfa.database.ProfileManager import io.nekohasekai.sfa.databinding.ActivityEditProfileContentBinding import io.nekohasekai.sfa.ktx.errorDialogBuilder +import io.nekohasekai.sfa.ktx.unwrap import io.nekohasekai.sfa.ui.shared.AbstractActivity import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -84,7 +85,7 @@ class EditProfileContentActivity : AbstractActivity { lifecycleScope.launch(Dispatchers.IO) { runCatching { - val content = Libbox.formatConfig(binding.editor.text.toString()) + val content = Libbox.formatConfig(binding.editor.text.toString()).unwrap if (binding.editor.text.toString() != content) { withContext(Dispatchers.Main) { binding.editor.setTextContent(content) diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/AbstractSettingsFragment.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/AbstractSettingsFragment.kt deleted file mode 100644 index 5043c1e33b..0000000000 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/AbstractSettingsFragment.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.nekohasekai.sfa.ui.settings - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.annotation.XmlRes -import androidx.preference.PreferenceFragmentCompat -import androidx.recyclerview.widget.RecyclerView -import io.nekohasekai.sfa.R - -open class AbstractSettingsFragment(@XmlRes val resId: Int) : PreferenceFragmentCompat() { - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(resId, rootKey) - } - - override fun onCreateRecyclerView( - inflater: LayoutInflater, - parent: ViewGroup, - savedInstanceState: Bundle? - ): RecyclerView { - val recyclerView = inflater - .inflate(R.layout.view_prefenence_screen, parent, false) as RecyclerView - recyclerView.layoutManager = onCreateLayoutManager() - return recyclerView - } - -} \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/CoreFragment.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/CoreFragment.kt deleted file mode 100644 index b3268853eb..0000000000 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/CoreFragment.kt +++ /dev/null @@ -1,6 +0,0 @@ -package io.nekohasekai.sfa.ui.settings - -import androidx.fragment.app.Fragment - -class CoreFragment : Fragment() { -} \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/Preference.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/Preference.kt deleted file mode 100644 index 738d624125..0000000000 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/ui/settings/Preference.kt +++ /dev/null @@ -1,45 +0,0 @@ -package io.nekohasekai.sfa.ui.settings - -import android.content.Context -import android.util.AttributeSet -import android.util.TypedValue -import androidx.preference.Preference -import io.nekohasekai.sfa.ktx.getAttrColor - -class Preference : Preference { - - constructor( - context: Context, - attrs: AttributeSet?, - defStyleAttr: Int, - defStyleRes: Int - ) : super(context, attrs, defStyleAttr, defStyleRes) { - icon?.setTint(context.getAttrColor(com.google.android.material.R.attr.colorOnSurface)) - } - - constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : this( - context, - attrs, - defStyleAttr, - 0 - ) - - constructor(context: Context, attrs: AttributeSet?) : this( - context, attrs, getAttr( - context, androidx.preference.R.attr.preferenceStyle, - android.R.attr.preferenceStyle - ) - ) - - companion object { - private fun getAttr(context: Context, attr: Int, fallbackAttr: Int): Int { - val value = TypedValue() - context.theme.resolveAttribute(attr, value, true) - if (value.resourceId != 0) { - return attr - } - return fallbackAttr - } - } - -} \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/utils/HTTPClient.kt b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/utils/HTTPClient.kt index 722347201a..baab03f9bb 100644 --- a/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/utils/HTTPClient.kt +++ b/sing-box/clients/android/app/src/main/java/io/nekohasekai/sfa/utils/HTTPClient.kt @@ -2,6 +2,7 @@ package io.nekohasekai.sfa.utils import io.nekohasekai.libbox.Libbox import io.nekohasekai.sfa.BuildConfig +import io.nekohasekai.sfa.ktx.unwrap import java.io.Closeable class HTTPClient : Closeable { @@ -30,7 +31,7 @@ class HTTPClient : Closeable { request.setUserAgent(userAgent) request.setURL(url) val response = request.execute() - return response.contentString + return response.content.unwrap } override fun close() { diff --git a/sing-box/clients/android/app/src/main/res/layout/fragment_settings_core.xml b/sing-box/clients/android/app/src/main/res/layout/fragment_settings_core.xml deleted file mode 100644 index 77d9ef65f8..0000000000 --- a/sing-box/clients/android/app/src/main/res/layout/fragment_settings_core.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/res/navigation/mobile_navigation.xml b/sing-box/clients/android/app/src/main/res/navigation/mobile_navigation.xml index 1cf86db9c9..cc64ba40de 100644 --- a/sing-box/clients/android/app/src/main/res/navigation/mobile_navigation.xml +++ b/sing-box/clients/android/app/src/main/res/navigation/mobile_navigation.xml @@ -29,10 +29,5 @@ android:label="@string/title_settings" tools:layout="@layout/fragment_settings" /> - \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/res/values/strings.xml b/sing-box/clients/android/app/src/main/res/values/strings.xml index 80a3535462..0172808309 100644 --- a/sing-box/clients/android/app/src/main/res/values/strings.xml +++ b/sing-box/clients/android/app/src/main/res/values/strings.xml @@ -194,6 +194,5 @@ background location permission is required. Select Allow all the time to grant the permission.]]> Open Settings - Core \ No newline at end of file diff --git a/sing-box/clients/android/app/src/main/res/xml/preferences_settings.xml b/sing-box/clients/android/app/src/main/res/xml/preferences_settings.xml deleted file mode 100644 index 1ba928fa37..0000000000 --- a/sing-box/clients/android/app/src/main/res/xml/preferences_settings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/sing-box/clients/android/build.gradle b/sing-box/clients/android/build.gradle index 9958810d7e..644045e3e4 100644 --- a/sing-box/clients/android/build.gradle +++ b/sing-box/clients/android/build.gradle @@ -5,10 +5,10 @@ buildscript { } plugins { - id 'com.android.application' version '8.7.2' apply false - id 'com.android.library' version '8.7.2' apply false - id 'org.jetbrains.kotlin.android' version '1.9.23' apply false - id 'com.google.devtools.ksp' version '1.9.23-1.0.20' apply false + id 'com.android.application' version '8.7.3' apply false + id 'com.android.library' version '8.7.3' apply false + id 'org.jetbrains.kotlin.android' version '2.1.0' apply false + id 'com.google.devtools.ksp' version '2.1.0-1.0.29' apply false id 'com.github.triplet.play' version '3.8.4' apply false } diff --git a/sing-box/clients/android/gradle.properties b/sing-box/clients/android/gradle.properties index a2e90d87bd..b822cc753e 100644 --- a/sing-box/clients/android/gradle.properties +++ b/sing-box/clients/android/gradle.properties @@ -6,7 +6,7 @@ # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects diff --git a/sing-box/clients/android/gradle/wrapper/gradle-wrapper.properties b/sing-box/clients/android/gradle/wrapper/gradle-wrapper.properties index a32e0b5ec0..d0124e5236 100644 --- a/sing-box/clients/android/gradle/wrapper/gradle-wrapper.properties +++ b/sing-box/clients/android/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ -#Sun Oct 06 20:10:49 CST 2024 +#Fri Nov 29 14:47:37 CST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/sing-box/clients/android/version.properties b/sing-box/clients/android/version.properties index 9f5cb776a3..2911da5812 100644 --- a/sing-box/clients/android/version.properties +++ b/sing-box/clients/android/version.properties @@ -1,3 +1,3 @@ -VERSION_CODE=432 -VERSION_NAME=1.10.3 -GO_VERSION=go1.23.3 +VERSION_CODE=443 +VERSION_NAME=1.10.4 +GO_VERSION=go1.23.4 diff --git a/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/DashboardView.swift b/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/DashboardView.swift index c7c851aa4c..b73b056117 100644 --- a/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/DashboardView.swift +++ b/sing-box/clients/apple/ApplicationLibrary/Views/Dashboard/DashboardView.swift @@ -165,7 +165,7 @@ public struct DashboardView: View { return } await MainActor.run { - alert = Alert(title: Text("Service Error"), message: Text(message)) + alert = Alert(title: Text("Service Error"), message: Text(message!.value)) } } diff --git a/sing-box/clients/apple/ApplicationLibrary/Views/Profile/EditProfileView.swift b/sing-box/clients/apple/ApplicationLibrary/Views/Profile/EditProfileView.swift index 65598ecdbf..25043c01b7 100644 --- a/sing-box/clients/apple/ApplicationLibrary/Views/Profile/EditProfileView.swift +++ b/sing-box/clients/apple/ApplicationLibrary/Views/Profile/EditProfileView.swift @@ -166,6 +166,7 @@ public struct EditProfileView: View { #else try await ProfileUpdateTask.configure() #endif + try await profile.onProfileUpdated() } catch { alert = Alert(error) return diff --git a/sing-box/clients/apple/Library/Database/Profile+Update.swift b/sing-box/clients/apple/Library/Database/Profile+Update.swift index c3bed660fe..0a1e07c385 100644 --- a/sing-box/clients/apple/Library/Database/Profile+Update.swift +++ b/sing-box/clients/apple/Library/Database/Profile+Update.swift @@ -13,8 +13,25 @@ public extension Profile { if let error { throw error } - try write(remoteContent) lastUpdated = Date() try await ProfileManager.update(self) + do { + let oldContent = try read() + if oldContent == remoteContent { + return + } + } catch {} + try write(remoteContent) + try await onProfileUpdated() + } + + nonisolated func onProfileUpdated() async throws { + if await SharedPreferences.selectedProfileID.get() == id { + if let profile = try? await ExtensionProfile.load() { + if profile.status == .connected { + try LibboxNewStandaloneCommandClient()!.serviceReload() + } + } + } } } diff --git a/sing-box/clients/apple/Library/Network/ExtensionProvider.swift b/sing-box/clients/apple/Library/Network/ExtensionProvider.swift index 400c781ee6..5936a106c9 100644 --- a/sing-box/clients/apple/Library/Network/ExtensionProvider.swift +++ b/sing-box/clients/apple/Library/Network/ExtensionProvider.swift @@ -103,14 +103,13 @@ open class ExtensionProvider: NEPacketTunnelProvider { guard let service else { return } - commandServer.setService(service) do { try service.start() } catch { - commandServer.setService(nil) writeFatalError("(packet-tunnel) error: start service: \(error.localizedDescription)") return } + commandServer.setService(service) boxService = service #if os(macOS) await SharedPreferences.startedByUser.set(true) diff --git a/sing-box/clients/apple/Library/Network/HTTPClient.swift b/sing-box/clients/apple/Library/Network/HTTPClient.swift index 5355b6ea44..2206c5a635 100644 --- a/sing-box/clients/apple/Library/Network/HTTPClient.swift +++ b/sing-box/clients/apple/Library/Network/HTTPClient.swift @@ -26,12 +26,8 @@ public class HTTPClient { request.setUserAgent(HTTPClient.userAgent) try request.setURL(url) let response = try request.execute() - var error: NSError? - let contentString = response.getContentString(&error) - if let error { - throw error - } - return contentString + let content = try response.getContent() + return content.value } deinit { diff --git a/sing-box/clients/apple/sing-box.xcodeproj/project.pbxproj b/sing-box/clients/apple/sing-box.xcodeproj/project.pbxproj index cd828c8f97..13031412b1 100644 --- a/sing-box/clients/apple/sing-box.xcodeproj/project.pbxproj +++ b/sing-box/clients/apple/sing-box.xcodeproj/project.pbxproj @@ -2147,7 +2147,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.10.3; + MARKETING_VERSION = 1.10.4; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; SDKROOT = appletvos; @@ -2182,7 +2182,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.10.3; + MARKETING_VERSION = 1.10.4; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; SDKROOT = appletvos; @@ -2487,7 +2487,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.10.3; + MARKETING_VERSION = 1.10.4; OTHER_CODE_SIGN_FLAGS = "--deep"; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; @@ -2529,7 +2529,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.10.3; + MARKETING_VERSION = 1.10.4; OTHER_CODE_SIGN_FLAGS = "--deep"; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; @@ -2552,7 +2552,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 290; + CURRENT_PROJECT_VERSION = 291; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 287TTNZF8L; ENABLE_HARDENED_RUNTIME = YES; @@ -2570,7 +2570,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.3; + MARKETING_VERSION = 1.10.4; OTHER_CODE_SIGN_FLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; @@ -2592,7 +2592,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 290; + CURRENT_PROJECT_VERSION = 291; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 287TTNZF8L; ENABLE_HARDENED_RUNTIME = YES; @@ -2610,7 +2610,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.3; + MARKETING_VERSION = 1.10.4; OTHER_CODE_SIGN_FLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt; PRODUCT_NAME = "sing-box"; @@ -2738,7 +2738,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.3; + MARKETING_VERSION = 1.10.4; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt.system; PRODUCT_NAME = "$(inherited)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2774,7 +2774,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.3; + MARKETING_VERSION = 1.10.4; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt.system; PRODUCT_NAME = "$(inherited)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2816,7 +2816,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.3; + MARKETING_VERSION = 1.10.4; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt.standalone; PRODUCT_NAME = SFM; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2857,7 +2857,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.10.3; + MARKETING_VERSION = 1.10.4; PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfavt.standalone; PRODUCT_NAME = SFM; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/sing-box/cmd/internal/app_store_connect/main.go b/sing-box/cmd/internal/app_store_connect/main.go new file mode 100644 index 0000000000..5a3d6ab923 --- /dev/null +++ b/sing-box/cmd/internal/app_store_connect/main.go @@ -0,0 +1,299 @@ +package main + +import ( + "context" + "net/http" + "os" + "strconv" + "time" + + "github.com/sagernet/sing-box/cmd/internal/build_shared" + "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing/common" + E "github.com/sagernet/sing/common/exceptions" + F "github.com/sagernet/sing/common/format" + + "github.com/cidertool/asc-go/asc" +) + +func main() { + ctx := context.Background() + switch os.Args[1] { + case "next_macos_project_version": + err := fetchMacOSVersion(ctx) + if err != nil { + log.Fatal(err) + } + case "publish_testflight": + err := publishTestflight(ctx) + if err != nil { + log.Fatal(err) + } + case "prepare_app_store": + err := prepareAppStore(ctx) + if err != nil { + log.Fatal(err) + } + case "publish_app_store": + err := publishAppStore(ctx) + if err != nil { + log.Fatal(err) + } + default: + log.Fatal("unknown action: ", os.Args[1]) + } +} + +const ( + appID = "6673731168" + groupID = "5c5f3b78-b7a0-40c0-bcad-e6ef87bbefda" +) + +func createClient() *asc.Client { + privateKey, err := os.ReadFile(os.Getenv("ASC_KEY_PATH")) + if err != nil { + log.Fatal(err) + } + tokenConfig, err := asc.NewTokenConfig(os.Getenv("ASC_KEY_ID"), os.Getenv("ASC_KEY_ISSUER_ID"), time.Minute, privateKey) + if err != nil { + log.Fatal(err) + } + return asc.NewClient(tokenConfig.Client()) +} + +func fetchMacOSVersion(ctx context.Context) error { + client := createClient() + versions, _, err := client.Apps.ListAppStoreVersionsForApp(ctx, appID, &asc.ListAppStoreVersionsQuery{ + FilterPlatform: []string{"MAC_OS"}, + }) + if err != nil { + return err + } + var versionID string +findVersion: + for _, version := range versions.Data { + switch *version.Attributes.AppStoreState { + case asc.AppStoreVersionStateReadyForSale, + asc.AppStoreVersionStatePendingDeveloperRelease: + versionID = version.ID + break findVersion + } + } + if versionID == "" { + return E.New("no version found") + } + latestBuild, _, err := client.Builds.GetBuildForAppStoreVersion(ctx, versionID, &asc.GetBuildForAppStoreVersionQuery{}) + if err != nil { + return err + } + versionInt, err := strconv.Atoi(*latestBuild.Data.Attributes.Version) + if err != nil { + return E.Cause(err, "parse version code") + } + os.Stdout.WriteString(F.ToString(versionInt+1, "\n")) + return nil +} + +func publishTestflight(ctx context.Context) error { + client := createClient() + var buildsToPublish []asc.Build + for _, platform := range []string{ + "IOS", + "MAC_OS", + "TV_OS", + } { + builds, _, err := client.Builds.ListBuilds(ctx, &asc.ListBuildsQuery{ + FilterApp: []string{appID}, + FilterPreReleaseVersionPlatform: []string{platform}, + }) + if err != nil { + return err + } + buildsToPublish = append(buildsToPublish, builds.Data[0]) + } + _, err := client.TestFlight.AddBuildsToBetaGroup(ctx, groupID, common.Map(buildsToPublish, func(it asc.Build) string { + return it.ID + })) + if err != nil { + return err + } + return nil +} + +func prepareAppStore(ctx context.Context) error { + tag, err := build_shared.ReadTag() + if err != nil { + return err + } + client := createClient() + for _, platform := range []asc.Platform{ + asc.PlatformIOS, + asc.PlatformMACOS, + asc.PlatformTVOS, + } { + log.Info(string(platform), " list versions") + versions, _, err := client.Apps.ListAppStoreVersionsForApp(ctx, appID, &asc.ListAppStoreVersionsQuery{ + FilterPlatform: []string{string(platform)}, + }) + if err != nil { + return err + } + version := common.Find(versions.Data, func(it asc.AppStoreVersion) bool { + return *it.Attributes.VersionString == tag + }) + log.Info(string(platform), " ", tag, " list builds") + builds, _, err := client.Builds.ListBuilds(ctx, &asc.ListBuildsQuery{ + FilterApp: []string{appID}, + FilterPreReleaseVersionPlatform: []string{string(platform)}, + }) + if err != nil { + return err + } + if len(builds.Data) == 0 { + log.Fatal(platform, " ", tag, " no build found") + } + buildID := common.Ptr(builds.Data[0].ID) + if version.ID == "" { + log.Info(string(platform), " ", tag, " create version") + newVersion, _, err := client.Apps.CreateAppStoreVersion(ctx, asc.AppStoreVersionCreateRequestAttributes{ + Platform: platform, + VersionString: tag, + }, appID, buildID) + if err != nil { + return err + } + version = newVersion.Data + + } else { + log.Info(string(platform), " ", tag, " check build") + currentBuild, response, err := client.Apps.GetBuildIDForAppStoreVersion(ctx, version.ID) + if err != nil { + return err + } + if response.StatusCode != http.StatusOK || currentBuild.Data.ID != *buildID { + switch *version.Attributes.AppStoreState { + case asc.AppStoreVersionStatePrepareForSubmission, + asc.AppStoreVersionStateRejected, + asc.AppStoreVersionStateDeveloperRejected: + case asc.AppStoreVersionStateWaitingForReview, + asc.AppStoreVersionStateInReview, + asc.AppStoreVersionStatePendingDeveloperRelease: + submission, _, err := client.Submission.GetAppStoreVersionSubmissionForAppStoreVersion(ctx, version.ID, nil) + if err != nil { + return err + } + if submission != nil { + log.Info(string(platform), " ", tag, " delete submission") + _, err = client.Submission.DeleteSubmission(ctx, submission.Data.ID) + if err != nil { + return err + } + time.Sleep(5 * time.Second) + } + default: + log.Fatal(string(platform), " ", tag, " unknown state ", string(*version.Attributes.AppStoreState)) + } + log.Info(string(platform), " ", tag, " update build") + _, _, err = client.Apps.UpdateBuildForAppStoreVersion(ctx, version.ID, buildID) + if err != nil { + return err + } + } else { + switch *version.Attributes.AppStoreState { + case asc.AppStoreVersionStatePrepareForSubmission, + asc.AppStoreVersionStateRejected, + asc.AppStoreVersionStateDeveloperRejected: + case asc.AppStoreVersionStateWaitingForReview, + asc.AppStoreVersionStateInReview, + asc.AppStoreVersionStatePendingDeveloperRelease: + continue + default: + log.Fatal(string(platform), " ", tag, " unknown state ", string(*version.Attributes.AppStoreState)) + } + } + } + log.Info(string(platform), " ", tag, " list localization") + localizations, _, err := client.Apps.ListLocalizationsForAppStoreVersion(ctx, version.ID, nil) + if err != nil { + return err + } + localization := common.Find(localizations.Data, func(it asc.AppStoreVersionLocalization) bool { + return *it.Attributes.Locale == "en-US" + }) + if localization.ID == "" { + log.Info(string(platform), " ", tag, " no en-US localization found") + } + if localization.Attributes.WhatsNew == nil && *localization.Attributes.WhatsNew == "" { + log.Info(string(platform), " ", tag, " update localization") + _, _, err = client.Apps.UpdateAppStoreVersionLocalization(ctx, localization.ID, &asc.AppStoreVersionLocalizationUpdateRequestAttributes{ + PromotionalText: common.Ptr("Yet another distribution for sing-box, the universal proxy platform."), + WhatsNew: common.Ptr(F.ToString("sing-box ", tag, ": Fixes and improvements.")), + }) + if err != nil { + return err + } + } + log.Info(string(platform), " ", tag, " create submission") + fixSubmit: + for { + _, response, err := client.Submission.CreateSubmission(ctx, version.ID) + if err != nil { + switch response.StatusCode { + case http.StatusInternalServerError: + continue + default: + response.Write(os.Stderr) + log.Info(string(platform), " ", tag, " unexpected response: ", response.Status) + } + } + switch response.StatusCode { + case http.StatusCreated: + break fixSubmit + default: + response.Write(os.Stderr) + log.Info(string(platform), " ", tag, " unexpected response: ", response.Status) + } + } + } + return nil +} + +func publishAppStore(ctx context.Context) error { + tag, err := build_shared.ReadTag() + if err != nil { + return err + } + client := createClient() + for _, platform := range []asc.Platform{ + asc.PlatformIOS, + asc.PlatformMACOS, + asc.PlatformTVOS, + } { + log.Info(string(platform), " list versions") + versions, _, err := client.Apps.ListAppStoreVersionsForApp(ctx, appID, &asc.ListAppStoreVersionsQuery{ + FilterPlatform: []string{string(platform)}, + }) + if err != nil { + return err + } + version := common.Find(versions.Data, func(it asc.AppStoreVersion) bool { + return *it.Attributes.VersionString == tag + }) + switch *version.Attributes.AppStoreState { + case asc.AppStoreVersionStatePrepareForSubmission, asc.AppStoreVersionStateDeveloperRejected: + log.Fatal(string(platform), " ", tag, " not submitted") + case asc.AppStoreVersionStateWaitingForReview, + asc.AppStoreVersionStateInReview: + log.Warn(string(platform), " ", tag, " waiting for review") + continue + case asc.AppStoreVersionStatePendingDeveloperRelease: + default: + log.Fatal(string(platform), " ", tag, " unknown state ", string(*version.Attributes.AppStoreState)) + } + _, _, err = client.Publishing.CreatePhasedRelease(ctx, common.Ptr(asc.PhasedReleaseStateComplete), version.ID) + if err != nil { + return err + } + } + return nil +} diff --git a/sing-box/cmd/internal/build_libbox/main.go b/sing-box/cmd/internal/build_libbox/main.go index cb493299c1..e37a9ff4dc 100644 --- a/sing-box/cmd/internal/build_libbox/main.go +++ b/sing-box/cmd/internal/build_libbox/main.go @@ -18,11 +18,13 @@ import ( var ( debugEnabled bool target string + platform string ) func init() { flag.BoolVar(&debugEnabled, "debug", false, "enable debug") flag.StringVar(&target, "target", "android", "target platform") + flag.StringVar(&platform, "platform", "", "specify platform") } func main() { @@ -33,8 +35,8 @@ func main() { switch target { case "android": buildAndroid() - case "ios": - buildiOS() + case "apple": + buildApple() } } @@ -81,7 +83,9 @@ func buildAndroid() { } var bindTarget string - if debugEnabled { + if platform != "" { + bindTarget = platform + } else if debugEnabled { bindTarget = "android/arm64" } else { bindTarget = "android" @@ -129,12 +133,14 @@ func buildAndroid() { } } -func buildiOS() { +func buildApple() { var bindTarget string - if debugEnabled { + if platform != "" { + bindTarget = platform + } else if debugEnabled { bindTarget = "ios" } else { - bindTarget = "ios,iossimulator,tvos,tvossimulator,macos" + bindTarget = "ios,tvos,macos" } args := []string{ diff --git a/sing-box/cmd/internal/build_shared/tag.go b/sing-box/cmd/internal/build_shared/tag.go index 16a97f3e1d..15f050907d 100644 --- a/sing-box/cmd/internal/build_shared/tag.go +++ b/sing-box/cmd/internal/build_shared/tag.go @@ -36,11 +36,3 @@ func ReadTagVersion() (badversion.Version, error) { } return version, nil } - -func IsDevBranch() bool { - branch, err := shell.Exec("git", "branch", "--show-current").ReadOutput() - if err != nil { - return false - } - return branch == "dev-next" -} diff --git a/sing-box/cmd/internal/read_tag/main.go b/sing-box/cmd/internal/read_tag/main.go index ae496ec67f..2cebaf7075 100644 --- a/sing-box/cmd/internal/read_tag/main.go +++ b/sing-box/cmd/internal/read_tag/main.go @@ -6,7 +6,6 @@ import ( "github.com/sagernet/sing-box/cmd/internal/build_shared" "github.com/sagernet/sing-box/log" - F "github.com/sagernet/sing/common/format" ) var nightly bool @@ -22,25 +21,14 @@ func main() { if err != nil { log.Fatal(err) } - var ( - versionStr string - isPrerelease bool - ) + var versionStr string if version.PreReleaseIdentifier != "" { - isPrerelease = true versionStr = version.VersionString() + "-nightly" } else { version.Patch++ versionStr = version.VersionString() + "-nightly" } - if build_shared.IsDevBranch() { - isPrerelease = true - } - err = setGitHubOutput("version", versionStr) - if err != nil { - log.Fatal(err) - } - err = setGitHubOutput("prerelease", F.ToString(isPrerelease)) + err = setGitHubEnv("version", versionStr) if err != nil { log.Fatal(err) } @@ -55,7 +43,7 @@ func main() { } } -func setGitHubOutput(name string, value string) error { +func setGitHubEnv(name string, value string) error { outputFile, err := os.OpenFile(os.Getenv("GITHUB_ENV"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644) if err != nil { return err diff --git a/sing-box/docs/changelog.md b/sing-box/docs/changelog.md index 2dfacfa94d..54b15271a6 100644 --- a/sing-box/docs/changelog.md +++ b/sing-box/docs/changelog.md @@ -2,7 +2,11 @@ icon: material/alert-decagram --- -#### 1.11.0-beta.9 +#### 1.11.0-beta.10 + +* Fixes and improvements + +### 1.10.4 * Fixes and improvements @@ -15,10 +19,6 @@ icon: material/alert-decagram See [Hysteria2](/configuration/inbound/hysteria2/#masquerade). -### 1.10.3 - -* Fixes and improvements - #### 1.11.0-alpha.25 * Update quic-go to v0.48.2 diff --git a/sing-box/go.mod b/sing-box/go.mod index 92a10040d7..be06556235 100644 --- a/sing-box/go.mod +++ b/sing-box/go.mod @@ -4,6 +4,7 @@ go 1.20 require ( github.com/caddyserver/certmagic v0.20.0 + github.com/cidertool/asc-go v0.5.1 github.com/cloudflare/circl v1.3.7 github.com/cretz/bine v0.2.0 github.com/go-chi/chi/v5 v5.1.0 @@ -58,7 +59,9 @@ require ( require ( github.com/ajg/form v1.5.1 // indirect github.com/andybalholm/brotli v1.0.6 // indirect + github.com/cenkalti/backoff/v4 v4.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect @@ -66,6 +69,7 @@ require ( github.com/gobwas/pool v0.2.1 // indirect github.com/google/btree v1.1.3 // indirect github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-querystring v1.0.0 // indirect github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect github.com/hashicorp/yamux v0.1.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/sing-box/go.sum b/sing-box/go.sum index 95072a0322..3f75a91ac4 100644 --- a/sing-box/go.sum +++ b/sing-box/go.sum @@ -4,6 +4,10 @@ github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sx github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc= github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg= +github.com/cenkalti/backoff/v4 v4.1.0 h1:c8LkOFQTzuO0WBM/ae5HdGQuZPfPxp7lqBRwQRm4fSc= +github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cidertool/asc-go v0.5.1 h1:KYki2Y8IXJMOkOXy9y1sdr8tz6IdW2ti770K4bk7WY0= +github.com/cidertool/asc-go v0.5.1/go.mod h1:LyrZWU7DeCh8cWrFwXcpl93ixRUUL2aEZV7/0h07FxA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -12,6 +16,8 @@ github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbe github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU= +github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= @@ -34,6 +40,8 @@ github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= @@ -195,6 +203,8 @@ golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE= diff --git a/small/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/small/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua index a63c1afc79..d766646af4 100644 --- a/small/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/small/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -557,9 +557,6 @@ if api.is_finded("smartdns") then o:depends({dns_shunt = "smartdns", tcp_proxy_mode = "proxy", chn_list = "direct"}) end -o = s:taboption("DNS", Flag, "dns_redirect", "DNS " .. translate("Redirect"), translate("Force Router DNS server to all local devices.")) -o.default = "0" - if (uci:get(appname, "@global_forwarding[0]", "use_nft") or "0") == "1" then o = s:taboption("DNS", Button, "clear_ipset", translate("Clear NFTSET"), translate("Try this feature if the rule modification does not take effect.")) else diff --git a/small/luci-app-passwall/po/zh-cn/passwall.po b/small/luci-app-passwall/po/zh-cn/passwall.po index 610fe9bcad..fa15bafc96 100644 --- a/small/luci-app-passwall/po/zh-cn/passwall.po +++ b/small/luci-app-passwall/po/zh-cn/passwall.po @@ -223,9 +223,6 @@ msgstr "需要代理的分流规则域名使用 FakeDNS。" msgid "Redirect" msgstr "重定向" -msgid "Force Router DNS server to all local devices." -msgstr "强制所有本地设备使用路由器 DNS。" - msgid "Clear IPSET" msgstr "清空 IPSET" diff --git a/small/luci-app-passwall/root/usr/share/passwall/app.sh b/small/luci-app-passwall/root/usr/share/passwall/app.sh index 4e1968a1f7..56a46c00aa 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/small/luci-app-passwall/root/usr/share/passwall/app.sh @@ -14,13 +14,10 @@ TMP_ROUTE_PATH=$TMP_PATH/route TMP_ACL_PATH=$TMP_PATH/acl TMP_IFACE_PATH=$TMP_PATH/iface TMP_PATH2=/tmp/etc/${CONFIG}_tmp -DNSMASQ_PATH=/etc/dnsmasq.d -DNSMASQ_CONF_DIR=/tmp/dnsmasq.d -TMP_DNSMASQ_PATH=${DNSMASQ_CONF_DIR}/${CONFIG} +GLOBAL_ACL_PATH=${TMP_ACL_PATH}/default LOG_FILE=/tmp/log/$CONFIG.log APP_PATH=/usr/share/$CONFIG RULES_PATH=/usr/share/${CONFIG}/rules -DNS_N=dnsmasq DNS_PORT=15353 TUN_DNS="127.0.0.1#${DNS_PORT}" LOCAL_DNS=119.29.29.29,223.5.5.5 @@ -359,6 +356,23 @@ parse_doh() { eval "${__url_var}='${__url}' ${__host_var}='${__host}' ${__port_var}='${__port}' ${__bootstrap_var}='${__bootstrap}'" } +get_geoip() { + local geoip_code="$1" + local geoip_type_flag="" + local geoip_path="$(config_t_get global_rules v2ray_location_asset)" + geoip_path="${geoip_path%*/}/geoip.dat" + [ -e "$geoip_path" ] || { echo ""; return; } + case "$2" in + "ipv4") geoip_type_flag="-ipv6=false" ;; + "ipv6") geoip_type_flag="-ipv4=false" ;; + esac + if type geoview &> /dev/null; then + geoview -input "$geoip_path" -list "$geoip_code" $geoip_type_flag -lowmem=true + else + echo "" + fi +} + run_ipt2socks() { local flag proto tcp_tproxy local_port socks_address socks_port socks_username socks_password log_file local _extra_param="" @@ -704,9 +718,9 @@ run_redir() { local node proto bind local_port config_file log_file eval_set_val $@ local tcp_node_socks_flag tcp_node_http_flag - [ -n "$config_file" ] && [ -z "$(echo ${config_file} | grep $TMP_PATH)" ] && config_file=${TMP_ACL_PATH}/default/${config_file} + [ -n "$config_file" ] && [ -z "$(echo ${config_file} | grep $TMP_PATH)" ] && config_file=${GLOBAL_ACL_PATH}/${config_file} if [ -n "$log_file" ] && [ -z "$(echo ${log_file} | grep $TMP_PATH)" ]; then - log_file=${TMP_ACL_PATH}/default/${log_file} + log_file=${GLOBAL_ACL_PATH}/${log_file} else log_file="/dev/null" fi @@ -1050,7 +1064,7 @@ run_redir() { [ "$tcp_node_socks" = "1" ] && { TCP_SOCKS_server="127.0.0.1:$tcp_node_socks_port" - echo "${TCP_SOCKS_server}" > $TMP_ACL_PATH/default/TCP_SOCKS_server + echo "${TCP_SOCKS_server}" > ${GLOBAL_ACL_PATH}/TCP_SOCKS_server } ;; esac @@ -1069,7 +1083,7 @@ start_redir() { local port=$(echo $(get_new_port $current_port $proto)) eval ${proto}_REDIR=$port run_redir node=$node proto=${proto} bind=0.0.0.0 local_port=$port config_file=$config_file log_file=$log_file - echo $node > $TMP_ACL_PATH/default/${proto}.id + echo $node > ${GLOBAL_ACL_PATH}/${proto}.id else [ "${proto}" = "UDP" ] && [ "$TCP_UDP" = "1" ] && return echolog "${proto}节点没有选择或为空,不代理${proto}。" @@ -1533,13 +1547,20 @@ start_dns() { dnsmasq_version=$(dnsmasq -v | grep -i "Dnsmasq version " | awk '{print $3}') [ "$(expr $dnsmasq_version \>= 2.87)" == 0 ] && echolog "Dnsmasq版本低于2.87,有可能无法正常使用!!!" } - source $APP_PATH/helper_dnsmasq.sh stretch - lua $APP_PATH/helper_dnsmasq_add.lua -FLAG "default" -TMP_DNSMASQ_PATH ${TMP_DNSMASQ_PATH} -DNSMASQ_CONF_DIR ${DNSMASQ_CONF_DIR} \ - -DNSMASQ_CONF_FILE "${DNSMASQ_CONF_DIR}/dnsmasq-${CONFIG}.conf" -DEFAULT_DNS ${DEFAULT_DNS} -LOCAL_DNS ${LOCAL_DNS} \ + + GLOBAL_DNSMASQ_PORT=$(get_new_port 11400) + local GLOBAL_DNSMASQ_CONF=${GLOBAL_ACL_PATH}/dnsmasq.conf + local GLOBAL_DNSMASQ_CONF_PATH=${GLOBAL_ACL_PATH}/dnsmasq.d + source $APP_PATH/helper_dnsmasq.sh copy_instance listen_port=$GLOBAL_DNSMASQ_PORT dnsmasq_conf="${GLOBAL_DNSMASQ_CONF}" dnsmasq_conf_path="${GLOBAL_DNSMASQ_CONF_PATH}" + lua $APP_PATH/helper_dnsmasq_add.lua -FLAG "default" -TMP_DNSMASQ_PATH ${GLOBAL_DNSMASQ_CONF_PATH} \ + -DNSMASQ_CONF_FILE ${GLOBAL_DNSMASQ_CONF} -DEFAULT_DNS ${DEFAULT_DNS} -LOCAL_DNS ${LOCAL_DNS} \ -TUN_DNS ${TUN_DNS} -REMOTE_FAKEDNS ${fakedns:-0} -USE_DEFAULT_DNS "${USE_DEFAULT_DNS:-direct}" -CHINADNS_DNS ${china_ng_listen:-0} \ -USE_DIRECT_LIST "${USE_DIRECT_LIST}" -USE_PROXY_LIST "${USE_PROXY_LIST}" -USE_BLOCK_LIST "${USE_BLOCK_LIST}" -USE_GFW_LIST "${USE_GFW_LIST}" -CHN_LIST "${CHN_LIST}" \ -TCP_NODE ${TCP_NODE} -DEFAULT_PROXY_MODE ${TCP_PROXY_MODE} -NO_PROXY_IPV6 ${DNSMASQ_FILTER_PROXY_IPV6:-0} -NFTFLAG ${nftflag:-0} \ -NO_LOGIC_LOG ${NO_LOGIC_LOG:-0} + ln_run "$(first_type dnsmasq)" "dnsmasq_default" "/dev/null" -C ${GLOBAL_DNSMASQ_CONF} -x ${GLOBAL_ACL_PATH}/dnsmasq.pid + echo "${GLOBAL_DNSMASQ_PORT}" > ${GLOBAL_ACL_PATH}/var_redirect_dns_port + DNS_REDIRECT_PORT=${GLOBAL_DNSMASQ_PORT} } add_ip2route() { @@ -1599,6 +1620,7 @@ acl_app() { redir_port=11200 dns_port=11300 dnsmasq_port=11400 + [ -n "${GLOBAL_DNSMASQ_PORT}" ] && dnsmasq_port=$(get_new_port $GLOBAL_DNSMASQ_PORT) chinadns_port=11500 for item in $items; do sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}') @@ -1625,9 +1647,10 @@ acl_app() { unset s2 done - mkdir -p $TMP_ACL_PATH/$sid + local acl_path=${TMP_ACL_PATH}/$sid + mkdir -p ${acl_path} - [ ! -z "${source_list}" ] && echo -e "${source_list}" | sed '/^$/d' > $TMP_ACL_PATH/$sid/source_list + [ ! -z "${source_list}" ] && echo -e "${source_list}" | sed '/^$/d' > ${acl_path}/source_list use_global_config=${use_global_config:-0} tcp_node=${tcp_node:-nil} @@ -1726,28 +1749,17 @@ acl_app() { } dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1)) - redirect_dns_port=$dnsmasq_port - mkdir -p $TMP_ACL_PATH/$sid/dnsmasq.d - [ -s "/tmp/etc/dnsmasq.conf.${DEFAULT_DNSMASQ_CFGID}" ] && { - cp -r /tmp/etc/dnsmasq.conf.${DEFAULT_DNSMASQ_CFGID} $TMP_ACL_PATH/$sid/dnsmasq.conf - sed -i "/ubus/d" $TMP_ACL_PATH/$sid/dnsmasq.conf - sed -i "/dhcp/d" $TMP_ACL_PATH/$sid/dnsmasq.conf - sed -i "/port=/d" $TMP_ACL_PATH/$sid/dnsmasq.conf - sed -i "/conf-dir/d" $TMP_ACL_PATH/$sid/dnsmasq.conf - sed -i "/server/d" $TMP_ACL_PATH/$sid/dnsmasq.conf - } - echo "port=${dnsmasq_port}" >> $TMP_ACL_PATH/$sid/dnsmasq.conf - [ "$use_default_dns" = "remote" ] && { - dnsmasq_version=$(dnsmasq -v | grep -i "Dnsmasq version " | awk '{print $3}') - [ "$(expr $dnsmasq_version \>= 2.87)" == 0 ] && echolog "Dnsmasq版本低于2.87,有可能无法正常使用!!!" - } - lua $APP_PATH/helper_dnsmasq_add.lua -FLAG ${sid} -TMP_DNSMASQ_PATH $TMP_ACL_PATH/$sid/dnsmasq.d -DNSMASQ_CONF_DIR ${DNSMASQ_CONF_DIR} \ - -DNSMASQ_CONF_FILE $TMP_ACL_PATH/$sid/dnsmasq.conf -DEFAULT_DNS $DEFAULT_DNS -LOCAL_DNS $LOCAL_DNS \ + local dnsmasq_conf=${acl_path}/dnsmasq.conf + local dnsmasq_conf_path=${acl_path}/dnsmasq.d + source $APP_PATH/helper_dnsmasq.sh copy_instance listen_port=$dnsmasq_port dnsmasq_conf="${dnsmasq_conf}" dnsmasq_conf_path="${dnsmasq_conf_path}" + lua $APP_PATH/helper_dnsmasq_add.lua -FLAG ${sid} -TMP_DNSMASQ_PATH ${dnsmasq_conf_path} \ + -DNSMASQ_CONF_FILE ${dnsmasq_conf} -DEFAULT_DNS $DEFAULT_DNS -LOCAL_DNS $LOCAL_DNS \ -USE_DIRECT_LIST "${use_direct_list}" -USE_PROXY_LIST "${use_proxy_list}" -USE_BLOCK_LIST "${use_block_list}" -USE_GFW_LIST "${use_gfw_list}" -CHN_LIST "${chn_list}" \ -TUN_DNS "127.0.0.1#${_dns_port}" -REMOTE_FAKEDNS 0 -USE_DEFAULT_DNS "${use_default_dns:-direct}" -CHINADNS_DNS ${_china_ng_listen:-0} \ -TCP_NODE $tcp_node -DEFAULT_PROXY_MODE ${tcp_proxy_mode} -NO_PROXY_IPV6 ${dnsmasq_filter_proxy_ipv6:-0} -NFTFLAG ${nftflag:-0} \ -NO_LOGIC_LOG 1 - ln_run "$(first_type dnsmasq)" "dnsmasq_${sid}" "/dev/null" -C $TMP_ACL_PATH/$sid/dnsmasq.conf -x $TMP_ACL_PATH/$sid/dnsmasq.pid + ln_run "$(first_type dnsmasq)" "dnsmasq_${sid}" "/dev/null" -C ${dnsmasq_conf} -x ${acl_path}/dnsmasq.pid + echo "${dnsmasq_port}" > ${acl_path}/var_redirect_dns_port eval node_${tcp_node}_$(echo -n "${tcp_proxy_mode}${remote_dns}" | md5sum | cut -d " " -f1)=${dnsmasq_port} } _redir_port=$(eval echo \${node_${tcp_node}_redir_port}) @@ -1760,7 +1772,7 @@ acl_app() { _dns_port=$(eval echo \${node_${tcp_node}_$(echo -n "${remote_dns}" | md5sum | cut -d " " -f1)}) run_dns ${_dns_port} else - redirect_dns_port=${_dnsmasq_port} + [ -n "${_dnsmasq_port}" ] && echo "${_dnsmasq_port}" > ${acl_path}/var_redirect_dns_port fi else socks_port=$(get_new_port $(expr $socks_port + 1)) @@ -1798,10 +1810,10 @@ acl_app() { fi run_dns ${_dns_port} fi - echo "${tcp_node}" > $TMP_ACL_PATH/$sid/var_tcp_node + echo "${tcp_node}" > ${acl_path}/var_tcp_node } fi - echo "${tcp_port}" > $TMP_ACL_PATH/$sid/var_tcp_port + echo "${tcp_port}" > ${acl_path}/var_tcp_port } [ "$udp_node" != "nil" ] && { [ "$udp_node" = "tcp" ] && udp_node=$tcp_node @@ -1850,18 +1862,16 @@ acl_app() { run_ipt2socks flag=acl_${udp_node} local_port=$redir_port socks_address=127.0.0.1 socks_port=$socks_port log_file=$log_file fi fi - echo "${udp_node}" > $TMP_ACL_PATH/$sid/var_udp_node + echo "${udp_node}" > ${acl_path}/var_udp_node fi } fi - echo "${udp_port}" > $TMP_ACL_PATH/$sid/var_udp_port + echo "${udp_port}" > ${acl_path}/var_udp_port udp_flag=1 } - [ -n "$redirect_dns_port" ] && echo "${redirect_dns_port}" > $TMP_ACL_PATH/$sid/var_redirect_dns_port unset enabled sid remarks sources interface use_global_config tcp_node udp_node use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode filter_proxy_ipv6 dns_mode remote_dns v2ray_dns_mode remote_dns_doh dns_client_ip unset _ip _mac _iprange _ipset _ip_or_mac source_list tcp_port udp_port config_file _extra_param unset _china_ng_listen _chinadns_local_dns _direct_dns_mode chinadns_ng_default_tag dnsmasq_filter_proxy_ipv6 - unset redirect_dns_port done unset socks_port redir_port dns_port dnsmasq_port chinadns_port } @@ -1904,13 +1914,12 @@ start() { } [ "$ENABLED_DEFAULT_ACL" == 1 ] && { - mkdir -p $TMP_ACL_PATH/default + mkdir -p ${GLOBAL_ACL_PATH} start_redir TCP start_redir UDP start_dns } [ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start - [ "$ENABLED_DEFAULT_ACL" == 1 ] && source $APP_PATH/helper_${DNS_N}.sh logic_restart start_crontab echolog "运行完成!\n" } @@ -1927,8 +1936,6 @@ stop() { unset XRAY_LOCATION_ASSET stop_crontab source $APP_PATH/helper_smartdns.sh del - source $APP_PATH/helper_dnsmasq.sh del - source $APP_PATH/helper_dnsmasq.sh restart no_log=1 [ -s "$TMP_PATH/bridge_nf_ipt" ] && sysctl -w net.bridge.bridge-nf-call-iptables=$(cat $TMP_PATH/bridge_nf_ipt) >/dev/null 2>&1 [ -s "$TMP_PATH/bridge_nf_ip6t" ] && sysctl -w net.bridge.bridge-nf-call-ip6tables=$(cat $TMP_PATH/bridge_nf_ip6t) >/dev/null 2>&1 rm -rf ${TMP_PATH} @@ -1999,17 +2006,6 @@ RESOLVFILE=/tmp/resolv.conf.d/resolv.conf.auto ISP_DNS=$(cat $RESOLVFILE 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u | grep -v 0.0.0.0 | grep -v 127.0.0.1) ISP_DNS6=$(cat $RESOLVFILE 2>/dev/null | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | awk -F % '{print $1}' | awk -F " " '{print $2}'| sort -u | grep -v -Fx ::1 | grep -v -Fx ::) -DEFAULT_DNSMASQ_CFGID="$(uci -q show "dhcp.@dnsmasq[0]" | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')" -if [ -f "/tmp/etc/dnsmasq.conf.$DEFAULT_DNSMASQ_CFGID" ]; then - DNSMASQ_CONF_DIR="$(awk -F '=' '/^conf-dir=/ {print $2}' "/tmp/etc/dnsmasq.conf.$DEFAULT_DNSMASQ_CFGID")" - if [ -n "$DNSMASQ_CONF_DIR" ]; then - DNSMASQ_CONF_DIR=${DNSMASQ_CONF_DIR%*/} - TMP_DNSMASQ_PATH=${DNSMASQ_CONF_DIR}/${CONFIG} - else - DNSMASQ_CONF_DIR="/tmp/dnsmasq.d" - fi -fi - DEFAULT_DNS=$(uci show dhcp.@dnsmasq[0] | grep "\.server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' '\n' | grep -v "\/" | head -2 | sed ':label;N;s/\n/,/;b label') [ -z "${DEFAULT_DNS}" ] && [ "$(echo $ISP_DNS | tr ' ' '\n' | wc -l)" -le 2 ] && DEFAULT_DNS=$(echo -n $ISP_DNS | tr ' ' '\n' | head -2 | tr '\n' ',') LOCAL_DNS="${DEFAULT_DNS:-119.29.29.29,223.5.5.5}" diff --git a/small/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.sh b/small/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.sh index d3d4bbd05c..746726084a 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.sh +++ b/small/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.sh @@ -1,89 +1,27 @@ #!/bin/sh -stretch() { - #zhenduiluanshezhiDNSderen - local dnsmasq_server=$(uci -q get dhcp.@dnsmasq[0].server) - local dnsmasq_noresolv=$(uci -q get dhcp.@dnsmasq[0].noresolv) - local _flag - for server in $dnsmasq_server; do - [ -z "$(echo $server | grep '\/')" ] && _flag=1 - done - [ -z "$_flag" ] && [ "$dnsmasq_noresolv" = "1" ] && { - uci -q delete dhcp.@dnsmasq[0].noresolv - uci -q set dhcp.@dnsmasq[0].resolvfile="$RESOLVFILE" - uci commit dhcp +copy_instance() { + local listen_port dnsmasq_conf + eval_set_val $@ + [ -s "/tmp/etc/dnsmasq.conf.${DEFAULT_DNSMASQ_CFGID}" ] && { + cp -r /tmp/etc/dnsmasq.conf.${DEFAULT_DNSMASQ_CFGID} $dnsmasq_conf + sed -i "/ubus/d" $dnsmasq_conf + sed -i "/dhcp/d" $dnsmasq_conf + sed -i "/port=/d" $dnsmasq_conf + sed -i "/conf-dir/d" $dnsmasq_conf + sed -i "/no-poll/d" $dnsmasq_conf + sed -i "/no-resolv/d" $dnsmasq_conf } + echo "port=${listen_port}" >> $dnsmasq_conf } -backup_servers() { - DNSMASQ_DNS=$(uci show dhcp.@dnsmasq[0] | grep ".server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' ',') - if [ -n "${DNSMASQ_DNS}" ]; then - uci -q set $CONFIG.@global[0].dnsmasq_servers="${DNSMASQ_DNS}" - uci commit $CONFIG - fi -} - -restore_servers() { - OLD_SERVER=$(uci -q get $CONFIG.@global[0].dnsmasq_servers | tr "," " ") - for server in $OLD_SERVER; do - uci -q del_list dhcp.@dnsmasq[0].server=$server - uci -q add_list dhcp.@dnsmasq[0].server=$server - done - uci commit dhcp - uci -q delete $CONFIG.@global[0].dnsmasq_servers - uci commit $CONFIG -} - -logic_restart() { - local no_log - eval_set_val $@ - _LOG_FILE=$LOG_FILE - [ -n "$no_log" ] && LOG_FILE="/dev/null" - if [ -f "$TMP_PATH/default_DNS" ]; then - backup_servers - #sed -i "/list server/d" /etc/config/dhcp >/dev/null 2>&1 - for server in $(uci -q get dhcp.@dnsmasq[0].server); do - [ -n "$(echo $server | grep '\/')" ] || uci -q del_list dhcp.@dnsmasq[0].server="$server" - done - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - restore_servers - else - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - fi - echolog "重启 dnsmasq 服务" - LOG_FILE=${_LOG_FILE} -} - -restart() { - local no_log - eval_set_val $@ - _LOG_FILE=$LOG_FILE - [ -n "$no_log" ] && LOG_FILE="/dev/null" - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - echolog "重启 dnsmasq 服务" - LOG_FILE=${_LOG_FILE} -} - -del() { - rm -rf $DNSMASQ_CONF_DIR/dnsmasq-$CONFIG.conf - rm -rf $DNSMASQ_PATH/dnsmasq-$CONFIG.conf - rm -rf $TMP_DNSMASQ_PATH -} +DEFAULT_DNSMASQ_CFGID="$(uci -q show "dhcp.@dnsmasq[0]" | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')" arg1=$1 shift case $arg1 in -stretch) - stretch $@ - ;; -del) - del $@ - ;; -restart) - restart $@ - ;; -logic_restart) - logic_restart $@ +copy_instance) + copy_instance $@ ;; *) ;; esac diff --git a/small/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua b/small/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua index fbb3e29785..6c01766076 100644 --- a/small/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua +++ b/small/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua @@ -4,7 +4,6 @@ local appname = "passwall" local var = api.get_args(arg) local FLAG = var["-FLAG"] -local DNSMASQ_CONF_DIR = var["-DNSMASQ_CONF_DIR"] local TMP_DNSMASQ_PATH = var["-TMP_DNSMASQ_PATH"] local DNSMASQ_CONF_FILE = var["-DNSMASQ_CONF_FILE"] local DEFAULT_DNS = var["-DEFAULT_DNS"] @@ -192,7 +191,6 @@ local setflag_4= (NFTFLAG == "1") and "4#inet#passwall#" or "" local setflag_6= (NFTFLAG == "1") and "6#inet#passwall#" or "" if not fs.access(CACHE_DNS_PATH) then - fs.mkdir(DNSMASQ_CONF_DIR) fs.mkdir(CACHE_DNS_PATH) --屏蔽列表 diff --git a/small/luci-app-passwall/root/usr/share/passwall/iptables.sh b/small/luci-app-passwall/root/usr/share/passwall/iptables.sh index 6015672616..ac28955666 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/iptables.sh +++ b/small/luci-app-passwall/root/usr/share/passwall/iptables.sh @@ -182,23 +182,6 @@ get_wan6_ip() { echo $NET_ADDR } -get_geoip() { - local geoip_code="$1" - local geoip_type_flag="" - local geoip_path="$(config_t_get global_rules v2ray_location_asset)" - geoip_path="${geoip_path%*/}/geoip.dat" - [ -e "$geoip_path" ] || { echo ""; return; } - case "$2" in - "ipv4") geoip_type_flag="-ipv6=false" ;; - "ipv6") geoip_type_flag="-ipv4=false" ;; - esac - if type geoview &> /dev/null; then - geoview -input "$geoip_path" -list "$geoip_code" $geoip_type_flag -lowmem=true - else - echo "" - fi -} - load_acl() { ([ "$ENABLED_ACLS" == 1 ] || ([ "$ENABLED_DEFAULT_ACL" == 1 ] && [ "$CLIENT_PROXY" == 1 ])) && echolog " - 访问控制:" [ "$ENABLED_ACLS" == 1 ] && { @@ -233,6 +216,7 @@ load_acl() { [ -s "${TMP_ACL_PATH}/${sid}/var_udp_node" ] && udp_node=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_node) [ -s "${TMP_ACL_PATH}/${sid}/var_tcp_port" ] && tcp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_tcp_port) [ -s "${TMP_ACL_PATH}/${sid}/var_udp_port" ] && udp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_port) + [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) use_shunt_tcp=0 use_shunt_udp=0 @@ -259,6 +243,9 @@ load_acl() { chn_list=${CHN_LIST} tcp_proxy_mode=${TCP_PROXY_MODE} udp_proxy_mode=${UDP_PROXY_MODE} + use_shunt_tcp=${USE_SHUNT_TCP} + use_shunt_udp=${USE_SHUNT_UDP} + dns_redirect_port=${DNS_REDIRECT_PORT} } _acl_list=${TMP_ACL_PATH}/${sid}/source_list @@ -333,7 +320,25 @@ load_acl() { echolog " - ${msg}不代理所有 UDP 端口" fi } - + + if ([ -n "$tcp_port" ] && [ -n "${tcp_proxy_mode}" ]) || ([ -n "$udp_port" ] && [ -n "${udp_proxy_mode}" ]); then + [ -n "$dns_redirect_port" ] && { + $ipt_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN + $ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null + $ipt_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN + $ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null + $ipt_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port + $ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null + $ipt_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port + $ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null + } + else + $ipt_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN + $ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null + $ipt_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN + $ip6t_n -A PSW_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null + fi + [ -n "$tcp_port" -o -n "$udp_port" ] && { [ "${use_direct_list}" = "1" ] && $ipt_n -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_WHITELIST) -j RETURN [ "${use_direct_list}" = "1" ] && $ipt_m -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_WHITELIST) -j RETURN @@ -380,7 +385,6 @@ load_acl() { [ -n "$tcp_port" ] && { if [ -n "${tcp_proxy_mode}" ]; then - [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && $ipt_n -A PSW_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) msg2="${msg}使用 TCP 节点[$tcp_node_remark]" if [ -n "${is_tproxy}" ]; then msg2="${msg2}(TPROXY:${tcp_port})" @@ -463,7 +467,7 @@ load_acl() { $ipt_m -A PSW $(comment "$remarks") ${_ipt_source} -p udp -j RETURN unset ipt_tmp ipt_j _ipt_source msg msg2 done - unset enabled sid remarks sources use_global_config use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode tcp_no_redir_ports udp_no_redir_ports tcp_proxy_drop_ports udp_proxy_drop_ports tcp_redir_ports udp_redir_ports tcp_node udp_node interface + unset enabled sid remarks sources use_global_config use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode dns_redirect_port tcp_no_redir_ports udp_no_redir_ports tcp_proxy_drop_ports udp_proxy_drop_ports tcp_redir_ports udp_redir_ports tcp_node udp_node interface unset tcp_port udp_port tcp_node_remark udp_node_remark _acl_list use_shunt_tcp use_shunt_udp done } @@ -495,6 +499,19 @@ load_acl() { fi } + if ([ "$TCP_NODE" != "nil" ] && [ -n "${TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${UDP_PROXY_MODE}" ]); then + [ -n "$DNS_REDIRECT_PORT" ] && { + $ipt_m -A PSW $(comment "默认") -p udp --dport 53 -j RETURN + $ip6t_m -A PSW $(comment "默认") -p udp --dport 53 -j RETURN 2>/dev/null + $ipt_m -A PSW $(comment "默认") -p tcp --dport 53 -j RETURN + $ip6t_m -A PSW $(comment "默认") -p tcp --dport 53 -j RETURN 2>/dev/null + $ipt_n -A PSW_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A PSW_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + $ipt_n -A PSW_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A PSW_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + } + fi + [ -n "${TCP_PROXY_MODE}" -o -n "${UDP_PROXY_MODE}" ] && { [ "${USE_DIRECT_LIST}" = "1" ] && $ipt_n -A PSW $(comment "默认") $(dst $IPSET_WHITELIST) -j RETURN [ "${USE_DIRECT_LIST}" = "1" ] && $ipt_m -A PSW $(comment "默认") $(dst $IPSET_WHITELIST) -j RETURN @@ -654,6 +671,10 @@ filter_node() { local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') local address=$(config_n_get $node address) local port=$(config_n_get $node port) + [ -z "$address" ] && [ -z "$port" ] && { + echolog " - 节点配置不正常,略过" + return 1 + } ipt_tmp=$ipt_n _is_tproxy=${is_tproxy} [ "$stream" == "udp" ] && _is_tproxy="TPROXY" @@ -665,7 +686,7 @@ filter_node() { fi else echolog " - 节点配置不正常,略过" - return 0 + return 1 fi local ADD_INDEX=$FORCE_INDEX @@ -674,7 +695,6 @@ filter_node() { [ "$_ipt" == "6" ] && _ipt=$ip6t_m && _set_name=$IPSET_VPSLIST6 $_ipt -n -L PSW_OUTPUT | grep -q "${address}:${port}" if [ $? -ne 0 ]; then - unset dst_rule local dst_rule="-j PSW_RULE" msg2="按规则路由(${msg})" [ "$_ipt" == "$ipt_m" -o "$_ipt" == "$ip6t_m" ] || { @@ -697,7 +717,7 @@ filter_node() { local proxy_protocol=$(config_n_get $proxy_node protocol) local proxy_type=$(echo $(config_n_get $proxy_node type nil) | tr 'A-Z' 'a-z') - [ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 0 + [ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 1 if [ "$proxy_protocol" == "_balancing" ]; then #echolog " - 多节点负载均衡(${proxy_type})..." proxy_node=$(config_n_get $proxy_node balancing_node) @@ -706,56 +726,40 @@ filter_node() { done elif [ "$proxy_protocol" == "_shunt" ]; then #echolog " - 按请求目的地址分流(${proxy_type})..." + local preproxy_enabled=$(config_n_get $proxy_node preproxy_enabled 0) + [ "$preproxy_enabled" == "1" ] && { + local preproxy_node=$(config_n_get $proxy_node main_node nil) + [ "$preproxy_node" != "nil" ] && { + local preproxy_node_address=$(config_n_get $preproxy_node address) + if [ -n "$preproxy_node_address" ]; then + filter_rules $preproxy_node $stream + else + preproxy_enabled=0 + fi + } + } local default_node=$(config_n_get $proxy_node default_node _direct) - local main_node=$(config_n_get $proxy_node main_node nil) - if [ "$main_node" != "nil" ]; then - filter_rules $main_node $stream - else - if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then - filter_rules $default_node $stream - fi + if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then + local default_proxy_tag=$(config_n_get $proxy_node default_proxy_tag nil) + [ "$default_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && default_proxy_tag="nil" + [ "$default_proxy_tag" == "nil" ] && filter_rules $default_node $stream fi -:</dev/null - $ipt_n -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "PSW_DNS_Hijack" 2>/dev/null - $ip6t_n -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "PSW_DNS_Hijack" 2>/dev/null - $ip6t_n -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "PSW_DNS_Hijack" 2>/dev/null - echolog " - 开启 DNS 重定向" - } -} - add_firewall_rule() { echolog "开始加载防火墙规则..." ipset -! create $IPSET_LANLIST nethash maxelem 1048576 @@ -1007,6 +1011,9 @@ add_firewall_rule() { $ip6t_n -A PSW_OUTPUT -m mark --mark 0xff -j RETURN } + $ip6t_n -N PSW_REDIRECT + $ip6t_n -I PREROUTING 1 -j PSW_REDIRECT + $ip6t_m -N PSW_DIVERT $ip6t_m -A PSW_DIVERT -j MARK --set-mark 1 $ip6t_m -A PSW_DIVERT -j ACCEPT @@ -1108,7 +1115,16 @@ add_firewall_rule() { echolog " - ${msg}不代理所有 UDP 端口" fi } - + + if ([ "$TCP_NODE" != "nil" ] && [ -n "${LOCALHOST_TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then + [ -n "$DNS_REDIRECT_PORT" ] && { + $ipt_n -A OUTPUT $(comment "PSW") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A OUTPUT $(comment "PSW") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + $ipt_n -A OUTPUT $(comment "PSW") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A OUTPUT $(comment "PSW") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + } + fi + [ -n "${LOCALHOST_TCP_PROXY_MODE}" -o -n "${LOCALHOST_UDP_PROXY_MODE}" ] && { [ "$TCP_PROXY_DROP_PORTS" != "disable" ] && { $ipt_m -A PSW_OUTPUT -p tcp $(factor $TCP_PROXY_DROP_PORTS "-m multiport --dport") -d $FAKE_IP -j DROP @@ -1266,9 +1282,6 @@ add_firewall_rule() { $ip6t_m -I OUTPUT $(comment "mangle-OUTPUT-PSW") -o lo -j RETURN insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW) -m mark --mark 1 -j RETURN" - - dns_hijack - } # 加载ACLS diff --git a/small/luci-app-passwall/root/usr/share/passwall/nftables.sh b/small/luci-app-passwall/root/usr/share/passwall/nftables.sh index 53affc84e2..eca8b922d8 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/nftables.sh +++ b/small/luci-app-passwall/root/usr/share/passwall/nftables.sh @@ -242,23 +242,6 @@ get_wan6_ip() { echo $NET_ADDR } -get_geoip() { - local geoip_code="$1" - local geoip_type_flag="" - local geoip_path="$(config_t_get global_rules v2ray_location_asset)" - geoip_path="${geoip_path%*/}/geoip.dat" - [ -e "$geoip_path" ] || { echo ""; return; } - case "$2" in - "ipv4") geoip_type_flag="-ipv6=false" ;; - "ipv6") geoip_type_flag="-ipv4=false" ;; - esac - if type geoview &> /dev/null; then - geoview -input "$geoip_path" -list "$geoip_code" $geoip_type_flag -lowmem=true - else - echo "" - fi -} - load_acl() { ([ "$ENABLED_ACLS" == 1 ] || ([ "$ENABLED_DEFAULT_ACL" == 1 ] && [ "$CLIENT_PROXY" == 1 ])) && echolog " - 访问控制:" [ "$ENABLED_ACLS" == 1 ] && { @@ -293,6 +276,7 @@ load_acl() { [ -s "${TMP_ACL_PATH}/${sid}/var_udp_node" ] && udp_node=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_node) [ -s "${TMP_ACL_PATH}/${sid}/var_tcp_port" ] && tcp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_tcp_port) [ -s "${TMP_ACL_PATH}/${sid}/var_udp_port" ] && udp_port=$(cat ${TMP_ACL_PATH}/${sid}/var_udp_port) + [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) use_shunt_tcp=0 use_shunt_udp=0 @@ -321,6 +305,7 @@ load_acl() { udp_proxy_mode=${UDP_PROXY_MODE} use_shunt_tcp=${USE_SHUNT_TCP} use_shunt_udp=${USE_SHUNT_UDP} + dns_redirect_port=${DNS_REDIRECT_PORT} } _acl_list=${TMP_ACL_PATH}/${sid}/source_list @@ -385,7 +370,25 @@ load_acl() { echolog " - ${msg}不代理所有 UDP 端口" fi } - + + if ([ -n "$tcp_port" ] && [ -n "${tcp_proxy_mode}" ]) || ([ -n "$udp_port" ] && [ -n "${udp_proxy_mode}" ]); then + [ -n "$dns_redirect_port" ] && { + nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + } + else + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\"" + fi + [ -n "$tcp_port" -o -n "$udp_port" ] && { [ "${use_direct_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ${_ipt_source} ip daddr @$NFTSET_WHITELIST counter return comment \"$remarks\"" [ "${use_direct_list}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ${_ipt_source} ip daddr @$NFTSET_WHITELIST counter return comment \"$remarks\"" @@ -433,7 +436,6 @@ load_acl() { [ -n "$tcp_port" ] && { if [ -n "${tcp_proxy_mode}" ]; then - [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter redirect to $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) comment \"$remarks\"" msg2="${msg}使用 TCP 节点[$tcp_node_remark]" if [ -n "${is_tproxy}" ]; then msg2="${msg2}(TPROXY:${tcp_port})" @@ -521,7 +523,7 @@ load_acl() { nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} counter return comment \"$remarks\"" 2>/dev/null unset nft_chain nft_j _ipt_source msg msg2 done - unset enabled sid remarks sources use_global_config use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode tcp_no_redir_ports udp_no_redir_ports tcp_proxy_drop_ports udp_proxy_drop_ports tcp_redir_ports udp_redir_ports tcp_node udp_node interface + unset enabled sid remarks sources use_global_config use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode dns_redirect_port tcp_no_redir_ports udp_no_redir_ports tcp_proxy_drop_ports udp_proxy_drop_ports tcp_redir_ports udp_redir_ports tcp_node udp_node interface unset tcp_port udp_port tcp_node_remark udp_node_remark _acl_list use_shunt_tcp use_shunt_udp done } @@ -550,6 +552,19 @@ load_acl() { fi } + if ([ "$TCP_NODE" != "nil" ] && [ -n "${TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${UDP_PROXY_MODE}" ]); then + [ -n "$DNS_REDIRECT_PORT" ] && { + nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp udp dport 53 counter return comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp udp dport 53 counter return comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp tcp dport 53 counter return comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp tcp dport 53 counter return comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW_REDIRECT meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + } + fi + [ -n "${TCP_PROXY_MODE}" -o -n "${UDP_PROXY_MODE}" ] && { [ "${USE_DIRECT_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ip daddr @$NFTSET_WHITELIST counter return comment \"默认\"" [ "${USE_DIRECT_LIST}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ip daddr @$NFTSET_WHITELIST counter return comment \"默认\"" @@ -725,6 +740,10 @@ filter_node() { local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') local address=$(config_n_get $node address) local port=$(config_n_get $node port) + [ -z "$address" ] && [ -z "$port" ] && { + echolog " - 节点配置不正常,略过" + return 1 + } _is_tproxy=${is_tproxy} [ "$stream" == "udp" ] && _is_tproxy="TPROXY" if [ -n "${_is_tproxy}" ]; then @@ -734,7 +753,7 @@ filter_node() { fi else echolog " - 节点配置不正常,略过" - return 0 + return 1 fi local ADD_INDEX=$FORCE_INDEX @@ -743,7 +762,6 @@ filter_node() { [ "$_ipt" == "6" ] && _ip_type=ip6 && _set_name=$NFTSET_VPSLIST6 nft "list chain $NFTABLE_NAME $nft_output_chain" 2>/dev/null | grep -q "${address}:${port}" if [ $? -ne 0 ]; then - unset dst_rule local dst_rule="jump PSW_RULE" msg2="按规则路由(${msg})" [ -n "${is_tproxy}" ] || { @@ -766,7 +784,7 @@ filter_node() { local proxy_protocol=$(config_n_get $proxy_node protocol) local proxy_type=$(echo $(config_n_get $proxy_node type nil) | tr 'A-Z' 'a-z') - [ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 0 + [ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 1 if [ "$proxy_protocol" == "_balancing" ]; then #echolog " - 多节点负载均衡(${proxy_type})..." proxy_node=$(config_n_get $proxy_node balancing_node) @@ -775,58 +793,40 @@ filter_node() { done elif [ "$proxy_protocol" == "_shunt" ]; then #echolog " - 按请求目的地址分流(${proxy_type})..." + local preproxy_enabled=$(config_n_get $proxy_node preproxy_enabled 0) + [ "$preproxy_enabled" == "1" ] && { + local preproxy_node=$(config_n_get $proxy_node main_node nil) + [ "$preproxy_node" != "nil" ] && { + local preproxy_node_address=$(config_n_get $preproxy_node address) + if [ -n "$preproxy_node_address" ]; then + filter_rules $preproxy_node $stream + else + preproxy_enabled=0 + fi + } + } local default_node=$(config_n_get $proxy_node default_node _direct) - local main_node=$(config_n_get $proxy_node main_node nil) - if [ "$main_node" != "nil" ]; then - filter_rules $main_node $stream - else - if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then - filter_rules $default_node $stream - fi + if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then + local default_proxy_tag=$(config_n_get $proxy_node default_proxy_tag nil) + [ "$default_proxy_tag" == "main" ] && [ "$preproxy_enabled" == "0" ] && default_proxy_tag="nil" + [ "$default_proxy_tag" == "nil" ] && filter_rules $default_node $stream fi -:</dev/null - nft insert rule $NFTABLE_NAME dstnat position 0 udp dport 53 counter redirect to :53 comment \"PSW_DNS_Hijack\" 2>/dev/null - nft insert rule $NFTABLE_NAME dstnat position 0 meta nfproto {ipv6} tcp dport 53 counter redirect to :53 comment \"PSW_DNS_Hijack\" 2>/dev/null - nft insert rule $NFTABLE_NAME dstnat position 0 meta nfproto {ipv6} udp dport 53 counter redirect to :53 comment \"PSW_DNS_Hijack\" 2>/dev/null - uci -q set dhcp.@dnsmasq[0].dns_redirect='0' 2>/dev/null - uci commit dhcp 2>/dev/null - echolog " - 开启 DNS 重定向" - } -} - add_firewall_rule() { echolog "开始加载防火墙规则..." gen_nft_tables @@ -1182,7 +1182,16 @@ add_firewall_rule() { echolog " - ${msg}不代理所有 UDP 端口" fi } - + + if ([ "$TCP_NODE" != "nil" ] && [ -n "${LOCALHOST_TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then + [ -n "$DNS_REDIRECT_PORT" ] && { + nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW\"" + nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW\"" + nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW\"" + nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW\"" + } + fi + [ -n "${LOCALHOST_TCP_PROXY_MODE}" -o -n "${LOCALHOST_UDP_PROXY_MODE}" ] && { [ "$TCP_PROXY_DROP_PORTS" != "disable" ] && { nft add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp ip daddr $FAKE_IP $(factor $TCP_PROXY_DROP_PORTS "tcp dport") counter drop @@ -1340,8 +1349,6 @@ add_firewall_rule() { nft "add rule $NFTABLE_NAME mangle_output oif lo counter return comment \"PSW_OUTPUT_MANGLE\"" nft "add rule $NFTABLE_NAME mangle_output meta mark 1 counter return comment \"PSW_OUTPUT_MANGLE\"" - - dns_hijack } # 加载ACLS diff --git a/small/luci-app-passwall2/Makefile b/small/luci-app-passwall2/Makefile index 08f79b5f39..bfc2ab4f66 100644 --- a/small/luci-app-passwall2/Makefile +++ b/small/luci-app-passwall2/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=24.12.11 -PKG_RELEASE:=3 +PKG_VERSION:=24.12.12 +PKG_RELEASE:=2 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ @@ -24,14 +24,13 @@ PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_SingBox \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client \ - CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Geoview \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin LUCI_TITLE:=LuCI support for PassWall 2 LUCI_PKGARCH:=all LUCI_DEPENDS:=+coreutils +coreutils-base64 +coreutils-nohup +curl \ +ip-full +libuci-lua +lua +luci-compat +luci-lib-jsonc +resolveip +tcping \ - +xray-core +v2ray-geoip +v2ray-geosite \ + +xray-core +geoview +v2ray-geoip +v2ray-geosite \ +unzip \ +PACKAGE_$(PKG_NAME)_INCLUDE_IPv6_Nat:ip6tables-mod-nat @@ -138,11 +137,6 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client select PACKAGE_tuic-client default n -config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Geoview - bool "Include V2ray_Geoview" - select PACKAGE_geoview - default y if aarch64||arm||i386||x86_64 - config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin bool "Include V2ray-Plugin (Shadowsocks Plugin)" select PACKAGE_v2ray-plugin diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua index c8b9693d6b..314e992186 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua @@ -259,6 +259,7 @@ if has_singbox then local geoip_path = s.fields["geoip_path"] and s.fields["geoip_path"]:formvalue(section) or nil if geoip_path then os.remove(geoip_path) + luci.sys.call("rm -f /tmp/etc/passwall2_tmp/geoip-*.json") end local geosite_path = s.fields["geosite_path"] and s.fields["geosite_path"]:formvalue(section) or nil if geosite_path then diff --git a/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index 20650ff6d8..254485783a 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -1386,6 +1386,11 @@ function gen_config(var) string.gsub(direct_ipset, '[^' .. "," .. ']+', function(w) sys.call("ipset -q -F " .. w) end) + local ipset_prefix_name = "passwall2_" .. node_id .. "_" + local ipset_list = sys.exec("ipset list | grep 'Name: ' | grep '" .. ipset_prefix_name .. "' | awk '{print $2}'") + string.gsub(ipset_list, '[^' .. "\r\n" .. ']+', function(w) + sys.call("ipset -q -F " .. w) + end) end if direct_nftset then string.gsub(direct_nftset, '[^' .. "," .. ']+', function(w) @@ -1398,6 +1403,13 @@ function gen_config(var) sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, set_name)) end end) + local family = "inet" + local table_name = "passwall2" + local nftset_prefix_name = "passwall2_" .. node_id .. "_" + local nftset_list = sys.exec("nft -a list sets | grep -E '" .. nftset_prefix_name .. "' | awk -F 'set ' '{print $2}' | awk '{print $1}'") + string.gsub(nftset_list, '[^' .. "\r\n" .. ']+', function(w) + sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, w)) + end) end end end diff --git a/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua index a179e34524..c4d1ddb551 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -1405,6 +1405,11 @@ function gen_config(var) string.gsub(direct_ipset, '[^' .. "," .. ']+', function(w) sys.call("ipset -q -F " .. w) end) + local ipset_prefix_name = "passwall2_" .. node_id .. "_" + local ipset_list = sys.exec("ipset list | grep 'Name: ' | grep '" .. ipset_prefix_name .. "' | awk '{print $2}'") + string.gsub(ipset_list, '[^' .. "\r\n" .. ']+', function(w) + sys.call("ipset -q -F " .. w) + end) end if direct_nftset then string.gsub(direct_nftset, '[^' .. "," .. ']+', function(w) @@ -1417,6 +1422,13 @@ function gen_config(var) sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, set_name)) end end) + local family = "inet" + local table_name = "passwall2" + local nftset_prefix_name = "passwall2_" .. node_id .. "_" + local nftset_list = sys.exec("nft -a list sets | grep -E '" .. nftset_prefix_name .. "' | awk -F 'set ' '{print $2}' | awk '{print $1}'") + string.gsub(nftset_list, '[^' .. "\r\n" .. ']+', function(w) + sys.call(string.format("nft flush set %s %s %s 2>/dev/null", family, table_name, w)) + end) end end end diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/0_default_config b/small/luci-app-passwall2/root/usr/share/passwall2/0_default_config index 5f5b8d0494..87b588d988 100644 --- a/small/luci-app-passwall2/root/usr/share/passwall2/0_default_config +++ b/small/luci-app-passwall2/root/usr/share/passwall2/0_default_config @@ -47,6 +47,7 @@ config global_rules option geosite_update '1' option geoip_update '1' option v2ray_location_asset '/usr/share/v2ray/' + option enable_geoview '1' config global_app option xray_file '/usr/bin/xray' diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/app.sh b/small/luci-app-passwall2/root/usr/share/passwall2/app.sh index 991ee546d0..c3ee5d6a32 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/small/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -302,6 +302,28 @@ get_geoip() { fi } +get_singbox_geoip() { + local geoip_code="$1" + local geoip_path=$(config_t_get global_singbox geoip_path) + [ -e "$geoip_path" ] || { echo ""; return; } + local has_geoip_tools=$($(first_type $(config_t_get global_app singbox_file) sing-box) geoip | grep "GeoIP tools") + if [ -n "${has_geoip_tools}" ]; then + [ -f "${geoip_path}" ] && local geoip_md5=$(md5sum ${geoip_path} | awk '{print $1}') + local output_file="${TMP_PATH2}/geoip-${geoip_md5}-${geoip_code}.json" + [ ! -f ${output_file} ] && $(first_type $(config_t_get global_app singbox_file) sing-box) geoip -f "${geoip_path}" export "${geoip_code}" -o "${output_file}" + case "$2" in + ipv4) + cat ${output_file} | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | awk -F '"' '{print $2}' | sed -e "/^$/d" + ;; + ipv6) + cat ${output_file} | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | awk -F '"' '{print $2}' | sed -e "/^$/d" + ;; + esac + else + echo "" + fi +} + run_xray() { local flag node redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password local dns_listen_port direct_dns_query_strategy remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy dns_cache write_ipset_direct @@ -735,6 +757,7 @@ run_global() { GLOBAL_DNSMASQ_PORT=$(get_new_port 11400) run_copy_dnsmasq flag="default" listen_port=$GLOBAL_DNSMASQ_PORT tun_dns="${TUN_DNS}" + DNS_REDIRECT_PORT=${GLOBAL_DNSMASQ_PORT} } start_socks() { diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/iptables.sh b/small/luci-app-passwall2/root/usr/share/passwall2/iptables.sh index ae79608f8c..d9095a59c7 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/iptables.sh +++ b/small/luci-app-passwall2/root/usr/share/passwall2/iptables.sh @@ -187,6 +187,91 @@ get_wan6_ip() { echo $NET_ADDR } +gen_shunt_list() { + local node=${1} + local shunt_list4_var_name=${2} + local shunt_list6_var_name=${3} + local _write_ipset_direct=${4} + local _set_name4=${5} + local _set_name6=${6} + [ -z "$node" ] && continue + unset ${shunt_list4_var_name} + unset ${shunt_list6_var_name} + local _SHUNT_LIST4 _SHUNT_LIST6 + local USE_SHUNT_NODE=0 + NODE_PROTOCOL=$(config_n_get $node protocol) + [ "$NODE_PROTOCOL" = "_shunt" ] && USE_SHUNT_NODE=1 + [ "$USE_SHUNT_NODE" = "1" ] && { + local default_node=$(config_n_get ${node} default_node _direct) + local default_outbound="redirect" + [ "$default_node" = "_direct" ] && default_outbound="direct" + local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') + for shunt_id in $shunt_ids; do + local shunt_node=$(config_n_get ${node} "${shunt_id}" nil) + [ "$shunt_node" != "nil" ] && { + local ipset_v4="passwall2_${node}_${shunt_id}" + local ipset_v6="passwall2_${node}_${shunt_id}6" + ipset -! create $ipset_v4 nethash maxelem 1048576 + ipset -! create $ipset_v6 nethash family inet6 maxelem 1048576 + local outbound="redirect" + [ "$shunt_node" = "_direct" ] && outbound="direct" + [ "$shunt_node" = "_default" ] && outbound="${default_outbound}" + _SHUNT_LIST4="${_SHUNT_LIST4} ${ipset_v4}:${outbound}" + _SHUNT_LIST6="${_SHUNT_LIST6} ${ipset_v6}:${outbound}" + + config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_v4 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_v6 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { + local _geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') + [ -n "$_geoip_code" ] && { + if [ "$(config_n_get $node type)" = "sing-box" ]; then + get_singbox_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_v4 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + get_singbox_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_v6 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + else + if type geoview &> /dev/null; then + get_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_v4 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + get_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_v6 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R + fi + fi + echolog " - [$?]解析分流规则[$shunt_id]-[geoip:${_geoip_code}]加入到 IPSET 完成" + } + } + } + done + [ "${_write_ipset_direct}" = "1" ] && { + _SHUNT_LIST4="${_SHUNT_LIST4} ${_set_name4}:direct" + _SHUNT_LIST6="${_SHUNT_LIST6} ${_set_name6}:direct" + } + [ "$default_node" != "nil" ] && { + local ipset_v4="passwall2_${node}_default" + local ipset_v6="passwall2_${node}_default6" + ipset -! create $ipset_v4 nethash maxelem 1048576 + ipset -! create $ipset_v6 nethash family inet6 maxelem 1048576 + _SHUNT_LIST4="${_SHUNT_LIST4} ${ipset_v4}:${default_outbound}" + _SHUNT_LIST6="${_SHUNT_LIST6} ${ipset_v6}:${default_outbound}" + } + } + [ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\" + [ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\" +} + +add_shunt_t_rule() { + local shunt_args=${1} + local t_args=${2} + local t_jump_args=${3} + [ -n "${shunt_args}" ] && { + for j in ${shunt_args}; do + local _set_name=$(echo ${j} | awk -F ':' '{print $1}') + local _outbound=$(echo ${j} | awk -F ':' '{print $2}') + [ -n "${_set_name}" ] && [ -n "${_outbound}" ] && { + local _t_arg="${t_jump_args}" + [ "${_outbound}" = "direct" ] && _t_arg="-j RETURN" + ${t_args} $(dst ${_set_name}) ${_t_arg} + } + done + } +} + load_acl() { [ "$ENABLED_ACLS" == 1 ] && { acl_app @@ -207,6 +292,8 @@ load_acl() { node_remark=$(config_n_get $NODE remarks) [ -s "${TMP_ACL_PATH}/${sid}/var_node" ] && node=$(cat ${TMP_ACL_PATH}/${sid}/var_node) [ -s "${TMP_ACL_PATH}/${sid}/var_port" ] && redir_port=$(cat ${TMP_ACL_PATH}/${sid}/var_port) + [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) + [ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT} [ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks) write_ipset_direct=${write_ipset_direct:-1} @@ -221,32 +308,7 @@ load_acl() { ipset -! create $ipset_whitelist6 nethash family inet6 maxelem 1048576 #分流规则的IP列表(使用分流节点时导入) - local _USE_SHUNT_NODE=0 - _NODE_PROTOCOL=$(config_n_get $node protocol) - [ "$_NODE_PROTOCOL" = "_shunt" ] && _USE_SHUNT_NODE=1 - [ "$_USE_SHUNT_NODE" = "1" ] && { - local _SHUNT_DEFAULT_NODE=$(config_n_get $NODE default_node _direct) - local _GEOIP_CODE="" - local _shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for _shunt_id in $_shunt_ids; do - local _SHUNT_RULE_NODE=$(config_n_get $NODE ${_shunt_id} nil) - [ "${_SHUNT_RULE_NODE}" == "_default" ] && _SHUNT_RULE_NODE=${_SHUNT_DEFAULT_NODE} - [ "${_SHUNT_RULE_NODE}" == "_direct" ] && { - config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_whitelist &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_whitelist6 &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { - local _geoip_code=$(config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') - [ -n "$_geoip_code" ] && _GEOIP_CODE="${_GEOIP_CODE:+$_GEOIP_CODE,}$_geoip_code" - } - } - done - } - - if [ -n "$_GEOIP_CODE" ] && type geoview &> /dev/null; then - get_geoip $_GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_whitelist &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - get_geoip $_GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_whitelist6 &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - echolog " - [$?]解析并加入分流节点 GeoIP 到 IPSET 完成" - fi + gen_shunt_list ${node} shunt_list4 shunt_list6 ${write_ipset_direct} ${ipset_whitelist} ${ipset_whitelist6} fi } @@ -324,11 +386,11 @@ load_acl() { } if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$redir_port" ]; then - [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && { - $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) - $ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) 2>/dev/null - $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) - $ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) 2>/dev/null + [ -n "$dns_redirect_port" ] && { + $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port + $ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null + $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port + $ip6t_n -A PSW2_REDIRECT $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null } else $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN @@ -349,24 +411,24 @@ load_acl() { [ "$accept_icmp" = "1" ] && { $ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} -d $FAKE_IP $(REDIRECT) - [ "${write_ipset_direct}" = "1" ] && $ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} $(dst $ipset_whitelist) -j RETURN + add_shunt_t_rule "${shunt_list4}" "$ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source}" "$(REDIRECT)" $ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} $(REDIRECT) } [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { $ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source} -d $FAKE_IP_6 $(REDIRECT) 2>/dev/null - [ "${write_ipset_direct}" = "1" ] && $ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source} $(dst $ipset_whitelist6) -j RETURN 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "$ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source}" "$(REDIRECT)" 2>/dev/null $ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source} $(REDIRECT) 2>/dev/null } $ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} -d $FAKE_IP ${ipt_j} - [ "${write_ipset_direct}" = "1" ] && $ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(dst $ipset_whitelist) -j RETURN + add_shunt_t_rule "${shunt_list4}" "$ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(factor $tcp_redir_ports "-m multiport --dport")" "${ipt_j}" $ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(factor $tcp_redir_ports "-m multiport --dport") ${ipt_j} [ -n "${is_tproxy}" ] && $ipt_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY) [ "$PROXY_IPV6" == "1" ] && { $ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} -d $FAKE_IP_6 -j PSW2_RULE 2>/dev/null - [ "${write_ipset_direct}" = "1" ] && $ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(dst $ipset_whitelist6) -j RETURN 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(factor $tcp_redir_ports "-m multiport --dport")" "${ipt_j}" 2>/dev/null $ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(factor $tcp_redir_ports "-m multiport --dport") -j PSW2_RULE 2>/dev/null $ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY) 2>/dev/null } @@ -379,13 +441,13 @@ load_acl() { msg2="${msg}使用 UDP 节点[$node_remark](TPROXY:${redir_port})" $ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP -j PSW2_RULE - [ "${write_ipset_direct}" = "1" ] && $ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(dst $ipset_whitelist) -j RETURN + add_shunt_t_rule "${shunt_list4}" "$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(factor $udp_redir_ports "-m multiport --dport")" "-j PSW2_RULE" $ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(factor $udp_redir_ports "-m multiport --dport") -j PSW2_RULE $ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(REDIRECT $redir_port TPROXY) [ "$PROXY_IPV6" == "1" ] && [ "$PROXY_IPV6_UDP" == "1" ] && { $ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP_6 -j PSW2_RULE 2>/dev/null - [ "${write_ipset_direct}" = "1" ] && $ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(dst $ipset_whitelist6) -j RETURN 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(factor $udp_redir_ports "-m multiport --dport")" "-j PSW2_RULE" 2>/dev/null $ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(factor $udp_redir_ports "-m multiport --dport") -j PSW2_RULE 2>/dev/null $ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(REDIRECT $redir_port TPROXY) 2>/dev/null } @@ -429,11 +491,11 @@ load_acl() { } if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ "$NODE" != "nil" ]; then - [ -s "${TMP_ACL_PATH}/default/var_redirect_dns_port" ] && { - $ipt_n -A PSW2_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) - $ip6t_n -A PSW2_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) 2>/dev/null - $ipt_n -A PSW2_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) - $ip6t_n -A PSW2_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) 2>/dev/null + [ -n "$DNS_REDIRECT_PORT" ] && { + $ipt_n -A PSW2_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A PSW2_REDIRECT $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + $ipt_n -A PSW2_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A PSW2_REDIRECT $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null } fi @@ -449,24 +511,24 @@ load_acl() { [ "$accept_icmp" = "1" ] && { $ipt_n -A PSW2 $(comment "默认") -p icmp -d $FAKE_IP $(REDIRECT) - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_n -A PSW2 $(comment "默认") -p icmp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_n -A PSW2 $(comment "默认") -p icmp" "$(REDIRECT)" $ipt_n -A PSW2 $(comment "默认") -p icmp $(REDIRECT) } [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { $ip6t_n -A PSW2 $(comment "默认") -p ipv6-icmp -d $FAKE_IP_6 $(REDIRECT) - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_n -A PSW2 $(comment "默认") -p ipv6-icmp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_n -A PSW2 $(comment "默认") -p ipv6-icmp" "$(REDIRECT)" $ip6t_n -A PSW2 $(comment "默认") -p ipv6-icmp $(REDIRECT) } $ipt_tmp -A PSW2 $(comment "默认") -p tcp -d $FAKE_IP ${ipt_j} - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_tmp -A PSW2 $(comment "默认") -p tcp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_tmp -A PSW2 $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport")" "${ipt_j}" $ipt_tmp -A PSW2 $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") ${ipt_j} [ -n "${is_tproxy}" ] && $ipt_m -A PSW2 $(comment "默认") -p tcp $(REDIRECT $REDIR_PORT TPROXY) [ "$PROXY_IPV6" == "1" ] && { $ip6t_m -A PSW2 $(comment "默认") -p tcp -d $FAKE_IP_6 -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_m -A PSW2 $(comment "默认") -p tcp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2 $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ip6t_m -A PSW2 $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ip6t_m -A PSW2 $(comment "默认") -p tcp $(REDIRECT $REDIR_PORT TPROXY) } @@ -478,13 +540,13 @@ load_acl() { msg2="${msg}使用 UDP 节点[$(config_n_get $NODE remarks)](TPROXY:${REDIR_PORT})" $ipt_m -A PSW2 $(comment "默认") -p udp -d $FAKE_IP -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_m -A PSW2 $(comment "默认") -p udp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_m -A PSW2 $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ipt_m -A PSW2 $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ipt_m -A PSW2 $(comment "默认") -p udp $(REDIRECT $REDIR_PORT TPROXY) if [ "$PROXY_IPV6_UDP" == "1" ]; then $ip6t_m -A PSW2 $(comment "默认") -p udp -d $FAKE_IP_6 -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_m -A PSW2 $(comment "默认") -p udp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2 $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ip6t_m -A PSW2 $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ip6t_m -A PSW2 $(comment "默认") -p udp $(REDIRECT $REDIR_PORT TPROXY) fi @@ -670,32 +732,7 @@ add_firewall_rule() { ipset -! create $ipset_global_whitelist6 nethash family inet6 maxelem 1048576 timeout 259200 #分流规则的IP列表(使用分流节点时导入) - local USE_SHUNT_NODE=0 - NODE_PROTOCOL=$(config_n_get $NODE protocol) - [ "$NODE_PROTOCOL" = "_shunt" ] && USE_SHUNT_NODE=1 - [ "$USE_SHUNT_NODE" = "1" ] && { - local SHUNT_DEFAULT_NODE=$(config_n_get $NODE default_node _direct) - local GEOIP_CODE="" - local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for shunt_id in $shunt_ids; do - local SHUNT_RULE_NODE=$(config_n_get $NODE ${shunt_id} nil) - [ "${SHUNT_RULE_NODE}" == "_default" ] && SHUNT_RULE_NODE=${SHUNT_DEFAULT_NODE} - [ "${SHUNT_RULE_NODE}" == "_direct" ] && { - config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_global_whitelist &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_global_whitelist6 &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { - local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') - [ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code" - } - } - done - } - - if [ -n "$GEOIP_CODE" ] && type geoview &> /dev/null; then - get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $ipset_global_whitelist &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $ipset_global_whitelist6 &/g" -e "s/$/ timeout 0/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - echolog " - [$?]解析并加入分流节点 GeoIP 到 IPSET 完成" - fi + gen_shunt_list ${NODE} SHUNT_LIST4 SHUNT_LIST6 ${WRITE_IPSET_DIRECT} ${ipset_global_whitelist} ${ipset_global_whitelist6} # 过滤所有节点IP filter_vpsip > /dev/null 2>&1 & @@ -867,11 +904,11 @@ add_firewall_rule() { } if [ "$NODE" != "nil" ] && ([ "$TCP_LOCALHOST_PROXY" = "1" ] || [ "$UDP_LOCALHOST_PROXY" = "1" ]); then - [ -s "${TMP_ACL_PATH}/default/var_redirect_dns_port" ] && { - $ipt_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) - $ip6t_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) 2>/dev/null - $ipt_n -A OUTPUT $(comment "PSW2") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) - $ip6t_n -A OUTPUT $(comment "PSW2") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) 2>/dev/null + [ -n "$DNS_REDIRECT_PORT" ] && { + $ipt_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null + $ipt_n -A OUTPUT $(comment "PSW2") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT + $ip6t_n -A OUTPUT $(comment "PSW2") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null } fi @@ -880,14 +917,14 @@ add_firewall_rule() { [ "$accept_icmp" = "1" ] && { $ipt_n -A OUTPUT -p icmp -j PSW2_OUTPUT $ipt_n -A PSW2_OUTPUT -p icmp -d $FAKE_IP $(REDIRECT) - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_n -A PSW2_OUTPUT -p icmp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_n -A PSW2_OUTPUT -p icmp" "$(REDIRECT)" $ipt_n -A PSW2_OUTPUT -p icmp $(REDIRECT) } [ "$accept_icmpv6" = "1" ] && { $ip6t_n -A OUTPUT -p ipv6-icmp -j PSW2_OUTPUT $ip6t_n -A PSW2_OUTPUT -p ipv6-icmp -d $FAKE_IP_6 $(REDIRECT) - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_n -A PSW2_OUTPUT -p ipv6-icmp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp" "$(REDIRECT)" $ip6t_n -A PSW2_OUTPUT -p ipv6-icmp $(REDIRECT) } @@ -898,7 +935,7 @@ add_firewall_rule() { fi $ipt_tmp -A PSW2_OUTPUT -p tcp -d $FAKE_IP ${ipt_j} - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_tmp -A PSW2_OUTPUT -p tcp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_tmp -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport")" "${ipt_j}" $ipt_tmp -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") ${ipt_j} [ -z "${is_tproxy}" ] && $ipt_n -A OUTPUT -p tcp -j PSW2_OUTPUT [ -n "${is_tproxy}" ] && { @@ -909,7 +946,7 @@ add_firewall_rule() { if [ "$PROXY_IPV6" == "1" ]; then $ip6t_m -A PSW2_OUTPUT -p tcp -d $FAKE_IP_6 -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_m -A PSW2_OUTPUT -p tcp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ip6t_m -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ip6t_m -A PSW2 $(comment "本机") -p tcp -i lo $(REDIRECT $REDIR_PORT TPROXY) $ip6t_m -A PSW2 $(comment "本机") -p tcp -i lo -j RETURN @@ -925,7 +962,7 @@ add_firewall_rule() { # 加载路由器自身代理 UDP if [ "$NODE" != "nil" ] && [ "$UDP_LOCALHOST_PROXY" = "1" ]; then $ipt_m -A PSW2_OUTPUT -p udp -d $FAKE_IP -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ipt_m -A PSW2_OUTPUT -p udp $(dst $ipset_global_whitelist) -j RETURN + add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ipt_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ipt_m -A PSW2 $(comment "本机") -p udp -i lo $(REDIRECT $REDIR_PORT TPROXY) $ipt_m -A PSW2 $(comment "本机") -p udp -i lo -j RETURN @@ -933,7 +970,7 @@ add_firewall_rule() { if [ "$PROXY_IPV6_UDP" == "1" ]; then $ip6t_m -A PSW2_OUTPUT -p udp -d $FAKE_IP_6 -j PSW2_RULE - [ "${WRITE_IPSET_DIRECT}" = "1" ] && $ip6t_m -A PSW2_OUTPUT -p udp $(dst $ipset_global_whitelist6) -j RETURN + add_shunt_t_rule "${SHUNT_LIST6}" "$ip6t_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" $ip6t_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ip6t_m -A PSW2 $(comment "本机") -p udp -i lo $(REDIRECT $REDIR_PORT TPROXY) $ip6t_m -A PSW2 $(comment "本机") -p udp -i lo -j RETURN @@ -996,6 +1033,7 @@ flush_ipset_reload() { del_firewall_rule flush_ipset rm -rf /tmp/singbox_passwall2_* + rm -f /tmp/etc/passwall2_tmp/geoip-*.json /etc/init.d/passwall2 reload } diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/nftables.sh b/small/luci-app-passwall2/root/usr/share/passwall2/nftables.sh index fb0112ec21..303431cb0c 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/nftables.sh +++ b/small/luci-app-passwall2/root/usr/share/passwall2/nftables.sh @@ -241,6 +241,92 @@ get_wan6_ip() { echo $NET_ADDR } +gen_shunt_list() { + local node=${1} + local shunt_list4_var_name=${2} + local shunt_list6_var_name=${3} + local _write_ipset_direct=${4} + local _set_name4=${5} + local _set_name6=${6} + [ -z "$node" ] && continue + unset ${shunt_list4_var_name} + unset ${shunt_list6_var_name} + local _SHUNT_LIST4 _SHUNT_LIST6 + local USE_SHUNT_NODE=0 + NODE_PROTOCOL=$(config_n_get $node protocol) + [ "$NODE_PROTOCOL" = "_shunt" ] && USE_SHUNT_NODE=1 + [ "$USE_SHUNT_NODE" = "1" ] && { + local default_node=$(config_n_get ${node} default_node _direct) + local default_outbound="redirect" + [ "$default_node" = "_direct" ] && default_outbound="direct" + local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') + for shunt_id in $shunt_ids; do + local shunt_node=$(config_n_get ${node} "${shunt_id}" nil) + [ "$shunt_node" != "nil" ] && { + local nftset_v4="passwall2_${node}_${shunt_id}" + local nftset_v6="passwall2_${node}_${shunt_id}6" + gen_nftset $nftset_v4 ipv4_addr 0 0 + gen_nftset $nftset_v6 ipv6_addr 0 0 + local outbound="redirect" + [ "$shunt_node" = "_direct" ] && outbound="direct" + [ "$shunt_node" = "_default" ] && outbound="${default_outbound}" + _SHUNT_LIST4="${_SHUNT_LIST4} ${nftset_v4}:${outbound}" + _SHUNT_LIST6="${_SHUNT_LIST6} ${nftset_v6}:${outbound}" + insert_nftset $nftset_v4 "0" $(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") + insert_nftset $nftset_v6 "0" $(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") + [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { + local _geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') + [ -n "$_geoip_code" ] && { + if [ "$(config_n_get $node type)" = "sing-box" ]; then + insert_nftset $nftset_v4 "0" $(get_singbox_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") + insert_nftset $nftset_v6 "0" $(get_singbox_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") + else + if type geoview &> /dev/null; then + insert_nftset $nftset_v4 "0" $(get_geoip $_geoip_code ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") + insert_nftset $nftset_v6 "0" $(get_geoip $_geoip_code ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") + fi + fi + echolog " - [$?]解析分流规则[$shunt_id]-[geoip:${_geoip_code}]加入到 NFTSET 完成" + } + } + } + done + [ "${_write_ipset_direct}" = "1" ] && { + _SHUNT_LIST4="${_SHUNT_LIST4} ${_set_name4}:direct" + _SHUNT_LIST6="${_SHUNT_LIST6} ${_set_name6}:direct" + } + [ "$default_node" != "nil" ] && { + local nftset_v4="passwall2_${node}_default" + local nftset_v6="passwall2_${node}_default6" + gen_nftset $nftset_v4 ipv4_addr 0 0 + gen_nftset $nftset_v6 ipv6_addr 0 0 + _SHUNT_LIST4="${_SHUNT_LIST4} ${nftset_v4}:${default_outbound}" + _SHUNT_LIST6="${_SHUNT_LIST6} ${nftset_v6}:${default_outbound}" + } + } + [ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\" + [ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\" +} + +add_shunt_t_rule() { + local shunt_args=${1} + local t_args=${2} + local t_jump_args=${3} + local t_comment=${4} + [ -n "${shunt_args}" ] && { + [ -n "${t_comment}" ] && t_comment="comment \"$t_comment\"" + for j in ${shunt_args}; do + local _set_name=$(echo ${j} | awk -F ':' '{print $1}') + local _outbound=$(echo ${j} | awk -F ':' '{print $2}') + [ -n "${_set_name}" ] && [ -n "${_outbound}" ] && { + local _t_arg="${t_jump_args}" + [ "${_outbound}" = "direct" ] && _t_arg="counter return" + ${t_args} @${_set_name} ${_t_arg} ${t_comment} + } + done + } +} + load_acl() { [ "$ENABLED_ACLS" == 1 ] && { acl_app @@ -261,6 +347,8 @@ load_acl() { node_remark=$(config_n_get $NODE remarks) [ -s "${TMP_ACL_PATH}/${sid}/var_node" ] && node=$(cat ${TMP_ACL_PATH}/${sid}/var_node) [ -s "${TMP_ACL_PATH}/${sid}/var_port" ] && redir_port=$(cat ${TMP_ACL_PATH}/${sid}/var_port) + [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && dns_redirect_port=$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) + [ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT} [ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks) write_ipset_direct=${write_ipset_direct:-1} @@ -275,32 +363,7 @@ load_acl() { gen_nftset $nftset_whitelist6 ipv6_addr 3d 3d #分流规则的IP列表(使用分流节点时导入) - local _USE_SHUNT_NODE=0 - _NODE_PROTOCOL=$(config_n_get $node protocol) - [ "$_NODE_PROTOCOL" = "_shunt" ] && _USE_SHUNT_NODE=1 - [ "$_USE_SHUNT_NODE" = "1" ] && { - local _SHUNT_DEFAULT_NODE=$(config_n_get $NODE default_node _direct) - local _GEOIP_CODE="" - local _shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for _shunt_id in $_shunt_ids; do - local _SHUNT_RULE_NODE=$(config_n_get $NODE ${_shunt_id} nil) - [ "${_SHUNT_RULE_NODE}" == "_default" ] && _SHUNT_RULE_NODE=${_SHUNT_DEFAULT_NODE} - [ "${_SHUNT_RULE_NODE}" == "_direct" ] && { - insert_nftset $nftset_whitelist "0" $(config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") - insert_nftset $nftset_whitelist6 "0" $(config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") - [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { - local _geoip_code=$(config_n_get $_shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') - [ -n "$_geoip_code" ] && _GEOIP_CODE="${_GEOIP_CODE:+$_GEOIP_CODE,}$_geoip_code" - } - } - done - } - - if [ -n "$_GEOIP_CODE" ] && type geoview &> /dev/null; then - insert_nftset $nftset_whitelist "0" $(get_geoip $_GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") - insert_nftset $nftset_whitelist6 "0" $(get_geoip $_GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") - echolog " - [$?]解析并加入分流节点 GeoIP 到 IPSET 完成" - fi + gen_shunt_list ${node} shunt_list4 shunt_list6 ${write_ipset_direct} ${nftset_whitelist} ${nftset_whitelist6} fi } @@ -368,11 +431,11 @@ load_acl() { } if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$redir_port" ]; then - [ -s "${TMP_ACL_PATH}/${sid}/var_redirect_dns_port" ] && { - nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) comment \"$remarks\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) comment \"$remarks\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) comment \"$remarks\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/${sid}/var_redirect_dns_port) comment \"$remarks\"" + [ -n "$dns_redirect_port" ] && { + nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" } else nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\"" @@ -395,26 +458,26 @@ load_acl() { [ "$accept_icmp" = "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} ip daddr $FAKE_IP $(REDIRECT) comment \"$remarks\"" - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} ip daddr @$nftset_whitelist counter return comment \"$remarks\"" + add_shunt_t_rule "${shunt_list4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} ip daddr" "$(REDIRECT)" "$remarks" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} $(REDIRECT) comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} return comment \"$remarks\"" } [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr $FAKE_IP_6 $(REDIRECT) comment \"$remarks\"" 2>/dev/null - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr @$nftset_whitelist6 counter return comment \"$remarks\"" 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr" "$(REDIRECT)" "$remarks" 2>/dev/null nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} $(REDIRECT) comment \"$remarks\"" 2>/dev/null nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} return comment \"$remarks\"" 2>/dev/null } nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} ip daddr $FAKE_IP ${nft_j} comment \"$remarks\"" - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} ip daddr @$nftset_whitelist counter return comment \"$remarks\"" + add_shunt_t_rule "${shunt_list4}" "nft add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ip daddr" "${nft_j}" "$remarks" nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ${nft_j} comment \"$remarks\"" [ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY4) comment \"$remarks\"" [ "$PROXY_IPV6" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} ip6 daddr $FAKE_IP_6 counter jump PSW2_RULE comment \"$remarks\"" - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} ip6 daddr @$nftset_whitelist6 counter return comment \"$remarks\"" 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "nft add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ip6 daddr" "counter jump PSW2_RULE" "$remarks" 2>/dev/null nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") counter jump PSW2_RULE comment \"$remarks\"" 2>/dev/null nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY) comment \"$remarks\"" 2>/dev/null } @@ -427,13 +490,13 @@ load_acl() { msg2="${msg}使用 UDP 节点[$node_remark](TPROXY:${redir_port})" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} ip daddr $FAKE_IP counter jump PSW2_RULE comment \"$remarks\"" - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} ip daddr @$nftset_whitelist counter return comment \"$remarks\"" + add_shunt_t_rule "${shunt_list4}" "nft add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") ip daddr" "counter jump PSW2_RULE" "$remarks" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") counter jump PSW2_RULE comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(REDIRECT $redir_port TPROXY4) comment \"$remarks\"" [ "$PROXY_IPV6" == "1" ] && [ "$PROXY_IPV6_UDP" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} ip6 daddr $FAKE_IP_6 counter jump PSW2_RULE comment \"$remarks\"" - [ "${write_ipset_direct}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} ip6 daddr @$nftset_whitelist6 counter return comment \"$remarks\"" 2>/dev/null + add_shunt_t_rule "${shunt_list6}" "nft add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") ip6 daddr" "counter jump PSW2_RULE" "$remarks" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") counter jump PSW2_RULE comment \"$remarks\"" 2>/dev/null nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(REDIRECT $redir_port TPROXY) comment \"$remarks\"" 2>/dev/null } @@ -475,11 +538,11 @@ load_acl() { } if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ "$NODE" != "nil" ]; then - [ -s "${TMP_ACL_PATH}/default/var_redirect_dns_port" ] && { - nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"默认\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"默认\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"默认\"" - nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"默认\"" + [ -n "$DNS_REDIRECT_PORT" ] && { + nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" + nft "add rule $NFTABLE_NAME PSW2_REDIRECT meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" } fi @@ -497,26 +560,26 @@ load_acl() { [ "$accept_icmp" = "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ip daddr $FAKE_IP $(REDIRECT) comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ip daddr @$nftset_global_whitelist counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ip daddr" "$(REDIRECT)" "默认" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp $(REDIRECT) comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp return comment \"默认\"" } [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr $FAKE_IP_6 $(REDIRECT) comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr @$nftset_global_whitelist6 counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr" "$(REDIRECT)" "默认" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 $(REDIRECT) comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT meta l4proto icmpv6 return comment \"默认\"" } nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr $FAKE_IP ${nft_j} comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr @$nftset_global_whitelist counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip daddr" "${nft_j}" "默认" nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ${nft_j} comment \"默认\"" [ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp $(REDIRECT $REDIR_PORT TPROXY4) comment \"默认\"" [ "$PROXY_IPV6" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 jump PSW2_RULE comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ip6 daddr @$nftset_global_whitelist6 counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip6 daddr" "${nft_j}" "默认" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") counter jump PSW2_RULE comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp $(REDIRECT $REDIR_PORT TPROXY) comment \"默认\"" } @@ -528,13 +591,13 @@ load_acl() { msg2="${msg}使用 UDP 节点[$(config_n_get $NODE remarks)](TPROXY:${REDIR_PORT})" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ip daddr @$nftset_global_whitelist counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") ip daddr" "counter jump PSW2_RULE" "默认" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp $(REDIRECT $REDIR_PORT TPROXY4) comment \"默认\"" [ "$PROXY_IPV6" == "1" ] && [ "$PROXY_IPV6_UDP" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 jump PSW2_RULE comment \"默认\"" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ip6 daddr @$nftset_global_whitelist6 counter return comment \"默认\"" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") ip6 daddr" "counter jump PSW2_RULE" "默认" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp $(REDIRECT $REDIR_PORT TPROXY) comment \"默认\"" } @@ -716,32 +779,7 @@ add_firewall_rule() { gen_nftset $nftset_global_whitelist6 ipv6_addr 0 0 #分流规则的IP列表(使用分流节点时导入) - local USE_SHUNT_NODE=0 - NODE_PROTOCOL=$(config_n_get $NODE protocol) - [ "$NODE_PROTOCOL" = "_shunt" ] && USE_SHUNT_NODE=1 - [ "$USE_SHUNT_NODE" = "1" ] && { - local SHUNT_DEFAULT_NODE=$(config_n_get $NODE default_node _direct) - local GEOIP_CODE="" - local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for shunt_id in $shunt_ids; do - local SHUNT_RULE_NODE=$(config_n_get $NODE ${shunt_id} nil) - [ "${SHUNT_RULE_NODE}" == "_default" ] && SHUNT_RULE_NODE=${SHUNT_DEFAULT_NODE} - [ "${SHUNT_RULE_NODE}" == "_direct" ] && { - insert_nftset $nftset_global_whitelist "0" $(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") - insert_nftset $nftset_global_whitelist6 "0" $(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") - [ "$(config_t_get global_rules enable_geoview)" = "1" ] && { - local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') - [ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code" - } - } - done - } - - if [ -n "$GEOIP_CODE" ] && type geoview &> /dev/null; then - insert_nftset $nftset_global_whitelist "0" $(get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}") - insert_nftset $nftset_global_whitelist6 "0" $(get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") - echolog " - [$?]解析并加入分流节点 GeoIP 到 IPSET 完成" - fi + gen_shunt_list ${NODE} SHUNT_LIST4 SHUNT_LIST6 ${WRITE_IPSET_DIRECT} ${nftset_global_whitelist} ${nftset_global_whitelist6} # 过滤所有节点IP filter_vpsip > /dev/null 2>&1 & @@ -925,11 +963,11 @@ add_firewall_rule() { } if [ "$NODE" != "nil" ] && ([ "$TCP_LOCALHOST_PROXY" = "1" ] || [ "$UDP_LOCALHOST_PROXY" = "1" ]); then - [ -s "${TMP_ACL_PATH}/default/var_redirect_dns_port" ] && { - nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"PSW2\"" - nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"PSW2\"" - nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"PSW2\"" - nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$(cat ${TMP_ACL_PATH}/default/var_redirect_dns_port) comment \"PSW2\"" + [ -n "$DNS_REDIRECT_PORT" ] && { + nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\"" + nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\"" + nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\"" + nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\"" } fi @@ -937,14 +975,14 @@ add_firewall_rule() { if [ "$NODE" != "nil" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then [ "$accept_icmp" = "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr $FAKE_IP counter redirect" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr @$nftset_global_whitelist counter return" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr" "counter redirect" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp counter redirect" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp counter return" } [ "$accept_icmpv6" = "1" ] && { nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 ip6 daddr $FAKE_IP_6 counter redirect" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 ip6 daddr @$nftset_global_whitelist6 counter return" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 ip6 daddr" "counter redirect" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 counter redirect" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo meta l4proto icmpv6 counter return" } @@ -958,7 +996,7 @@ add_firewall_rule() { fi nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr $FAKE_IP ${nft_j}" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ip daddr @$nftset_global_whitelist counter return" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip daddr" "${nft_j}" nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(factor $TCP_REDIR_PORTS "tcp dport") ${nft_j}" [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME nat_output ip protocol tcp counter jump PSW2_OUTPUT_NAT" [ -n "${is_tproxy}" ] && { @@ -969,7 +1007,7 @@ add_firewall_rule() { [ "$PROXY_IPV6" == "1" ] && { nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 jump PSW2_RULE" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp ip6 daddr @$nftset_global_whitelist6 counter return" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip6 daddr" "counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp iif lo $(REDIRECT $REDIR_PORT TPROXY) comment \"本机\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp iif lo counter return comment \"本机\"" @@ -984,7 +1022,7 @@ add_firewall_rule() { # 加载路由器自身代理 UDP if [ "$NODE" != "nil" ] && [ "$UDP_LOCALHOST_PROXY" = "1" ]; then nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp ip daddr @$nftset_global_whitelist counter return" + add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") ip daddr" "counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp iif lo $(REDIRECT $REDIR_PORT TPROXY4) comment \"本机\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp iif lo counter return comment \"本机\"" @@ -992,7 +1030,7 @@ add_firewall_rule() { if [ "$PROXY_IPV6_UDP" == "1" ]; then nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 jump PSW2_RULE" - [ "${WRITE_IPSET_DIRECT}" = "1" ] && nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr @$nftset_global_whitelist6 counter return" + add_shunt_t_rule "${SHUNT_LIST6}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") ip6 daddr" "counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo $(REDIRECT $REDIR_PORT TPROXY) comment \"本机\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp iif lo counter return comment \"本机\"" @@ -1073,6 +1111,7 @@ flush_nftset_reload() { del_firewall_rule flush_table rm -rf /tmp/singbox_passwall2_* + rm -f /tmp/etc/passwall2_tmp/geoip-*.json /etc/init.d/passwall2 reload } diff --git a/xray-core/transport/internet/splithttp/client.go b/xray-core/transport/internet/splithttp/client.go index 35aad1ec85..925d3b0d2a 100644 --- a/xray-core/transport/internet/splithttp/client.go +++ b/xray-core/transport/internet/splithttp/client.go @@ -39,8 +39,7 @@ type DialerClient interface { type DefaultDialerClient struct { transportConfig *Config client *http.Client - isH2 bool - isH3 bool + httpVersion string // pool of net.Conn, created using dialUploadConn uploadRawPool *sync.Pool dialUploadConn func(ctxInner context.Context) (net.Conn, error) @@ -172,7 +171,7 @@ func (c *DefaultDialerClient) SendUploadRequest(ctx context.Context, url string, req.ContentLength = contentLength req.Header = c.transportConfig.GetRequestHeader() - if c.isH2 || c.isH3 { + if c.httpVersion != "1.1" { resp, err := c.client.Do(req) if err != nil { return err diff --git a/xray-core/transport/internet/splithttp/dialer.go b/xray-core/transport/internet/splithttp/dialer.go index 14e8c9c341..cd0abc85bd 100644 --- a/xray-core/transport/internet/splithttp/dialer.go +++ b/xray-core/transport/internet/splithttp/dialer.go @@ -3,6 +3,7 @@ package splithttp import ( "context" gotls "crypto/tls" + "fmt" "io" "net/http" "net/http/httptrace" @@ -83,33 +84,31 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in return res.Resource.(DialerClient), res } -func h(tlsConfig *tls.Config, realityConfig *reality.Config) int { +func decideHTTPVersion(tlsConfig *tls.Config, realityConfig *reality.Config) string { if realityConfig != nil { - return 2 + return "2" } if tlsConfig == nil { - return 1 + return "1.1" } if len(tlsConfig.NextProtocol) != 1 { - return 2 + return "2" } if tlsConfig.NextProtocol[0] == "http/1.1" { - return 1 + return "1.1" } if tlsConfig.NextProtocol[0] == "h3" { - return 3 + return "3" } - return 2 + return "2" } func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStreamConfig) DialerClient { tlsConfig := tls.ConfigFromStreamSettings(streamSettings) realityConfig := reality.ConfigFromStreamSettings(streamSettings) - isH2 := h(tlsConfig, realityConfig) == 2 - isH3 := h(tlsConfig, realityConfig) == 3 - - if isH3 { + httpVersion := decideHTTPVersion(tlsConfig, realityConfig) + if httpVersion == "3" { dest.Network = net.Network_UDP // better to keep this line } @@ -149,7 +148,7 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea var transport http.RoundTripper - if isH3 { + if httpVersion == "3" { if keepAlivePeriod == 0 { keepAlivePeriod = quicgoH3KeepAlivePeriod } @@ -205,7 +204,7 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea return quic.DialEarly(ctx, udpConn, udpAddr, tlsCfg, cfg) }, } - } else if isH2 { + } else if httpVersion == "2" { if keepAlivePeriod == 0 { keepAlivePeriod = chromeH2KeepAlivePeriod } @@ -239,8 +238,7 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea client: &http.Client{ Transport: transport, }, - isH2: isH2, - isH3: isH3, + httpVersion: httpVersion, uploadRawPool: &sync.Pool{}, dialUploadConn: dialContext, } @@ -256,10 +254,10 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me tlsConfig := tls.ConfigFromStreamSettings(streamSettings) realityConfig := reality.ConfigFromStreamSettings(streamSettings) - if h(tlsConfig, realityConfig) == 3 { + httpVersion := decideHTTPVersion(tlsConfig, realityConfig) + if httpVersion == "3" { dest.Network = net.Network_UDP } - errors.LogInfo(ctx, "XHTTP is dialing to: ", dest) transportConfiguration := streamSettings.ProtocolSettings.(*Config) var requestURL url.URL @@ -286,6 +284,19 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me httpClient, muxRes := getHTTPClient(ctx, dest, streamSettings) + mode := transportConfiguration.Mode + if mode == "" || mode == "auto" { + mode = "packet-up" + if httpVersion == "2" { + mode = "stream-up" + } + if realityConfig != nil && transportConfiguration.DownloadSettings == nil { + mode = "stream-one" + } + } + + errors.LogInfo(ctx, fmt.Sprintf("XHTTP is dialing to %s, mode %s, HTTP version %s, host %s", dest, mode, httpVersion, requestURL.Host)) + requestURL2 := requestURL httpClient2 := httpClient var muxRes2 *muxResource @@ -299,10 +310,10 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me dest2 := *memory2.Destination // just panic tlsConfig2 := tls.ConfigFromStreamSettings(memory2) realityConfig2 := reality.ConfigFromStreamSettings(memory2) - if h(tlsConfig2, realityConfig2) == 3 { + httpVersion2 := decideHTTPVersion(tlsConfig2, realityConfig2) + if httpVersion2 == "3" { dest2.Network = net.Network_UDP } - errors.LogInfo(ctx, "XHTTP is downloading from: ", dest2) if tlsConfig2 != nil || realityConfig2 != nil { requestURL2.Scheme = "https" } else { @@ -322,20 +333,9 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me requestURL2.Path = config2.GetNormalizedPath() + sessionIdUuid.String() requestURL2.RawQuery = config2.GetNormalizedQuery() httpClient2, muxRes2 = getHTTPClient(ctx, dest2, memory2) + errors.LogInfo(ctx, fmt.Sprintf("XHTTP is downloading from %s, mode %s, HTTP version %s, host %s", dest2, "stream-down", httpVersion2, requestURL2.Host)) } - mode := transportConfiguration.Mode - if mode == "" || mode == "auto" { - mode = "packet-up" - if h(tlsConfig, realityConfig) == 2 { - mode = "stream-up" - } - if realityConfig != nil && transportConfiguration.DownloadSettings == nil { - mode = "stream-one" - } - } - errors.LogInfo(ctx, "XHTTP is using mode: ", mode) - var writer io.WriteCloser var reader io.ReadCloser var remoteAddr, localAddr net.Addr diff --git a/yt-dlp/yt_dlp/extractor/patreon.py b/yt-dlp/yt_dlp/extractor/patreon.py index 6bdeaf1571..a0e831a5ce 100644 --- a/yt-dlp/yt_dlp/extractor/patreon.py +++ b/yt-dlp/yt_dlp/extractor/patreon.py @@ -457,7 +457,7 @@ class PatreonCampaignIE(PatreonBaseIE): _VALID_URL = r'''(?x) https?://(?:www\.)?patreon\.com/(?: (?:m|api/campaigns)/(?P\d+)| - (?P(?!creation[?/]|posts/|rss[?/])[\w-]+) + (?:c/)?(?P(?!creation[?/]|posts/|rss[?/])[\w-]+) )(?:/posts)?/?(?:$|[?#])''' _TESTS = [{ 'url': 'https://www.patreon.com/dissonancepod/', @@ -509,6 +509,26 @@ class PatreonCampaignIE(PatreonBaseIE): 'thumbnail': r're:^https?://.*$', }, 'playlist_mincount': 201, + }, { + 'url': 'https://www.patreon.com/c/OgSog', + 'info_dict': { + 'id': '8504388', + 'title': 'OGSoG', + 'description': r're:(?s)Hello and welcome to our Patreon page. We are Mari, Lasercorn, .+', + 'channel': 'OGSoG', + 'channel_id': '8504388', + 'channel_url': 'https://www.patreon.com/OgSog', + 'uploader_url': 'https://www.patreon.com/OgSog', + 'uploader_id': '72323575', + 'uploader': 'David Moss', + 'thumbnail': r're:https?://.+/.+', + 'channel_follower_count': int, + 'age_limit': 0, + }, + 'playlist_mincount': 331, + }, { + 'url': 'https://www.patreon.com/c/OgSog/posts', + 'only_matching': True, }, { 'url': 'https://www.patreon.com/dissonancepod/posts', 'only_matching': True, diff --git a/yt-dlp/yt_dlp/extractor/soundcloud.py b/yt-dlp/yt_dlp/extractor/soundcloud.py index e0dda8ff89..66bc5f9c58 100644 --- a/yt-dlp/yt_dlp/extractor/soundcloud.py +++ b/yt-dlp/yt_dlp/extractor/soundcloud.py @@ -259,6 +259,8 @@ class SoundcloudBaseIE(InfoExtractor): preset_base = preset.partition('_')[0] protocol = traverse_obj(t, ('format', 'protocol', {str})) or 'http' + if protocol.startswith(('ctr-', 'cbc-')): + continue if protocol == 'progressive': protocol = 'http' if protocol != 'hls' and '/hls' in format_url: diff --git a/yt-dlp/yt_dlp/extractor/youtube.py b/yt-dlp/yt_dlp/extractor/youtube.py index e69373ba2f..7eb522a47a 100644 --- a/yt-dlp/yt_dlp/extractor/youtube.py +++ b/yt-dlp/yt_dlp/extractor/youtube.py @@ -4689,7 +4689,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor): (?=(?P[^\n]+))(?P=artist)\n+ (?=(?P[^\n]+))(?P=album)\n (?:.+?℗\s*(?P\d{4})(?!\d))? - (?:.+?Released on\s*:\s*(?P\d{4}-\d{2}-\d{2}))? + (?:.+?Released\ on\s*:\s*(?P\d{4}-\d{2}-\d{2}))? (.+?\nArtist\s*:\s* (?=(?P[^\n]+))(?P=clean_artist)\n )?.+\nAuto-generated\ by\ YouTube\.\s*$ @@ -5282,6 +5282,7 @@ class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor): 'channelRenderer': lambda x: self._grid_entries({'items': [{'channelRenderer': x}]}), 'hashtagTileRenderer': lambda x: [self._hashtag_tile_entry(x)], 'richGridRenderer': lambda x: self._extract_entries(x, continuation_list), + 'lockupViewModel': lambda x: [self._extract_lockup_view_model(x)], } for key, renderer in isr_content.items(): if key not in known_renderers: