🌴 Sync 2026-09-09 14:20:42

This commit is contained in:
github-actions[bot] committed 2026-09-09 14:20:42 +08:00
1 parent 99e36fe9b0
commit e45467bc23
77 files changed
+2534 -2032

No files matched your search

+2 -2
View File
@@ -12,7 +12,7 @@ PKG_ARCH_LINKEASE:=$(ARCH)
PKG_NAME:=linkease-common-bin
# use PKG_SOURCE_DATE instead of PKG_VERSION for compitable
PKG_SOURCE_DATE:=1.7.5
PKG_RELEASE:=26
PKG_RELEASE:=27
ARCH_HEXCODE:=
ifeq ($(ARCH),x86_64)
@@ -28,7 +28,7 @@ else ifeq ($(ARCH),mipsel)
ARCH_HEXCODE=1b0c
endif
PKG_SOURCE_VERSION:=5d3413bb9fc988a148a8a9593c5e3bf49042a141
PKG_SOURCE_VERSION:=679d98db83ff6708167bcaf8c5c5c0ab5cc2426b
PKG_SOURCE:=linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/
PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE)
+2 -2
View File
@@ -12,7 +12,7 @@ PKG_ARCH_LINKEASE:=$(ARCH)
PKG_NAME:=linkease
# use PKG_SOURCE_DATE instead of PKG_VERSION for compitable
PKG_SOURCE_DATE:=1.7.5
PKG_RELEASE:=29
PKG_RELEASE:=30
ARCH_HEXCODE:=
ifeq ($(ARCH),x86_64)
@@ -28,7 +28,7 @@ else ifeq ($(ARCH),mipsel)
ARCH_HEXCODE=1b0c
endif
PKG_SOURCE_VERSION:=5d3413bb9fc988a148a8a9593c5e3bf49042a141
PKG_SOURCE_VERSION:=679d98db83ff6708167bcaf8c5c5c0ab5cc2426b
PKG_SOURCE:=linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/
PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE)
+2 -2
View File
@@ -11,7 +11,7 @@ PKG_ARCH_LINKEASE:=$(ARCH)
PKG_NAME:=linkeasefull
# use PKG_SOURCE_DATE instead of PKG_VERSION for compitable
PKG_SOURCE_DATE:=3.0.17
PKG_RELEASE:=28
PKG_RELEASE:=29
ARCH_HEXCODE:=
ifeq ($(ARCH),x86_64)
@@ -24,7 +24,7 @@ LINKEASE_RUNTIME_ARCH:=arm64
PKG_HASH:=skip
endif
PKG_SOURCE_VERSION:=5d3413bb9fc988a148a8a9593c5e3bf49042a141
PKG_SOURCE_VERSION:=679d98db83ff6708167bcaf8c5c5c0ab5cc2426b
PKG_SOURCE:=linkease-runtime-$(PKG_SOURCE_DATE)-linux-$(LINKEASE_RUNTIME_ARCH).tar.gz
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkeasefull-runtime-v$(PKG_SOURCE_DATE)/
PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-runtime-$(PKG_SOURCE_DATE)-linux-$(LINKEASE_RUNTIME_ARCH)
+135 -101
View File
@@ -1,6 +1,6 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2026-08-31 16:28+0000\n"
"PO-Revision-Date: 2026-08-31 20:02+0000\n"
"Last-Translator: Martin Olmer <m_iv@seznam.cz>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrpc/cs/>\n"
@@ -397,14 +397,17 @@ msgid ""
"visitor sections. Use frp includes or per-proxy raw settings for proxy/"
"visitor tables."
msgstr ""
"Další součásti nastavení na úrovni správce, obsažené před vytvořenými "
"sekcemi pro proxy a návštěvníky. Použijte frp includes nebo holá nastavení "
"pro jednotlivá proxy pro tabulky proxy/návštěvníků."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:900
msgid "Fallback timeout in milliseconds for XTCP."
msgstr ""
msgstr "Časový limit náhradního (v milisekundách) pro XTCP."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:899
msgid "Fallback timeout ms"
msgstr ""
msgstr "Časový limit náhradního (ms)"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:895
msgid "Fallback to"
@@ -412,7 +415,7 @@ msgstr "Náhradně použít"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:896
msgid "Fallback visitor name for XTCP."
msgstr ""
msgstr "Náhradní název návštěvníka pro XTCP."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:594
msgid "Feature gates"
@@ -420,7 +423,7 @@ msgstr "Propagovat brány"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1047
msgid "For virtual_net visitor plugin."
msgstr ""
msgstr "Pro zásuvný modul virtual_net návštěvník."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1460
msgid "General Settings"
@@ -432,23 +435,23 @@ msgstr "Udělit přístup k LuCI aplikaci frpc"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1462
msgid "HTTP / Domain"
msgstr ""
msgstr "HTTP / doména"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:820
msgid "HTTP health check headers. Use Header=Value."
msgstr ""
msgstr "Hlavičky kontroly vitality HTTP. Použijte Hlavička=Hodnota."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:801
msgid "HTTP health check path."
msgstr ""
msgstr "Popis umístění pro kontrolu vitality HTTP."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:747
msgid "HTTP or TCPMUX basic auth password."
msgstr ""
msgstr "Heslo pro HTTP nebo TCPMUX basic auth."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:744
msgid "HTTP or TCPMUX basic auth username."
msgstr ""
msgstr "Uživatelské jméno pro HTTP nebo TCPMUX basic auth."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:746
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:935
@@ -457,7 +460,7 @@ msgstr "HTTP heslo"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1211
msgid "HTTP path must start with /."
msgstr ""
msgstr "Je třeba, aby HTTP popis umístění začínal na / (lomítko)."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:743
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:931
@@ -470,43 +473,45 @@ msgstr "Kontrola vitality"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:819
msgid "Health check headers"
msgstr ""
msgstr "Hlavičky kontroly vitality"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:796
msgid "Health check interval"
msgstr ""
msgstr "Interval kontroly vitality"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:797
msgid "Health check interval in seconds."
msgstr ""
msgstr "Interval kontroly vitality (v sekundách)."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:792
msgid "Health check max failed"
msgstr ""
msgstr "Nejvýše přijatelných nezdarů kontroly vitality"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:800
msgid "Health check path"
msgstr ""
msgstr "Popis umístění pro kontrolu vitality"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:813
msgid "Health check path is required when health check type is http."
msgstr ""
"Pokud je typ kontroly http, je zapotřebí popis umístění pro kontrolu "
"vitality."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:788
msgid "Health check timeout"
msgstr ""
msgstr "Časový limit kontroly vitality"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:789
msgid "Health check timeout in seconds."
msgstr ""
msgstr "Časový limit kontroly vitality (v sekundách)."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:784
msgid "Health check type"
msgstr ""
msgstr "Typ kontroly vitality"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:785
msgid "Health check type."
msgstr ""
msgstr "Typ kontroly vitality."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:530
msgid "Heartbeat interval"
@@ -514,7 +519,7 @@ msgstr "Interval kontroly stavu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:531
msgid "Heartbeat interval in seconds."
msgstr ""
msgstr "Interval kontroly vitality (v sekundách)."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:534
msgid "Heartbeat timeout"
@@ -530,15 +535,15 @@ msgstr "Přepsání hlavičky hostitel"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:225
msgid "Include config files"
msgstr ""
msgstr "Zahrnout soubory s nastaveními"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:884
msgid "Keep XTCP tunnel open."
msgstr ""
msgstr "Ponechat XTCP tunel otevřený."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:883
msgid "Keep tunnel open"
msgstr ""
msgstr "Ponechat tunel otevřený"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:511
msgid "Keepalive interval for TCP mux."
@@ -550,15 +555,16 @@ msgstr "Rozprostírání zátěže"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:763
msgid "Load balancer group"
msgstr ""
msgstr "Skupina rozprostírání zátěže"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:776
msgid "Load balancer group is required when group key is set."
msgstr ""
"Pokud je nastavený klíč skupiny, je zapotřebí skupina rozprostírání zátěže."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:767
msgid "Load balancer group key"
msgstr ""
msgstr "Klíč skupiny rozprostírání zátěže"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:255
msgid ""
@@ -578,6 +584,8 @@ msgstr "Lokální IP adresa"
msgid ""
"Local IP bound when connecting to frps. Only valid for tcp, websocket or wss."
msgstr ""
"Navázání na lokální IP adresu při připojování k frps. Platné pouze pro tcp, "
"websocket nebo wss."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:967
msgid ""
@@ -585,14 +593,20 @@ msgid ""
"and tls2raw, this is the local service address reached after frp terminates "
"external TLS; for http2https/http2http, it is the local upstream address."
msgstr ""
"Adresa lokální podpůrné vrstvy použitá zásuvnými moduly typu most. Pro "
"https2http, https2https a tls2raw, je toto adresa lokální služby dosažená "
"poté, co frp terminuje externí TLS; pro http2https/htttp2http, se jedná o "
"lokální nadřazenou adresu."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:862
msgid "Local bind address for visitor."
msgstr ""
msgstr "Lokální adresa pro navázání pro návštěvníka."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:866
msgid "Local bind port for visitor. Use a negative value to avoid binding."
msgstr ""
"Lokální port pro navázání pro návštěvníka. Pokud se chcete vyhnout navázání "
"se na, použijte zápornou hodnotu."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:663
msgid "Local port"
@@ -600,11 +614,11 @@ msgstr "Lokální port"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:660
msgid "Local service IP or host."
msgstr ""
msgstr "IP adresa nebo hostitel lokální služby."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:664
msgid "Local service port."
msgstr ""
msgstr "Port lokální služby."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:711
msgid "Locations"
@@ -640,7 +654,7 @@ msgstr "Zaznamenávat standardní výstup"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:887
msgid "Max retries per hour"
msgstr ""
msgstr "Nejvýše opakovaných pokusů za hodinu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:392
msgid "Maximum number of days to keep logs."
@@ -652,19 +666,19 @@ msgstr "Metadata"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:891
msgid "Min retry interval"
msgstr ""
msgstr "Nejmenší interval opakovaného pokusu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:892
msgid "Minimum XTCP retry interval."
msgstr ""
msgstr "Nejmenší interval XTCP opakovaného pokusu."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:757
msgid "Multiplexer"
msgstr ""
msgstr "Multiplexer"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:197
msgid "NAT hole STUN server"
msgstr ""
msgstr "STUN server NAT prostupu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1390
msgid "NOT RUNNING"
@@ -672,7 +686,7 @@ msgstr "NESPUŠTĚNÉ"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:359
msgid "OIDC additional endpoint params"
msgstr ""
msgstr "Další parametry koncového bodu OIDC"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:347
msgid "OIDC audience"
@@ -680,19 +694,19 @@ msgstr "OIDC publikum"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:339
msgid "OIDC client ID"
msgstr ""
msgstr "OIDC identifikátor klienta"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:343
msgid "OIDC client secret"
msgstr ""
msgstr "OIDC tajemství klienta"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:373
msgid "OIDC insecure skip verify"
msgstr ""
msgstr "OIDC nezabezpečené přeskočení ověření"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:377
msgid "OIDC proxy URL"
msgstr ""
msgstr "URL OIDC proxy"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:351
msgid "OIDC scope"
@@ -700,11 +714,11 @@ msgstr "OIDC rozsah"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:355
msgid "OIDC token endpoint URL"
msgstr ""
msgstr "URL koncového bodu OIDC tokenu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:369
msgid "OIDC trusted CA file"
msgstr ""
msgstr "Soubor s důvěryhodnou cert. autoritou pro OIDC"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:166
msgid "OS environments passed to frp for config file template, see %s."
@@ -715,23 +729,27 @@ msgstr ""
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:218
msgid "Only start specified proxies or visitors. Empty means start all."
msgstr ""
"Spouštět pouze uvedené proxy nebo návštěvníky. Nevyplněné znamená spustit "
"vše."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1231
msgid "Only the virtual_net plugin is valid for visitors."
msgstr ""
msgstr "Pro návštěvníky je platný pouze zásuvný modul virtual_net."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:712
msgid "Only valid for HTTP proxy."
msgstr ""
msgstr "Platné pouze pro HTTP proxy."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:840
msgid ""
"Only visitors from specified users can connect. Use * to allow all users."
msgstr ""
"Připojit se mohou pouze návštěvníci od uvedených uživatelů. Pokud chcete "
"umožnit všechny uživatele, použijte * (hvězdička)."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:184
msgid "Optional unique identifier for this frpc instance."
msgstr ""
msgstr "Volitelný neopakující se identifikátor pro tuto instanci frpc."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:271
msgid "Path of token file."
@@ -763,10 +781,12 @@ msgstr "Popis umístění souboru s certifikátem důvěryhodné cert. autority.
msgid ""
"Persist runtime proxy and visitor configuration for Web UI or API management."
msgstr ""
"Učinit nastavení pro Web UI nebo správu API ohledně běhové proxy a "
"návštěvníka trvalým."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1221
msgid "Please use KEY=value format."
msgstr ""
msgstr "Použijte formát KLÍČ=hodnota."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:909
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1463
@@ -779,23 +799,23 @@ msgstr "Zásuvný modul HTTP/2"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:979
msgid "Plugin certificate path"
msgstr ""
msgstr "Popis umístění certifikátu zásuvného modulu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1003
msgid "Plugin host header rewrite"
msgstr ""
msgstr "Přepis hlavičky hostitele zásuvného modulu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:991
msgid "Plugin key path"
msgstr ""
msgstr "Popis umístění klíče zásuvného modulu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:966
msgid "Plugin local address"
msgstr ""
msgstr "Lokální adresa zásuvného modulu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1031
msgid "Plugin request headers"
msgstr ""
msgstr "Hlavičky požadavku zásuvného modulu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:910
msgid "Plugin type."
@@ -811,23 +831,25 @@ msgstr "Je třeba, aby port byl z rozmezí 0 až 65535."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1187
msgid "Port must be negative or a number between 1 and 65535."
msgstr ""
msgstr "Je třeba, aby port byl záporný nebo číslo z rozsahu 1 až 65535."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1191
msgid "Port must be negative or between 1 and 65535."
msgstr ""
msgstr "Je třeba, aby port byl záporný nebo z rozmezí 1 až 65535."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:191
msgid "Port of the frps server. Default is 7000."
msgstr ""
msgstr "Port frps serveru. Výchozí je 7000."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:195
msgid "Prefix for proxy names. If set, proxy names become {user}.{proxy}."
msgstr ""
"Předpona pro názvy proxy. Pokud nastaveno, názvy proxy se stanou {user}."
"{proxy}."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1449
msgid "Proxy / Visitor Settings"
msgstr ""
msgstr "Nastavení proxy/návštěvníka"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:490
msgid "Proxy URL"
@@ -835,11 +857,12 @@ msgstr "URL proxy"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:378
msgid "Proxy URL for OIDC token endpoint."
msgstr ""
msgstr "URL proxy pro koncový bod OIDC tokenu."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:491
msgid "Proxy URL used to connect to frps. Supports http, socks5 and ntlm."
msgstr ""
"URL proxy sloužící pro připojování k frps. Podporuje http, socks5 a ntlm."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1059
msgid "Proxy metadatas"
@@ -851,11 +874,11 @@ msgstr "Název proxy"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:194
msgid "Proxy name prefix"
msgstr ""
msgstr "Předpona názvu proxy"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:696
msgid "Proxy protocol version"
msgstr ""
msgstr "Verze protokolu proxy"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:643
msgid "Proxy type"
@@ -888,10 +911,12 @@ msgstr "Vzdálený port"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:668
msgid "Remote port listened by frps. If 0, frps assigns a random port."
msgstr ""
"Vzdálený port na kterém frps očekává spojení. Pokud 0 (nula), frps přiřadí "
"náhodný port."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:793
msgid "Remove proxy from frps after continuous failures."
msgstr ""
msgstr "Po pokračujících nezdarech, odebrat proxy z frps."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:723
msgid "Request headers"
@@ -907,7 +932,7 @@ msgstr "Hlavičky odpovědí"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:721
msgid "Rewrite Host header."
msgstr ""
msgstr "Přepsat záhlaví hostitele."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:831
msgid "Role"
@@ -915,11 +940,11 @@ msgstr "Role"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:753
msgid "Route HTTP or TCPMUX requests by HTTP basic auth user."
msgstr ""
msgstr "Směrovat HTTP nebo TCPMUX požadavky podle HTTP basic auth uživatele."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:752
msgid "Route by HTTP user"
msgstr ""
msgstr "Směrovat podle HTTP uživatele"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:153
msgid "Run daemon as group"
@@ -939,11 +964,11 @@ msgstr "SOCKS5 uživatel"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1464
msgid "STCP / XTCP / SUDP"
msgstr ""
msgstr "STCP / XTCP / SUDP"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:198
msgid "STUN server used for NAT traversal."
msgstr ""
msgstr "STUN server sloužící pro překonávání NAT překladu."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:835
msgid "Secret key"
@@ -951,7 +976,7 @@ msgstr "Tajný klíč"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:836
msgid "Secret key used by STCP/XTCP/SUDP proxies and visitors."
msgstr ""
msgstr "Tajný klíč používaný STCP/XTCP/SUDP proxy a návštěvníky."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:186
msgid "Server address"
@@ -963,11 +988,11 @@ msgstr "Název serveru"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:855
msgid "Server name is required for visitors."
msgstr ""
msgstr "Pro návštěvníky je zapotřebí název serveru."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:565
msgid "Server name used for TLS verification."
msgstr ""
msgstr "Název serveru sloužící pro TLS ověřování."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:190
msgid "Server port"
@@ -975,7 +1000,7 @@ msgstr "Port na serveru"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:848
msgid "Server proxy name to visit."
msgstr ""
msgstr "Název proxy serveru k navštívení."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:843
msgid "Server user"
@@ -983,28 +1008,30 @@ msgstr "Uživatel serveru"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:844
msgid "Server user for visitor."
msgstr ""
msgstr "Serverový uživatel pro návštěvníka."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:724
msgid "Set request headers. Use Header=Value."
msgstr ""
msgstr "Nastavit hlavičky požadavku. Použijte Hlavička=Hodnota."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:733
msgid "Set response headers. Use Header=Value."
msgstr ""
msgstr "Nastavit hlavičky odpovědi. Použijte Hlavička=Hodnota."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:569
msgid "Since frp v0.50.0, default is true."
msgstr ""
msgstr "Od verze frp 0.50.0 je výchozí zapnuto."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:374
msgid ""
"Skip TLS verification for OIDC endpoint. Not recommended for production."
msgstr ""
"Přeskočit TLS ověřování pro OIDC koncový bod. Nedoporučováno pro produkční "
"nasazení."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:217
msgid "Start proxies / visitors"
msgstr ""
msgstr "Spustit proxy / návštěvníky"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1432
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1442
@@ -1013,15 +1040,15 @@ msgstr "Nastavení spouštění"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:958
msgid "Static file local path"
msgstr ""
msgstr "Lokální popis umístění statického souboru"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:962
msgid "Static file strip prefix"
msgstr ""
msgstr "Oříznout předponu statického souboru"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:607
msgid "Store file path"
msgstr ""
msgstr "Popis umístění souboru pro ukládání"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:706
msgid "Subdomain"
@@ -1030,10 +1057,12 @@ msgstr "Dílčí doména"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:487
msgid "TCP keepalive interval in seconds. Negative value disables keepalive."
msgstr ""
"Interval udržování TCP spojení (v sekundách). Záporná hodnota udržování "
"vypíná."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:758
msgid "TCP multiplexer."
msgstr ""
msgstr "TCP multiplexer."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:498
msgid "TCP mux"
@@ -1041,7 +1070,7 @@ msgstr "TCP mux"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:510
msgid "TCP mux keepalive interval"
msgstr ""
msgstr "Interval udržování spojení TCP multiplexeru"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:540
msgid "TLS"
@@ -1049,37 +1078,40 @@ msgstr "TLS"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1428
msgid "TLS / QUIC"
msgstr ""
msgstr "TLS / QUIC"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:428
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:552
msgid "TLS certificate path"
msgstr ""
msgstr "Popis umístění TLS certifikátu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:440
msgid "TLS certificate path is required when web HTTPS is enabled."
msgstr ""
"Pokud je zapnuté web HTTPS, je zapotřebí popis umístění TLS certifikátu."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:446
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:556
msgid "TLS private key path"
msgstr ""
msgstr "Popis umístění soukromého TLS klíče"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:458
msgid "TLS private key path is required when web HTTPS is enabled."
msgstr ""
"V případě, že je web HTTPS zapnuté, je zapotřebí popisu umístění soukromého "
"TLS klíče."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:564
msgid "TLS server name"
msgstr ""
msgstr "Název TLS serveru"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:560
msgid "TLS trusted CA path"
msgstr ""
msgstr "Popis umístění TLS důvěryhodné cert. autority"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:483
msgid "Timeout in seconds for connecting to frps."
msgstr ""
msgstr "Časový limit (v sekundách) pro připojování k frps."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:235
msgid "Token"
@@ -1088,43 +1120,43 @@ msgstr "Token"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:244
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:264
msgid "Token and token source are mutually exclusive."
msgstr ""
msgstr "Token a zdroj tokenu není možné použít dohromady."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:293
msgid "Token source command"
msgstr ""
msgstr "Příkaz zdroje tokenu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:316
msgid "Token source command arguments"
msgstr ""
msgstr "Argumenty pro příkaz zdroje tokenu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:310
msgid "Token source command is required when token source type is exec."
msgstr ""
msgstr "Pokud je typ zdroje tokenu vykonat, je zapotřebí příkaz zdroje tokenu."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:326
msgid "Token source environment"
msgstr ""
msgstr "Prostředí zdroje tokenu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:270
msgid "Token source file"
msgstr ""
msgstr "Soubor zdroje tokenu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:287
msgid "Token source file path is required when token source type is file."
msgstr ""
msgstr "Pokud je typ zdroje tokenu soubor, je zapotřebí popis jeho umístění."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:254
msgid "Token source type"
msgstr ""
msgstr "Typ zdroje tokenu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:236
msgid "Token used for authentication."
msgstr ""
msgstr "Token sloužící pro ověřování se."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1461
msgid "Transport"
msgstr ""
msgstr "Transport"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1427
msgid "Transport Settings"
@@ -1136,15 +1168,16 @@ msgstr "Transportní protokol"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:515
msgid "Transport protocol used to connect to frps."
msgstr ""
msgstr "Transportní protokol používaný pro připojení se k frps."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:221
msgid "UDP packet size"
msgstr ""
msgstr "Velikost UDP paketu"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:222
msgid "UDP packet size in bytes. Should match frps. Default is 1500."
msgstr ""
"Velikost UDP paketu (v bajtech). Mělo by se shodovat s frps. Výchozí je 1500."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:947
msgid "Unix domain socket path"
@@ -1157,10 +1190,11 @@ msgstr "Použijte hlavička=hodnota."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:697
msgid "Use proxy protocol to transfer connection info to local service."
msgstr ""
"Použít proxy protokol pro přenesení informací o spojení na lokální službu."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:604
msgid "Virtual network address. Requires VirtualNet feature gate."
msgstr ""
msgstr "Virtuální síťová adresa. Vyžaduje bránu funkce VirtualNet."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:603
msgid "VirtualNet address"
@@ -1168,11 +1202,11 @@ msgstr "VirtualNet adresa"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1046
msgid "VirtualNet destination IP"
msgstr ""
msgstr "Cílová IP adresa VirtualNet"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1245
msgid "VirtualNet destination IP is required for virtual_net visitors."
msgstr ""
msgstr "Pro virtual_net návštěvníky je zapotřebí VirtualNet cílová IP adresa."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1429
msgid "Web Server"
@@ -1218,11 +1252,11 @@ msgstr "Uživatelské jméno webového serveru."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:685
msgid "Where to limit bandwidth."
msgstr ""
msgstr "Kde omezovat šířku pásma."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:518
msgid "Wire protocol"
msgstr ""
msgstr "Wire protokol"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:879
msgid "XTCP protocol"
@@ -1230,7 +1264,7 @@ msgstr "Protokol XTCP"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:880
msgid "XTCP visitor tunnel protocol."
msgstr ""
msgstr "Protokol tunelu XTCP návštěvníka."
#: applications/luci-app-frpc/root/usr/share/luci/menu.d/luci-app-frpc.json:4
msgid "frp"
+7 -3
View File
@@ -1,6 +1,6 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2026-03-24 19:09+0000\n"
"PO-Revision-Date: 2026-09-07 17:15+0000\n"
"Last-Translator: HerbJul <19JulianHerbst95@web.de>\n"
"Language-Team: German <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrpc/de/>\n"
@@ -8,7 +8,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.17-dev\n"
"X-Generator: Weblate 2026.9.1.dev0\n"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1454
msgid "Add new proxy or visitor..."
@@ -567,6 +567,10 @@ msgid ""
"and tls2raw, this is the local service address reached after frp terminates "
"external TLS; for http2https/http2http, it is the local upstream address."
msgstr ""
"Lokale Backend-Adresse, die von Bridge-Plugins verwendet wird. Bei "
"https2http, https2https und tls2raw handelt es sich um die lokale Service-"
"Adresse, die nach Beendigung des externen TLS durch FRP erreichbar ist; bei "
"http2https/http2http ist es die lokale Upstream-Adresse."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:862
msgid "Local bind address for visitor."
@@ -1215,7 +1219,7 @@ msgstr ""
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1393
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1400
msgid "frp Client"
msgstr ""
msgstr "frp Client"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:519
msgid ""
+3 -3
View File
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2026-08-31 06:44+0000\n"
"PO-Revision-Date: 2026-09-06 03:21+0000\n"
"Last-Translator: Franco Castillo <castillofrancodamian@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrpc/es/>\n"
@@ -11,7 +11,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.9.dev0\n"
"X-Generator: Weblate 2026.9.1.dev0\n"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1454
msgid "Add new proxy or visitor..."
@@ -599,7 +599,7 @@ msgstr "Localizaciones"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1431
msgid "Log Settings"
msgstr "Ajustes de registro"
msgstr "Configuración del registro"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:387
msgid "Log level"
File diff suppressed because it is too large. Load diff
+5 -5
View File
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2026-08-31 16:28+0000\n"
"Last-Translator: Piotr Kołtun <pkoltungm@gmail.com>\n"
"PO-Revision-Date: 2026-09-06 03:21+0000\n"
"Last-Translator: Matthaiks <kitynska@gmail.com>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrpc/pl/>\n"
"Language: pl\n"
@@ -9,7 +9,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 2026.9.dev0\n"
"X-Generator: Weblate 2026.9.1.dev0\n"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1454
msgid "Add new proxy or visitor..."
@@ -41,7 +41,7 @@ msgstr "Dodatkowe metadane serwera proxy. Użyj klucz=wartość."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:251
msgid "Additional scopes to include authentication information."
msgstr "Dodatkowe zakresy obejmujące informacje uwierzytelniające."
msgstr "Dodatkowe zakresy do uwzględnienia informacji uwierzytelniających."
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:187
msgid "Address of the frps server."
@@ -688,7 +688,7 @@ msgstr "Dodatkowe parametry punktu końcowego OIDC"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:347
msgid "OIDC audience"
msgstr "OIDC audience"
msgstr "Odbiorcy OIDC"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:339
msgid "OIDC client ID"
File diff suppressed because it is too large. Load diff
+5 -5
View File
@@ -1,14 +1,14 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2024-03-31 19:53+0000\n"
"Last-Translator: Oğuz Han <h4n.3545@gmail.com>\n"
"PO-Revision-Date: 2026-08-31 20:56+0000\n"
"Last-Translator: Martin Olmer <m_iv@seznam.cz>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrpc/tr/>\n"
"Language: tr\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.5-dev\n"
"X-Generator: Weblate 2026.9.dev0\n"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:1454
msgid "Add new proxy or visitor..."
@@ -104,7 +104,7 @@ msgstr ""
#: applications/luci-app-frpc/root/usr/share/luci/menu.d/luci-app-frpc.json:11
msgid "Client"
msgstr ""
msgstr "İstemci"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:183
msgid "Client ID"
@@ -342,7 +342,7 @@ msgstr ""
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:647
msgid "Enabled"
msgstr "Etkin"
msgstr "Etkinleştirildi"
#: applications/luci-app-frpc/htdocs/luci-static/resources/view/frpc.js:689
msgid "Encrypt proxy traffic."
+31 -25
View File
@@ -1,6 +1,6 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2026-08-31 15:23+0000\n"
"PO-Revision-Date: 2026-08-31 20:02+0000\n"
"Last-Translator: Martin Olmer <m_iv@seznam.cz>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrps/cs/>\n"
@@ -522,19 +522,19 @@ msgstr "Popis umístění automaticky vytvářeného soukromého klíče SSH tun
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:570
msgid "SSH tunnel bind port"
msgstr ""
msgstr "Port na který navázat SSH tunel"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:571
msgid "SSH tunnel gateway bind port. Empty disables this feature."
msgstr ""
msgstr "Port na který navázat bránu SSH tunelu. Nevyplnění tuto funkci vypne."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:574
msgid "SSH tunnel private key file"
msgstr ""
msgstr "Soubor se soukromým klíčem SSH tunelu"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:508
msgid "Send specific error details to frpc."
msgstr ""
msgstr "Odeslat frpc podrobnosti konkrétní chyby."
#: applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json:11
msgid "Server"
@@ -543,10 +543,11 @@ msgstr "Server"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:358
msgid "Skip checking whether OIDC token issuer matches configured issuer."
msgstr ""
"Přeskočit ověřování zda vydavatel OIDC tokenu odpovídá tomu nastavenému."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:354
msgid "Skip checking whether the OIDC token is expired."
msgstr ""
msgstr "Přeskočit kontrolování zda OIDC tokenu neskončila platnost."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:985
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:996
@@ -563,7 +564,7 @@ msgstr "TCP udržování spojení"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:496
msgid "TCP keepalive interval. Negative value disables keepalive."
msgstr ""
msgstr "Interval udržování TCP spojení. Záporná hodnota udržování vypíná."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:479
msgid "TCP mux"
@@ -571,41 +572,44 @@ msgstr "TCP mux"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:491
msgid "TCP mux keepalive interval"
msgstr ""
msgstr "Interval udržování spojení TCP multiplexeru"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:215
msgid "TCPMUX HTTP CONNECT port"
msgstr ""
msgstr "Port pro TCPMUX HTTP CONNECT"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:219
msgid "TCPMUX passthrough"
msgstr ""
msgstr "Průchod TCPMUX"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:980
msgid "TLS / QUIC"
msgstr ""
msgstr "TLS / QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:413
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:525
msgid "TLS certificate path"
msgstr ""
msgstr "Popis umístění TLS certifikátu"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:425
msgid "TLS certificate path is required when web HTTPS is enabled."
msgstr ""
"Pokud je zapnuté web HTTPS, je zapotřebí popis umístění TLS certifikátu."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:431
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:529
msgid "TLS private key path"
msgstr ""
msgstr "Popis umístění soukromého TLS klíče"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:443
msgid "TLS private key path is required when web HTTPS is enabled."
msgstr ""
"V případě, že je web HTTPS zapnuté, je zapotřebí popisu umístění soukromého "
"TLS klíče."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:533
msgid "TLS trusted CA path"
msgstr ""
msgstr "Popis umístění TLS důvěryhodné cert. autority"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:241
msgid "Token"
@@ -614,39 +618,39 @@ msgstr "Token"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:250
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:270
msgid "Token and token source are mutually exclusive."
msgstr ""
msgstr "Token a zdroj tokenu není možné použít dohromady."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:299
msgid "Token source command"
msgstr ""
msgstr "Příkaz zdroje tokenu"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:322
msgid "Token source command arguments"
msgstr ""
msgstr "Argumenty pro příkaz zdroje tokenu"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:316
msgid "Token source command is required when token source type is exec."
msgstr ""
msgstr "Pokud je typ zdroje tokenu vykonat, je zapotřebí příkaz zdroje tokenu."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:332
msgid "Token source environment"
msgstr ""
msgstr "Prostředí zdroje tokenu"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:276
msgid "Token source file"
msgstr ""
msgstr "Soubor zdroje tokenu"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:293
msgid "Token source file path is required when token source type is file."
msgstr ""
msgstr "Pokud je typ zdroje tokenu soubor, je zapotřebí popis jeho umístění."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:260
msgid "Token source type"
msgstr ""
msgstr "Typ zdroje tokenu"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:242
msgid "Token used for authentication."
msgstr ""
msgstr "Token sloužící pro ověřování se."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:979
msgid "Transport Settings"
@@ -654,11 +658,11 @@ msgstr "Nastavení transportu"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:231
msgid "UDP packet size"
msgstr ""
msgstr "Velikost UDP paketu"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:232
msgid "UDP packet size in bytes. Should match frpc."
msgstr ""
msgstr "Velikost UDP paketu (v bajtech). Mělo by se shodovat s frpc."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:162
msgid ""
@@ -673,6 +677,8 @@ msgid ""
"UDP port used for QUIC. Empty disables QUIC. Do not reuse the same UDP port "
"as KCP."
msgstr ""
"UDP port použitý pro QUIC. Nevyplnění QUIC vypíná. Nepoužívejte stejný UDP "
"port jako KCP."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:589
msgid "Unique HTTP plugin name."
+3 -3
View File
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2026-08-31 06:44+0000\n"
"PO-Revision-Date: 2026-09-06 03:21+0000\n"
"Last-Translator: Franco Castillo <castillofrancodamian@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrps/es/>\n"
@@ -11,7 +11,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 2026.9.dev0\n"
"X-Generator: Weblate 2026.9.1.dev0\n"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:982
msgid "Access Control"
@@ -260,7 +260,7 @@ msgstr ""
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:984
msgid "Log Settings"
msgstr "Ajustes de registro"
msgstr "Configuración del registro"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:367
msgid "Log level"
+168 -113
View File
@@ -1,15 +1,15 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2026-02-10 18:11+0000\n"
"PO-Revision-Date: 2026-09-02 17:27+0000\n"
"Last-Translator: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>\n"
"Language-Team: Irish <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrps/ga/>\n"
"Language: ga\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : (n>2 && n<7) ? 2 :"
"(n>6 && n<11) ? 3 : 4;\n"
"X-Generator: Weblate 5.16-dev\n"
"Plural-Forms: nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : (n>2 && n<7) ? 2 :(n>"
"6 && n<11) ? 3 : 4;\n"
"X-Generator: Weblate 2026.9.dev0\n"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:982
msgid "Access Control"
@@ -17,11 +17,11 @@ msgstr "Rialú Rochtana"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:1008
msgid "Add new HTTP plugin..."
msgstr ""
msgstr "Cuir breiseán HTTP nua leis..."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:256
msgid "Additional auth scopes"
msgstr ""
msgstr "Scóip údaraithe breise"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:144
msgid "Additional configs"
@@ -29,15 +29,15 @@ msgstr "Cumraíochtaí breise"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:257
msgid "Additional scopes to include authentication information."
msgstr ""
msgstr "Raointe breise chun faisnéis fíordheimhnithe a áireamh."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:154
msgid "Address that frps binds to."
msgstr ""
msgstr "Seoladh a cheanglaíonn frps leis."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:200
msgid "Address that proxy listeners bind to."
msgstr ""
msgstr "Seoladh a cheanglaíonn éisteoirí seachfhreastalaí leis."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:551
msgid "Allow ports"
@@ -49,7 +49,7 @@ msgstr "Sócmhainní dir"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:350
msgid "Audience OIDC tokens should contain."
msgstr ""
msgstr "Ba chóir go mbeadh comharthaí OIDC an lucht féachana ann."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:978
msgid "Authentication"
@@ -57,15 +57,15 @@ msgstr "Fíordheimhniú"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:237
msgid "Authentication method"
msgstr ""
msgstr "Modh fíordheimhnithe"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:238
msgid "Authentication method used to authenticate frpc."
msgstr ""
msgstr "Modh fíordheimhnithe a úsáidtear chun frpc a fhíordheimhniú."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:583
msgid "Authorized keys file for SSH tunnel gateway."
msgstr ""
msgstr "Comhad eochracha údaraithe do gheata tolláin SSH."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:153
msgid "Bind address"
@@ -77,17 +77,19 @@ msgstr "Port ceangail"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:969
msgid "Collecting data ..."
msgstr "Sonraí á mbailiú ..."
msgstr "Ag bailiú sonraí ..."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:323
msgid "Command arguments passed to token source exec."
msgstr ""
msgstr "Argóintí ordaithe curtha chuig feidhmchláir foinse an chomhartha."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:300
msgid ""
"Command used to obtain the token. The init script adds --allow-"
"unsafe=TokenSourceExec when this source type is used."
msgstr ""
"An t-ordú a úsáideadh chun an comhartha a fháil. Cuireann an script init --"
"allow-unsafe=TokenSourceExec leis nuair a úsáidtear an cineál foinse seo."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:977
msgid "Common Settings"
@@ -95,19 +97,19 @@ msgstr "Socruithe Coitianta"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:368
msgid "Configuration key: log.level."
msgstr ""
msgstr "Eochair chumraíochta: log.level."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:538
msgid "Configuration key: transport.quic.keepalivePeriod."
msgstr ""
msgstr "Eochair chumraíochta: transport.quic.keepalivePeriod."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:542
msgid "Configuration key: transport.quic.maxIdleTimeout."
msgstr ""
msgstr "Eochair chumraíochta: transport.quic.maxIdleTimeout."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:546
msgid "Configuration key: transport.quic.maxIncomingStreams."
msgstr ""
msgstr "Eochair chumraíochta: transport.quic.maxIncomingStreams."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:227
msgid "Custom 404 page"
@@ -115,7 +117,7 @@ msgstr "Saincheaptha 404 leathanach"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:507
msgid "Detailed errors to client"
msgstr ""
msgstr "Earráidí mionsonraithe don chliant"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:375
msgid "Disable log color"
@@ -123,7 +125,7 @@ msgstr "Díchumasaigh dath an loga"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:376
msgid "Disable log colors when log output is console."
msgstr ""
msgstr "Díchumasaigh dathanna loga nuair a bhíonn aschur loga sa chonsól."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:264
msgid "Disabled"
@@ -131,39 +133,48 @@ msgstr "Míchumasaithe"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:220
msgid "Do not update traffic when TCPMUX passthrough is enabled."
msgstr ""
msgstr "Ná nuashonraigh trácht nuair a bhíonn pas-trí TCPMUX cumasaithe."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:224
msgid "Domain suffix for subdomain-based HTTP/HTTPS proxies."
msgstr ""
"Iarmhír fearainn le haghaidh seachfhreastalaithe HTTP/HTTPS bunaithe ar fho-"
"fhearainn."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:454
msgid ""
"Enable Go pprof debug/profiling endpoints on the web server. It only takes "
"effect when web server port is set."
msgstr ""
"Cumasaigh críochphointí dífhabhtaithe/próifílithe Go pprof ar an "
"bhfreastalaí gréasáin. Ní thagann sé i bhfeidhm ach amháin nuair a "
"shocraítear port an fhreastalaí gréasáin."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:403
msgid ""
"Enable HTTPS for the frps web server. This switch controls whether "
"webServer.tls.certFile and webServer.tls.keyFile are emitted."
msgstr ""
"Cumasaigh HTTPS don fhreastalaí gréasáin frps. Rialaíonn an lasc seo an "
"astaítear webServer.tls.certFile agus webServer.tls.keyFile."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:463
msgid "Enable Prometheus"
msgstr ""
msgstr "Cumasaigh Proiméitéas"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:480
msgid "Enable TCP stream multiplexing. This setting must match frpc."
msgstr ""
"Cumasaigh ilphléacsú srutha TCP. Ní mór don socrú seo a bheith mar an "
"gcéanna le frpc."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:453
msgid "Enable pprof"
msgstr ""
msgstr "Cumasaigh pprof"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:402
msgid "Enable web HTTPS"
msgstr ""
msgstr "Cumasaigh HTTPS gréasáin"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:135
msgid "Environment variable"
@@ -171,27 +182,34 @@ msgstr "Athróg timpeallachta"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:755
msgid "Environment variable must use KEY=value format."
msgstr ""
msgstr "Ní mór don athróg timpeallachta an fhormáid KEY=value a úsáid."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:333
msgid "Environment variables passed to token source exec. Use KEY=value."
msgstr ""
"Athróga timpeallachta a chuirtear chuig feidhmchláir foinse an chomhartha. "
"Úsáid KEY=luach."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:464
msgid ""
"Export Prometheus metrics on webServer /metrics API. It only takes effect "
"when web server port is set."
msgstr ""
"Easpórtáil méadrachtaí Prometheus ar webServer /metrics API. Ní thagann sé i "
"bhfeidhm ach amháin nuair a shocraítear port an fhreastalaí gréasáin."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:145
msgid ""
"Extra root-level configuration fragments included before generated HTTP "
"plugin sections. Use raw settings for table-specific extra options."
msgstr ""
"Blúirí cumraíochta breise ar leibhéal an fhréamh curtha san áireamh roimh "
"rannóga breiseáin HTTP a ghintear. Bain úsáid as socruithe amha le haghaidh "
"roghanna breise atá sainiúil don tábla."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:521
msgid "Force TLS"
msgstr ""
msgstr "Fórsáil TLS"
#: applications/luci-app-frps/root/usr/share/rpcd/acl.d/luci-app-frps.json:3
msgid "Grant access to LuCI app frps"
@@ -199,33 +217,35 @@ msgstr "Deonaigh rochtain ar frps app LuCI"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:1003
msgid "HTTP Plugin Settings"
msgstr ""
msgstr "Socruithe Breiseán HTTP"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:781
msgid "HTTP plugin URL must include a host."
msgstr ""
msgstr "Ní mór óstach a bheith san áireamh i URL breiseáin HTTP."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:777
msgid "HTTP plugin address must be a single address."
msgstr ""
msgstr "Ní mór seoladh breiseáin HTTP a bheith ina sheoladh aonair."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:593
msgid "HTTP plugin backend address."
msgstr ""
msgstr "Seoladh cúil breiseán HTTP."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:797
msgid ""
"HTTP plugin operation must be a frps operation name, for example Login or "
"NewProxy."
msgstr ""
"Ní mór d’oibríocht breiseán HTTP a bheith ina ainm oibríochta frps, mar "
"shampla Logáil Isteach nó NewProxy."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:765
msgid "HTTP plugin path must start with /."
msgstr ""
msgstr "Ní mór do chonair breiseán HTTP tosú le /."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:604
msgid "HTTP plugin request path."
msgstr ""
msgstr "Cosán iarrata breiseán HTTP."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:499
msgid "Heartbeat timeout"
@@ -233,7 +253,7 @@ msgstr "Teorainn ama buille croí"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:500
msgid "Heartbeat timeout in seconds."
msgstr ""
msgstr "Am scoir buille croí i soicindí."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:161
msgid "KCP bind port"
@@ -242,11 +262,11 @@ msgstr "Port ceangail KCP"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:174
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:193
msgid "KCP bind port and QUIC bind port must be different."
msgstr ""
msgstr "Caithfidh port ceangail KCP agus port ceangail QUIC a bheith difriúil."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:492
msgid "Keepalive interval for TCP mux."
msgstr ""
msgstr "Eatramh coinnigh beo le haghaidh TCP mux."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:261
msgid ""
@@ -254,6 +274,9 @@ msgid ""
"exec runs a command and requires frp unsafe permission. Mutually exclusive "
"with auth.token."
msgstr ""
"Luchtaigh comhartha ó fhoinse sheachtrach. Léann an comhad an comhartha ó "
"chomhad áitiúil; ritheann exec ordú agus éilíonn sé cead neamhshábháilte "
"frp. Eisiatach go frithpháirteach le auth.token."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:984
msgid "Log Settings"
@@ -269,11 +292,11 @@ msgstr "Íoslódáil max laethanta"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:363
msgid "Log output"
msgstr ""
msgstr "Aschur loga"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:364
msgid "Log output path or console."
msgstr ""
msgstr "Cosán aschuir nó consól logála."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:112
msgid "Log stderr"
@@ -285,7 +308,7 @@ msgstr "Logáil isteach stdout"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:475
msgid "Max pool count"
msgstr ""
msgstr "Uaslíon linn"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:560
msgid "Max ports per client"
@@ -293,145 +316,157 @@ msgstr "Uaschalafoirt in aghaidh an chliaint"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:372
msgid "Maximum number of days to keep logs."
msgstr ""
msgstr "Uasmhéid laethanta chun logaí a choinneáil."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:476
msgid "Maximum pool count for each proxy."
msgstr ""
msgstr "Uaslíon linn do gach seachfhreastalaí."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:561
msgid "Maximum ports each client can use. 0 means no limit."
msgstr ""
"Uasmhéid na gcalafort is féidir le gach cliant a úsáid. Ciallaíonn 0 gan aon "
"teorainn."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:504
msgid "Maximum time to wait for a work connection."
msgstr ""
msgstr "Uasmhéid ama le fanacht le haghaidh nasc oibre."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:564
msgid "NAT hole analysis reserve hours"
msgstr ""
msgstr "Uaireanta cúltaca anailíse poill NAT"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:942
msgid "NOT RUNNING"
msgstr "NÍ RÚCHÁN"
msgstr "NÍL AG RITH"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:349
msgid "OIDC audience"
msgstr ""
msgstr "Lucht féachana OIDC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:345
msgid "OIDC issuer"
msgstr ""
msgstr "Eisitheoir OIDC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:346
msgid "OIDC issuer used to verify tokens."
msgstr ""
msgstr "Eisitheoir OIDC a úsáidtear chun comharthaí a fhíorú."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:353
msgid "OIDC skip expiry check"
msgstr ""
msgstr "Seiceáil éaga scipeála OIDC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:357
msgid "OIDC skip issuer check"
msgstr ""
msgstr "Seiceáil eisitheora scipeáil OIDC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:136
msgid "OS environments passed to frp for config file template, see %s."
msgstr ""
"Timpeallachtaí OS curtha chuig frp le haghaidh teimpléad comhaid "
"chumraíochta, féach %s."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:522
msgid "Only accept TLS-encrypted frpc connections."
msgstr ""
msgstr "Glactar le naisc frpc criptithe le TLS amháin."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:579
msgid "Path for auto-generated private key."
msgstr ""
msgstr "Cosán don eochair phríobháideach uathghinte."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:277
msgid "Path of token file."
msgstr ""
msgstr "Cosán an chomhaid chomhartha."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:228
msgid "Path to custom 404 page for HTTP requests."
msgstr ""
msgstr "Cosán chuig leathanach saincheaptha 404 le haghaidh iarratais HTTP."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:526
msgid "Path to the TLS certificate file."
msgstr ""
msgstr "Cosán chuig an gcomhad deimhnithe TLS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:530
msgid "Path to the TLS private key file."
msgstr ""
msgstr "Cosán chuig an gcomhad eochrach príobháideach TLS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:414
msgid "Path to the certificate file used by the HTTPS web server."
msgstr ""
"Cosán chuig an gcomhad deimhnithe a úsáideann an freastalaí gréasáin HTTPS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:432
msgid "Path to the private key file used by the HTTPS web server."
msgstr ""
"Cosán chuig an gcomhad eochrach príobháideach a úsáideann an freastalaí "
"gréasáin HTTPS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:534
msgid "Path to the trusted CA certificate file."
msgstr ""
msgstr "Cosán chuig an gcomhad deimhnithe Údaráis Deimhnithe iontaofa."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:592
msgid "Plugin address"
msgstr ""
msgstr "Seoladh breiseáin"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:588
msgid "Plugin name"
msgstr ""
msgstr "Ainm an bhreiseáin"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:614
msgid "Plugin operations"
msgstr ""
msgstr "Oibríochtaí breiseán"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:603
msgid "Plugin path"
msgstr ""
msgstr "Cosán breiseáin"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:204
msgid "Port for HTTP virtual host requests. Empty or 0 disables it."
msgstr ""
"Port le haghaidh iarratais óstach fíorúil HTTP. Díchumasaíonn folamh nó 0 é."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:208
msgid "Port for HTTPS virtual host requests. Empty or 0 disables it."
msgstr ""
"Port le haghaidh iarratais óstach fíorúil HTTPS. Díchumasaíonn folamh nó 0 é."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:216
msgid "Port for TCPMUX HTTP CONNECT requests. Empty or 0 disables it."
msgstr ""
"Port le haghaidh iarratais TCPMUX HTTP CONNECT. Díchumasaíonn folamh nó 0 é."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:719
msgid "Port must be a number between 0 and 65535."
msgstr ""
msgstr "Ní mór don phort a bheith ina uimhir idir 0 agus 65535."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:723
msgid "Port must be between 0 and 65535."
msgstr ""
msgstr "Caithfidh an port a bheith idir 0 agus 65535."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:742
msgid "Port must be between 1 and 65535."
msgstr ""
msgstr "Caithfidh an port a bheith idir 1 agus 65535."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:745
msgid "Port range start must not be greater than end."
msgstr ""
msgstr "Ní mór tús an raoin calafoirt a bheith níos mó ná deireadh."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:158
msgid "Port that frps listens on."
msgstr ""
msgstr "Port a n-éisteann frps leis."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:552
msgid ""
"Ports clients are allowed to bind. Use single port like 3001 or range like "
"2000-3000."
msgstr ""
"Ceadaítear do chliaint calafoirt ceangal. Bain úsáid as calafort aonair "
"cosúil le 3001 nó raon cosúil le 2000-3000."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:575
msgid "Private key file for SSH tunnel gateway."
msgstr ""
msgstr "Comhad eochrach príobháideach do gheata tolláin SSH."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:199
msgid "Proxy bind address"
@@ -443,19 +478,19 @@ msgstr "Port ceangail QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:537
msgid "QUIC keepalive period"
msgstr ""
msgstr "Tréimhse choinneála QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:541
msgid "QUIC max idle timeout"
msgstr ""
msgstr "Uasmhéid ama díomhaoin QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:545
msgid "QUIC max incoming streams"
msgstr ""
msgstr "Uasmhéid sruthanna isteach QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:942
msgid "RUNNING"
msgstr "REATHA"
msgstr "AG RITH"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:125
msgid "Respawn when crashed"
@@ -464,10 +499,11 @@ msgstr "Respawn nuair a tuairteála"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:212
msgid "Response header timeout for vhost HTTP server, in seconds."
msgstr ""
"Am críochnaithe ceanntásc freagartha do fhreastalaí HTTP vhost, i soicindí."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:565
msgid "Retention time for NAT hole punching strategy data."
msgstr ""
msgstr "Am coinneála le haghaidh sonraí straitéise pollta NAT."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:123
msgid "Run daemon as group"
@@ -479,43 +515,45 @@ msgstr "Rith deamhan mar úsáideoir"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:983
msgid "SSH Tunnel"
msgstr ""
msgstr "Tollán SSH"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:582
msgid "SSH tunnel authorized keys file"
msgstr ""
msgstr "Comhad eochracha údaraithe tollán SSH"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:578
msgid "SSH tunnel auto-generated private key path"
msgstr ""
msgstr "Cosán eochrach príobháideach uathghinte tollán SSH"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:570
msgid "SSH tunnel bind port"
msgstr ""
msgstr "Port ceangail tolláin SSH"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:571
msgid "SSH tunnel gateway bind port. Empty disables this feature."
msgstr ""
msgstr "Port ceangail geata tolláin SSH. Díchumasaíonn folamh an ghné seo."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:574
msgid "SSH tunnel private key file"
msgstr ""
msgstr "Comhad eochrach príobháideach tollán SSH"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:508
msgid "Send specific error details to frpc."
msgstr ""
msgstr "Seol sonraí sonracha faoin earráid chuig frpc."
#: applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json:11
msgid "Server"
msgstr ""
msgstr "Freastalaí"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:358
msgid "Skip checking whether OIDC token issuer matches configured issuer."
msgstr ""
"Seachain seiceáil an bhfuil eisitheoir an chomhartha OIDC ag teacht leis an "
"eisitheoir cumraithe."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:354
msgid "Skip checking whether the OIDC token is expired."
msgstr ""
msgstr "Seachain seiceáil an bhfuil an comhartha OIDC imithe in éag."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:985
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:996
@@ -528,11 +566,11 @@ msgstr "Óstach subdomain"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:495
msgid "TCP keepalive"
msgstr ""
msgstr "Coinnigh TCP beo"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:496
msgid "TCP keepalive interval. Negative value disables keepalive."
msgstr ""
msgstr "Eatramh coinneála TCP. Díchumasaíonn luach diúltach an coinneáil beo."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:479
msgid "TCP mux"
@@ -540,41 +578,44 @@ msgstr "TCP mux"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:491
msgid "TCP mux keepalive interval"
msgstr ""
msgstr "Eatramh coinneála beo TCP mux"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:215
msgid "TCPMUX HTTP CONNECT port"
msgstr ""
msgstr "TCPMUX HTTP CONNECT port"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:219
msgid "TCPMUX passthrough"
msgstr ""
msgstr "TCPMUX Pas tríd"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:980
msgid "TLS / QUIC"
msgstr ""
msgstr "TLS / QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:413
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:525
msgid "TLS certificate path"
msgstr ""
msgstr "Cosán deimhnithe TLS"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:425
msgid "TLS certificate path is required when web HTTPS is enabled."
msgstr ""
"Tá cosán deimhnithe TLS ag teastáil nuair a bhíonn HTTPS gréasáin cumasaithe."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:431
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:529
msgid "TLS private key path"
msgstr ""
msgstr "Cosán eochrach príobháideach TLS"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:443
msgid "TLS private key path is required when web HTTPS is enabled."
msgstr ""
"Tá cosán eochrach príobháideach TLS ag teastáil nuair a bhíonn HTTPS "
"gréasáin cumasaithe."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:533
msgid "TLS trusted CA path"
msgstr ""
msgstr "Cosán iontaofa TLS CA"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:241
msgid "Token"
@@ -583,84 +624,96 @@ msgstr "Comhartha"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:250
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:270
msgid "Token and token source are mutually exclusive."
msgstr ""
msgstr "Tá comhartha agus foinse comhartha eisiach dá chéile."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:299
msgid "Token source command"
msgstr ""
msgstr "Ordú foinse comharthaí"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:322
msgid "Token source command arguments"
msgstr ""
msgstr "Argóintí ordaithe foinse chomhartha"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:316
msgid "Token source command is required when token source type is exec."
msgstr ""
"Tá an t-ordú foinse comhartha ag teastáil nuair is é an cineál foinse "
"comhartha exec."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:332
msgid "Token source environment"
msgstr ""
msgstr "Timpeallacht foinse comharthaí"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:276
msgid "Token source file"
msgstr ""
msgstr "Comhad foinse comharthaí"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:293
msgid "Token source file path is required when token source type is file."
msgstr ""
"Tá cosán comhaid foinse an chomhartha ag teastáil nuair is comhad an cineál "
"foinse comhartha."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:260
msgid "Token source type"
msgstr ""
msgstr "Cineál foinse comharthaí"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:242
msgid "Token used for authentication."
msgstr ""
msgstr "Comhartha a úsáidtear le haghaidh fíordheimhnithe."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:979
msgid "Transport Settings"
msgstr ""
msgstr "Socruithe Iompair"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:231
msgid "UDP packet size"
msgstr ""
msgstr "Méid an phaicéid UDP"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:232
msgid "UDP packet size in bytes. Should match frpc."
msgstr ""
"Méid an phaicéid UDP i mbéiteanna. Ba chóir go mbeadh sé mar an gcéanna le "
"frpc."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:162
msgid ""
"UDP port used for KCP. Empty disables KCP. Do not reuse the same UDP port as "
"QUIC."
msgstr ""
"Port UDP a úsáidtear le haghaidh KCP. Díchumasaíonn folamh KCP. Ná hathúsáid "
"an port UDP céanna le QUIC."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:181
msgid ""
"UDP port used for QUIC. Empty disables QUIC. Do not reuse the same UDP port "
"as KCP."
msgstr ""
"Port UDP a úsáidtear le haghaidh QUIC. Díchumasaíonn folamh QUIC. Ná "
"hathúsáid an port UDP céanna le KCP."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:589
msgid "Unique HTTP plugin name."
msgstr ""
msgstr "Ainm uathúil breiseáin HTTP."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:736
msgid "Use a single port like 3001 or a range like 2000-3000."
msgstr ""
msgstr "Bain úsáid as port aonair cosúil le 3001 nó raon cosúil le 2000-3000."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:503
msgid "User connection timeout"
msgstr ""
msgstr "Am críochnaithe nasc úsáideora"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:626
msgid "Verify plugin TLS"
msgstr ""
msgstr "Fíoraigh TLS breiseáin"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:627
msgid ""
"Verify the HTTP plugin TLS certificate when the plugin address uses HTTPS."
msgstr ""
"Fíoraigh teastas TLS an bhreiseáin HTTP nuair a úsáideann seoladh an "
"bhreiseáin HTTPS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:203
msgid "Vhost HTTP port"
@@ -676,47 +729,49 @@ msgstr "Vhost calafort HTTPS"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:981
msgid "Web Server"
msgstr ""
msgstr "Freastalaí Gréasáin"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:381
msgid "Web server address"
msgstr ""
msgstr "Seoladh freastalaí gréasáin"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:450
msgid "Web server assets directory."
msgstr ""
msgstr "Eolaire sócmhainní freastalaí gréasáin."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:382
msgid "Web server bind address."
msgstr ""
msgstr "Seoladh ceangail freastalaí gréasáin."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:395
msgid "Web server password"
msgstr ""
msgstr "Pasfhocal freastalaí gréasáin"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:396
msgid "Web server password."
msgstr ""
msgstr "Pasfhocal freastalaí gréasáin."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:385
msgid "Web server port"
msgstr ""
msgstr "Port freastalaí gréasáin"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:386
msgid "Web server port. Leave empty or set to 0 to disable the web server."
msgstr ""
"Port freastalaí gréasáin. Fág folamh nó socraigh go 0 chun an freastalaí "
"gréasáin a dhíchumasú."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:389
msgid "Web server user"
msgstr ""
msgstr "Úsáideoir freastalaí gréasáin"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:390
msgid "Web server username."
msgstr ""
msgstr "Ainm úsáideora an fhreastalaí gréasáin."
#: applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json:4
msgid "frp"
msgstr ""
msgstr "frp"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:945
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:952
@@ -725,7 +780,7 @@ msgstr "Freastalaí frp"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:615
msgid "frps operations handled by this HTTP plugin."
msgstr ""
msgstr "Oibríochtaí frps a láimhseálann an breiseán HTTP seo."
#~ msgid "Advanced"
#~ msgstr "Ardleibhéil"
+6 -6
View File
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2026-08-31 16:28+0000\n"
"Last-Translator: Piotr Kołtun <pkoltungm@gmail.com>\n"
"PO-Revision-Date: 2026-09-06 03:21+0000\n"
"Last-Translator: Matthaiks <kitynska@gmail.com>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrps/pl/>\n"
"Language: pl\n"
@@ -9,7 +9,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 2026.9.dev0\n"
"X-Generator: Weblate 2026.9.1.dev0\n"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:982
msgid "Access Control"
@@ -29,11 +29,11 @@ msgstr "Dodatkowe konfiguracje"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:257
msgid "Additional scopes to include authentication information."
msgstr "Dodatkowe zakresy obejmujące informacje uwierzytelniające."
msgstr "Dodatkowe zakresy do uwzględnienia informacji uwierzytelniających."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:154
msgid "Address that frps binds to."
msgstr "Adres, z którym wiąże się frps."
msgstr "Adres, do którego wiąże się frps."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:200
msgid "Address that proxy listeners bind to."
@@ -338,7 +338,7 @@ msgstr "NIEURUCHOMIONE"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:349
msgid "OIDC audience"
msgstr "OIDC audience"
msgstr "Odbiorcy OIDC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:345
msgid "OIDC issuer"
+158 -118
View File
@@ -1,8 +1,8 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2026-04-22 23:36+0000\n"
"Last-Translator: SnIPeRSnIPeR "
"<snipersniper@users.noreply.hosted.weblate.org>\n"
"PO-Revision-Date: 2026-09-07 04:02+0000\n"
"Last-Translator: SnIPeRSnIPeR <snipersniper@users.noreply.hosted.weblate.org>"
"\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrps/ru/>\n"
"Language: ru\n"
@@ -10,7 +10,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.17.1-dev\n"
"X-Generator: Weblate 2026.9.1.dev0\n"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:982
msgid "Access Control"
@@ -18,11 +18,11 @@ msgstr "Контроль доступа"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:1008
msgid "Add new HTTP plugin..."
msgstr ""
msgstr "Добавить новый HTTP-плагин..."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:256
msgid "Additional auth scopes"
msgstr ""
msgstr "Дополнительные области действия авторизации"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:144
msgid "Additional configs"
@@ -30,15 +30,15 @@ msgstr "Дополнительные конфигурации"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:257
msgid "Additional scopes to include authentication information."
msgstr ""
msgstr "Дополнительные области действия для включения данных аутентификации."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:154
msgid "Address that frps binds to."
msgstr ""
msgstr "Адрес, к которому привязывается frps."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:200
msgid "Address that proxy listeners bind to."
msgstr ""
msgstr "Адрес, к которому привязываются слушатели прокси."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:551
msgid "Allow ports"
@@ -50,7 +50,7 @@ msgstr "Каталог ресурсов"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:350
msgid "Audience OIDC tokens should contain."
msgstr ""
msgstr "Аудитория, которую должны содержать OIDC-токены."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:978
msgid "Authentication"
@@ -58,15 +58,15 @@ msgstr "Аутентификация"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:237
msgid "Authentication method"
msgstr ""
msgstr "Метод аутентификации"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:238
msgid "Authentication method used to authenticate frpc."
msgstr ""
msgstr "Метод аутентификации, используемый для проверки frpc."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:583
msgid "Authorized keys file for SSH tunnel gateway."
msgstr ""
msgstr "Файл авторизованных ключей для шлюза SSH-туннеля."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:153
msgid "Bind address"
@@ -82,13 +82,15 @@ msgstr "Сбор данных ..."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:323
msgid "Command arguments passed to token source exec."
msgstr ""
msgstr "Аргументы команды для исполняемого файла источника токена."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:300
msgid ""
"Command used to obtain the token. The init script adds --allow-"
"unsafe=TokenSourceExec when this source type is used."
msgstr ""
"Команда получения токена. При использовании этого типа источника init-скрипт "
"добавляет --allow-unsafe=TokenSourceExec."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:977
msgid "Common Settings"
@@ -96,19 +98,19 @@ msgstr "Общие настройки"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:368
msgid "Configuration key: log.level."
msgstr ""
msgstr "Ключ конфигурации: log.level."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:538
msgid "Configuration key: transport.quic.keepalivePeriod."
msgstr ""
msgstr "Ключ конфигурации: transport.quic.keepalivePeriod."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:542
msgid "Configuration key: transport.quic.maxIdleTimeout."
msgstr ""
msgstr "Ключ конфигурации: transport.quic.maxIdleTimeout."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:546
msgid "Configuration key: transport.quic.maxIncomingStreams."
msgstr ""
msgstr "Ключ конфигурации: transport.quic.maxIncomingStreams."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:227
msgid "Custom 404 page"
@@ -116,7 +118,7 @@ msgstr "Своя страница 404"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:507
msgid "Detailed errors to client"
msgstr ""
msgstr "Подробные ошибки клиенту"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:375
msgid "Disable log color"
@@ -124,7 +126,7 @@ msgstr "Отключить цвета в журнале"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:376
msgid "Disable log colors when log output is console."
msgstr ""
msgstr "Отключить цвета в логах при выводе в консоль."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:264
msgid "Disabled"
@@ -132,39 +134,44 @@ msgstr "Отключено"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:220
msgid "Do not update traffic when TCPMUX passthrough is enabled."
msgstr ""
msgstr "Не обновлять трафик, когда включён сквозной режим TCPMUX."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:224
msgid "Domain suffix for subdomain-based HTTP/HTTPS proxies."
msgstr ""
msgstr "Доменный суффикс для HTTP/HTTPS-прокси на основе поддоменов."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:454
msgid ""
"Enable Go pprof debug/profiling endpoints on the web server. It only takes "
"effect when web server port is set."
msgstr ""
"Включить конечные точки отладки/профилирования Go pprof на веб-сервере. "
"Действует только при заданном порте веб-сервера."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:403
msgid ""
"Enable HTTPS for the frps web server. This switch controls whether "
"webServer.tls.certFile and webServer.tls.keyFile are emitted."
msgstr ""
"Включить HTTPS для веб-сервера frps. Этот переключатель управляет выдачей "
"параметров webServer.tls.certFile и webServer.tls.keyFile."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:463
msgid "Enable Prometheus"
msgstr ""
msgstr "Включить Prometheus"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:480
msgid "Enable TCP stream multiplexing. This setting must match frpc."
msgstr ""
"Включить мультиплексирование TCP-потоков. Должно совпадать с настройкой frpc."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:453
msgid "Enable pprof"
msgstr ""
msgstr "Включить pprof"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:402
msgid "Enable web HTTPS"
msgstr ""
msgstr "Включить HTTPS"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:135
msgid "Environment variable"
@@ -172,27 +179,34 @@ msgstr "Переменные окружения"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:755
msgid "Environment variable must use KEY=value format."
msgstr ""
msgstr "Переменная окружения должна быть в формате KEY=value."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:333
msgid "Environment variables passed to token source exec. Use KEY=value."
msgstr ""
"Переменные окружения, передаваемые исполняемому файлу источника токена. "
"Используйте формат KEY=value."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:464
msgid ""
"Export Prometheus metrics on webServer /metrics API. It only takes effect "
"when web server port is set."
msgstr ""
"Экспортировать метрики Prometheus через API /metrics веб-сервера. Действует "
"только при заданном порте веб-сервера."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:145
msgid ""
"Extra root-level configuration fragments included before generated HTTP "
"plugin sections. Use raw settings for table-specific extra options."
msgstr ""
"Дополнительные фрагменты корневой конфигурации, включаемые перед "
"сгенерированными секциями HTTP-плагинов. Используйте raw-настройки для "
"дополнительных опций конкретных таблиц."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:521
msgid "Force TLS"
msgstr ""
msgstr "Принудительный TLS"
#: applications/luci-app-frps/root/usr/share/rpcd/acl.d/luci-app-frps.json:3
msgid "Grant access to LuCI app frps"
@@ -200,33 +214,35 @@ msgstr "Предоставить доступ к LuCI-приложению frps"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:1003
msgid "HTTP Plugin Settings"
msgstr ""
msgstr "Настройки HTTP-плагина"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:781
msgid "HTTP plugin URL must include a host."
msgstr ""
msgstr "URL HTTP-плагина должен содержать хост."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:777
msgid "HTTP plugin address must be a single address."
msgstr ""
msgstr "Адрес HTTP-плагина должен быть одиночным адресом."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:593
msgid "HTTP plugin backend address."
msgstr ""
msgstr "Адрес бэкенда HTTP-плагина."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:797
msgid ""
"HTTP plugin operation must be a frps operation name, for example Login or "
"NewProxy."
msgstr ""
"Операция HTTP-плагина должна быть именем операции frps, например Login или "
"NewProxy."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:765
msgid "HTTP plugin path must start with /."
msgstr ""
msgstr "Путь HTTP-плагина должен начинаться с /."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:604
msgid "HTTP plugin request path."
msgstr ""
msgstr "Путь запроса HTTP-плагина."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:499
msgid "Heartbeat timeout"
@@ -234,7 +250,7 @@ msgstr "Heartbeat тайм-аут"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:500
msgid "Heartbeat timeout in seconds."
msgstr ""
msgstr "Тайм-аут сигнала heartbeat в секундах."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:161
msgid "KCP bind port"
@@ -243,11 +259,11 @@ msgstr "Порт привязки KCP"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:174
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:193
msgid "KCP bind port and QUIC bind port must be different."
msgstr ""
msgstr "Порт привязки KCP и порт привязки QUIC должны различаться."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:492
msgid "Keepalive interval for TCP mux."
msgstr ""
msgstr "Интервал keepalive для TCP-мультиплексора."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:261
msgid ""
@@ -255,6 +271,9 @@ msgid ""
"exec runs a command and requires frp unsafe permission. Mutually exclusive "
"with auth.token."
msgstr ""
"Загружать токен из внешнего источника. Значение file читает токен из "
"локального файла; значение exec выполняет команду и требует небезопасного "
"разрешения для frp. Не может использоваться одновременно с auth.token."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:984
msgid "Log Settings"
@@ -270,11 +289,11 @@ msgstr "Хранить журнал (дней)"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:363
msgid "Log output"
msgstr ""
msgstr "Вывод журнала"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:364
msgid "Log output path or console."
msgstr ""
msgstr "Путь вывода журнала или консоль."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:112
msgid "Log stderr"
@@ -286,7 +305,7 @@ msgstr "Сохранять вывод stdout"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:475
msgid "Max pool count"
msgstr ""
msgstr "Макс. количество пулов"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:560
msgid "Max ports per client"
@@ -294,23 +313,25 @@ msgstr "Максимальное количество портов для одн
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:372
msgid "Maximum number of days to keep logs."
msgstr ""
msgstr "Максимальное число дней хранения журналов."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:476
msgid "Maximum pool count for each proxy."
msgstr ""
msgstr "Максимальное количество пулов для каждого прокси."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:561
msgid "Maximum ports each client can use. 0 means no limit."
msgstr ""
"Максимальное количество портов, доступных каждому клиенту. 0 — без "
"ограничений."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:504
msgid "Maximum time to wait for a work connection."
msgstr ""
msgstr "Максимальное время ожидания рабочего соединения."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:564
msgid "NAT hole analysis reserve hours"
msgstr ""
msgstr "Срок хранения данных анализа NAT-дыр (часы)"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:942
msgid "NOT RUNNING"
@@ -318,121 +339,130 @@ msgstr "НЕ ЗАПУЩЕНО"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:349
msgid "OIDC audience"
msgstr ""
msgstr "Аудитория OIDC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:345
msgid "OIDC issuer"
msgstr ""
msgstr "Эмитент OIDC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:346
msgid "OIDC issuer used to verify tokens."
msgstr ""
msgstr "Эмитент OIDC, используемый для проверки токенов."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:353
msgid "OIDC skip expiry check"
msgstr ""
msgstr "Пропускать проверку истечения срока через OIDC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:357
msgid "OIDC skip issuer check"
msgstr ""
msgstr "Пропускать проверку эмитента OIDC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:136
msgid "OS environments passed to frp for config file template, see %s."
msgstr ""
"Переменные окружения ОС, передаваемые в frp для шаблона файла конфигурации, "
"см. %s."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:522
msgid "Only accept TLS-encrypted frpc connections."
msgstr ""
msgstr "Принимать только TLS-зашифрованные соединения от frpc."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:579
msgid "Path for auto-generated private key."
msgstr ""
msgstr "Путь для автоматически сгенерированного закрытого ключа."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:277
msgid "Path of token file."
msgstr ""
msgstr "Путь к файлу токена."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:228
msgid "Path to custom 404 page for HTTP requests."
msgstr ""
msgstr "Путь к пользовательской странице 404 для HTTP-запросов."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:526
msgid "Path to the TLS certificate file."
msgstr ""
msgstr "Путь к файлу сертификата TLS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:530
msgid "Path to the TLS private key file."
msgstr ""
msgstr "Путь к файлу закрытого ключа TLS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:414
msgid "Path to the certificate file used by the HTTPS web server."
msgstr ""
msgstr "Путь к файлу сертификата, используемому веб-сервером HTTPS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:432
msgid "Path to the private key file used by the HTTPS web server."
msgstr ""
msgstr "Путь к файлу закрытого ключа, используемому веб-сервером HTTPS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:534
msgid "Path to the trusted CA certificate file."
msgstr ""
msgstr "Путь к файлу доверенного сертификата CA."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:592
msgid "Plugin address"
msgstr ""
msgstr "Адрес плагина"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:588
msgid "Plugin name"
msgstr ""
msgstr "Имя плагина"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:614
msgid "Plugin operations"
msgstr ""
msgstr "Операции плагина"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:603
msgid "Plugin path"
msgstr ""
msgstr "Путь плагина"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:204
msgid "Port for HTTP virtual host requests. Empty or 0 disables it."
msgstr ""
"Порт для HTTP-запросов виртуального хоста. Пустое значение или 0 отключает "
"его."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:208
msgid "Port for HTTPS virtual host requests. Empty or 0 disables it."
msgstr ""
"Порт для HTTPS-запросов виртуального хоста. Пустое значение или 0 отключает "
"его."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:216
msgid "Port for TCPMUX HTTP CONNECT requests. Empty or 0 disables it."
msgstr ""
"Порт для HTTP CONNECT запросов TCPMUX. Пустое значение или 0 отключает его."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:719
msgid "Port must be a number between 0 and 65535."
msgstr ""
msgstr "Порт должен быть числом от 0 до 65535."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:723
msgid "Port must be between 0 and 65535."
msgstr ""
msgstr "Порт должен быть в диапазоне от 0 до 65535."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:742
msgid "Port must be between 1 and 65535."
msgstr ""
msgstr "Порт должен быть от 1 до 65535."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:745
msgid "Port range start must not be greater than end."
msgstr ""
msgstr "Начало диапазона портов не должно быть больше конца."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:158
msgid "Port that frps listens on."
msgstr ""
msgstr "Порт, который слушает frps."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:552
msgid ""
"Ports clients are allowed to bind. Use single port like 3001 or range like "
"2000-3000."
msgstr ""
"Порты, которые разрешено занимать клиентам. Можно указать одиночный порт "
"(например, 3001) или диапазон (например, 2000-3000)."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:575
msgid "Private key file for SSH tunnel gateway."
msgstr ""
msgstr "Файл закрытого ключа для шлюза SSH-туннеля."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:199
msgid "Proxy bind address"
@@ -444,19 +474,19 @@ msgstr "Порт QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:537
msgid "QUIC keepalive period"
msgstr ""
msgstr "Период keepalive QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:541
msgid "QUIC max idle timeout"
msgstr ""
msgstr "Максимальное время простоя QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:545
msgid "QUIC max incoming streams"
msgstr ""
msgstr "Максимум входящих потоков QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:942
msgid "RUNNING"
msgstr "ЗАПУЩЕН"
msgstr "ЗАПУЩЕНО"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:125
msgid "Respawn when crashed"
@@ -464,11 +494,11 @@ msgstr "Перезапускаться после вылета"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:212
msgid "Response header timeout for vhost HTTP server, in seconds."
msgstr ""
msgstr "Тайм-аут заголовка ответа для HTTP-сервера vhost, в секундах."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:565
msgid "Retention time for NAT hole punching strategy data."
msgstr ""
msgstr "Срок хранения данных стратегии пробивания NAT-дыр."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:123
msgid "Run daemon as group"
@@ -480,43 +510,44 @@ msgstr "Запуск демона от имени пользователя"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:983
msgid "SSH Tunnel"
msgstr ""
msgstr "SSH-туннель"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:582
msgid "SSH tunnel authorized keys file"
msgstr ""
msgstr "Файл авторизованных ключей SSH-туннеля"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:578
msgid "SSH tunnel auto-generated private key path"
msgstr ""
msgstr "Путь к автоматически сгенерированному закрытому ключу SSH-туннеля"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:570
msgid "SSH tunnel bind port"
msgstr ""
msgstr "Порт привязки SSH-туннеля"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:571
msgid "SSH tunnel gateway bind port. Empty disables this feature."
msgstr ""
msgstr "Порт привязки шлюза SSH-туннеля. Пустое значение отключает эту функцию."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:574
msgid "SSH tunnel private key file"
msgstr ""
msgstr "Файл закрытого ключа SSH-туннеля"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:508
msgid "Send specific error details to frpc."
msgstr ""
msgstr "Отправлять frpc конкретные детали ошибок."
#: applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json:11
msgid "Server"
msgstr ""
msgstr "Сервер"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:358
msgid "Skip checking whether OIDC token issuer matches configured issuer."
msgstr ""
"Пропускать проверку соответствия эмитента OIDC-токена настроенному эмитенту."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:354
msgid "Skip checking whether the OIDC token is expired."
msgstr ""
msgstr "Пропускать проверку истечения срока действия OIDC-токена."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:985
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:996
@@ -529,11 +560,11 @@ msgstr "Зона для поддоменов"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:495
msgid "TCP keepalive"
msgstr ""
msgstr "TCP keepalive"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:496
msgid "TCP keepalive interval. Negative value disables keepalive."
msgstr ""
msgstr "Интервал TCP keepalive. Отрицательное значение отключает keepalive."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:479
msgid "TCP mux"
@@ -541,41 +572,41 @@ msgstr "TCP мультиплексор"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:491
msgid "TCP mux keepalive interval"
msgstr ""
msgstr "Интервал keepalive мультиплексора TCP"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:215
msgid "TCPMUX HTTP CONNECT port"
msgstr ""
msgstr "Порт TCPMUX HTTP CONNECT"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:219
msgid "TCPMUX passthrough"
msgstr ""
msgstr "Сквозной режим TCPMUX"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:980
msgid "TLS / QUIC"
msgstr ""
msgstr "TLS / QUIC"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:413
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:525
msgid "TLS certificate path"
msgstr ""
msgstr "Путь к сертификату TLS"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:425
msgid "TLS certificate path is required when web HTTPS is enabled."
msgstr ""
msgstr "Путь к сертификату TLS обязателен, если включён веб-сервер HTTPS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:431
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:529
msgid "TLS private key path"
msgstr ""
msgstr "Путь к закрытому ключу TLS"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:443
msgid "TLS private key path is required when web HTTPS is enabled."
msgstr ""
msgstr "Путь к закрытому ключу TLS обязателен, если включён веб-сервер HTTPS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:533
msgid "TLS trusted CA path"
msgstr ""
msgstr "Путь к доверенному сертификату CA для TLS"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:241
msgid "Token"
@@ -584,84 +615,91 @@ msgstr "Токен"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:250
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:270
msgid "Token and token source are mutually exclusive."
msgstr ""
msgstr "Токен и источник токена являются взаимоисключающими."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:299
msgid "Token source command"
msgstr ""
msgstr "Команда источника токена"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:322
msgid "Token source command arguments"
msgstr ""
msgstr "Аргументы команды источника токена"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:316
msgid "Token source command is required when token source type is exec."
msgstr ""
msgstr "Команда источника токена обязательна, если тип источника токена — exec."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:332
msgid "Token source environment"
msgstr ""
msgstr "Переменные окружения источника токена"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:276
msgid "Token source file"
msgstr ""
msgstr "Файл источника токена"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:293
msgid "Token source file path is required when token source type is file."
msgstr ""
"Путь к файлу источника токена обязателен, если тип источника токена — file."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:260
msgid "Token source type"
msgstr ""
msgstr "Тип источника токена"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:242
msgid "Token used for authentication."
msgstr ""
msgstr "Токен, используемый для аутентификации."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:979
msgid "Transport Settings"
msgstr ""
msgstr "Настройки транспорта"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:231
msgid "UDP packet size"
msgstr ""
msgstr "Размер UDP-пакета"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:232
msgid "UDP packet size in bytes. Should match frpc."
msgstr ""
msgstr "Размер UDP-пакета в байтах. Должен совпадать с frpc."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:162
msgid ""
"UDP port used for KCP. Empty disables KCP. Do not reuse the same UDP port as "
"QUIC."
msgstr ""
"UDP-порт для KCP. Пустое значение отключает KCP. Не используйте тот же UDP-"
"порт, что и для QUIC."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:181
msgid ""
"UDP port used for QUIC. Empty disables QUIC. Do not reuse the same UDP port "
"as KCP."
msgstr ""
"UDP-порт для QUIC. Пустое значение отключает QUIC. Не используйте тот же UDP-"
"порт, что и для KCP."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:589
msgid "Unique HTTP plugin name."
msgstr ""
msgstr "Уникальное имя HTTP-плагина."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:736
msgid "Use a single port like 3001 or a range like 2000-3000."
msgstr ""
"Используйте одиночный порт, например 3001, или диапазон, например 2000-3000."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:503
msgid "User connection timeout"
msgstr ""
msgstr "Тайм-аут пользовательского соединения"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:626
msgid "Verify plugin TLS"
msgstr ""
msgstr "Проверять TLS плагина"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:627
msgid ""
"Verify the HTTP plugin TLS certificate when the plugin address uses HTTPS."
msgstr ""
"Проверять TLS-сертификат HTTP-плагина, когда адрес плагина использует HTTPS."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:203
msgid "Vhost HTTP port"
@@ -677,47 +715,49 @@ msgstr "HTTPS-порт виртуального хоста"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:981
msgid "Web Server"
msgstr ""
msgstr "Веб-сервер"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:381
msgid "Web server address"
msgstr ""
msgstr "Адрес веб-сервера"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:450
msgid "Web server assets directory."
msgstr ""
msgstr "Каталог ресурсов веб-сервера."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:382
msgid "Web server bind address."
msgstr ""
msgstr "Адрес привязки веб-сервера."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:395
msgid "Web server password"
msgstr ""
msgstr "Пароль веб-сервера"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:396
msgid "Web server password."
msgstr ""
msgstr "Пароль веб-сервера."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:385
msgid "Web server port"
msgstr ""
msgstr "Порт веб-сервера"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:386
msgid "Web server port. Leave empty or set to 0 to disable the web server."
msgstr ""
"Порт веб-сервера. Оставьте пустым или установите 0, чтобы отключить веб-"
"сервер."
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:389
msgid "Web server user"
msgstr ""
msgstr "Пользователь веб-сервера"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:390
msgid "Web server username."
msgstr ""
msgstr "Имя пользователя веб-сервера."
#: applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json:4
msgid "frp"
msgstr ""
msgstr "frp"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:945
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:952
@@ -726,7 +766,7 @@ msgstr "frp сервер"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:615
msgid "frps operations handled by this HTTP plugin."
msgstr ""
msgstr "Операции frps, обрабатываемые этим HTTP-плагином."
#~ msgid "Advanced"
#~ msgstr "Дополнительно"
+4 -4
View File
@@ -1,14 +1,14 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2026-08-13 09:16+0000\n"
"Last-Translator: Jonatan Nyberg <nickwick@users.noreply.hosted.weblate.org>\n"
"PO-Revision-Date: 2026-09-01 13:11+0000\n"
"Last-Translator: Martin Olmer <m_iv@seznam.cz>\n"
"Language-Team: Swedish <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrps/sv/>\n"
"Language: sv\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.17-dev\n"
"X-Generator: Weblate 2026.9.dev0\n"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:982
msgid "Access Control"
@@ -533,7 +533,7 @@ msgstr ""
#: applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json:11
msgid "Server"
msgstr ""
msgstr "Server"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:358
msgid "Skip checking whether OIDC token issuer matches configured issuer."
+4 -4
View File
@@ -1,14 +1,14 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2024-03-31 19:53+0000\n"
"Last-Translator: Oğuz Han <h4n.3545@gmail.com>\n"
"PO-Revision-Date: 2026-08-31 20:02+0000\n"
"Last-Translator: Martin Olmer <m_iv@seznam.cz>\n"
"Language-Team: Turkish <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsfrps/tr/>\n"
"Language: tr\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.5-dev\n"
"X-Generator: Weblate 2026.9.dev0\n"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:982
msgid "Access Control"
@@ -506,7 +506,7 @@ msgstr ""
#: applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json:11
msgid "Server"
msgstr ""
msgstr "Sunucu"
#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:358
msgid "Skip checking whether OIDC token issuer matches configured issuer."
@@ -295,10 +295,11 @@ return L.view.extend({
o.default = "off";
// Same rmempty/default collision as mptcp_pm_type above: without this,
// every interface currently set to "off" has network.<iface>.multipath
// silently deleted on each Save & Apply of this page. Currently harmless
// (the init script's own fallback for an absent value is also "off"),
// but keep the persisted value explicit so a future fallback change
// can't quietly flip behavior for these interfaces too.
// silently deleted on each Save & Apply of this page. Not harmless: the
// init script falls back to its own copy of the mode in
// openmptcprouter.<iface>.multipath before it falls back to "off", so a
// deleted setting brings back whatever mode the interface had before
// (discussion #4368).
o.rmempty = false;
o = s.option(form.Value, "multipath_weight", _("Weight"), _("Only used by *weight schedulers/path managers. Ignored if no weight scheduler is selected.") + '<br />' + _("A weight >100 make it more attractive, a weight <100 make it less attractive. Max 256"));
@@ -847,7 +847,13 @@ local methods = {
local iface = args.iface or ""
local interface = get_device(iface)
local server = uci:get("shadowsocks-libev", "sss0", "server") or ""
if server == "" then return { output = "" } end
-- Placeholders the shadowsocks config ships until a VPS is set
-- (127.0.0.1 now, 192.168.1.3 in older releases): tracing to them
-- would report a path that has nothing to do with the proxy.
if server == "" or server == "127.0.0.1" or server == "::1"
or server == "192.168.1.3" then
return { output = "" }
end
local cmd
if interface == "" then
cmd = "tracebox -s /usr/share/tracebox/omr-mptcp-trace.lua " .. server
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2017 chenhw2
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-19
View File
@@ -1,19 +0,0 @@
#
# Copyright (C) 2016 chenhw2 <chenhw2@github.com>
# Copyright (C) 2018-2019 Ycarus (Yannick Chabanois) <ycarus@zugaina.org>
#
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI Support for nginx load balancing
LUCI_DEPENDS:=+nginx
KCONFIG:=CONFIG_NGINX_STREAM_CORE_MODULE
PKG_LICENSE:=MIT
#include $(TOPDIR)/feeds/luci/luci.mk
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
@@ -1,5 +0,0 @@
module("luci.controller.nginx-ha", package.seeall)
function index()
entry({"admin", "services", "nginx-ha"}, cbi("nginx-ha"), _("Nginx High Availability"))
end
@@ -1,37 +0,0 @@
local m, s, o
if luci.sys.call("pgrep nginx >/dev/null") == 0 then
m = Map("nginx-ha", translate("Nginx High Availability"), "%s - %s" %{translate("Nginx High Availability"), translate("RUNNING")})
else
m = Map("nginx-ha", translate("Nginx High Availability"), "%s - %s" %{translate("Nginx High Availability"), translate("NOT RUNNING")})
end
s = m:section(TypedSection, "nginxha", translate("Settings"))
s.addremove = true
o = s:option(Flag, "enable", translate("Enable"))
o.rmempty = false
o = s:option(Value, "listen", translate("Listen Address:Port"))
o.placeholder = "0.0.0.0:6666"
o.default = "0.0.0.0:6666"
o.rmempty = false
o = s:option(Value, "timeout", translate("Timeout Connect (ms)"))
o.placeholder = "1000"
o.default = "1000"
o.datatype = "range(33, 10000)"
o.rmempty = false
o = s:option(Value, "retries", translate("Retries"))
o.placeholder = "1"
o.default = "1"
o.datatype = "range(1, 10)"
o.rmempty = false
o = s:option(DynamicList, "upstreams", translate("UpStream Server"), translate("e.g. [123.123.123.123:65101 weight=1 max_fails=3 fail_timeout=30s]"))
o.placeholder = "123.123.123.123:65101 weight=1 max_fails=3 fail_timeout=30s"
o.rmempty = false
return m
-52
View File
@@ -1,52 +0,0 @@
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.0.6\n"
"Last-Translator: Ycarus <ycarus@zugaina.org>\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Language: fr\n"
msgid "%u seconds"
msgstr "%u secondes"
msgid "Enable"
msgstr "Activé"
msgid "General Setting"
msgstr "Paramètres généraux"
msgid "Listen Address:Port"
msgstr "Écoute adresse:Port"
msgid "NOT RUNNING"
msgstr "NON LANCÉ"
msgid "Nginx High Availability"
msgstr ""
msgid "Not enabled"
msgstr "Non activé"
msgid "RUNNING"
msgstr "LANCÉ"
msgid "Retries"
msgstr "Tentatives"
msgid "Startup Delay"
msgstr "Délai de démarrage"
msgid "Timeout Connect (ms)"
msgstr "Délais d'attente (s)"
msgid "UpStream Server"
msgstr "Serveur"
msgid "e.g. [123.123.123.123:65101 weight=1 max_fails=3 fail_timeout=30s]"
msgstr ""
@@ -1,41 +0,0 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "%u seconds"
msgstr ""
msgid "Enable"
msgstr ""
msgid "General Setting"
msgstr ""
msgid "Listen Address:Port"
msgstr ""
msgid "NOT RUNNING"
msgstr ""
msgid "Nginx High Availability"
msgstr ""
msgid "Not enabled"
msgstr ""
msgid "RUNNING"
msgstr ""
msgid "Retries"
msgstr ""
msgid "Startup Delay"
msgstr ""
msgid "Timeout Connect (ms)"
msgstr ""
msgid "UpStream Server"
msgstr ""
msgid "e.g. [123.123.123.123:65101 weight=1 max_fails=3 fail_timeout=30s]"
msgstr ""
@@ -1,14 +0,0 @@
config nginxha 'ShadowSocks'
option enable '0'
option retries '1'
option timeout '1000'
option listen '0.0.0.0:65101'
list upstreams '1.2.3.4:65101 weight=1 max_fails=3 fail_timeout=30s'
config nginxha 'VPN'
option enable '0'
option retries '1'
option timeout '1000'
option listen '0.0.0.0:65001'
list upstreams '1.2.3.4:65001 weight=1 max_fails=3 fail_timeout=30s'
-115
View File
@@ -1,115 +0,0 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2016 chenhw2 <chenhw2@github.com>
# Copyright (C) 2018 Ycarus (Yannick Chabanois) <ycarus@zugaina.org>
START=85
USE_PROCD=1
PROG_NAME=nginx
PROG=/usr/sbin/${PROG_NAME}
NAME=nginx-ha
PIDCOUNT=0
_log() {
logger -p daemon.info -t ${PROG_NAME} "$@"
}
_err() {
logger -p daemon.err -t ${PROG_NAME} "$@"
}
validate_section() {
uci_validate_section nginx-ha nginxha "${1}" \
'enable:bool:0' \
'retries:uinteger:3' \
'timeout:uinteger:4000' \
'listen:string' \
'upstreams:list(string)'
}
genline_srv(){
echo " server $1;"
}
start_instance() {
local enable retries timeout startup_delay listen upstreams
validate_section "${1}" || {
_err "validation failed"
return 1
}
[ "$enable" = 1 ] || return 1
stream="${stream}
upstream ${1} {
zone dynamic 64k;
$(config_list_foreach "${1}" "upstreams" genline_srv)
}
server {
listen ${listen:-0.0.0.0:6666} udp;
listen ${listen:-0.0.0.0:6666} so_keepalive=off;
proxy_pass ${1};
}
"
}
start_service() {
local stream=""
config_load nginx-ha
config_foreach start_instance nginxha
[ -z "$stream" ] && return
mkdir -p /var/log/nginx
mkdir -p /var/etc
cat <<-EOF > /var/etc/$PROG_NAME.cfg
user nobody nogroup;
worker_processes $(grep -c '^processor' /proc/cpuinfo | tr -d "\n");
worker_rlimit_nofile 300000;
events {
worker_connections 15000;
multi_accept on;
use epoll;
}
stream {
${stream}
}
EOF
procd_open_instance "nginx-ha"
procd_set_param command /usr/sbin/nginx -c /var/etc/$PROG_NAME.cfg -g 'daemon off;'
procd_set_param file /var/etc/$PROG_NAME.cfg
procd_set_param respawn
procd_close_instance
}
reload_service() {
stop
start
}
stop_service() {
local _PID=$(cat /var/run/nginx.pid 2>/dev/null)
kill -15 $_PID 2>/dev/null
sleep 1 # give time to shutdown
local _tmp=$(pgrep nginx | tr "\n" " ")
if [ -z "$_tmp" ]; then
logger -p daemon.notice -t "nginx-ha[$_PID]" "Shutdown successfully"
else
kill -9 $_tmp # Normally never come here
logger -p daemon.warn -t "nginx-ha[$_tmp]" "Shutdown forced by KILL"
fi
return 0
}
service_triggers() {
procd_add_reload_trigger nginx-ha
}
@@ -1,23 +0,0 @@
#!/bin/sh
[ ! -f "/usr/share/ucitrack/luci-app-nginx-ha.json" ] && {
cat > /usr/share/ucitrack/luci-app-nginx-ha.json << EEOF
{
"config": "nginx-ha",
"init": "nginx-ha"
}
EEOF
}
uci -q batch <<-EOF >/dev/null
delete ucitrack.@nginx-ha[-1]
add ucitrack nginx-ha
set ucitrack.@nginx-ha[-1].init=nginx-ha
commit ucitrack
EOF
/etc/init.d/nginx stop >/dev/null 2>&1
/etc/init.d/nginx disable >/dev/null 2>&1
/etc/init.d/nginx-ha enable >/dev/null 2>&1
rm -f /tmp/luci-indexcache
exit 0
@@ -1,13 +0,0 @@
{
"admin/services/nginx-ha": {
"title": "Nginx High Availability",
"order": 80,
"action": {
"type": "cbi",
"path": "nginx-ha"
},
"depends": {
"acl": [ "luci-app-nginx-ha" ]
}
}
}
@@ -1,11 +0,0 @@
{
"luci-app-nginx-ha": {
"description": "Grant UCI access for luci-app-nginx-ha",
"read": {
"uci": [ "nginx-ha" ]
},
"write": {
"uci": [ "nginx-ha" ]
}
}
}
+2 -2
View File
@@ -6,8 +6,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2
PKG_VERSION:=26.9.2
PKG_RELEASE:=114
PKG_VERSION:=26.9.9
PKG_RELEASE:=115
PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \
@@ -443,7 +443,15 @@ function add_node()
uci_set(uid, "group", group)
end
uci_set(uid, "type", "Xray")
if api.finded_com("sing-box") then
uci_set(uid, "type", "sing-box")
elseif api.finded_com("xray") then
uci_set(uid, "type", "Xray")
elseif api.is_finded("sslocal") then
uci_set(uid, "type", "SS-Rust")
elseif api.is_finded("ssr-local") then
uci_set(uid, "type", "SSR")
end
if redirect == "1" then
uci_save()
@@ -43,20 +43,21 @@ end
-- [[ ACLs Settings ]]--
s = m:section(NamedSection, arg[1], translate("ACLs"), translate("ACLs"))
s.addremove = false
s.dynamic = false
---- Enable
o = s:option(Flag, "enabled", translate("Enable"))
s:tab("Main", translate("Main"))
s:tab("Proxy", translate("Proxy"))
s:tab("DNS", translate("DNS"))
s:tab("Log", translate("Log"))
o = s:taboption("Main", Flag, "enabled", translate("Enable"))
o.default = 1
o.rmempty = false
---- Remarks
o = s:option(Value, "remarks", translate("Remarks"))
o = s:taboption("Main", Value, "remarks", translate("Remarks"))
o.default = arg[1]
o.rmempty = false
o = s:option(Value, "interface", translate("Source Interface"))
o = s:taboption("Main", Value, "interface", translate("Source Interface"))
o:value("", translate("All"))
local iface = api.get_network_devices()
for _, d in ipairs(iface) do
@@ -90,7 +91,7 @@ table.sort(mac_t, function(a,b)
end)
---- Source
sources = s:option(DynamicList, "sources", translate("Source"))
sources = s:taboption("Main", DynamicList, "sources", translate("Source"))
sources.description = "<ul><li>" .. translate("Example:")
.. "</li><li>" .. translate("MAC") .. ": 00:00:00:FF:FF:FF"
.. "</li><li>" .. translate("IP") .. ": 192.168.1.100"
@@ -140,36 +141,36 @@ sources.validate = function(self, value, t)
end
local NODE = m:get("@global[0]", "node")
o = s:option(ListValue, "mode", translate("Mode"))
o = s:taboption("Main", ListValue, "mode", translate("Mode"))
o:value("0", translate("No Proxy"))
o:value("1", translate("Proxy"))
o:value("2", translate("Proxy") .. " " .. translate("Use global config") .. "(" .. api.get_node_name(NODE) .. ")")
o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
o = s:taboption("Proxy", Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
o:value("", translate("No patterns are used"))
o:value("1:65535", translate("All"))
o:depends("mode", "1")
o:depends("mode", "2")
o.validate = port_validate
o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"))
o = s:taboption("Proxy", Value, "udp_no_redir_ports", translate("UDP No Redir Ports"))
o:value("", translate("No patterns are used"))
o:value("1:65535", translate("All"))
o:depends("mode", "1")
o:depends("mode", "2")
o.validate = port_validate
o = s:option(DummyValue, "_show_tcp_redir", "")
o = s:taboption("Main", DummyValue, "_show_tcp_redir", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ tcp_no_redir_ports = "1:65535", ['!reverse'] = true })
o = s:option(DummyValue, "_show_udp_redir", "")
o = s:taboption("Main", DummyValue, "_show_udp_redir", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ udp_no_redir_ports = "1:65535", ['!reverse'] = true })
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
o = s:taboption("Proxy", Value, "tcp_redir_ports", translate("TCP Redir Ports"))
o:value("1:65535", translate("All"))
o:value("22,25,53,80,143,443,465,587,853,873,993,995,5222,8080,8443,9418", translate("Common Use"))
o:value("80,443", "80,443")
@@ -178,14 +179,14 @@ o.validate = port_validate
o:depends({ _node = "1", _show_tcp_redir = "1" })
o:depends({ mode = "2", _show_tcp_redir = "1" })
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
o = s:taboption("Proxy", Value, "udp_redir_ports", translate("UDP Redir Ports"))
o:value("1:65535", translate("All"))
o.default = o.keylist[1]
o.validate = port_validate
o:depends({ _node = "1", _show_udp_redir = "1" })
o:depends({ mode = "2", _show_udp_redir = "1" })
o = s:option(DummyValue, "tips", " ")
o = s:taboption("Proxy", DummyValue, "tips", " ")
o.rawhtml = true
o.cfgvalue = function(t, n)
return string.format('<font color="red">%s</font>',
@@ -194,47 +195,53 @@ end
o:depends("mode", "1")
o:depends("mode", "2")
o = s:option(DummyValue, "_no_proxy", "")
o = s:taboption("Main", DummyValue, "_no_proxy", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends("mode", "0")
o:depends({ tcp_no_redir_ports = "1:65535", udp_no_redir_ports = "1:65535" })
o = s:option(DummyValue, "_show_node_option", "")
o = s:taboption("Main", DummyValue, "_show_node_option", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ mode = "1", _no_proxy = "" })
o = s:option(ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>")
o = s:taboption("Main", ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>")
o.group = {}
o:depends("_show_node_option", "1")
o.template = m:template_path("/cbi/nodes_listvalue")
current_node_id = o:formvalue(arg[1])
if not current_node_id then
current_node_id = m:get(arg[1], "node")
current_node_id = m:get(arg[1], "node")
local node_value = s.fields["node"]:formvalue(s.section)
if node_value then
current_node_id = node_value
end
current_node = current_node_id and m:get(current_node_id) or {}
o = s:option(DummyValue, "_node", "")
o = s:taboption("Main", DummyValue, "node_save_before", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = current_node[".name"]
o.cbid = function(self, section) return "node_save_before" end
o = s:taboption("Main", DummyValue, "_node", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ node = "", ['!reverse'] = true })
o = s:option(DummyValue, "_is_singbox", "")
o = s:taboption("Main", DummyValue, "_is_singbox", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends("_hide", "1")
o = s:option(DummyValue, "_is_xray", "")
o = s:taboption("Main", DummyValue, "_is_xray", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends("_hide", "1")
o = s:option(Flag, "log", translate("Enable Node Log"))
o = s:taboption("Log", Flag, "log", translate("Enable Node Log"))
o:depends("_node", "1")
o = s:option(ListValue, "loglevel", translate("Log Level"))
o = s:taboption("Log", ListValue, "loglevel", translate("Log Level"))
o.default = "warn"
o:value("debug", "Debug")
o:value("info", "Info")
@@ -242,33 +249,37 @@ o:value("warn", "Warning")
o:value("error", "Error")
o:depends("log", "1")
o = s:option(DummyValue, "_acl_log", translate("Log File"))
o = s:taboption("Log", DummyValue, "_acl_log", translate("Log File"))
o.rawhtml = true
o.cfgvalue = function(t, n)
local log_path = api.TMP_PATH .. "/acl/" .. arg[1] .. ".log"
local log_file = api.TMP_PATH .. "/acl/" .. arg[1] .. ".log"
local log_url = api.url("get_redir_log") .. "?id=" .. arg[1]
return string.format(
'<code>%s</code>&nbsp;&nbsp;<input class="btn cbi-button cbi-button-apply" type="button" value="%s" onclick="window.open(\'%s\', \'_blank\')" />',
log_path,
translate("View Log"),
log_url
)
local s = "<code>%s</code>&nbsp;&nbsp;" % log_file
if api.fs.access(log_file) then
local btn = string.format(
'<input class="btn cbi-button cbi-button-apply" type="button" value="%s" onclick="window.open(\'%s\', \'_blank\')" />',
translate("View Log"),
log_url
)
s = s .. btn
end
return s
end
o:depends("log", "1")
o = s:option(DummyValue, "_show_dns_option", "")
o = s:taboption("DNS", DummyValue, "_show_dns_option", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = "1"
o:depends({ mode = "1", _node = "1" })
o = s:option(ListValue, "direct_dns_query_strategy", translate("Direct Query Strategy"))
o = s:taboption("DNS", ListValue, "direct_dns_query_strategy", translate("Direct Query Strategy"))
o.default = "UseIP"
o:value("UseIP")
o:value("UseIPv4")
o:value("UseIPv6")
o:depends("_show_dns_option", "1")
o = s:option(ListValue, "remote_dns_protocol", translate("Remote DNS Protocol"))
o = s:taboption("DNS", ListValue, "remote_dns_protocol", translate("Remote DNS Protocol"))
o:value("tcp", "TCP")
o:value("doh", "DoH")
o:value("udp", "UDP")
@@ -286,7 +297,7 @@ end
o:depends("_show_dns_option", "1")
---- DNS over TCP or UDP or TLS (DoT) or QUIC (DoQ)
o = s:option(Value, "remote_dns", translate("Remote DNS"))
o = s:taboption("DNS", Value, "remote_dns", translate("Remote DNS"))
o.datatype = "or(ipaddr,ipaddrport(1))"
o.default = "1.1.1.1"
o:value("1.1.1.1", "1.1.1.1 (CloudFlare)")
@@ -303,7 +314,7 @@ o:depends("remote_dns_protocol", "quic")
o:depends("remote_dns_protocol", "tls")
---- DNS over HTTP (DoH) or DNS over HTTP3(DoH3)
o = s:option(Value, "remote_dns_doh", translate("Remote DNS DoH"))
o = s:taboption("DNS", Value, "remote_dns_doh", translate("Remote DNS DoH"))
o:value("https://1.1.1.1/dns-query", "CloudFlare")
o:value("https://1.1.1.2/dns-query", "CloudFlare-Security")
o:value("https://8.8.4.4/dns-query", "Google 8844")
@@ -319,42 +330,42 @@ o.validate = doh_validate
o:depends("remote_dns_protocol", "doh")
o:depends("remote_dns_protocol", "http3")
o = s:option(Value, "remote_dns_client_ip", translate("Remote DNS EDNS Client Subnet"))
o = s:taboption("DNS", Value, "remote_dns_client_ip", translate("Remote DNS EDNS Client Subnet"))
o.description = translate("Notify the DNS server when the DNS query is notified, the location of the client (cannot be a private IP address).") .. "<br />" ..
translate("This feature requires the DNS server to support the Edns Client Subnet (RFC7871).")
o.datatype = "ipaddr"
o:depends("_show_dns_option", "1")
o = s:option(ListValue, "remote_dns_detour", translate("Remote DNS Outbound"))
o = s:taboption("DNS", ListValue, "remote_dns_detour", translate("Remote DNS Outbound"))
o.default = "remote"
o:value("remote", translate("Remote"))
o:value("direct", translate("Direct"))
o:depends("_show_dns_option", "1")
o = s:option(Flag, "remote_fakedns", "FakeDNS", translate("Use FakeDNS work in the domain that proxy."))
o = s:taboption("DNS", Flag, "remote_fakedns", "FakeDNS", translate("Use FakeDNS work in the domain that proxy."))
o.default = "0"
o.rmempty = false
o:depends("_hide", "1")
o = s:option(ListValue, "remote_dns_query_strategy", translate("Remote Query Strategy"))
o = s:taboption("DNS", ListValue, "remote_dns_query_strategy", translate("Remote Query Strategy"))
o.default = "UseIPv4"
o:value("UseIP")
o:value("UseIPv4")
o:value("UseIPv6")
o:depends("_show_dns_option", "1")
o = s:option(Value, "remote_rewrite_ttl", translate("Remote DNS") .. " TTL")
o = s:taboption("DNS", Value, "remote_rewrite_ttl", translate("Remote DNS") .. " TTL")
o.datatype = "min(1)"
o.default = "30"
o:depends({ _show_dns_option = "1", _is_singbox = "1" })
o = s:option(ListValue, "dns_hosts_mode", translate("Domain Override"))
o = s:taboption("DNS", ListValue, "dns_hosts_mode", translate("Domain Override"))
o:value("default", translate("Use global config"))
o:value("disable", translate("No patterns are used"))
o:value("custom", translate("-- custom --"))
o:depends("_show_dns_option", "1")
o = s:option(TextValue, "dns_hosts", translate("Domain Override"))
o = s:taboption("DNS", TextValue, "dns_hosts", translate("Domain Override"))
o.rows = 5
o.wrap = "off"
o:depends("dns_hosts_mode", "custom")
@@ -390,19 +401,16 @@ for k, v in pairs(nodes_table) do
end
end
--[[
-- Shunt
if current_node.protocol == "_shunt" then
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall2/client/include/shunt_options.lua")
setfenv(shunt_lua, getfenv(1))(m, s, {
s_cfgid = s.section,
node_id = current_node_id,
node = current_node,
verify_option = s.fields["node"]
verify_option = s.fields["node"],
tab = "Shunt",
tab_desc = translate("Shunt Rule"),
})
end
m:appendTemplate("/acl/shunt", { shunt_list = api.jsonc.stringify(shunt_list), section = s.section })
]]--
m:appendTemplate("/include/node_change", { verify_option = s.fields["node"], shunt_list = api.jsonc.stringify(shunt_list) })
return api.return_map(m)
@@ -96,25 +96,27 @@ o.value = "1"
o:depends("_hide", "1")
current_node_id = m:get(s.section, "node")
local node_value = s.fields["node"]:formvalue(s.section)
if node_value then
current_node_id = node_value
end
current_node = current_node_id and m:get(current_node_id) or {}
o = s:taboption("Main", DummyValue, "node_save_before", "")
o.template = m:template_path("/cbi/hidevalue")
o.value = current_node[".name"]
o.cbid = function(self, section) return "node_save_before" end
-- Shunt Start
if (has_singbox or has_xray) and #nodes_table > 0 then
if #normal_list > 0 or #iface_list > 0 then
if current_node.protocol == "_shunt" then
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall2/client/include/shunt_options.lua")
setfenv(shunt_lua, getfenv(1))(m, s, {
s_cfgid = s.section,
node_id = current_node_id,
node = current_node,
socks_list = socks_list,
urltest_list = urltest_list,
balancing_list = balancing_list,
iface_list = iface_list,
normal_list = normal_list,
verify_option = s.fields["node"],
tab = "Shunt",
tab_desc = translate("Shunt Rule")
tab_desc = translate("Shunt Rule"),
})
end
else
@@ -334,6 +336,8 @@ s:tab("maintain", translate("Maintain"))
o = s:taboption("maintain", DummyValue, "")
o.template = m:template_path("/global/backup")
m:appendTemplate("/include/node_change", { verify_option = s.fields["node"], shunt_list = api.jsonc.stringify(shunt_list) })
-- [[ Socks Server ]]--
o = s:taboption("Main", Flag, "socks_enabled", "Socks " .. translate("Main switch"))
o.rmempty = false
@@ -417,7 +421,7 @@ for k, v in pairs(nodes_table) do
end
end
m:appendTemplate("/global/footer", {shunt_list = api.jsonc.stringify(shunt_list)})
m:appendTemplate("/global/footer")
m:appendTemplate("/global/status_bottom")
m:appendTemplate("/cbi/sortable", {sectiontype = s2.sectiontype})
@@ -1,13 +1,28 @@
local m, s, data = ...
if not data.node_id or not data.node then
if not data.node or not data.node[".name"] then
return
end
local api = m.api
local s_cfgid = data.s_cfgid
local current_node_id = data.node_id
local section_id = s.section
local current_node = data.node
local current_node_id = current_node[".name"]
local verify_option = data.verify_option
local node_list = data.node_list or api.get_node_list()
local shunt_section_type = "shunt_option_list"
if data.tab then
if #s.tab_names > 0 then
table.insert(s.tab_names, 2, data.tab)
s.tabs[data.tab] = {
title = data.tab_desc,
childs = { }
}
else
s:tab(data.tab, data.tab_desc)
end
end
local groups = {}
m:foreach("shunt_rules", function(s)
@@ -16,6 +31,9 @@ m:foreach("shunt_rules", function(s)
end
end)
local node_save_before = luci.http.formvalue("node_save_before")
local load_shunt = luci.http.formvalue("load_shunt")
local function get_cfgvalue()
return function(self, section)
return m:get(current_node_id, self.option)
@@ -23,8 +41,10 @@ local function get_cfgvalue()
end
local function get_write()
return function(self, section, value)
if data.verify_option then
if data.verify_option:formvalue(section) == current_node_id then
if node_save_before and node_save_before ~= current_node_id then return end
if load_shunt == "1" then return end
if verify_option then
if verify_option:formvalue(section) == current_node_id then
m:set(current_node_id, self.option, value)
end
else
@@ -34,8 +54,10 @@ local function get_write()
end
local function get_remove()
return function(self, section)
if data.verify_option then
if data.verify_option:formvalue(section) == current_node_id then
if node_save_before and node_save_before ~= current_node_id then return end
if load_shunt == "1" then return end
if verify_option then
if verify_option:formvalue(section) == current_node_id then
m:del(current_node_id, self.option)
end
else
@@ -44,10 +66,6 @@ local function get_remove()
end
end
if data.tab then
s:tab(data.tab, data.tab_desc)
end
local function add_option(class, option_name, option_title, option_desc)
local a
if data.tab then
@@ -63,8 +81,8 @@ local function add_option(class, option_name, option_title, option_desc)
a.write = get_write()
a.remove = get_remove()
end
if data.verify_option then
a:depends(data.verify_option.option, current_node_id)
if verify_option then
a:depends(verify_option.option, current_node_id)
end
return a
end
@@ -81,7 +99,7 @@ local function add_depends(o, deps)
end
end
if data.node.type == "Xray" then
if current_node.type == "Xray" then
o = add_option(ListValue, "domainStrategy", translate("Domain Strategy"))
o:value("AsIs")
o:value("IPIfNonMatch")
@@ -148,7 +166,7 @@ table.insert(shunt_rules, {
s2 = m:section(Table, shunt_rules, " ")
s2.config = m.config
s2.sectiontype = "shunt_option_list"
s2.sectiontype = shunt_section_type
o = s2:option(DummyValue, "remarks", translate("Rule"))
o.rawhtml = true
@@ -171,9 +189,13 @@ _node.cfgvalue = function(self, section)
return m:get(current_node_id, shunt_rules[section]["_node_option"]) or shunt_rules[section]["_node_default"]
end
_node.write = function(self, section, value)
if node_save_before and node_save_before ~= current_node_id then return end
if load_shunt == "1" then return end
return m:set(current_node_id, shunt_rules[section]["_node_option"], value)
end
_node.remove = function(self, section)
if node_save_before and node_save_before ~= current_node_id then return end
if load_shunt == "1" then return end
return m:del(current_node_id, shunt_rules[section]["_node_option"])
end
@@ -184,9 +206,13 @@ o.cfgvalue = function(self, section)
return m:get(current_node_id, shunt_rules[section]["_fakedns_option"])
end
o.write = function(self, section, value)
if node_save_before and node_save_before ~= current_node_id then return end
if load_shunt == "1" then return end
return m:set(current_node_id, shunt_rules[section]["_fakedns_option"], value)
end
o.remove = function(self, section)
if node_save_before and node_save_before ~= current_node_id then return end
if load_shunt == "1" then return end
return m:del(current_node_id, shunt_rules[section]["_fakedns_option"])
end
@@ -200,9 +226,13 @@ proxy_tag_node.cfgvalue = function(self, section)
return m:get(current_node_id, shunt_rules[section]["_proxy_tag_option"])
end
proxy_tag_node.write = function(self, section, value)
if node_save_before and node_save_before ~= current_node_id then return end
if load_shunt == "1" then return end
return m:set(current_node_id, shunt_rules[section]["_proxy_tag_option"], value)
end
proxy_tag_node.remove = function(self, section)
if node_save_before and node_save_before ~= current_node_id then return end
if load_shunt == "1" then return end
return m:del(current_node_id, shunt_rules[section]["_proxy_tag_option"])
end
@@ -218,4 +248,11 @@ for k1, v1 in pairs(node_list) do
end
end
m:appendTemplate("/include/shunt_options", {id = current_node_id, s_cfgid = s_cfgid or current_node_id, normal_list = api.jsonc.stringify(node_list.normal_list)})
m:appendTemplate("/include/shunt_options", {
node_id = current_node_id,
section_id = section_id or current_node_id,
section_type = shunt_section_type,
tab_name = data.tab,
normal_list = api.jsonc.stringify(node_list.normal_list),
shunt_list = api.jsonc.stringify(node_list.shunt_list)
})
@@ -61,7 +61,6 @@ end
local types_dir = "/usr/lib/lua/luci/model/cbi/" .. api.appname .. "/client/type/"
s.val = {}
s.val["type"] = m:get(arg[1], "type")
s.val["protocol"] = m:get(arg[1], "protocol")
if luci.http.formvalue("cbi.submit") == "1" then
local formvalue_type = luci.http.formvalue(formvalue_key .. "type")
@@ -17,15 +17,11 @@ if s1.val["type"] ~= type_name then
return
end
local s = NamedSection(m, arg[1], "server")
local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype)
s.parent = s1
s.type_name = type_name
s.option_prefix = "singbox_"
local formvalue_proto = luci.http.formvalue(formvalue_key .. "protocol")
if formvalue_proto then s1.val["protocol"] = formvalue_proto end
local arg_select_proto = luci.http.formvalue("select_proto") or ""
api.set_type_cbi(s)
local ss_method_new_list = {
"none", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"
@@ -75,24 +71,20 @@ end
o:value("_urltest", translate("URLTest"))
o:value("_shunt", translate("Shunt"))
o:value("_iface", translate("Custom Interface"))
function o.custom_cfgvalue(self, section)
if arg_select_proto ~= "" then
return arg_select_proto
else
return m:get(section, self.config_option)
end
local protocol_val = m:get(s.section, "protocol")
local formvalue_proto = s.fields["protocol"]:formvalue(s.section)
if formvalue_proto then
protocol_val = formvalue_proto
end
local load_urltest_options = s1.val["protocol"] == "_urltest" or arg_select_proto == "_urltest"
local load_shunt_options = s1.val["protocol"] == "_shunt" or arg_select_proto == "_shunt"
local load_iface_options = s1.val["protocol"] == "_iface" or arg_select_proto == "_iface"
local load_urltest_options = protocol_val == "_urltest"
local load_shunt_options = protocol_val == "_shunt"
local load_iface_options = protocol_val == "_iface"
local load_normal_options = true
if load_urltest_options or load_shunt_options or load_iface_options then
load_normal_options = nil
end
if not arg_select_proto:find("_") then
load_normal_options = true
end
local netdev_list = api.get_network_devices()
local node_list = api.get_node_list()
@@ -117,12 +109,10 @@ if load_urltest_options then -- [[ URLTest Start ]]
end
end
end
-- Reading the old DynamicList
function o.custom_cfgvalue(self, section)
function o.cfgvalue(self, section)
return table.concat(m:get(section, "urltest_node") or {}, " ")
end
-- Write-and-hold DynamicList
function o.custom_write(self, section, value)
function o.write(self, section, value)
local old = m:get(section, "urltest_node") or {}
local new, set = {}, {}
for v in value:gmatch("%S+") do
@@ -994,7 +984,7 @@ if not load_shunt_options then
for k1, v1 in pairs(node_list) do
if k1 ~= "shunt_list" and k1 ~= "iface_list" then
for i, v in ipairs(v1) do
if v.id ~= arg[1] then
if v.id ~= s.section then
o1:value(v.id, v.remark)
o1.group[#o1.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
if k1 == "normal_list" then
@@ -1008,14 +998,15 @@ if not load_shunt_options then
end
end
api.luci_types(s1, s)
api.type_cbi_section(s1, s)
if load_shunt_options then
local current_node = m:get(arg[1]) or {}
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall2/client/include/shunt_options.lua")
setfenv(shunt_lua, getfenv(1))(m, s1, {
node_id = arg[1],
node = current_node,
node = {
[".name"] = s.section,
type = type_name,
},
node_list = node_list,
})
end
@@ -15,15 +15,11 @@ if s1.val["type"] ~= type_name then
return
end
local s = NamedSection(m, arg[1], "server")
local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype)
s.parent = s1
s.type_name = type_name
s.option_prefix = "xray_"
local formvalue_proto = luci.http.formvalue(formvalue_key .. "protocol")
if formvalue_proto then s1.val["protocol"] = formvalue_proto end
local arg_select_proto = luci.http.formvalue("select_proto") or ""
api.set_type_cbi(s)
local ss_method_list = {
"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "xchacha20-poly1305", "xchacha20-ietf-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"
@@ -53,31 +49,27 @@ if api.compare_versions(xray_version, ">=", "1.8.12") then
end
o:value("_shunt", translate("Shunt"))
o:value("_iface", translate("Custom Interface"))
function o.custom_cfgvalue(self, section)
if arg_select_proto ~= "" then
return arg_select_proto
else
return m:get(section, self.config_option)
end
local protocol_val = m:get(s.section, "protocol")
local formvalue_proto = s.fields["protocol"]:formvalue(s.section)
if formvalue_proto then
protocol_val = formvalue_proto
end
local load_balancing_options = s1.val["protocol"] == "_balancing" or arg_select_proto == "_balancing"
local load_shunt_options = s1.val["protocol"] == "_shunt" or arg_select_proto == "_shunt"
local load_iface_options = s1.val["protocol"] == "_iface" or arg_select_proto == "_iface"
local load_balancing_options = protocol_val == "_balancing"
local load_shunt_options = protocol_val == "_shunt"
local load_iface_options = protocol_val == "_iface"
local load_normal_options = true
if load_balancing_options or load_shunt_options or load_iface_options then
load_normal_options = nil
end
if not arg_select_proto:find("_") then
load_normal_options = true
end
local netdev_list = api.get_network_devices()
local node_list = api.get_node_list()
local fallback_list = {}
local is_balancer = nil
for k, e in ipairs(node_list.balancing_list or {}) do
if e.id ~= arg[1] then
if e.id ~= s.section then
fallback_list[#fallback_list + 1] = {
id = e["id"],
remark = e["remark"],
@@ -109,12 +101,10 @@ if load_balancing_options then -- [[ Load balancing Start ]]
end
end
end
-- Reading the old DynamicList
function o.custom_cfgvalue(self, section)
function o.cfgvalue(self, section)
return table.concat(m:get(section, "balancing_node") or {}, " ")
end
-- Write-and-hold DynamicList
function o.custom_write(self, section, value)
function o.write(self, section, value)
local old = m:get(section, "balancing_node") or {}
local new, set = {}, {}
for v in value:gmatch("%S+") do
@@ -213,7 +203,7 @@ if load_balancing_options then -- [[ Load balancing Start ]]
local depth = get_fallback_depth(v.id)
-- Once the maximum number of nested doll layers is exceeded, further selection of the balancer is not allowed.
if depth < MAX_FALLBACK_DEPTH
and not will_loop(arg[1], v.id)
and not will_loop(s.section, v.id)
then
o:value(v.id, v.remark)
o.group[#o.group + 1] = (v.group and v.group ~= "") and v.group or translate("default")
@@ -687,13 +677,13 @@ o.validate = function(self, value)
if v then return v end
return nil, "XHTTP Extra " .. translate("Must be JSON text!")
end
o.custom_cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section, value)
local raw = m:get(section, "xhttp_extra")
if raw then
return api.base64Decode(raw)
end
end
o.custom_write = function(self, section, value)
o.write = function(self, section, value)
m:set(section, "xhttp_extra", api.base64Encode(value) or "")
local success, data = pcall(api.jsonc.parse, value)
if success and data then
@@ -709,7 +699,7 @@ o.custom_write = function(self, section, value)
m:del(section, "download_address")
end
end
o.custom_remove = function(self, section, value)
o.remove = function(self, section, value)
m:del(section, "xhttp_extra")
m:del(section, "download_address")
end
@@ -774,13 +764,13 @@ o.validate = function(self, value)
if v then return v end
return nil, "FinalMask " .. translate("Must be JSON text!")
end
o.custom_cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section, value)
local raw = m:get(section, "finalmask")
if raw then
return api.base64Decode(raw)
end
end
o.custom_write = function(self, section, value)
o.write = function(self, section, value)
m:set(section, "finalmask", api.base64Encode(value) or "")
end
@@ -878,7 +868,7 @@ if not load_shunt_options then
for k1, v1 in pairs(node_list) do
if k1 ~= "shunt_list" and k1 ~= "iface_list" then
for i, v in ipairs(v1) do
if v.id ~= arg[1] then
if v.id ~= s.section then
o1:value(v.id, v.remark)
o1.group[#o1.group+1] = (v.group and v.group ~= "") and v.group or translate("default")
if k1 == "normal_list" then
@@ -892,14 +882,15 @@ if not load_shunt_options then
end
end
api.luci_types(s1, s)
api.type_cbi_section(s1, s)
if load_shunt_options then
local current_node = m:get(arg[1]) or {}
local shunt_lua = loadfile("/usr/lib/lua/luci/model/cbi/passwall2/client/include/shunt_options.lua")
setfenv(shunt_lua, getfenv(1))(m, s1, {
node_id = arg[1],
node = current_node,
node = {
[".name"] = s.section,
type = type_name,
},
node_list = node_list,
})
end
@@ -12,9 +12,11 @@ if s1.val["type"] ~= type_name then
return
end
local s = NamedSection(m, arg[1], "server")
local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype)
s.parent = s1
s.type_name = type_name
s.option_prefix = "ssrust_"
api.set_type_cbi(s)
local ssrust_encrypt_method_list = {
"none", "plain",
@@ -65,4 +67,4 @@ end
o = s:option(Value, "plugin_opts", translate("opts"))
o:depends({ plugin_enabled = true })
api.luci_types(s1, s)
api.type_cbi_section(s1, s)
@@ -12,9 +12,11 @@ if s1.val["type"] ~= type_name then
return
end
local s = NamedSection(m, arg[1], "server")
local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype)
s.parent = s1
s.type_name = type_name
s.option_prefix = "ssr_"
api.set_type_cbi(s)
local ssr_encrypt_method_list = {
"none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb",
@@ -63,4 +65,4 @@ o.default = 300
o = s:option(Flag, "tcp_fast_open", "TCP " .. translate("Fast Open"), translate("Need node support required"))
o.default = 0
api.luci_types(s1, s)
api.type_cbi_section(s1, s)
@@ -21,9 +21,11 @@ if s1.val["type"] and s1.val["type"] ~= type_name then
return
end
local s = NamedSection(m, arg[1], "server")
local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype)
s.parent = s1
s.type_name = type_name
s.option_prefix = "singbox_"
api.set_type_cbi(s)
local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'")
@@ -48,13 +50,13 @@ o.validate = function(self, value)
if v then return v end
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
end
o.custom_cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section, value)
local config_str = m:get(section, "config_str")
if config_str then
return api.base64Decode(config_str)
end
end
o.custom_write = function(self, section, value)
o.write = function(self, section, value)
m:set(section, "config_str", api.base64Encode(value) or "")
end
@@ -307,8 +309,8 @@ o:depends({ protocol = "hysteria" })
-- [[ TLS ]] --
o = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. s.section .. ".pem"
if o and o:formvalue(s.section) then o.default = o:formvalue(s.section) end
o:depends({ tls = true, reality = false })
o:depends({ protocol = "naive" })
o:depends({ protocol = "hysteria" })
@@ -326,8 +328,8 @@ o.validate = function(self, value, t)
end
o = s:option(FileUpload, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. s.section .. ".key"
if o and o:formvalue(s.section) then o.default = o:formvalue(s.section) end
o:depends({ tls = true, reality = false })
o:depends({ protocol = "naive" })
o:depends({ protocol = "hysteria" })
@@ -559,4 +561,4 @@ o:value("warn")
o:value("error")
o:depends({ log = true })
api.luci_types(s1, s)
api.type_cbi_section(s1, s)
@@ -19,9 +19,11 @@ if s1.val["type"] and s1.val["type"] ~= type_name then
return
end
local s = NamedSection(m, arg[1], "server")
local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype)
s.parent = s1
s.type_name = type_name
s.option_prefix = "xray_"
api.set_type_cbi(s)
local ss_method_list = {
"aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305"
@@ -44,13 +46,13 @@ o.validate = function(self, value)
if v then return v end
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
end
o.custom_cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section, value)
local config_str = m:get(section, "config_str")
if config_str then
return api.base64Decode(config_str)
end
end
o.custom_write = function(self, section, value)
o.write = function(self, section, value)
m:set(section, "config_str", api.base64Encode(value) or "")
end
@@ -257,8 +259,8 @@ end
-- [[ TLS ]] --
o = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. s.section .. ".pem"
if o and o:formvalue(s.section) then o.default = o:formvalue(s.section) end
o:depends({ tls = true, reality = false })
o:depends({ protocol = "hysteria2"})
o.validate = function(self, value, t)
@@ -273,8 +275,8 @@ o.validate = function(self, value, t)
end
o = s:option(FileUpload, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. s.section .. ".key"
if o and o:formvalue(s.section) then o.default = o:formvalue(s.section) end
o:depends({ tls = true, reality = false })
o:depends({ protocol = "hysteria2"})
o.validate = function(self, value, t)
@@ -401,13 +403,13 @@ o:depends({ use_finalmask = true })
o.rows = 10
o.wrap = "off"
o.datatype = "json"
o.custom_cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section, value)
local raw = m:get(section, "finalmask")
if raw then
return api.base64Decode(raw)
end
end
o.custom_write = function(self, section, value)
o.write = function(self, section, value)
m:set(section, "finalmask", api.base64Encode(value) or "")
end
@@ -554,4 +556,4 @@ o:value("warning")
o:value("error")
o:depends({ log = true })
api.luci_types(s1, s)
api.type_cbi_section(s1, s)
@@ -16,9 +16,11 @@ if s1.val["type"] and s1.val["type"] ~= type_name then
return
end
local s = NamedSection(m, arg[1], "server")
local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype)
s.parent = s1
s.type_name = type_name
s.option_prefix = "ssrust_"
api.set_type_cbi(s)
local ssrust_encrypt_method_list = {
"plain", "none",
@@ -39,13 +41,13 @@ o.validate = function(self, value)
if v then return v end
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
end
o.custom_cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section, value)
local config_str = m:get(section, "config_str")
if config_str then
return api.base64Decode(config_str)
end
end
o.custom_write = function(self, section, value)
o.write = function(self, section, value)
m:set(section, "config_str", api.base64Encode(value) or "")
end
@@ -88,4 +90,4 @@ o = s:option(Flag, "log", translate("Log"))
o.default = "1"
o.rmempty = false
api.luci_types(s1, s)
api.type_cbi_section(s1, s)
@@ -16,9 +16,11 @@ if s1.val["type"] and s1.val["type"] ~= type_name then
return
end
local s = NamedSection(m, arg[1], "server")
local s = NamedSection(m, arg[1], "tmp_" .. s1.sectiontype)
s.parent = s1
s.type_name = type_name
s.option_prefix = "ssr_"
api.set_type_cbi(s)
local ssr_encrypt_method_list = {
"none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb",
@@ -52,13 +54,13 @@ o.validate = function(self, value)
if v then return v end
return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!")
end
o.custom_cfgvalue = function(self, section, value)
o.cfgvalue = function(self, section, value)
local config_str = m:get(section, "config_str")
if config_str then
return api.base64Decode(config_str)
end
end
o.custom_write = function(self, section, value)
o.write = function(self, section, value)
m:set(section, "config_str", api.base64Encode(value) or "")
end
@@ -119,4 +121,4 @@ o = s:option(Flag, "log", translate("Log"))
o.default = "1"
o.rmempty = false
api.luci_types(s1, s)
api.type_cbi_section(s1, s)
+77 -99
View File
@@ -15,7 +15,7 @@ datatypes = require "luci.cbi.datatypes"
jsonc = require "luci.jsonc"
i18n = require "luci.i18n"
curl_args = { "-skfL", "--connect-timeout 3", "--retry 3" }
curl_args = { "-skfL", "--connect-timeout 3", "--retry 3", "-H 'Accept: */*'" }
command_timeout = 300
OPENWRT_ARCH = nil
DISTRIB_ARCH = nil
@@ -1557,110 +1557,88 @@ function return_map(map)
return map
end
function luci_types(s, s2)
function set_type_cbi(s)
local cbi = require "luci.cbi"
local m = s.map
local id = s2.section
local type_name = s2.type_name
local option_prefix = s2.option_prefix
local fv_type
local field_type = s.fields["type"]
if field_type then
fv_type = field_type:formvalue(id)
local s1 = s.parent
function s.option(self, class, option, ...)
local obj = class(self.map, self, option, ...)
obj.config_option = option
obj.option_prefix = self.option_prefix
obj.option = self.option_prefix .. option
obj.cfgvalue = function(o_self, section)
if o_self.rewrite_option then
return o_self.map:get(section, o_self.rewrite_option)
else
return o_self.map:get(section, o_self.config_option)
end
end
obj.write = function(o_self, section, value)
if s1.fields["type"]:formvalue(self.section) == self.type_name then
local new_val = value
if util.instanceof(o_self, cbi.DynamicList) then
local new_t = {}
if type(value) == "table" then
new_t = table_remove_duplicates(value)
else
new_t = { value }
end
if o_self.cast == "string" then
new_val = table.concat(new_t, " ")
else
new_val = new_t
end
end
if o_self.rewrite_option then
o_self.map:set(section, o_self.rewrite_option, new_val)
else
o_self.map:set(section, o_self.config_option, new_val)
end
end
end
obj.remove = function(o_self, section)
if s1.fields["type"]:formvalue(self.section) == self.type_name then
if o_self.rewrite_option then
o_self.map:del(section, o_self.rewrite_option)
else
o_self.map:del(section, o_self.config_option)
end
end
end
obj.depends = function(o_self, field, value)
local deps
if type(field) == "string" then
deps = {}
deps[field] = value
else
deps = field
end
local new_deps = {}
for k, v in pairs(deps) do
local n_k = k
if self.fields[k] then
n_k = self.fields[k].option
end
new_deps[n_k] = v
end
new_deps["type"] = self.type_name
if next(new_deps) then
table.insert(o_self.deps, new_deps)
end
end
self:append(obj)
self.fields[option] = obj
return obj
end
end
function type_cbi_section(s, s2)
for i, v in ipairs(s2.children) do
local o = s2.children[i]
o.config_option = o.option
o.option_prefix = option_prefix
o.option = option_prefix .. o.option
if not o.not_rewrite then
o.cfgvalue = function(self, section)
-- Add a custom `custom_cfgvalue` attribute. If a custom `custom_cfgvalue` function exists, the custom `cfgvalue` logic will be used.
if self.custom_cfgvalue then
return self:custom_cfgvalue(section)
else
if self.rewrite_option then
return m:get(section, self.rewrite_option)
else
return m:get(section, self.config_option)
end
end
end
o.write = function(self, section, value)
if s.fields["type"]:formvalue(id) == type_name then
-- Add a custom `custom_write` attribute; if a custom `custom_write` function exists, then use the custom write logic.
if self.custom_write then
self:custom_write(section, value)
else
local new_val = value
if util.instanceof(self, cbi.DynamicList) then
local new_t = {}
if type(value) == "table" then
new_t = table_remove_duplicates(value)
else
new_t = { value }
end
if self.cast == "string" then
new_val = table.concat(new_t, " ")
else
new_val = new_t
end
end
if self.rewrite_option then
m:set(section, self.rewrite_option, new_val)
else
m:set(section, self.config_option, new_val)
end
end
end
end
o.remove = function(self, section)
if s.fields["type"]:formvalue(id) == type_name then
-- Add a custom `custom_remove` attribute; if a custom `custom_remove` function exists, use the custom remove logic.
if self.custom_remove then
self:custom_remove(section)
else
if self.rewrite_option then
m:del(section, self.rewrite_option)
else
m:del(section, self.config_option)
end
end
end
end
if #o.deps == 0 then
o:depends({ type = s2.type_name })
end
local deps = o.deps
if #deps > 0 then
local function process_deps(dep)
local rewrite_deps = {}
for k, v in pairs(dep) do
if k:find("!") then
rewrite_deps[k] = v
else
rewrite_deps[option_prefix .. k] = v
end
end
if not rewrite_deps['!reverse'] then
rewrite_deps["type"] = type_name
end
return rewrite_deps
end
for index, value in ipairs(deps) do
local rewrite_deps = process_deps(value)
if rewrite_deps then
deps[index] = rewrite_deps
end
end
else
o:depends({ type = type_name })
end
if fv_type and fv_type ~= type_name then
o.rmempty = true
end
s:append(o)
s.fields[o.option] = o
end
end
@@ -1773,7 +1773,12 @@ function gen_config(var)
domain_table.fakedns = true
end
if outboundTag then
local b_add = true
if not rule.domain and not rule.domain_suffix and not rule.domain_keyword and not rule.domain_regex and not rule.rule_set then
-- No domain
b_add = nil
end
if outboundTag and b_add then
table.insert(dns_domain_rules, api.clone(domain_table))
end
end
@@ -59,6 +59,7 @@ function gen_outbound(flag, node, tag, proxy_table)
local remarks = node.remarks
local proxy_tag = nil
local dialer_proxy_tag = nil
local fragment = nil
local noise = nil
local run_socks_instance = true
@@ -97,12 +98,7 @@ function gen_outbound(flag, node, tag, proxy_table)
node.stream_security = "none"
proxy_tag = "socks <- " .. node_id
else
if proxy_tag then
node.proxySettings = {
tag = proxy_tag,
transportLayer = true
}
end
dialer_proxy_tag = proxy_tag
end
if node.type == "Xray" then
@@ -146,14 +142,13 @@ function gen_outbound(flag, node, tag, proxy_table)
_flag = flag,
_flag_proxy_tag = proxy_tag,
tag = tag,
proxySettings = node.proxySettings or nil,
protocol = node.protocol,
mux = {
enabled = (node.mux == "1") and true or false,
concurrency = (node.mux == "1" and ((node.mux_concurrency) and tonumber(node.mux_concurrency) or -1)) or nil,
xudpConcurrency = (node.mux == "1" and ((node.xudp_concurrency) and tonumber(node.xudp_concurrency) or 8)) or nil
} or nil,
streamSettings = (node.streamSettings or node.protocol == "vmess" or node.protocol == "vless" or node.protocol == "socks" or node.protocol == "shadowsocks" or node.protocol == "trojan" or node.protocol == "hysteria") and {
streamSettings = (node.streamSettings or dialer_proxy_tag or node.protocol == "vmess" or node.protocol == "vless" or node.protocol == "socks" or node.protocol == "shadowsocks" or node.protocol == "trojan" or node.protocol == "hysteria") and {
sockopt = {
mark = 255,
domainStrategy = node.domain_strategy or "UseIP",
@@ -164,7 +159,8 @@ function gen_outbound(flag, node, tag, proxy_table)
PrioritizeIPv6 = false,
Interleave = 1,
MaxConcurrentTry = 4
} or nil
} or nil,
dialerProxy = dialer_proxy_tag,
},
[(api.compare_versions(xray_version, "<", "26.7.11")) and "network" or "method"] = node.transport, -- Todo: Remove version check and "network"
security = node.stream_security,
@@ -1208,10 +1204,9 @@ function gen_config(var)
end
if preproxy_outbound then
outbound.tag = preproxy_outbound.tag .. " -> " .. outbound.tag
outbound.proxySettings = {
tag = preproxy_outbound.tag,
transportLayer = true
}
outbound.streamSettings = outbound.streamSettings or {}
outbound.streamSettings.sockopt = outbound.streamSettings.sockopt or {}
outbound.streamSettings.sockopt.dialerProxy = preproxy_outbound.tag
if not exist then
last_insert_outbound = preproxy_outbound
end
@@ -1259,10 +1254,9 @@ function gen_config(var)
if to_outbound then
to_outbound.tag = outbound.tag .. " -> " .. to_outbound.tag
if to_node.type == "Xray" then
to_outbound.proxySettings = {
tag = outbound.tag,
transportLayer = true
}
to_outbound.streamSettings = to_outbound.streamSettings or {}
to_outbound.streamSettings.sockopt = to_outbound.streamSettings.sockopt or {}
to_outbound.streamSettings.sockopt.dialerProxy = outbound.tag
end
table.insert(outbounds_table, to_outbound)
default_outTag = to_outbound.tag
@@ -1459,12 +1453,15 @@ function gen_config(var)
if inner_fakedns == "1" and node[e[".name"] .. "_fakedns"] == "1" and #domains > 0 then
domain_table.fakedns = true
end
if outboundTag then
table.insert(dns_domain_rules, api.clone(domain_table))
end
local b_add = true
if #domains == 0 then
-- No domain
b_add = nil
domains = nil
end
if outboundTag and b_add then
table.insert(dns_domain_rules, api.clone(domain_table))
end
end
local ip = nil
if e.ip_list then
@@ -1754,8 +1751,8 @@ function gen_config(var)
}
} or nil
},
proxySettings = {
tag = "direct"
streamSettings = {
sockopt = { dialerProxy = "direct" }
}
}
local remote_type_dns = {
@@ -1780,7 +1777,7 @@ function gen_config(var)
dns_outbound = {
tag = "dns-out",
protocol = "dns",
proxySettings = type_dns.proxySettings,
streamSettings = type_dns.streamSettings,
settings = type_dns.settings
}
table.insert(outbounds, dns_outbound)
@@ -2042,13 +2039,13 @@ function gen_config(var)
local direct_outbound = {
protocol = "freedom",
tag = "direct",
settings = {
domainStrategy = (direct_dns_query_strategy and direct_dns_query_strategy ~= "") and direct_dns_query_strategy or "UseIP",
settings = (api.compare_versions(xray_version, ">", "26.4.25")) and { -- Todo: Remove version check
finalRules = {{ action = "allow" }}
},
} or nil,
streamSettings = {
sockopt = {
mark = 255
mark = 255,
domainStrategy = (direct_dns_query_strategy and direct_dns_query_strategy ~= "") and direct_dns_query_strategy or "UseIP"
}
}
}
@@ -1,38 +0,0 @@
<%
local map = self.map
local api = map.api
local appname = map.config
local section = self.section
-%>
<script type="text/javascript">
//<![CDATA[
const shunt_list = JSON.parse('<%=self.shunt_list%>');
document.addEventListener("DOMContentLoaded", () => setTimeout(() => {
const hiddenSelect = document.getElementById("cbid.<%=appname%>.<%=section%>.node");
let o_val = hiddenSelect.value
const o_hasItem = shunt_list.find(element => element.id == o_val);
hiddenSelect.addEventListener("change", function(el){
let new_val = el.target.value
let new_hasItem = shunt_list.find(element => element.id == new_val);
new_hasItem = true;
if (new_hasItem) {
XHR.get('<%=api.url("update_config")%>', {
id: "<%=section%>",
data: JSON.stringify({
node: new_val
})
},
function(x, data) {
if (x && x.status == 200 && data.code == 1) {
window.location.reload();
}
else {
alert("<%:Error%>");
}
});
}
});
}, 100));
//]]>
</script>
@@ -14,11 +14,6 @@ local sid = "@global[0]"
}
}
.shunt-tab-hidden {
display: none !important;
visibility: hidden !important;
}
@media screen and (max-width: 1152px) {
#cbi-<%=appname%>-socks .cbi-section-table-titles {
display: none !important;
@@ -38,7 +33,6 @@ local sid = "@global[0]"
<script type="text/javascript">
//<![CDATA[
let global_id = "<%=sid%>";
const shunt_list = JSON.parse('<%=self.shunt_list%>');
function to_edit_node(btn, stype) {
if (!btn) return;
@@ -198,47 +192,5 @@ local sid = "@global[0]"
}
waitStable();
})();
document.addEventListener("DOMContentLoaded", () => setTimeout(() => {
const hiddenSelect = document.getElementById("cbid.<%=appname%>.<%=sid%>.node");
let o_val = hiddenSelect.value
const o_hasItem = shunt_list.find(element => element.id == o_val);
hiddenSelect.addEventListener("change", function(el){
let new_val = el.target.value
const new_hasItem = shunt_list.find(element => element.id == new_val);
if (new_hasItem) {
XHR.get('<%=api.url("update_config")%>', {
id: "<%=sid%>",
data: JSON.stringify({
node: new_val
})
},
function(x, data) {
if (x && x.status == 200 && data.code == 1) {
window.location.reload();
}
else {
alert("<%:Error%>");
}
});
} else {
try {
document.getElementById("tab.<%=appname%>.<%=sid%>.Shunt").classList.add('shunt-tab-hidden');
document.getElementById("tab.<%=appname%>.<%=sid%>.Shunt").style.display = "none";
} catch (error) {}
try {
document.querySelector('li[data-tab*="Shunt"]').classList.add('shunt-tab-hidden');
document.querySelector('li[data-tab*="Shunt"]').style.display = "none";
} catch (error) {}
}
});
let shunt_taboption = document.getElementById("container.<%=appname%>.<%=sid%>.Shunt");
if (shunt_taboption) {
let shunt_option_list = document.getElementById("cbi-<%=appname%>-shunt_option_list");
if (shunt_option_list) {
shunt_taboption.appendChild(shunt_option_list);
}
}
}, 100));
//]]>
</script>
@@ -0,0 +1,73 @@
<%
local map = self.map
local api = map.api
local config = map.config
local verify_option = self.verify_option
local section_id = verify_option.section.section
-%>
<% if verify_option then -%>
<script type="text/javascript">
//<![CDATA[
document.addEventListener("DOMContentLoaded", () => {
const shunt_list = JSON.parse('<%=self.shunt_list%>');
const dom_node_id = "<%=verify_option:cbid(section_id)%>";
let uci_node_val = "";
const onChange = (e) => {
const new_val = e.target.value;
const to_shunt = shunt_list.some(element => element.id == new_val);
if (to_shunt) {
const map = document.getElementById("cbi-<%=config%>");
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = 'node_save_before';
hiddenInput.value = uci_node_val;
map.appendChild(hiddenInput);
const saveBtn = document.getElementsByClassName('cbi-button-save');
if (saveBtn && saveBtn.length > 0) {
saveBtn[saveBtn.length - 1].click();
}
/*
XHR.get('<%=api.url("update_config")%>', {
id: "<%=section_id%>",
data: JSON.stringify({
node: new_val,
mode: "1"
})
}, function(x, data) {
if (x && x.status == 200 && data.code == 1) {
window.location.reload();
} else {
alert("<%:Error%>");
}
});
*/
} else {
try { shunt.hide(); } catch (error) {}
}
};
const check = () => {
const el = document.getElementById(dom_node_id);
if (!el) {
try { shunt.hide(); } catch (error) {}
return;
}
let is_shunt = shunt_list.some(element => element.id == el.value);
if (is_shunt) {
try { shunt.show(); } catch (error) {}
}
if (!el.hasEventListener) {
uci_node_val = el.value;
el.addEventListener("change", onChange);
el.hasEventListener = true;
}
};
const observer = new MutationObserver(check);
observer.observe(document.body, {
childList: true,
subtree: true
});
check();
});
//]]>
</script>
<%- end %>
@@ -2,18 +2,22 @@
local map = self.map
local api = map.api
local config = map.config
local id = self.id
local s_cfgid = self.s_cfgid
local node_id = self.node_id
local verify_option = self.verify_option
local section_id = self.section_id
local section_type = self.section_type
local tab_name = self.tab_name
-%>
<style>
.hidden {
.shunt_hidden {
display: none !important;
visibility: hidden !important;
}
</style>
<script type="text/javascript">
//<![CDATA[
const normal_list = JSON.parse('<%=self.normal_list%>');
var normal_list = JSON.parse('<%=self.normal_list%>');
function check_fakedns(id, val) {
const dom_id = "cbid.table." + id + ".";
const fakedns_dom = document.getElementById(dom_id + "_fakedns");
@@ -21,12 +25,14 @@ local s_cfgid = self.s_cfgid
const selectNode = document.getElementById(dom_id + "_node");
val = selectNode.value;
}
if (val == "" || val == "_direct") {
fakedns_dom.value = 0;
fakedns_dom.checked = false;
fakedns_dom.classList.add('hidden');
} else {
fakedns_dom.classList.remove('hidden');
if (fakedns_dom) {
if (val == "" || val == "_direct") {
fakedns_dom.value = 0;
fakedns_dom.checked = false;
fakedns_dom.classList.add('shunt_hidden');
} else {
fakedns_dom.classList.remove('shunt_hidden');
}
}
}
function check_proxy_tag(id, val) {
@@ -45,13 +51,13 @@ local s_cfgid = self.s_cfgid
const searchInput = document.getElementById(cbid + ".search");
const listContainer = document.getElementById(cbid + ".list");
lv_change(cbid, listContainer, hiddenSelect, labelSpan, searchInput, "", "<%:Close (Not use)%>");
proxy_tag_dom.classList.add('hidden');
proxy_tag_dom?.classList.add('shunt_hidden');
} else {
proxy_tag_dom.classList.remove('hidden');
proxy_tag_dom?.classList.remove('shunt_hidden');
}
}
function refresh_depends() {
const table_dom = document.getElementById("cbi-passwall2-shunt_option_list");
const table_dom = document.getElementById("cbi-<%=config%>-<%=section_type%>");
if (table_dom) {
const trs = table_dom.getElementsByTagName("tr");
for (let i = 1; i < trs.length;i++) {
@@ -60,40 +66,82 @@ local s_cfgid = self.s_cfgid
}
}
}
const shunt = {
tab() {
// Move the shunt options to Tab
<% if tab_name then -%>
const shunt_taboption = document.getElementById("container.<%=config%>.<%=section_id%>.<%=tab_name%>");
if (shunt_taboption) {
const shunt_option_list = document.getElementById("cbi-<%=config%>-<%=section_type%>");
if (shunt_option_list) {
shunt_taboption.appendChild(shunt_option_list);
}
}
<%- end %>
},
hide() {
document.getElementById("cbi-<%=config%>-<%=section_type%>")?.classList.add('shunt_hidden');
<% if tab_name then -%>
try { document.getElementById("tab.<%=config%>.<%=section_id%>.<%=tab_name%>")?.classList.add('shunt_hidden'); } catch (error) {}
try { document.querySelector('li[data-tab*="<%=tab_name%>"]')?.classList.add('shunt_hidden'); } catch (error) {}
const shunt_taboption = document.getElementById("container.<%=config%>.<%=section_id%>.<%=tab_name%>");
if (shunt_taboption) {
[...shunt_taboption.querySelectorAll('[name]')].forEach(el => {
const nameValue = el.getAttribute('name');
el.setAttribute('o-name', nameValue);
el.removeAttribute('name');
});
}
<%- end %>
},
show() {
document.getElementById("cbi-<%=config%>-<%=section_type%>")?.classList.remove('shunt_hidden');
<% if tab_name then -%>
try { document.getElementById("tab.<%=config%>.<%=section_id%>.<%=tab_name%>")?.classList.remove('shunt_hidden'); } catch (error) {}
try { document.querySelector('li[data-tab*="<%=tab_name%>"]')?.classList.remove('shunt_hidden'); } catch (error) {}
const shunt_taboption = document.getElementById("container.<%=config%>.<%=section_id%>.<%=tab_name%>");
if (shunt_taboption) {
[...shunt_taboption.querySelectorAll('[o-name]')].forEach(el => {
const nameValue = el.getAttribute('o-name');
el.setAttribute('name', nameValue);
el.removeAttribute('o-name');
});
}
<%- end %>
}
}
document.addEventListener("DOMContentLoaded", function () {
shunt.tab();
waitForElement('select[name*="<%=config%>"][name*="shunt_group"]', function(el) {
let o_val = el.value;
el.addEventListener("change", () => {
el.blur();
if (o_val != el.value) {
let save = true;
if (save) {
update_config("<%=id%>", {
shunt_group: getOption("<%=config%>", "<%=s_cfgid%>", "shunt_group").value,
}, get_current_url());
}
update_config("<%=node_id%>", {
shunt_group: getOption("<%=config%>", "<%=section_id%>", "shunt_group").value,
}, get_current_url());
}
});
});
});
document.addEventListener("DOMContentLoaded", () => setTimeout(() => {
refresh_depends();
const table_dom = document.getElementById("cbi-passwall2-shunt_option_list");
if (table_dom) {
const trs = table_dom.getElementsByTagName("tr");
for (let i = 1; i < trs.length;i++) {
const selectNode = document.getElementById("cbid.table." + i + "._node.main");
selectNode.addEventListener("change", function(el){
let new_val = el.target.value
check_fakedns(i, new_val);
check_proxy_tag(i, new_val);
});
if (i == trs.length - 1) {
const newArray = window.lv_dropdown_data["cbid.table." + i + "._node"].ungrouped.filter(item => item.key !== "_default");
window.lv_dropdown_data["cbid.table." + i + "._node"].ungrouped = newArray
setTimeout(() => {
refresh_depends();
const table_dom = document.getElementById("cbi-<%=config%>-<%=section_type%>");
if (table_dom) {
const trs = table_dom.getElementsByTagName("tr");
for (let i = 1; i < trs.length;i++) {
const selectNode = document.getElementById("cbid.table." + i + "._node.main");
selectNode.addEventListener("change", function(el){
let new_val = el.target.value
check_fakedns(i, new_val);
check_proxy_tag(i, new_val);
});
if (i == trs.length - 1) {
const newArray = window.lv_dropdown_data["cbid.table." + i + "._node"].ungrouped.filter(item => item.key !== "_default");
window.lv_dropdown_data["cbid.table." + i + "._node"].ungrouped = newArray
}
}
}
}
}, 100));
}, 200)
});
//]]>
</script>
@@ -35,27 +35,30 @@ local config = map.config
});
waitForElement('select[name*="<%=config%>"][name*="protocol"]', function(el) {
let o_val = el.value;
const name_split = el.name.split(".");
const name = name_split[name_split.length - 1];
el.addEventListener("change", () => {
el.blur();
if (el.value.startsWith("_") || (o_val.startsWith("_") && !el.value.startsWith("_"))) {
let name_split = el.name.split(".");
let name = name_split[name_split.length - 1];
let save = true;
if (save) {
/*
const saveBtn = document.getElementsByClassName('cbi-button-save');
if (saveBtn && saveBtn.length > 0) {
saveBtn[saveBtn.length - 1].click();
}
*/
update_config(node_id, {
remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value,
group: getOption("<%=config%>", "<%=sid%>", "group").value,
protocol: getOption("<%=config%>", "<%=sid%>", name).value,
}, node_config_url);
} else {
window.location.href = node_config_url + "?select_proto=" + encodeURIComponent(el.value);
if (el.value.startsWith("_")) {
const map = document.getElementById("cbi-<%=config%>");
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = 'load' + el.value;
hiddenInput.value = '1';
map.appendChild(hiddenInput);
}
const saveBtn = document.getElementsByClassName('cbi-button-save');
if (saveBtn && saveBtn.length > 0) {
saveBtn[saveBtn.length - 1].click();
}
/*
update_config(node_id, {
remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value,
group: getOption("<%=config%>", "<%=sid%>", "group").value,
protocol: getOption("<%=config%>", "<%=sid%>", name).value,
}, node_config_url);
*/
}
});
});
@@ -818,13 +818,6 @@ run_ipset_dnsmasq() {
}
acl_node() {
[ ! -f ${TMP_ACL_PATH}/acl_node_default ] && ENABLED_DEFAULT_ACL=0
local acl_node_num=$(jsonfilter -s "${acl_json}" -e '$.node_order[*]' | wc -l)
[ "${acl_node_num}" == 0 ] && {
ENABLED_DEFAULT_ACL=0
ENABLED_ACLS=0
return
}
[ "$(uci -q get dhcp.@dnsmasq[0].dns_redirect)" == "1" ] && {
uci -q set ${CONFIG}.@global[0].dnsmasq_dns_redirect='1'
uci -q commit ${CONFIG}
@@ -838,7 +831,7 @@ acl_node() {
local run_func
[ -n "${XRAY_BIN}" ] && run_func="run_xray"
[ -n "${SINGBOX_BIN}" ] && run_func="run_singbox"
for nid in $(jsonfilter -s "${acl_json}" -e '$.node_order[*]'); do
for nid in $(jsonfilter -s "${ACL_JSON}" -e '$.node_order[*]'); do
[ ! -f ${TMP_ACL_PATH}/acl_node_${nid} ] && continue
local _var=$(cat ${TMP_ACL_PATH}/acl_node_${nid} 2>/dev/null)
eval local ${_var}
@@ -917,8 +910,19 @@ start() {
nftflag=0
USE_TABLES=""
check_run_environment
[ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start
set_cache_var "USE_TABLES" "$USE_TABLES"
[ -n "$USE_TABLES" ] && {
ACL_JSON=$(lua $APP_PATH/app_acl.lua)
[ ! -f ${TMP_ACL_PATH}/acl_node_default ] && ENABLED_DEFAULT_ACL=0
local acl_node_num=$(jsonfilter -s "${ACL_JSON}" -e '$.node_order[*]' | wc -l)
if [ "${acl_node_num}" == 0 ]; then
ENABLED_DEFAULT_ACL=0
ENABLED_ACLS=0
else
source $APP_PATH/${USE_TABLES}.sh start
set_cache_var "USE_TABLES" "$USE_TABLES"
fi
}
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then
bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables)
set_cache_var "bak_bridge_nf_ipt" "$bridge_nf_ipt"
@@ -230,7 +230,7 @@ gen_shunt_list() {
}
[ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\"
[ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\"
set_cache_var "${node}_gen_shunt_list" "1"
set_cache_var "gen_shunt_list_${node}" "1"
}
add_shunt_t_rule() {
@@ -257,170 +257,16 @@ add_shunt_t_rule() {
load_acl() {
log_i18n 1 "Access Control:"
acl_json=$(lua $APP_PATH/app_acl.lua)
acl_node
for sid in $(jsonfilter -s "${acl_json}" -e '$.acl[*].flag'); do
for sid in $(jsonfilter -s "${ACL_JSON}" -e '$.acl[*].flag'); do
eval local $(cat "${TMP_ACL_PATH}/${sid}/var")
[ -z "$(get_cache_var "${node}_gen_shunt_list")" ] && [ -n "${node}" ] && gen_shunt_list "${node}" shunt_list4 shunt_list6
[ -z "$(get_cache_var "gen_shunt_list_${node}")" ] && [ -n "${node}" ] && gen_shunt_list "${node}" shunt_list4 shunt_list6
[ -n "${use}" ] && local dns_redirect_port=$(get_cache_var "ACL_${use}_dns_port")
local ipt_tmp=$ipt_n
[ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m
[ "${client_proxy}" = "1" ] && {
msg1="$(i18n "[%s]," "${remarks}")"
for i in $(cat ${TMP_ACL_PATH}/${sid}/source_list); do
local _ipt_source _ipv4
local msg
if [ -n "${interface}" ]; then
local gateway device
network_get_gateway gateway "${interface}"
network_get_device device "${interface}"
# network_get_device returns empty for non-UP interfaces (e.g. auto='0').
# Try ubus directly, then check if the name is a kernel device.
[ -z "${device}" ] && device=$(ubus call "network.interface.${interface}" status 2>/dev/null | jsonfilter -e '@.device' 2>/dev/null)
[ -z "${device}" ] && [ -d "/sys/class/net/${interface}" ] && device="${interface}"
[ -z "${device}" ] && device="${interface}"
_ipt_source="-i ${device} "
msg=$(i18n "Source iface [%s]," "${device}")
else
msg=$(i18n "Source iface [%s]," $(i18n "All"))
fi
if [ -n "$(echo ${i} | grep '^iprange:')" ]; then
_iprange=$(echo ${i} | sed 's#iprange:##g')
_ipt_source=$(factor ${_iprange} "${_ipt_source}-m iprange --src-range")
msg="${msg}$(i18n "IP range [%s]," "${_iprange}")"
_ipv4="1"
unset _iprange
elif [ -n "$(echo ${i} | grep '^ipset:')" ]; then
_ipset=$(echo ${i} | sed 's#ipset:##g')
msg="${msg}IPset$(i18n "[%s]," "${_ipset}")"
ipset -q list ${_ipset} >/dev/null
if [ $? -eq 0 ]; then
_ipt_source="${_ipt_source}-m set --match-set ${_ipset} src"
unset _ipset
else
log 2 "$(i18n "[%s]," "${remarks}")${msg}$(i18n "Does not exist, ignore.")"
unset _ipset
continue
fi
elif [ -n "$(echo ${i} | grep '^ip:')" ]; then
_ip=$(echo ${i} | sed 's#ip:##g')
_ipt_source=$(factor ${_ip} "${_ipt_source}-s")
msg="${msg}IP$(i18n "[%s]," "${_ip}")"
_ipv4="1"
unset _ip
elif [ -n "$(echo ${i} | grep '^mac:')" ]; then
_mac=$(echo ${i} | sed 's#mac:##g')
_ipt_source=$(factor ${_mac} "${_ipt_source}-m mac --mac-source")
msg="${msg}MAC$(i18n "[%s]," "${_mac}")"
unset _mac
elif [ -n "$(echo ${i} | grep '^any')" ]; then
msg="${msg}$(i18n "All device,")"
else
continue
fi
msg="${msg1}${msg}"
[ -n "$tcp_no_redir_ports" ] && {
if ! has_1_65535 "$tcp_no_redir_ports"; then
[ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN" 2>/dev/null
add_port_rules "$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN"
log 2 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${tcp_no_redir_ports}")"
else
# It will return when it ends, so no extra rules are needed.
no_tcp_proxy="1"
log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
fi
}
[ -n "$udp_no_redir_ports" ] && {
if ! has_1_65535 "$udp_no_redir_ports"; then
[ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" 2>/dev/null
add_port_rules "$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN"
log 2 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${udp_no_redir_ports}")"
else
# It will return when it ends, so no extra rules are needed.
no_udp_proxy="1"
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
fi
}
if ([ -z "$no_tcp_proxy" ] || [ -z "$no_udp_proxy" ]) && [ -n "$dns_redirect_port" ]; then
$ipt_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
log 2 "${msg}$(i18n "DNS will redirected to the dedicated DNS server [%s]." "${dns_redirect_port}")"
else
$ipt_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
fi
[ -z "$no_tcp_proxy" ] && [ -n "$redir_port" ] && {
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "${node_remarks}")"
if [ -n "${is_tproxy}" ]; then
msg2="${msg2}(TPROXY:${redir_port})"
ipt_j="-j PSW2_RULE"
else
msg2="${msg2}(REDIRECT:${redir_port})"
ipt_j="$(REDIRECT $redir_port)"
fi
[ "$accept_icmp" = "1" ] && {
$ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} -d $FAKE_IP $(REDIRECT)
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
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}
add_shunt_t_rule "${shunt_list4}" "$ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source}" "${ipt_j}" $tcp_redir_ports
add_port_rules "$ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_redir_ports "${ipt_j}"
[ -n "${is_tproxy}" ] && $ipt_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY)
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && {
$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} -d $FAKE_IP_6 -j PSW2_RULE 2>/dev/null
add_shunt_t_rule "${shunt_list6}" "$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source}" "${ipt_j}" $tcp_redir_ports 2>/dev/null
add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_redir_ports "-j PSW2_RULE" 2>/dev/null
$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY) 2>/dev/null
}
log 2 "${msg2}"
}
$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp -j RETURN
[ "$_ipv4" != "1" ] && $ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp -j RETURN 2>/dev/null
[ -z "$no_udp_proxy" ] && [ -n "$redir_port" ] && {
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "${node_remarks}")(TPROXY:${redir_port})"
$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP -j PSW2_RULE
add_shunt_t_rule "${shunt_list4}" "$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source}" "-j PSW2_RULE" $udp_redir_ports
add_port_rules "$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source}" $udp_redir_ports "-j PSW2_RULE"
$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(REDIRECT $redir_port TPROXY)
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && {
$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP_6 -j PSW2_RULE 2>/dev/null
add_shunt_t_rule "${shunt_list6}" "$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source}" "-j PSW2_RULE" $udp_redir_ports 2>/dev/null
add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source}" $udp_redir_ports "-j PSW2_RULE" 2>/dev/null
$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(REDIRECT $redir_port TPROXY) 2>/dev/null
}
log 2 "${msg2}"
}
$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp -j RETURN
[ "$_ipv4" != "1" ] && $ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp -j RETURN 2>/dev/null
unset ipt_j _ipt_source msg msg2 _ipv4 no_tcp_proxy no_udp_proxy
done
unset msg1
}
[ "${local_proxy}" = "1" ] && {
msg="$(i18n "[Local],")"
[ -n "$tcp_no_redir_ports" ] && {
@@ -443,9 +289,15 @@ load_acl() {
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
fi
}
local comment_l="$(i18n "Local")"
if [ -n "$node" ] && ([ -z "$no_tcp_local_proxy" ] || [ -z "$no_udp_local_proxy" ]); then
[ -n "$dns_redirect_port" ] && {
#$ipt_m -A PSW2_OUTPUT $(comment "${comment_l}") -p udp --dport 53 -j ACCEPT
#$ipt_m -A PSW2_OUTPUT $(comment "${comment_l}") -p tcp --dport 53 -j ACCEPT
#$ip6t_m -A PSW2_OUTPUT $(comment "${comment_l}") -p udp --dport 53 -j ACCEPT 2>/dev/null
#$ip6t_m -A PSW2_OUTPUT $(comment "${comment_l}") -p tcp --dport 53 -j ACCEPT 2>/dev/null
$ipt_n -A OUTPUT $(comment "PSW2_DNS") -p udp -o lo --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A OUTPUT $(comment "PSW2_DNS") -p udp -o lo --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
$ipt_n -A OUTPUT $(comment "PSW2_DNS") -p tcp -o lo --dport 53 -j REDIRECT --to-ports $dns_redirect_port
@@ -454,8 +306,6 @@ load_acl() {
}
fi
local comment_l="$(i18n "Local")"
# Loading local router proxy TCP
if [ -n "$node" ] && [ -z "$no_tcp_local_proxy" ]; then
[ "$accept_icmp" = "1" ] && {
@@ -544,13 +394,165 @@ load_acl() {
$ip6t_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -m mark --mark ${FWMARK} -j RETURN"
$ipt_m -I PSW2 -p tcp --dport 53 -j ACCEPT
$ipt_m -I PSW2 -p udp --dport 53 -j ACCEPT
$ip6t_m -I PSW2 -p tcp --dport 53 -j ACCEPT
$ip6t_m -I PSW2 -p udp --dport 53 -j ACCEPT
unset msg msg2 comment_l
}
[ "${client_proxy}" = "1" ] && {
msg1="$(i18n "[%s]," "${remarks}")"
for i in $(cat ${TMP_ACL_PATH}/${sid}/source_list); do
local _ipt_source _ipv4
local msg
if [ -n "${interface}" ]; then
local gateway device
network_get_gateway gateway "${interface}"
network_get_device device "${interface}"
# network_get_device returns empty for non-UP interfaces (e.g. auto='0').
# Try ubus directly, then check if the name is a kernel device.
[ -z "${device}" ] && device=$(ubus call "network.interface.${interface}" status 2>/dev/null | jsonfilter -e '@.device' 2>/dev/null)
[ -z "${device}" ] && [ -d "/sys/class/net/${interface}" ] && device="${interface}"
[ -z "${device}" ] && device="${interface}"
_ipt_source="-i ${device} "
msg=$(i18n "Source iface [%s]," "${device}")
else
msg=$(i18n "Source iface [%s]," $(i18n "All"))
fi
if [ -n "$(echo ${i} | grep '^iprange:')" ]; then
_iprange=$(echo ${i} | sed 's#iprange:##g')
_ipt_source=$(factor ${_iprange} "${_ipt_source}-m iprange --src-range")
msg="${msg}$(i18n "IP range [%s]," "${_iprange}")"
_ipv4="1"
unset _iprange
elif [ -n "$(echo ${i} | grep '^ipset:')" ]; then
_ipset=$(echo ${i} | sed 's#ipset:##g')
msg="${msg}IPset$(i18n "[%s]," "${_ipset}")"
ipset -q list ${_ipset} >/dev/null
if [ $? -eq 0 ]; then
_ipt_source="${_ipt_source}-m set --match-set ${_ipset} src"
unset _ipset
else
log 2 "$(i18n "[%s]," "${remarks}")${msg}$(i18n "Does not exist, ignore.")"
unset _ipset
continue
fi
elif [ -n "$(echo ${i} | grep '^ip:')" ]; then
_ip=$(echo ${i} | sed 's#ip:##g')
_ipt_source=$(factor ${_ip} "${_ipt_source}-s")
msg="${msg}IP$(i18n "[%s]," "${_ip}")"
_ipv4="1"
unset _ip
elif [ -n "$(echo ${i} | grep '^mac:')" ]; then
_mac=$(echo ${i} | sed 's#mac:##g')
_ipt_source=$(factor ${_mac} "${_ipt_source}-m mac --mac-source")
msg="${msg}MAC$(i18n "[%s]," "${_mac}")"
unset _mac
elif [ -n "$(echo ${i} | grep '^any')" ]; then
msg="${msg}$(i18n "All device,")"
else
continue
fi
msg="${msg1}${msg}"
[ -n "$tcp_no_redir_ports" ] && {
if ! has_1_65535 "$tcp_no_redir_ports"; then
[ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN" 2>/dev/null
add_port_rules "$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp" $tcp_no_redir_ports "-j RETURN"
log 2 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${tcp_no_redir_ports}")"
else
# It will return when it ends, so no extra rules are needed.
no_tcp_proxy="1"
log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
fi
}
[ -n "$udp_no_redir_ports" ] && {
if ! has_1_65535 "$udp_no_redir_ports"; then
[ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" 2>/dev/null
add_port_rules "$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN"
log 2 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${udp_no_redir_ports}")"
else
# It will return when it ends, so no extra rules are needed.
no_udp_proxy="1"
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
fi
}
if ([ -z "$no_tcp_proxy" ] || [ -z "$no_udp_proxy" ]) && [ -n "$dns_redirect_port" ]; then
$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j ACCEPT
$ipt_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j ACCEPT
$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j ACCEPT 2>/dev/null
$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j ACCEPT 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
log 2 "${msg}$(i18n "DNS will redirected to the dedicated DNS server [%s]." "${dns_redirect_port}")"
else
$ipt_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
fi
[ -z "$no_tcp_proxy" ] && [ -n "$redir_port" ] && {
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "${node_remarks}")"
if [ -n "${is_tproxy}" ]; then
msg2="${msg2}(TPROXY:${redir_port})"
ipt_j="-j PSW2_RULE"
else
msg2="${msg2}(REDIRECT:${redir_port})"
ipt_j="$(REDIRECT $redir_port)"
fi
[ "$accept_icmp" = "1" ] && {
$ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} -d $FAKE_IP $(REDIRECT)
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
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}
add_shunt_t_rule "${shunt_list4}" "$ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source}" "${ipt_j}" $tcp_redir_ports
add_port_rules "$ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_redir_ports "${ipt_j}"
[ -n "${is_tproxy}" ] && $ipt_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY)
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && {
$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} -d $FAKE_IP_6 -j PSW2_RULE 2>/dev/null
add_shunt_t_rule "${shunt_list6}" "$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source}" "${ipt_j}" $tcp_redir_ports 2>/dev/null
add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_redir_ports "-j PSW2_RULE" 2>/dev/null
$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(REDIRECT $redir_port TPROXY) 2>/dev/null
}
log 2 "${msg2}"
}
$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp -j RETURN
[ "$_ipv4" != "1" ] && $ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp -j RETURN 2>/dev/null
[ -z "$no_udp_proxy" ] && [ -n "$redir_port" ] && {
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "${node_remarks}")(TPROXY:${redir_port})"
$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP -j PSW2_RULE
add_shunt_t_rule "${shunt_list4}" "$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source}" "-j PSW2_RULE" $udp_redir_ports
add_port_rules "$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source}" $udp_redir_ports "-j PSW2_RULE"
$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(REDIRECT $redir_port TPROXY)
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && {
$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP_6 -j PSW2_RULE 2>/dev/null
add_shunt_t_rule "${shunt_list6}" "$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source}" "-j PSW2_RULE" $udp_redir_ports 2>/dev/null
add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source}" $udp_redir_ports "-j PSW2_RULE" 2>/dev/null
$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(REDIRECT $redir_port TPROXY) 2>/dev/null
}
log 2 "${msg2}"
}
$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp -j RETURN
[ "$_ipv4" != "1" ] && $ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp -j RETURN 2>/dev/null
unset ipt_j _ipt_source msg msg2 _ipv4 no_tcp_proxy no_udp_proxy
done
unset msg1
}
unset dns_redirect_port ipt_tmp
unset $(cat "${TMP_ACL_PATH}/${sid}/var" | awk -F '=' '{print $1}' | tr "\n" " ")
done
@@ -734,7 +736,7 @@ add_firewall_rule() {
$ipt_n -N PSW2_OUTPUT
$ipt_n -A PSW2_OUTPUT $(dst $IPSET_VPS) -j RETURN
$ipt_n -A PSW2_OUTPUT -m mark --mark 255 -j RETURN
$ipt_n -A PSW2_OUTPUT -m mark --mark 0xff/0xff -j RETURN
$ipt_n -N PSW2_DNS
if [ $(config_n_get @global[0] dns_redirect "1") = "0" ]; then
@@ -764,7 +766,7 @@ add_firewall_rule() {
$ipt_m -N PSW2_OUTPUT
$ipt_m -A PSW2_OUTPUT $(dst $IPSET_VPS) -j RETURN
$ipt_m -A PSW2_OUTPUT -m conntrack --ctdir REPLY -j RETURN
$ipt_m -A PSW2_OUTPUT -m mark --mark 255 -j RETURN
$ipt_m -A PSW2_OUTPUT -m mark --mark 0xff/0xff -j RETURN
ip rule add fwmark ${FWMARK} table 999 priority 999
ip route add local 0.0.0.0/0 dev lo table 999
@@ -776,7 +778,7 @@ add_firewall_rule() {
$ip6t_n -N PSW2_OUTPUT
$ip6t_n -A PSW2_OUTPUT $(dst $IPSET_VPS6) -j RETURN
$ip6t_n -A PSW2_OUTPUT -m mark --mark 255 -j RETURN
$ip6t_n -A PSW2_OUTPUT -m mark --mark 0xff/0xff -j RETURN
}
$ip6t_n -N PSW2_DNS
@@ -805,7 +807,7 @@ add_firewall_rule() {
insert_rule_before "$ip6t_m" "PREROUTING" "mwan3" "$(dst $IPSET_DIRECT6 !) -j PSW2"
$ip6t_m -N PSW2_OUTPUT
$ip6t_m -A PSW2_OUTPUT -m mark --mark 255 -j RETURN
$ip6t_m -A PSW2_OUTPUT -m mark --mark 0xff/0xff -j RETURN
$ip6t_m -A PSW2_OUTPUT $(dst $IPSET_VPS6) -j RETURN
$ip6t_m -A PSW2_OUTPUT -m conntrack --ctdir REPLY -j RETURN
@@ -271,7 +271,7 @@ gen_shunt_list() {
}
[ -n "${_SHUNT_LIST4}" ] && eval ${shunt_list4_var_name}=\"${_SHUNT_LIST4}\"
[ -n "${_SHUNT_LIST6}" ] && eval ${shunt_list6_var_name}=\"${_SHUNT_LIST6}\"
set_cache_var "${node}_gen_shunt_list" "1"
set_cache_var "gen_shunt_list_${node}" "1"
}
add_shunt_t_rule() {
@@ -295,163 +295,13 @@ add_shunt_t_rule() {
load_acl() {
log_i18n 1 "Access Control:"
acl_json=$(lua $APP_PATH/app_acl.lua)
acl_node
for sid in $(jsonfilter -s "${acl_json}" -e '$.acl[*].flag'); do
for sid in $(jsonfilter -s "${ACL_JSON}" -e '$.acl[*].flag'); do
eval $(cat "${TMP_ACL_PATH}/${sid}/var")
[ -z "$(get_cache_var "${node}_gen_shunt_list")" ] && [ -n "${node}" ] && gen_shunt_list "${node}" shunt_list4 shunt_list6
[ -z "$(get_cache_var "gen_shunt_list_${node}")" ] && [ -n "${node}" ] && gen_shunt_list "${node}" shunt_list4 shunt_list6
[ -n "${use}" ] && local dns_redirect_port=$(get_cache_var "ACL_${use}_dns_port")
[ "${client_proxy}" = "1" ] && {
msg1="$(i18n "[%s]," "${remarks}")"
for i in $(cat ${TMP_ACL_PATH}/${sid}/source_list); do
local _ipt_source _ipv4
local msg
if [ -n "${interface}" ]; then
local gateway device
network_get_gateway gateway "${interface}"
network_get_device device "${interface}"
# network_get_device returns empty for non-UP interfaces (e.g. auto='0').
# Try ubus directly, then check if the name is a kernel device.
[ -z "${device}" ] && device=$(ubus call "network.interface.${interface}" status 2>/dev/null | jsonfilter -e '@.device' 2>/dev/null)
[ -z "${device}" ] && [ -d "/sys/class/net/${interface}" ] && device="${interface}"
[ -z "${device}" ] && device="${interface}"
_ipt_source="iifname ${device} "
msg=$(i18n "Source iface [%s]," "${device}")
else
msg=$(i18n "Source iface [%s]," $(i18n "All"))
fi
if [ -n "$(echo ${i} | grep '^iprange:')" ]; then
_iprange=$(echo ${i} | sed 's#iprange:##g')
_ipt_source=$(factor ${_iprange} "${_ipt_source}ip saddr")
msg="${msg}$(i18n "IP range [%s]," "${_iprange}")"
_ipv4="1"
unset _iprange
elif [ -n "$(echo ${i} | grep '^ipset:')" ]; then
_ipset=$(echo ${i} | sed 's#ipset:##g')
_ipt_source="${_ipt_source}ip daddr @${_ipset}"
msg="${msg}Nftset$(i18n "[%s]," "${_ipset}")"
unset _ipset
elif [ -n "$(echo ${i} | grep '^ip:')" ]; then
_ip=$(echo ${i} | sed 's#ip:##g')
_ipt_source=$(factor ${_ip} "${_ipt_source}ip saddr")
msg="${msg}IP$(i18n "[%s]," "${_ip}")"
_ipv4="1"
unset _ip
elif [ -n "$(echo ${i} | grep '^mac:')" ]; then
_mac=$(echo ${i} | sed 's#mac:##g')
_ipt_source=$(factor ${_mac} "${_ipt_source}ether saddr")
msg="${msg}MAC$(i18n "[%s]," "${_mac}")"
unset _mac
elif [ -n "$(echo ${i} | grep '^any')" ]; then
msg="${msg}$(i18n "All device,")"
else
continue
fi
msg="${msg1}${msg}"
[ -n "$tcp_no_redir_ports" ] && {
if ! has_1_65535 "$tcp_no_redir_ports"; then
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ${_ipt_source} ip protocol tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\""
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ${_ipt_source} meta l4proto tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\""
log 2 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${tcp_no_redir_ports}")"
else
# It will return when it ends, so no extra rules are needed.
no_tcp_proxy="1"
log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
fi
}
[ -n "$udp_no_redir_ports" ] && {
if ! has_1_65535 "$udp_no_redir_ports"; then
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\""
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" 2>/dev/null
log 2 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${udp_no_redir_ports}")"
else
# It will return when it ends, so no extra rules are needed.
no_udp_proxy="1"
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
fi
}
if ([ -z "$no_tcp_proxy" ] || [ -z "$no_udp_proxy" ]) && [ -n "$dns_redirect_port" ]; then
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
log 2 "${msg}$(i18n "DNS will redirected to the dedicated DNS server [%s]." "${dns_redirect_port}")"
else
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
fi
[ -z "$no_tcp_proxy" ] && [ -n "$redir_port" ] && {
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "${node_remarks}")"
if [ -n "${is_tproxy}" ]; then
msg2="${msg2}(TPROXY:${redir_port})"
nft_chain="PSW2_MANGLE"
nft_j="counter jump PSW2_RULE"
else
msg2="${msg2}(REDIRECT:${redir_port})"
nft_chain="PSW2_NAT"
nft_j="$(REDIRECT $redir_port)"
fi
[ "$accept_icmp" = "1" ] && {
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} ip daddr $FAKE_IP $(REDIRECT) 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
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\""
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" ] && [ "$_ipv4" != "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\""
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
}
log 2 "${msg2}"
}
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp ${_ipt_source} counter return comment \"$remarks\""
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} counter return comment \"$remarks\"" 2>/dev/null
[ -z "$no_udp_proxy" ] && [ -n "$redir_port" ] && {
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "${node_remarks}")(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\""
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" ] && [ "$_ipv4" != "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\""
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" 2>/dev/null
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
}
log 2 "${msg2}"
}
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} counter return comment \"$remarks\""
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} counter return comment \"$remarks\"" 2>/dev/null
unset nft_chain nft_j _ipt_source msg msg2 _ipv4 no_tcp_proxy no_udp_proxy
done
unset msg1
}
[ "${local_proxy}" = "1" ] && {
msg="$(i18n "[Local],")"
[ -n "$tcp_no_redir_ports" ] && {
@@ -475,8 +325,14 @@ load_acl() {
fi
}
local comment_l="$(i18n "Local")"
if [ -n "$node" ] && ([ -z "$no_tcp_local_proxy" ] || [ -z "$no_udp_local_proxy" ]); then
[ -n "$dns_redirect_port" ] && {
#nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp udp dport 53 counter accept"
#nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol tcp tcp dport 53 counter accept"
#nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp udp dport 53 counter accept"
#nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto tcp tcp dport 53 counter accept"
nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$dns_redirect_port comment \"PSW2_DNS\""
nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$dns_redirect_port comment \"PSW2_DNS\""
nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$dns_redirect_port comment \"PSW2_DNS\""
@@ -485,8 +341,6 @@ load_acl() {
}
fi
local comment_l="$(i18n "Local")"
# Loading local router proxy TCP
if [ -n "$node" ] && [ -z "$no_tcp_local_proxy" ]; then
[ "$accept_icmp" = "1" ] && {
@@ -572,13 +426,161 @@ load_acl() {
nft "add rule $NFTABLE_NAME mangle_output oif lo counter return comment \"PSW2_OUTPUT_MANGLE\""
nft "add rule $NFTABLE_NAME mangle_output meta mark ${FWMARK} counter return comment \"PSW2_OUTPUT_MANGLE\""
nft "insert rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp tcp dport 53 counter accept"
nft "insert rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp udp dport 53 counter accept"
nft "insert rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp tcp dport 53 counter accept"
nft "insert rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp udp dport 53 counter accept"
unset msg msg2 comment_l
}
[ "${client_proxy}" = "1" ] && {
msg1="$(i18n "[%s]," "${remarks}")"
for i in $(cat ${TMP_ACL_PATH}/${sid}/source_list); do
local _ipt_source _ipv4
local msg
if [ -n "${interface}" ]; then
local gateway device
network_get_gateway gateway "${interface}"
network_get_device device "${interface}"
# network_get_device returns empty for non-UP interfaces (e.g. auto='0').
# Try ubus directly, then check if the name is a kernel device.
[ -z "${device}" ] && device=$(ubus call "network.interface.${interface}" status 2>/dev/null | jsonfilter -e '@.device' 2>/dev/null)
[ -z "${device}" ] && [ -d "/sys/class/net/${interface}" ] && device="${interface}"
[ -z "${device}" ] && device="${interface}"
_ipt_source="iifname ${device} "
msg=$(i18n "Source iface [%s]," "${device}")
else
msg=$(i18n "Source iface [%s]," $(i18n "All"))
fi
if [ -n "$(echo ${i} | grep '^iprange:')" ]; then
_iprange=$(echo ${i} | sed 's#iprange:##g')
_ipt_source=$(factor ${_iprange} "${_ipt_source}ip saddr")
msg="${msg}$(i18n "IP range [%s]," "${_iprange}")"
_ipv4="1"
unset _iprange
elif [ -n "$(echo ${i} | grep '^ipset:')" ]; then
_ipset=$(echo ${i} | sed 's#ipset:##g')
_ipt_source="${_ipt_source}ip daddr @${_ipset}"
msg="${msg}Nftset$(i18n "[%s]," "${_ipset}")"
unset _ipset
elif [ -n "$(echo ${i} | grep '^ip:')" ]; then
_ip=$(echo ${i} | sed 's#ip:##g')
_ipt_source=$(factor ${_ip} "${_ipt_source}ip saddr")
msg="${msg}IP$(i18n "[%s]," "${_ip}")"
_ipv4="1"
unset _ip
elif [ -n "$(echo ${i} | grep '^mac:')" ]; then
_mac=$(echo ${i} | sed 's#mac:##g')
_ipt_source=$(factor ${_mac} "${_ipt_source}ether saddr")
msg="${msg}MAC$(i18n "[%s]," "${_mac}")"
unset _mac
elif [ -n "$(echo ${i} | grep '^any')" ]; then
msg="${msg}$(i18n "All device,")"
else
continue
fi
msg="${msg1}${msg}"
[ -n "$tcp_no_redir_ports" ] && {
if ! has_1_65535 "$tcp_no_redir_ports"; then
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ${_ipt_source} ip protocol tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\""
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ${_ipt_source} meta l4proto tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\""
log 2 "${msg}$(i18n "not proxy %s port [%s]" "TCP" "${tcp_no_redir_ports}")"
else
# It will return when it ends, so no extra rules are needed.
no_tcp_proxy="1"
log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
fi
}
[ -n "$udp_no_redir_ports" ] && {
if ! has_1_65535 "$udp_no_redir_ports"; then
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\""
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" 2>/dev/null
log 2 "${msg}$(i18n "not proxy %s port [%s]" "UDP" "${udp_no_redir_ports}")"
else
# It will return when it ends, so no extra rules are needed.
no_udp_proxy="1"
log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
fi
}
if ([ -z "$no_tcp_proxy" ] || [ -z "$no_udp_proxy" ]) && [ -n "$dns_redirect_port" ]; then
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} udp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol tcp ${_ipt_source} tcp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} udp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} tcp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
log 2 "${msg}$(i18n "DNS will redirected to the dedicated DNS server [%s]." "${dns_redirect_port}")"
else
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
fi
[ -z "$no_tcp_proxy" ] && [ -n "$redir_port" ] && {
msg2="${msg}$(i18n "Use the %s node [%s]" "TCP" "${node_remarks}")"
if [ -n "${is_tproxy}" ]; then
msg2="${msg2}(TPROXY:${redir_port})"
nft_chain="PSW2_MANGLE"
nft_j="counter jump PSW2_RULE"
else
msg2="${msg2}(REDIRECT:${redir_port})"
nft_chain="PSW2_NAT"
nft_j="$(REDIRECT $redir_port)"
fi
[ "$accept_icmp" = "1" ] && {
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT ip protocol icmp ${_ipt_source} ip daddr $FAKE_IP $(REDIRECT) 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
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\""
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" ] && [ "$_ipv4" != "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\""
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
}
log 2 "${msg2}"
}
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp ${_ipt_source} counter return comment \"$remarks\""
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto tcp ${_ipt_source} counter return comment \"$remarks\"" 2>/dev/null
[ -z "$no_udp_proxy" ] && [ -n "$redir_port" ] && {
msg2="${msg}$(i18n "Use the %s node [%s]" "UDP" "${node_remarks}")(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\""
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" ] && [ "$_ipv4" != "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\""
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" 2>/dev/null
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
}
log 2 "${msg2}"
}
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} counter return comment \"$remarks\""
[ "$_ipv4" != "1" ] && nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 meta l4proto udp ${_ipt_source} counter return comment \"$remarks\"" 2>/dev/null
unset nft_chain nft_j _ipt_source msg msg2 _ipv4 no_tcp_proxy no_udp_proxy
done
unset msg1
}
unset dns_redirect_port
unset $(cat "${TMP_ACL_PATH}/${sid}/var" | awk -F '=' '{print $1}' | tr "\n" " ")
done
@@ -806,7 +808,7 @@ add_firewall_rule() {
nft "flush chain $NFTABLE_NAME PSW2_OUTPUT_MANGLE"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip daddr @$NFTSET_VPS counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ct direction reply counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE meta mark 255 counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE meta mark and 0xff == 0xff counter return"
# jump chains
# Only TCP, UDP Invalid.
@@ -824,7 +826,7 @@ add_firewall_rule() {
nft "add chain $NFTABLE_NAME PSW2_OUTPUT_NAT"
nft "flush chain $NFTABLE_NAME PSW2_OUTPUT_NAT"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_NAT ip daddr @$NFTSET_VPS counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_NAT meta mark 255 counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_NAT meta mark and 0xff == 0xff counter return"
}
#icmp ipv6-icmp redirect
@@ -860,7 +862,7 @@ add_firewall_rule() {
nft "flush chain $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ip6 daddr @$NFTSET_VPS6 counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 ct direction reply counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta mark 255 counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta mark and 0xff == 0xff counter return"
[ -n "$RETURN_DNS" ] && {
for _dns in $(echo $RETURN_DNS | tr ',' ' '); do
@@ -35,6 +35,7 @@ local function curl(url, file)
"--connect-timeout 3",
"--max-time 300",
"--speed-limit 51200 --speed-time 15",
"-H 'Accept: */*'",
'-A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36"',
"--dump-header -",
"-w '\\n%{http_code}'"
@@ -1979,7 +1979,7 @@ end
local function curl(url, file, ua, mode, hwid)
if not url or url == "" then return 22, 404 end
local curl_args = {
"-fskL", "-w %{http_code}", "--retry 3", "--connect-timeout 3", "-H 'Accept-Encoding: identity'"
"-fskL", "-w %{http_code}", "--retry 3", "--connect-timeout 3", "-H 'Accept: */*'", "-H 'Accept-Encoding: identity'"
}
if ua and ua ~= "" and ua ~= "curl" then
ua = (ua == "passwall2") and ("passwall2/" .. api.get_version()) or ua
@@ -276,20 +276,34 @@ return view.extend({
o.default = "4";
o.depends("autorate","1");
// cake-autorate types these by whether the value carries a decimal
// point (typeof float vs integer) and refuses to start an instance
// whose value has the wrong type, so always persist a float here.
var writeFloat = function(section_id, value) {
if (value != null && value !== '' && String(value).indexOf('.') < 0)
value = String(value) + '.0';
return form.Value.prototype.write.call(this, section_id, value);
};
o = s.taboption("tab_autorate", form.Value, "delay_thr_ms",_("delay threshold in ms:"));
o.default = "25.0";
o.datatype = 'ufloat';
o.write = writeFloat;
o.depends("autorate","1");
o = s.taboption("tab_autorate", form.Flag, "enable_sleep_function", _("Sleep functionnality"));
o = s.taboption("tab_autorate", form.Flag, "enable_sleep_functions", _("Sleep functionnality"));
o.default = true;
o.depends("autorate","1");
o = s.taboption("tab_autorate", form.Value, "connection_active_thr_kbps",_("Threshold in Kbit/s below which dl/ul is considered idle"));
o.default = "500";
o = s.taboption("tab_autorate", form.Value, "connection_active_thr_kpbs",_("Threshold in Kbit/s below which dl/ul is considered idle"));
o.default = "1000";
o.datatype = 'uinteger';
o.depends("autorate","1");
o = s.taboption("tab_autorate", form.Value, "substained_idle_sleep_thr_s",_("Time threshold to put pingers to sleep on substained dl/ul achieved rate < idle_threshold"));
o.default = "60";
o = s.taboption("tab_autorate", form.Value, "sustained_idle_sleep_thr",_("Time threshold to put pingers to sleep on substained dl/ul achieved rate < idle_threshold"));
o.default = "150.0";
o.datatype = 'ufloat';
o.write = writeFloat;
o.depends("autorate","1");
o = s.taboption("tab_autorate", form.Value, "startup_wait_s",_("Number of seconds to wait on startup:"));
@@ -297,6 +311,46 @@ return view.extend({
o.datatype = 'float'
o.depends("autorate","1");
o = s.taboption("tab_autorate", form.Flag, "congestion_sync", _("Sync bufferbloat threshold with congestion score"),
_("When enabled, this WAN's delay threshold is periodically tightened or relaxed to track omr-metrics' congestion score for this interface (loss, jitter, TC queue, signal quality) instead of relying only on cake-autorate's own delay measurement. This restarts this WAN's autorate instance whenever the threshold actually changes; other WANs are not affected. Turning it off restores the baseline delay threshold below on the next tracker cycle. Requires omr-metrics."));
o.default = false;
o.depends("autorate","1");
o = s.taboption("tab_autorate", form.Value, "congestion_sync_factor_moderate", _("Delay threshold factor at moderate congestion (score ≥40)"));
o.datatype = "and(ufloat,min(0))";
o.default = "0.75";
o.depends({ autorate: "1", congestion_sync: "1" });
o = s.taboption("tab_autorate", form.Value, "congestion_sync_factor_high", _("Delay threshold factor at high congestion (score ≥60)"));
o.datatype = "and(ufloat,min(0))";
o.default = "0.5";
o.depends({ autorate: "1", congestion_sync: "1" });
o = s.taboption("tab_autorate", form.Value, "congestion_sync_factor_severe", _("Delay threshold factor at severe congestion (score ≥80)"));
o.datatype = "and(ufloat,min(0))";
o.default = "0.3";
o.depends({ autorate: "1", congestion_sync: "1" });
o = s.taboption("tab_autorate", form.Value, "congestion_sync_min_delay_thr_ms", _("Minimum delay threshold this sync will ever set (ms)"));
o.datatype = "and(ufloat,min(0))";
o.default = "10.0";
o.depends({ autorate: "1", congestion_sync: "1" });
o = s.taboption("tab_autorate", form.Value, "congestion_sync_cooldown_s", _("Minimum time between two sync-triggered restarts (seconds)"));
o.datatype = "and(uinteger,min(0))";
o.default = "120";
o.depends({ autorate: "1", congestion_sync: "1" });
o = s.taboption("tab_autorate", form.Value, "congestion_sync_base_delay_thr_ms",
_("Baseline delay threshold (ms)"),
_("Captured automatically from \"delay threshold in ms\" the first time this is enabled; every target above is computed as a fraction of this value, which is never overwritten automatically afterwards. Clear this field to recapture it from the current delay threshold. It is kept when the sync is turned off so the delay threshold can be restored to it."));
o.datatype = "and(ufloat,min(0))";
o.depends({ autorate: "1", congestion_sync: "1" });
// Survive being hidden: 050-congestion-sync needs this value to
// restore delay_thr_ms after congestion_sync (or autorate) is turned
// off; without retain LuCI deletes it with the other hidden fields.
o.retain = true;
return m.render();
}
+1 -1
View File
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-wechatpush
PKG_VERSION:=3.6.12
PKG_RELEASE:=7
PKG_RELEASE:=8
PKG_MAINTAINER:=tty228 <tty228@yeah.net>
PKG_CONFIG_DEPENDS:= \
+1
View File
@@ -21,6 +21,7 @@
| :-------- | :----- | :----- |
| 微信 | Server酱 | https://sct.ftqq.com/
| 微信 | 推送加 | http://www.pushplus.plus/
| 微信等 | WPUSH | https://wpush.cn/
| 微信 | WxPusher | https://wxpusher.zjiecode.com/docs
| 企业微信 | 应用推送 | https://work.weixin.qq.com/api/doc/90000/90135/90248
| Telegram | bot | https://t.me/BotFather
+1
View File
@@ -22,6 +22,7 @@ Supported services:
| :-------- | :----- | :----- |
| WeChat | Server Chan | https://sct.ftqq.com/
| WeChat | PushPlus | http://www.pushplus.plus/
| WeChat etc. | WPUSH | https://wpush.cn/
| WeChat | WxPusher | https://wxpusher.zjiecode.com/docs
| WeChat for Enterprise | Application Push | https://work.weixin.qq.com/api/doc/90000/90135/90248
| Telegram | bot | https://t.me/BotFather
@@ -146,6 +146,8 @@ return view.extend({
_('Another channel for WeChat push, the configuration is relatively simple, and only supports official accounts'));
o.value('/usr/share/wechatpush/api/pushplus.json', _('pushplus'),
_('Another channel for WeChat push, the configuration is relatively simple, and it supports multiple push methods'));
o.value('/usr/share/wechatpush/api/wpush.json', _('WPUSH'),
_('Multi-channel push via WPUSH (WeChat, App, Feishu, DingTalk, and more). Success when response code===0'));
o.value('/usr/share/wechatpush/api/telegram.json', _('Telegram'),
_('Telegram Bot Push'));
o.value('/usr/share/wechatpush/api/msmtp.json', _('msmtp'),
@@ -222,6 +224,11 @@ return view.extend({
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/pushplus.json');
o = s.taboption('basic', form.Value, 'wpush_apikey', _('WPUSH apikey'));
o.description = _('Get Instructions') + ' <a href="https://wpush.cn/" target="_blank">' + _('Click here') + '</a>' + _('<br />API docs: https://docs.wpush.cn/docs/api/message.html — success when code===0');
o.rmempty = false;
o.depends('jsonpath', '/usr/share/wechatpush/api/wpush.json');
o = s.taboption('basic', form.Value, 'tg_token', _('Bot Token'));
o.description = _('Get Bot') + ' <a href="https://t.me/BotFather" target="_blank">' + _('Click here') + '</a>' + _('<br />Send a message to the created bot to initiate a conversation.');
o.rmempty = false;
@@ -311,6 +318,7 @@ return view.extend({
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_mpnews.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/wxpusher.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/pushplus.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/wpush.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/telegram.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/diy.json');
@@ -336,6 +344,7 @@ return view.extend({
o.depends('jsonpath', '/usr/share/wechatpush/api/qywx_mpnews.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/wxpusher.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/pushplus.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/wpush.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/telegram.json');
o.depends('jsonpath', '/usr/share/wechatpush/api/diy.json');
@@ -100,6 +100,22 @@ msgstr "微信推送的另一个通道,配置较简单,只支持公众号"
msgid "Another channel for WeChat push, the configuration is relatively simple, and it supports multiple push methods"
msgstr "微信推送的另一个通道,配置较简单,支持多项推送方式"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js
msgid "WPUSH"
msgstr "WPUSH"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js
msgid "Multi-channel push via WPUSH (WeChat, App, Feishu, DingTalk, and more). Success when response code===0"
msgstr "通过 WPUSH 多通道推送(微信、App、飞书、钉钉等)。成功判定为响应 code===0"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js
msgid "WPUSH apikey"
msgstr "WPUSH apikey"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js
msgid "<br />API docs: https://docs.wpush.cn/docs/api/message.html — success when code===0"
msgstr "<br />接口文档:https://docs.wpush.cn/docs/api/message.html — 成功时 code===0"
#: applications/luci-app-wechatpush/htdocs/luci-static/resources/view/wechatpush/config.js:146
msgid "Telegram Bot Push"
msgstr "Telegram bot 推送,若无梯子,请勿使用"
@@ -0,0 +1,21 @@
{
"_api": "这是 wpush api 文件",
"_api": "【wpush】",
"_readme": "成功判定:响应 JSON 的 application code===0(pushplus 为 code===200;本插件与 pushplus 相同,diy_send 仅检查 curl 退出码)",
"url": "https://api.wpush.cn/api/v1/send",
"data": "@${tempjsonpath}",
"content_type": "Content-Type: application/json",
"str_title_start": "##### ",
"str_title_end": "",
"str_linefeed": "\\n",
"str_splitline": "\\n----\\n",
"str_space": " ",
"str_tab": " ",
"type":
{
"title": "\"${1}\"",
"content": "\"${2}\"",
"apikey": "\"${wpush_apikey}\""
}
}
@@ -44,7 +44,7 @@ wait_and_cat() {
read_config() {
get_config \
"enable" "lite_enable" "device_name" "proxy_address" "sleeptime" "oui_data" "reset_regularly" "debuglevel" "lang" \
"jsonpath" "sckey" "sc3key" "sc3uid" "sc3tags" "corpid" "userid" "agentid" "corpsecret" "mediapath" "wxpusher_apptoken" "wxpusher_uids" "wxpusher_topicIds" "pushplus_token" "tg_api_server" "tg_token" "tg_chat_id" "tg_thread_id" "recipient_email" "smtp_host" "smtp_port" "smtp_tls" "smtp_starttls" "smtp_user" "smtp_passwordeval" "smtp_from" "smtp_from_full_name" \
"jsonpath" "sckey" "sc3key" "sc3uid" "sc3tags" "corpid" "userid" "agentid" "corpsecret" "mediapath" "wxpusher_apptoken" "wxpusher_uids" "wxpusher_topicIds" "pushplus_token" "wpush_apikey" "tg_api_server" "tg_token" "tg_chat_id" "tg_thread_id" "recipient_email" "smtp_host" "smtp_port" "smtp_tls" "smtp_starttls" "smtp_user" "smtp_passwordeval" "smtp_from" "smtp_from_full_name" \
"get_ipv4_mode" "ipv4_interface" "get_ipv6_mode" "ipv6_interface" \
"device_notification" "cpu_notification" "cpu_load_threshold" "temperature_threshold" \
"client_usage" "client_usage_max" "client_usage_disturb" "client_usage_whitelist" \
@@ -174,7 +174,7 @@ init() {
[ -z "$ip_version" ] && log_change "[ERROR] $(translate "Cannot get iputils-arping version, please confirm if plugin is running properly")"
[ -z "$cu_version" ] && log_change "[ERROR] $(translate "Cannot get curl version, please confirm if plugin is running properly")"
[ -n "$jsonpath" ] && [ -z "${sckey}${sc3key}${sc3uid}${sc3tags}${tg_token}${pushplus_token}${corpid}${wxpusher_apptoken}${wxpusher_uids}${wxpusher_topicIds}${recipient_email}" -a "${jsonpath}" != "/usr/share/wechatpush/api/diy.json" ] && log_change "[ERROR] $(translate "Please fill in the correct API key")" && return 1
[ -n "$jsonpath" ] && [ -z "${sckey}${sc3key}${sc3uid}${sc3tags}${tg_token}${pushplus_token}${wpush_apikey}${corpid}${wxpusher_apptoken}${wxpusher_uids}${wxpusher_topicIds}${recipient_email}" -a "${jsonpath}" != "/usr/share/wechatpush/api/diy.json" ] && log_change "[ERROR] $(translate "Please fill in the correct API key")" && return 1
local interfacelist=$(getinterfacelist) && [ -z "$interfacelist" ] && log_change "[WARN] $(translate "Multiple interfaces detected or configuration error, may not get interface uptime information, please confirm if plugin is running properly")"
@@ -2509,7 +2509,7 @@ send() {
if [ -z "$1" ] && (echo "$send_notification" | grep -q "router_status"); then
cat /proc/loadavg | awk '{print $1" "$2" "$3}' >"$output_dir/systemload" &
free -m | sed -n '2p' | awk '{printf "%.2f%%\n",($3/$2)*100}' >"$output_dir/mem_usage" &
curl -o /dev/null --connect-timeout 5 -s -w %{http_code} www.google.com >"$output_dir/Qwai" &
curl -o /dev/null --connect-timeout 5 -s -w %{http_code} https://www.google.com >"$output_dir/Qwai" &
system_uptime=$(cat /proc/uptime | awk '{print int($1)}')
[ -n "$system_uptime" ] && system_status_time=$(translate "Uptime: %dd %dh %dm %ds" "$((system_uptime / 86400))" "$(((system_uptime % 86400) / 3600))" "$(((system_uptime % 3600) / 60))" "$((system_uptime % 60))")
+3 -3
View File
@@ -15,12 +15,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-wwand
PKG_RELEASE:=13
PKG_RELEASE:=14
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/ddimension/luci-app-wwand.git
PKG_SOURCE_VERSION:=e519a102fe0e4849323781fcb2bdf1cd8946eaf7
PKG_SOURCE_DATE:=2026-09-07
PKG_SOURCE_VERSION:=8ac66dc263c430b6f81c55dd97133d83000c750a
PKG_SOURCE_DATE:=2026-09-09
PKG_MIRROR_HASH:=skip
PKG_LICENSE:=GPL-2.0-only
+1 -1
View File
@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=mptcp
PKG_VERSION:=6.1
PKG_RELEASE:=14
PKG_RELEASE:=15
PKG_MAINTAINER:=Ycarus (Yannick Chabanois) <ycarus@zugaina.org>
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+17 -17
View File
@@ -616,23 +616,23 @@ interface_multipath_settings() {
fi
if [ "$(uci -q get openmptcprouter.settings.force_multipath)" != "0" ] && [ -n "$(ip a show dev $iface | grep inet)" ]; then
if ([ "$mode" = "master" ] || [ "$mode" = "on" ]) && [ -z "$(multipath $iface | grep default)" ]; then
if [ "$(uci -q get openmptcprouter.${config}.state)" = "down" ]; then
# omr-tracker still considers this interface down (it only
# flips state to "up" once its recovery counter is
# satisfied): this reload was triggered by netifd's own
# ifup/link-up event, independent of that check, so keep the
# endpoint as backup instead of promoting it straight to
# master/on - the tracker's own post-tracking (003-up) will
# do the real promotion once recovery is actually confirmed.
# Prevents re-promoting a still-flaky WAN right after link
# recovery (issue #4355).
logger -t "MPTCP" "$iface tracker state is down, keep as backup instead of $mode from $(multipath $iface)"
multipath "$iface" "backup" "$id"
else
logger -t "MPTCP" "Set $iface to $mode from $(multipath $iface)"
multipath "$iface" "on" "$id"
fi
local tracker_state
tracker_state="$(uci -q get openmptcprouter.${config}.state)"
if [ "$tracker_state" = "down" ] && [ -n "$mode" ] && [ "$mode" != "off" ]; then
# omr-tracker still considers this interface down: it only flips state
# to "up" once its recovery counter (tries_up) is satisfied, and
# post-tracking's 002-error has already taken the endpoint out of
# MPTCP. This reload comes from netifd's own ifup/ifupdate/link-up
# event, which knows nothing about that check, so leave the endpoint
# alone instead of putting the interface back into MPTCP: adding it
# back - even as backup - makes the kernel keep opening subflows over
# a link OMR knows is dead, and on a flapping modem that re-add ran on
# every ifup (discussion #4368). 003-up adds the endpoint back in the
# configured mode as soon as the recovery is confirmed (issue #4355).
logger -t "MPTCP" "$iface tracker state is down, not adding it to MPTCP ($(multipath $iface))"
elif ([ "$mode" = "master" ] || [ "$mode" = "on" ]) && [ -z "$(multipath $iface | grep default)" ]; then
logger -t "MPTCP" "Set $iface to $mode from $(multipath $iface)"
multipath "$iface" "on" "$id"
elif ([ "$mode" = "off" ] || [ -z "$mode" ]) && [ -z "$(multipath $iface | grep deactivated)" ]; then
logger -t "MPTCP" "Set $iface to $mode from $(multipath $iface)"
multipath "$iface" "$mode" "$id"
+3 -3
View File
@@ -2,12 +2,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=proot
PKG_VERSION:=5.4.0
PKG_RELEASE:=3
PKG_VERSION:=5.4.1
PKG_RELEASE:=4
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/proot-me/proot.git
PKG_SOURCE_VERSION:=65f3f7dbc20776d6ccc1f0b49e6d560161ea384f
PKG_SOURCE_VERSION:=d4b49e2243dee34e41c13dfeca6a3d07e9cf0f00
include $(INCLUDE_DIR)/package.mk
include $(TOPDIR)/feeds/packages/lang/python/python3-version.mk
+1 -1
View File
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=sqm-autorate
PKG_VERSION:=0.1
PKG_RELEASE:=5
PKG_RELEASE:=6
include $(INCLUDE_DIR)/package.mk
@@ -22,4 +22,41 @@ uci -q batch <<-EOF >/dev/null
commit ucitrack
EOF
# Older luci-app-sqm-autorate wrote three autorate options under names
# config_template.sh never read, so whatever the user entered there was
# silently ignored. Carry each value over to the key the template actually
# reads (never clobbering one already set under the right name) and drop
# the dead key.
. /lib/functions.sh
_migrate_autorate_keys() {
local sec="$1" pair old new val cur
for pair in \
enable_sleep_function:enable_sleep_functions \
connection_active_thr_kbps:connection_active_thr_kpbs \
substained_idle_sleep_thr_s:sustained_idle_sleep_thr; do
old="${pair%%:*}"
new="${pair##*:}"
val="$(uci -q get "sqm.${sec}.${old}")"
[ -n "$val" ] || continue
cur="$(uci -q get "sqm.${sec}.${new}")"
if [ -z "$cur" ]; then
# cake-autorate types this one as a float and refuses to start
# an instance whose value has no decimal point.
if [ "$new" = "sustained_idle_sleep_thr" ]; then
case "$val" in
*.*) ;;
*) val="${val}.0" ;;
esac
fi
uci -q set "sqm.${sec}.${new}=${val}"
fi
uci -q delete "sqm.${sec}.${old}"
done
}
config_load sqm
config_foreach _migrate_autorate_keys queue
uci -q commit sqm
exit 0
@@ -8,8 +8,12 @@
# ubus call sqm-autorate set_config '{"section":"wan1","download":"50000","max_download":"80000","restart":true}'
# ubus call sqm-autorate get_metrics '{"section":"wan1"}'
# ubus call sqm-autorate get_metrics {}
# ubus call sqm-autorate restart_instance '{"section":"wan1"}'
CONFIG_DIR="/usr/share/sqm-autorate"
# Overridable for tests; production always uses the defaults below (same
# defaults launcher.sh uses, and for the same reason).
CONFIG_DIR="${SQM_AUTORATE_DIR:-/usr/share/sqm-autorate}"
RUN_DIR="${SQM_AUTORATE_RUN_DIR:-/var/run/sqm-autorate}"
# UCI options readable via get_config / settable via set_config -- mirrors
# what luci-app-sqm-autorate's sqm.js form exposes, plus the autorate-only
@@ -24,7 +28,11 @@ VALID_OPTIONS="enabled autorate interface download min_download max_download \
output_reflector_stats output_cake_changes debug sss_compensation pinger \
no_pingers reflector_ping_interval_s delay_thr_ms enable_sleep_functions \
connection_active_thr_kpbs sustained_idle_sleep_thr \
min_shaper_rates_enforcement startup_wait_s"
min_shaper_rates_enforcement startup_wait_s \
congestion_sync congestion_sync_base_delay_thr_ms \
congestion_sync_factor_moderate congestion_sync_factor_high \
congestion_sync_factor_severe congestion_sync_min_delay_thr_ms \
congestion_sync_cooldown_s"
_json_str() {
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
@@ -103,19 +111,56 @@ _metrics_json() {
"$(_json_str "$base_ul")" "$(_json_str "$min_ul")" "$(_json_str "$max_ul")" "$(_iface_metrics_json "$ul_if")"
}
# Ask launcher.sh to kill+respawn only this section's cake-autorate.sh
# instance, leaving every other WAN's warm state untouched (see
# launcher.sh's handle_restart_requests). Returns an error rather than
# silently no-op'ing when the service (or this one instance) isn't running,
# so callers can tell the difference from a successful restart.
_restart_instance() {
local sec="$1"
local config_file="${CONFIG_DIR}/config.${sec}.sh"
if [ ! -f "$config_file" ]; then
echo "{\"error\":\"no generated instance config for section '$(_json_str "$sec")' -- is autorate enabled for it?\"}"
return 1
fi
local launcher_pid=""
[ -f "${RUN_DIR}/launcher.pid" ] && read -r launcher_pid < "${RUN_DIR}/launcher.pid"
if [ -z "$launcher_pid" ] || ! kill -0 "$launcher_pid" 2>/dev/null; then
echo '{"error":"sqm-autorate launcher is not running -- use set_config with restart:true, or start the service"}'
return 1
fi
mkdir -p "${RUN_DIR}/restart-request"
: > "${RUN_DIR}/restart-request/${sec}"
kill -USR1 "$launcher_pid" 2>/dev/null
printf '{"result":"ok","section":"%s","restarted_instance":true}' "$(_json_str "$sec")"
}
case "$1" in
list)
echo '{
"get_config": { "section": "str" },
"set_config": { "section": "str", "restart": false },
"get_metrics": { "section": "str" }
"get_metrics": { "section": "str" },
"restart_instance": { "section": "str" }
}'
# get_config/get_metrics: omit "section" to get every sqm queue section.
# set_config: pass any subset of the known sqm option names alongside
# "section" (e.g. download, max_download, delay_thr_ms, ...); only
# recognised options are applied. restart=true also bounces the
# recognised options are applied. restart=true bounces the whole
# sqm-autorate service afterwards (regenerates and relaunches every
# instance -- there is no per-interface restart, see launcher.sh).
# instance). For a config change scoped to one WAN, prefer applying
# it with restart:false and then calling restart_instance for just
# that section instead -- it leaves every other WAN's cake-autorate
# instance (and its warm OWD baselines/shaper rate) untouched.
# restart_instance: signals launcher.sh to kill+respawn only the
# named section's cake-autorate.sh, re-reading sqm.<section>.* from
# UCI fresh (no live "reload config" path exists in cake-autorate
# itself, see docs/dev-guide.md).
;;
call)
@@ -206,6 +251,19 @@ case "$1" in
fi
;;
restart_instance)
section=$(echo "$input" | jsonfilter -q -e '@.section')
if [ -z "$section" ]; then
echo '{"error":"missing section parameter"}'
exit 1
fi
if ! _section_exists "$section"; then
echo "{\"error\":\"section '$(_json_str "$section")' not found in sqm config\"}"
exit 1
fi
_restart_instance "$section" || exit 1
;;
*)
echo '{"error":"unknown method"}'
exit 1
@@ -0,0 +1,174 @@
#
# Copyright (C) 2026 Yannick Chabanois for OpenMPTCProuter
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# Feeds omr-metrics' per-WAN congestion score (queuing delay, loss, jitter,
# TC backlog/ECN, BBR delivery gap, signal quality -- see 040-metrics in the
# omr-metrics package) into cake-autorate's own OWD-based bufferbloat
# threshold (sqm.<iface>.delay_thr_ms), instead of the two running as fully
# independent control loops: cake-autorate reacts sub-second to queuing
# delay it measures itself via ICMP timestamps, but has no visibility into
# loss/jitter/signal/TC-queue conditions omr-metrics already tracks, so a
# WAN that's degrading on those fronts without yet showing up as OWD delay
# only gets cake-autorate's normal (comparatively insensitive) threshold.
#
# cake-autorate.sh itself is never touched (see docs/dev-guide.md, it is
# treated as an upstream black box with no live "reload config" signal) --
# this only ever writes sqm.<iface>.delay_thr_ms via UCI and, when the
# change is significant enough, asks the sqm-autorate rpcd plugin's
# restart_instance to kill+respawn just that one WAN's cake-autorate
# instance so it re-reads the new value (every other WAN's instance, and
# its warm OWD baselines/shaper rate, is left untouched).
#
# Opt-in per WAN via: uci set sqm.<iface>.congestion_sync='1'
# (default off -- this periodically restarts the WAN's autorate instance).
# Turning it back off is handled here too: as long as a baseline is still
# recorded for the WAN, the next run restores delay_thr_ms to it (one
# restart), deletes the baseline, and stops -- so disabling the feature
# never leaves a WAN silently stuck at a tightened threshold.
#
# Tunables (all sqm.<iface>.*, all optional):
# congestion_sync_factor_moderate delay_thr_ms multiplier at congestion
# score >=40 (default 0.75)
# congestion_sync_factor_high ... at score >=60 (0.5)
# congestion_sync_factor_severe ... at score >=80 (0.3)
# congestion_sync_min_delay_thr_ms floor below which the threshold is
# never tightened (10.0)
# congestion_sync_cooldown_s minimum time between two sync-triggered
# restarts of this WAN's instance (120)
# congestion_sync_base_delay_thr_ms
# captured automatically (from the WAN's delay_thr_ms at the time
# congestion_sync was first turned on) as the un-tightened ceiling
# every target is computed from -- never itself overwritten by this
# script once set. To force a new baseline (e.g. after manually
# retuning bufferbloat sensitivity), clear this option; it is
# recaptured from the WAN's current delay_thr_ms on the next run.
# Deleted by this script itself only when it restores the baseline
# after congestion_sync was turned off (see above).
#
# Score bands mirror omr-metrics' own none/low/moderate/high/severe
# buckets (see 040-metrics' _compute_congestion); "none"/"low" always map
# to factor 1.0 (baseline, i.e. defer entirely to cake-autorate's own OWD
# measurement) rather than being independently configurable.
_iface="$OMR_TRACKER_INTERFACE"
[ -n "$_iface" ] || exit 0
[ "$OMR_TRACKER_STATUS" = "OK" ] || exit 0
# SQM_AUTORATE_DIR is overridable for tests; production always uses the
# real install path (same default launcher.sh/the rpcd plugin use).
config_file="${SQM_AUTORATE_DIR:-/usr/share/sqm-autorate}/config.${_iface}.sh"
last_action_file="${OMR_METRICS_DIR:-/tmp/metrics}/.${_iface}.sqm_congestion_sync"
# cake-autorate's config validation types delay_thr_ms as a float and
# rejects a value without a decimal point at instance startup, so every
# value this script writes goes through here first.
_norm() {
awk -v v="$1" 'BEGIN{printf "%.1f", v+0}'
}
_request_restart() {
# Only meaningful once autorate actually generated (and, in practice,
# launched) an instance for this WAN -- see sqm-autorate's init.d
# _config_autorate for the enabled/autorate/download/upload qualification.
[ -f "$config_file" ] || return 0
ubus call sqm-autorate restart_instance "{\"section\":\"${_iface}\"}" >/dev/null 2>&1
}
base="$(uci -q get "sqm.${_iface}.congestion_sync_base_delay_thr_ms")"
if [ "$(uci -q get "sqm.${_iface}.congestion_sync")" != "1" ]; then
# Feature off (or never on) for this WAN. A baseline still on record
# means it was on earlier and may have left delay_thr_ms tightened:
# put the baseline back exactly once and forget it. This deliberately
# runs before the instance-config check below so it also covers a WAN
# whose autorate was disabled outright (no config.<iface>.sh any more)
# -- the UCI value is fixed either way, the restart is simply skipped.
# sqm.js keeps congestion_sync_base_delay_thr_ms (retain) precisely so
# this path can still see it after the form hid it together with the
# other congestion_sync_* fields.
[ -n "$base" ] || exit 0
restore="$(_norm "$base")"
current="$(uci -q get "sqm.${_iface}.delay_thr_ms")"
uci -q delete "sqm.${_iface}.congestion_sync_base_delay_thr_ms"
if [ -n "$current" ] && [ "$(_norm "$current")" != "$restore" ]; then
uci -q set "sqm.${_iface}.delay_thr_ms=${restore}"
uci -q commit sqm
logger -t "sqm-autorate-congestion-sync" "interface ${_iface}: congestion sync disabled -- restoring delay_thr_ms ${current} -> ${restore}ms, requesting per-interface restart"
_request_restart
else
uci -q commit sqm
fi
rm -f "$last_action_file"
exit 0
fi
[ -f "$config_file" ] || exit 0
command -v jsonfilter >/dev/null 2>&1 || exit 0
metrics_file="${OMR_METRICS_DIR:-/tmp/metrics}/${_iface}.json"
[ -f "$metrics_file" ] || exit 0
score=$(jsonfilter -i "$metrics_file" -q -e '@.congestion.score' 2>/dev/null)
score_int="${score%%.*}"
case "$score_int" in ''|*[!0-9]*) exit 0 ;; esac
factor_severe="$(uci -q get "sqm.${_iface}.congestion_sync_factor_severe")"
factor_high="$(uci -q get "sqm.${_iface}.congestion_sync_factor_high")"
factor_moderate="$(uci -q get "sqm.${_iface}.congestion_sync_factor_moderate")"
: "${factor_severe:=0.3}" "${factor_high:=0.5}" "${factor_moderate:=0.75}"
if [ "$score_int" -ge 80 ]; then
band="severe"; factor="$factor_severe"
elif [ "$score_int" -ge 60 ]; then
band="high"; factor="$factor_high"
elif [ "$score_int" -ge 40 ]; then
band="moderate"; factor="$factor_moderate"
else
band="none"; factor="1.0"
fi
# Capture the ceiling this and every future target is computed from, once,
# the first time the feature runs for this WAN.
if [ -z "$base" ]; then
base="$(uci -q get "sqm.${_iface}.delay_thr_ms")"
[ -z "$base" ] && base="250.0" # config_template.sh's own fallback default
uci -q set "sqm.${_iface}.congestion_sync_base_delay_thr_ms=${base}"
uci -q commit sqm
fi
min_delay="$(uci -q get "sqm.${_iface}.congestion_sync_min_delay_thr_ms")"
: "${min_delay:=10.0}"
target=$(awk -v base="$base" -v factor="$factor" -v floor="$min_delay" 'BEGIN{v=base*factor; if (v<floor) v=floor; printf "%.1f", v}')
current="$(uci -q get "sqm.${_iface}.delay_thr_ms")"
[ -z "$current" ] && current="250.0"
current_norm="$(_norm "$current")"
# Nothing to do: already at the value this band calls for.
[ "$target" = "$current_norm" ] && exit 0
cooldown_s="$(uci -q get "sqm.${_iface}.congestion_sync_cooldown_s")"
: "${cooldown_s:=120}"
now=$(date +%s)
last_action=0
[ -f "$last_action_file" ] && read -r last_action < "$last_action_file" 2>/dev/null
case "$last_action" in ''|*[!0-9]*) last_action=0 ;; esac
if [ "$last_action" -gt 0 ] 2>/dev/null && [ $((now - last_action)) -lt "$cooldown_s" ]; then
exit 0
fi
uci -q set "sqm.${_iface}.delay_thr_ms=${target}"
uci -q commit sqm
logger -t "sqm-autorate-congestion-sync" "interface ${_iface}: congestion score ${score_int} (band ${band}) -- delay_thr_ms ${current_norm} -> ${target}ms, requesting per-interface restart"
_request_restart
printf '%s' "$now" > "$last_action_file"
exit 0
@@ -8,7 +8,7 @@
},
"write": {
"ubus": {
"sqm-autorate": [ "set_config" ]
"sqm-autorate": [ "set_config", "restart_instance" ]
}
}
}
@@ -1,26 +1,166 @@
#!/bin/bash
cake_instances=(/usr/share/sqm-autorate/config.*.sh)
cake_instance_pids=()
# launcher.sh spawns one cake-autorate.sh process per generated instance
# config (files/usr/share/sqm-autorate/config.<iface>.sh) and supervises
# them for the lifetime of the sqm-autorate service.
#
# Besides the original "kill everything on stop" behavior, it also acts as
# a minimal per-interface supervisor: on SIGUSR1 it looks for pending
# restart requests (one empty marker file per interface, dropped into
# RESTART_REQUEST_DIR by the sqm-autorate rpcd plugin's restart_instance
# call) and kills+respawns only the named interface's cake-autorate.sh,
# leaving every other WAN's instance -- and its warm OWD baselines/shaper
# rate history -- untouched. cake-autorate.sh itself is not modified for
# this: it is treated as an upstream black box (see docs/dev-guide.md);
# all of the per-interface reload logic lives here instead.
# Overridable for tests; production always uses the defaults below.
PREFIX="${SQM_AUTORATE_DIR:-/usr/share/sqm-autorate}"
RUN_DIR="${SQM_AUTORATE_RUN_DIR:-/var/run/sqm-autorate}"
RESTART_REQUEST_DIR="${RUN_DIR}/restart-request"
mkdir -p "${RESTART_REQUEST_DIR}"
rm -f "${RESTART_REQUEST_DIR}"/* 2>/dev/null
# interface -> pid / interface -> config file path
declare -A cake_instance_pids
declare -A cake_instance_configs
shutting_down=0
trap kill_cake_instances INT TERM EXIT
trap handle_restart_requests USR1
# Same derivation cake-autorate.sh itself uses for its own $INTERFACE
# (INTERFACE=$(basename "$1" | cut -d. -f2)), kept in sync with it.
config_iface()
{
basename "${1}" | cut -d. -f2
}
start_instance()
{
local config_file="${1}"
local iface
iface=$(config_iface "${config_file}")
"${PREFIX}/cake-autorate.sh" "${config_file}" &
cake_instance_pids["${iface}"]=${!}
cake_instance_configs["${iface}"]="${config_file}"
}
kill_cake_instances()
{
trap - INT TERM EXIT
trap - INT TERM EXIT USR1
shutting_down=1
echo "Killing all instances of cake one-by-one now."
for ((cake_instance=0; cake_instance<${#cake_instances[@]}; cake_instance++))
local iface
for iface in "${!cake_instance_pids[@]}"
do
kill "${cake_instance_pids[${cake_instance}]}" 2>/dev/null || true
kill "${cake_instance_pids[${iface}]}" 2>/dev/null || true
done
# Clean up state files before the (potentially longer) wait below, not
# after: the trap was just disarmed above, so a second incoming signal
# during `wait` would kill this process outright with the default TERM
# disposition, same as it always could here (this trap-disarm-first
# ordering predates this file's per-interface supervisor logic) --
# skipping straight to "exit" rather than reaching the rest of this
# function. Confirmed live: a real `/etc/init.d/sqm-autorate stop`
# killed every cake-autorate.sh child correctly but left launcher.pid
# and restart-request/ behind because the code below the wait never
# ran. Harmless on its own (restart_instance's kill -0 check already
# treats a dead pid as "not running", and the next start overwrites/
# clears both), but doing it first removes the gap entirely.
rm -f "${RUN_DIR}/launcher.pid"
rm -rf "${RESTART_REQUEST_DIR}"
wait
}
# Runs synchronously as a signal trap, interrupting any in-flight `wait -n`
# in the main loop below. Restarting is a plain kill + respawn: cake-autorate
# has no live "reload config" signal of its own (see docs/dev-guide.md), so
# the replacement process simply re-reads sqm.<iface>.* from UCI from
# scratch on start, same as any other fresh instance launch.
handle_restart_requests()
{
local request iface pid config_file
for request in "${RESTART_REQUEST_DIR}"/*
do
[[ -e "${request}" ]] || continue
iface=$(basename "${request}")
rm -f "${request}"
pid="${cake_instance_pids[${iface}]:-}"
config_file="${cake_instance_configs[${iface}]:-}"
if [[ -z "${pid}" || -z "${config_file}" ]]
then
echo "Restart requested for unknown/inactive interface: ${iface}. Ignoring."
continue
fi
echo "Restarting cake-autorate instance for interface: ${iface}."
# Remove from tracking before killing so the reconciliation pass in
# the main loop below doesn't treat this as an instance that died
# on its own (which is left dead, not auto-restarted -- see below).
unset "cake_instance_pids[${iface}]"
unset "cake_instance_configs[${iface}]"
kill "${pid}" 2>/dev/null || true
# cake-autorate's own cleanup_and_killall trap tears down its child
# processes (pingers, log file writer, ...) and removes its temp
# dir synchronously before the process itself exits, so waiting on
# it here ensures the replacement never races the old instance's
# own cleanup (e.g. both briefly touching the same tc qdisc).
wait "${pid}" 2>/dev/null || true
# A TERM/INT that landed while we were blocked in that wait ran
# kill_cake_instances *nested* inside this handler (bash runs a trap
# for a different signal from within a running trap). It has already
# taken every instance down and disarmed the traps, so respawning now
# would leave a fresh cake-autorate.sh nobody tracks or kills -- the
# main loop below exits straight away on shutting_down -- and the
# next service start would then double up on this WAN's qdisc.
# Reproduced by tests/test_010_launcher_supervisor.sh.
((shutting_down)) && return
[[ -f "${config_file}" ]] && start_instance "${config_file}"
done
}
# Only advertise our pid once the USR1 trap above is armed and its handler
# defined: a restart_instance landing before that would hit bash's default
# USR1 disposition and terminate the launcher outright.
printf '%s' "$$" > "${RUN_DIR}/launcher.pid"
cake_instances=("${PREFIX}"/config.*.sh)
for cake_instance in "${cake_instances[@]}"
do
/usr/share/sqm-autorate/cake-autorate.sh "${cake_instance}" &
cake_instance_pids+=(${!})
[[ -f "${cake_instance}" ]] && start_instance "${cake_instance}"
done
# Supervise: block until every tracked instance has exited. `wait -n` also
# returns (with an exit status >128) when interrupted by the USR1 trap
# above, in which case nothing has actually exited -- so every wakeup, for
# whatever reason, is followed by a reconciliation pass that prunes any pid
# no longer alive. An instance killed via handle_restart_requests is
# already removed from (and, on successful respawn, back in) the tracking
# arrays by the time this runs, so only instances that died on their own
# (crashed, or failed cake-autorate's config validation gate) get pruned
# here -- matching the original script's behavior of not auto-restarting a
# crashed instance.
while (( ${#cake_instance_pids[@]} > 0 ))
do
wait -n 2>/dev/null
((shutting_down)) && break
for iface in "${!cake_instance_pids[@]}"
do
kill -0 "${cake_instance_pids[${iface}]}" 2>/dev/null || {
unset "cake_instance_pids[${iface}]"
unset "cake_instance_configs[${iface}]"
}
done
done
wait
+5 -5
View File
@@ -43,12 +43,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=wwand
PKG_RELEASE:=28
PKG_RELEASE:=29
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/ddimension/wwand.git
PKG_SOURCE_VERSION:=8ae26ffec877e2b3cfc3440220f48cbf2b5e8186
PKG_SOURCE_DATE:=2026-09-07
PKG_SOURCE_VERSION:=6d91d2c332f5b796f0c954b496c0f45d377ae1c5
PKG_SOURCE_DATE:=2026-09-09
PKG_MIRROR_HASH:=skip
PKG_LICENSE:=GPL-2.0-only
@@ -201,13 +201,13 @@ define Package/wwand/install
# new_id bind / late kmodloader) re-kick a modem parked in no_at_port backoff
$(INSTALL_DIR) $(1)/etc/hotplug.d/tty
$(INSTALL_DATA) $(PKG_BUILD_DIR)/files/wwand.hotplug.tty $(1)/etc/hotplug.d/tty/20-wwand
# usb hotplug: bind qmi_wwan to the Huawei E1820's ethernet function. The
# usb hotplug: bind qmi_wwan to the Huawei E182E's ethernet function. The
# kernel hands the device to qmi_wwan (cdc_ether blacklists it) but its
# table entry wants a vendor-specific class this old 802.3 layout does not
# carry, so a scoped dynamic new_id is what makes the control channel appear
# at all — and it is volatile, so it has to be re-created on every replug.
$(INSTALL_DIR) $(1)/etc/hotplug.d/usb
$(INSTALL_DATA) $(PKG_BUILD_DIR)/files/wwand.hotplug.e1820 $(1)/etc/hotplug.d/usb/21-wwand-e1820
$(INSTALL_DATA) $(PKG_BUILD_DIR)/files/wwand.hotplug.e182e $(1)/etc/hotplug.d/usb/21-wwand-e182e
# NOTE: the kernel-wwan-subsystem hotplug (/etc/hotplug.d/wwan/20-wwand) is
# NOT installed here — it belongs to wwand-mhi, which also pulls the MHI
# drivers that create /sys/class/wwan in the first place (procd only arms a
+2 -2
View File
@@ -1,8 +1,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=Xray-core
PKG_VERSION:=26.9.8
PKG_RELEASE:=22
PKG_VERSION:=26.9.9
PKG_RELEASE:=23
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/XTLS/Xray-core/tar.gz/v$(PKG_VERSION)?