mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-06 19:46:52 +03:00
Compare commits
20 Commits
0.7.7
...
14f704fcb8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14f704fcb8 | ||
|
|
ff43f477e9 | ||
|
|
576e58fd17 | ||
|
|
7a497f1e31 | ||
|
|
d52f6e26ae | ||
|
|
68c61aed50 | ||
|
|
626ac981eb | ||
|
|
031c419ffb | ||
|
|
c13fdf5785 | ||
|
|
1b7ab606ba | ||
|
|
2bf208ecac | ||
|
|
e256e4bee5 | ||
|
|
32c385b309 | ||
|
|
56829c74c8 | ||
|
|
9d78cd2ce4 | ||
|
|
d9ce3b361e | ||
|
|
c67aadf267 | ||
|
|
ac4d7570f3 | ||
|
|
86897fd0af | ||
|
|
230ffbce46 |
@@ -81,4 +81,46 @@ trojan://ou8pLSyx9N@127.0.0.1:17737?type=httpupgrade&path=%2Fhttpupgradepath&hos
|
|||||||
|
|
||||||
# XHTTP
|
# XHTTP
|
||||||
trojan://VEetltxLtw@127.0.0.1:59072?type=xhttp&path=%2Fxhttppath&host=google.com&mode=auto&security=none#trojan-xhttp
|
trojan://VEetltxLtw@127.0.0.1:59072?type=xhttp&path=%2Fxhttppath&host=google.com&mode=auto&security=none#trojan-xhttp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hysteria2
|
||||||
|
|
||||||
|
hysteria2://
|
||||||
|
```
|
||||||
|
# Basic (no authentication)
|
||||||
|
hysteria2://127.0.0.1:443/#hysteria2-basic
|
||||||
|
hysteria2://127.0.0.1:443/?insecure=1#hysteria2-basic-insecure
|
||||||
|
|
||||||
|
# With password
|
||||||
|
hysteria2://password@example.com:443/#hysteria2-password
|
||||||
|
hysteria2://password@example.com:443/?insecure=0#hysteria2-password-insecure
|
||||||
|
|
||||||
|
# With SNI
|
||||||
|
hysteria2://password@example.com:443/?sni=example.com#hysteria2-password-sni
|
||||||
|
|
||||||
|
# With obfuscation
|
||||||
|
hysteria2://password@example.com:443/?obfs=salamander&obfs-password=obfspassword#hysteria2-obfs
|
||||||
|
|
||||||
|
# All parameters combined
|
||||||
|
hysteria2://mypassword@example.com:8443/?sni=example.com&obfs=salamander&obfs-password=obfspass&insecure=0#hysteria2-all-params
|
||||||
|
```
|
||||||
|
|
||||||
|
hy2://
|
||||||
|
```
|
||||||
|
# Basic (no authentication)
|
||||||
|
hy2://127.0.0.1:443/#hysteria2-basic
|
||||||
|
hy2://127.0.0.1:443/?insecure=1#hysteria2-basic-insecure
|
||||||
|
|
||||||
|
# With password
|
||||||
|
hy2://password@example.com:443/#hysteria2-password
|
||||||
|
hy2://password@example.com:443/?insecure=0#hysteria2-password-insecure
|
||||||
|
|
||||||
|
# With SNI
|
||||||
|
hy2://password@example.com:443/?sni=example.com#hysteria2-password-sni
|
||||||
|
|
||||||
|
# With obfuscation
|
||||||
|
hy2://password@example.com:443/?obfs=salamander&obfs-password=obfspassword#hysteria2-obfs
|
||||||
|
|
||||||
|
# All parameters combined
|
||||||
|
hy2://mypassword@example.com:8443/?sni=example.com&obfs=salamander&obfs-password=obfspass&insecure=0#hysteria2-all-params
|
||||||
```
|
```
|
||||||
@@ -41,6 +41,13 @@
|
|||||||
"src/podkop/tabs/diagnostic/checks/runNftCheck.ts:106"
|
"src/podkop/tabs/diagnostic/checks/runNftCheck.ts:106"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall.",
|
||||||
|
"key": "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall.",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Applicable for SOCKS and Shadowsocks proxy",
|
"call": "Applicable for SOCKS and Shadowsocks proxy",
|
||||||
"key": "Applicable for SOCKS and Shadowsocks proxy",
|
"key": "Applicable for SOCKS and Shadowsocks proxy",
|
||||||
@@ -101,14 +108,14 @@
|
|||||||
"call": "Cache File Path",
|
"call": "Cache File Path",
|
||||||
"key": "Cache File Path",
|
"key": "Cache File Path",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:329"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:348"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Cache file path cannot be empty",
|
"call": "Cache file path cannot be empty",
|
||||||
"key": "Cache file path cannot be empty",
|
"key": "Cache file path cannot be empty",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:343"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:362"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -178,7 +185,7 @@
|
|||||||
"call": "Config File Path",
|
"call": "Config File Path",
|
||||||
"key": "Config File Path",
|
"key": "Config File Path",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:316"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:335"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -276,14 +283,14 @@
|
|||||||
"call": "Disable QUIC",
|
"call": "Disable QUIC",
|
||||||
"key": "Disable QUIC",
|
"key": "Disable QUIC",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:265"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Disable the QUIC protocol to improve compatibility or fix issues with video streaming",
|
"call": "Disable the QUIC protocol to improve compatibility or fix issues with video streaming",
|
||||||
"key": "Disable the QUIC protocol to improve compatibility or fix issues with video streaming",
|
"key": "Disable the QUIC protocol to improve compatibility or fix issues with video streaming",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:266"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -365,7 +372,7 @@
|
|||||||
"call": "Dont Touch My DHCP!",
|
"call": "Dont Touch My DHCP!",
|
||||||
"key": "Dont Touch My DHCP!",
|
"key": "Dont Touch My DHCP!",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:307"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:326"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -387,22 +394,22 @@
|
|||||||
"call": "Download Lists via Proxy/VPN",
|
"call": "Download Lists via Proxy/VPN",
|
||||||
"key": "Download Lists via Proxy/VPN",
|
"key": "Download Lists via Proxy/VPN",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:269"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:288"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Download Lists via specific proxy section",
|
"call": "Download Lists via specific proxy section",
|
||||||
"key": "Download Lists via specific proxy section",
|
"key": "Download Lists via specific proxy section",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:278"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:297"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Downloading all lists via specific Proxy/VPN",
|
"call": "Downloading all lists via specific Proxy/VPN",
|
||||||
"key": "Downloading all lists via specific Proxy/VPN",
|
"key": "Downloading all lists via specific Proxy/VPN",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270",
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:289",
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:279"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:298"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -455,6 +462,13 @@
|
|||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:237"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:237"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Enable YACD WAN Access",
|
||||||
|
"key": "Enable YACD WAN Access",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Enter complete outbound configuration in JSON format",
|
"call": "Enter complete outbound configuration in JSON format",
|
||||||
"key": "Enter complete outbound configuration in JSON format",
|
"key": "Enter complete outbound configuration in JSON format",
|
||||||
@@ -515,14 +529,14 @@
|
|||||||
"call": "Exclude NTP",
|
"call": "Exclude NTP",
|
||||||
"key": "Exclude NTP",
|
"key": "Exclude NTP",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:365"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:384"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN",
|
"call": "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN",
|
||||||
"key": "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN",
|
"key": "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:385"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -838,7 +852,7 @@
|
|||||||
"call": "List Update Frequency",
|
"call": "List Update Frequency",
|
||||||
"key": "List Update Frequency",
|
"key": "List Update Frequency",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:276"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -977,21 +991,21 @@
|
|||||||
"call": "Path must be absolute (start with /)",
|
"call": "Path must be absolute (start with /)",
|
||||||
"key": "Path must be absolute (start with /)",
|
"key": "Path must be absolute (start with /)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:347"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Path must contain at least one directory (like /tmp/cache.db)",
|
"call": "Path must contain at least one directory (like /tmp/cache.db)",
|
||||||
"key": "Path must contain at least one directory (like /tmp/cache.db)",
|
"key": "Path must contain at least one directory (like /tmp/cache.db)",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:356"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:375"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Path must end with cache.db",
|
"call": "Path must end with cache.db",
|
||||||
"key": "Path must end with cache.db",
|
"key": "Path must end with cache.db",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:351"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:370"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1023,7 +1037,7 @@
|
|||||||
"call": "Podkop will not modify your DHCP configuration",
|
"call": "Podkop will not modify your DHCP configuration",
|
||||||
"key": "Podkop will not modify your DHCP configuration",
|
"key": "Podkop will not modify your DHCP configuration",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:308"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:327"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1093,7 +1107,7 @@
|
|||||||
"call": "Routing Excluded IPs",
|
"call": "Routing Excluded IPs",
|
||||||
"key": "Routing Excluded IPs",
|
"key": "Routing Excluded IPs",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:376"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:395"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1152,6 +1166,13 @@
|
|||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:328"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:328"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "Secret key for authenticating remote access to YACD when WAN access is enabled.",
|
||||||
|
"key": "Secret key for authenticating remote access to YACD when WAN access is enabled.",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "Sections",
|
"call": "Sections",
|
||||||
"key": "Sections",
|
"key": "Sections",
|
||||||
@@ -1184,7 +1205,7 @@
|
|||||||
"call": "Select how often the domain or subnet lists are updated automatically",
|
"call": "Select how often the domain or subnet lists are updated automatically",
|
||||||
"key": "Select how often the domain or subnet lists are updated automatically",
|
"key": "Select how often the domain or subnet lists are updated automatically",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:258"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:277"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1213,14 +1234,14 @@
|
|||||||
"call": "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing",
|
"call": "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing",
|
||||||
"key": "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing",
|
"key": "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:330"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:349"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"call": "Select path for sing-box config file. Change this ONLY if you know what you are doing",
|
"call": "Select path for sing-box config file. Change this ONLY if you know what you are doing",
|
||||||
"key": "Select path for sing-box config file. Change this ONLY if you know what you are doing",
|
"key": "Select path for sing-box config file. Change this ONLY if you know what you are doing",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:317"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:336"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1347,7 +1368,7 @@
|
|||||||
"call": "Specify a local IP address to be excluded from routing",
|
"call": "Specify a local IP address to be excluded from routing",
|
||||||
"key": "Specify a local IP address to be excluded from routing",
|
"key": "Specify a local IP address to be excluded from routing",
|
||||||
"places": [
|
"places": [
|
||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:377"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:396"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1702,6 +1723,13 @@
|
|||||||
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:330"
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:330"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"call": "YACD Secret Key",
|
||||||
|
"key": "YACD Secret Key",
|
||||||
|
"places": [
|
||||||
|
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:256"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"call": "You can select Output Network Interface, by default autodetect",
|
"call": "You can select Output Network Interface, by default autodetect",
|
||||||
"key": "You can select Output Network Interface, by default autodetect",
|
"key": "You can select Output Network Interface, by default autodetect",
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PODKOP\n"
|
"Project-Id-Version: PODKOP\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-10-27 11:15+0200\n"
|
"POT-Creation-Date: 2025-11-06 14:19+0200\n"
|
||||||
"PO-Revision-Date: 2025-10-27 11:15+0200\n"
|
"PO-Revision-Date: 2025-11-06 14:19+0200\n"
|
||||||
"Last-Translator: divocat <divocatt@gmail.com>\n"
|
"Last-Translator: divocat <divocatt@gmail.com>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"Language: \n"
|
"Language: \n"
|
||||||
@@ -40,6 +40,10 @@ msgstr ""
|
|||||||
msgid "Additional marking rules found"
|
msgid "Additional marking rules found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247
|
||||||
|
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:175
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:175
|
||||||
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -72,11 +76,11 @@ msgstr ""
|
|||||||
msgid "Browser is using FakeIP correctly"
|
msgid "Browser is using FakeIP correctly"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:329
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:348
|
||||||
msgid "Cache File Path"
|
msgid "Cache File Path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:343
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:362
|
||||||
msgid "Cache file path cannot be empty"
|
msgid "Cache file path cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -119,7 +123,7 @@ msgstr ""
|
|||||||
msgid "Community Lists"
|
msgid "Community Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:316
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:335
|
||||||
msgid "Config File Path"
|
msgid "Config File Path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -175,11 +179,11 @@ msgstr ""
|
|||||||
msgid "Disable autostart"
|
msgid "Disable autostart"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:265
|
||||||
msgid "Disable QUIC"
|
msgid "Disable QUIC"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:266
|
||||||
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -228,7 +232,7 @@ msgstr ""
|
|||||||
msgid "Domain Resolver"
|
msgid "Domain Resolver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:307
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:326
|
||||||
msgid "Dont Touch My DHCP!"
|
msgid "Dont Touch My DHCP!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -241,16 +245,16 @@ msgstr ""
|
|||||||
msgid "Download"
|
msgid "Download"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:269
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:288
|
||||||
msgid "Download Lists via Proxy/VPN"
|
msgid "Download Lists via Proxy/VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:278
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:297
|
||||||
msgid "Download Lists via specific proxy section"
|
msgid "Download Lists via specific proxy section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:289
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:279
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:298
|
||||||
msgid "Downloading all lists via specific Proxy/VPN"
|
msgid "Downloading all lists via specific Proxy/VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -283,6 +287,10 @@ msgstr ""
|
|||||||
msgid "Enable YACD"
|
msgid "Enable YACD"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246
|
||||||
|
msgid "Enable YACD WAN Access"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65
|
||||||
msgid "Enter complete outbound configuration in JSON format"
|
msgid "Enter complete outbound configuration in JSON format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -315,11 +323,11 @@ msgstr ""
|
|||||||
msgid "Every 5 minutes"
|
msgid "Every 5 minutes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:365
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:384
|
||||||
msgid "Exclude NTP"
|
msgid "Exclude NTP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:385
|
||||||
msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN"
|
msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -503,7 +511,7 @@ msgstr ""
|
|||||||
msgid "Latest"
|
msgid "Latest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:276
|
||||||
msgid "List Update Frequency"
|
msgid "List Update Frequency"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -585,15 +593,15 @@ msgstr ""
|
|||||||
msgid "Path cannot be empty"
|
msgid "Path cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:347
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366
|
||||||
msgid "Path must be absolute (start with /)"
|
msgid "Path must be absolute (start with /)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:356
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:375
|
||||||
msgid "Path must contain at least one directory (like /tmp/cache.db)"
|
msgid "Path must contain at least one directory (like /tmp/cache.db)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:351
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:370
|
||||||
msgid "Path must end with cache.db"
|
msgid "Path must end with cache.db"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -613,7 +621,7 @@ msgstr ""
|
|||||||
msgid "Podkop Settings"
|
msgid "Podkop Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:308
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:327
|
||||||
msgid "Podkop will not modify your DHCP configuration"
|
msgid "Podkop will not modify your DHCP configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -653,7 +661,7 @@ msgstr ""
|
|||||||
msgid "Router DNS is routed through sing-box"
|
msgid "Router DNS is routed through sing-box"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:376
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:395
|
||||||
msgid "Routing Excluded IPs"
|
msgid "Routing Excluded IPs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -689,6 +697,10 @@ msgstr ""
|
|||||||
msgid "Russia inside restrictions"
|
msgid "Russia inside restrictions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257
|
||||||
|
msgid "Secret key for authenticating remote access to YACD when WAN access is enabled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36
|
||||||
msgid "Sections"
|
msgid "Sections"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -705,7 +717,7 @@ msgstr ""
|
|||||||
msgid "Select DNS protocol to use"
|
msgid "Select DNS protocol to use"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:258
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:277
|
||||||
msgid "Select how often the domain or subnet lists are updated automatically"
|
msgid "Select how often the domain or subnet lists are updated automatically"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -722,11 +734,11 @@ msgstr ""
|
|||||||
msgid "Select or enter DNS server address"
|
msgid "Select or enter DNS server address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:330
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:349
|
||||||
msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing"
|
msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:317
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:336
|
||||||
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
|
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -799,7 +811,7 @@ msgstr ""
|
|||||||
msgid "Source Network Interface"
|
msgid "Source Network Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:377
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:396
|
||||||
msgid "Specify a local IP address to be excluded from routing"
|
msgid "Specify a local IP address to be excluded from routing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1014,6 +1026,10 @@ msgstr ""
|
|||||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:256
|
||||||
|
msgid "YACD Secret Key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127
|
||||||
msgid "You can select Output Network Interface, by default autodetect"
|
msgid "You can select Output Network Interface, by default autodetect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PODKOP\n"
|
"Project-Id-Version: PODKOP\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-10-27 13:15+0200\n"
|
"POT-Creation-Date: 2025-11-06 16:19+0200\n"
|
||||||
"PO-Revision-Date: 2025-10-27 13:15+0200\n"
|
"PO-Revision-Date: 2025-11-06 16:19+0200\n"
|
||||||
"Last-Translator: divocat\n"
|
"Last-Translator: divocat\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
@@ -35,6 +35,9 @@ msgstr "Активные соединения"
|
|||||||
msgid "Additional marking rules found"
|
msgid "Additional marking rules found"
|
||||||
msgstr "Найдены дополнительные правила маркировки"
|
msgstr "Найдены дополнительные правила маркировки"
|
||||||
|
|
||||||
|
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
|
||||||
|
msgstr "Обеспечивает доступ к YACD из WAN. Убедитесь, что в брандмауэре открыт соответствующий порт."
|
||||||
|
|
||||||
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
||||||
msgstr "Применимо для SOCKS и Shadowsocks прокси"
|
msgstr "Применимо для SOCKS и Shadowsocks прокси"
|
||||||
|
|
||||||
@@ -206,6 +209,9 @@ msgstr "Включить смешанный прокси-сервер, разр
|
|||||||
msgid "Enable YACD"
|
msgid "Enable YACD"
|
||||||
msgstr "Включить YACD"
|
msgstr "Включить YACD"
|
||||||
|
|
||||||
|
msgid "Enable YACD WAN Access"
|
||||||
|
msgstr "Включить доступ YACD WAN"
|
||||||
|
|
||||||
msgid "Enter complete outbound configuration in JSON format"
|
msgid "Enter complete outbound configuration in JSON format"
|
||||||
msgstr "Введите полную конфигурацию исходящего соединения в формате JSON"
|
msgstr "Введите полную конфигурацию исходящего соединения в формате JSON"
|
||||||
|
|
||||||
@@ -497,6 +503,9 @@ msgstr "Запустить диагностику"
|
|||||||
msgid "Russia inside restrictions"
|
msgid "Russia inside restrictions"
|
||||||
msgstr "Ограничения Russia inside"
|
msgstr "Ограничения Russia inside"
|
||||||
|
|
||||||
|
msgid "Secret key for authenticating remote access to YACD when WAN access is enabled."
|
||||||
|
msgstr "Секретный ключ для аутентификации удаленного доступа к YACD при включенном доступе через WAN."
|
||||||
|
|
||||||
msgid "Sections"
|
msgid "Sections"
|
||||||
msgstr "Секции"
|
msgstr "Секции"
|
||||||
|
|
||||||
@@ -722,5 +731,8 @@ msgstr "Предупреждение: %s нельзя использовать
|
|||||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
||||||
msgstr "Предупреждение: Russia inside может быть использован только с %s. %s уже есть в Russia inside и будет удален из выбранных."
|
msgstr "Предупреждение: Russia inside может быть использован только с %s. %s уже есть в Russia inside и будет удален из выбранных."
|
||||||
|
|
||||||
|
msgid "YACD Secret Key"
|
||||||
|
msgstr "Секретный ключ YACD"
|
||||||
|
|
||||||
msgid "You can select Output Network Interface, by default autodetect"
|
msgid "You can select Output Network Interface, by default autodetect"
|
||||||
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { getConfigSections } from './getConfigSections';
|
||||||
|
|
||||||
|
export async function getClashApiSecret() {
|
||||||
|
const sections = await getConfigSections();
|
||||||
|
|
||||||
|
const settings = sections.find((section) => section['.type'] === 'settings');
|
||||||
|
|
||||||
|
return settings?.yacd_secret_key || '';
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
import { getConfigSections } from './getConfigSections';
|
import { getConfigSections } from './getConfigSections';
|
||||||
import { getDashboardSections } from './getDashboardSections';
|
import { getDashboardSections } from './getDashboardSections';
|
||||||
|
import { getClashApiSecret } from './getClashApiSecret';
|
||||||
|
|
||||||
export const CustomPodkopMethods = {
|
export const CustomPodkopMethods = {
|
||||||
getConfigSections,
|
getConfigSections,
|
||||||
getDashboardSections,
|
getDashboardSections,
|
||||||
|
getClashApiSecret,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { CustomPodkopMethods, PodkopShellMethods } from '../../methods';
|
|||||||
import { logger, socket, store, StoreType } from '../../services';
|
import { logger, socket, store, StoreType } from '../../services';
|
||||||
import { renderSections, renderWidget } from './partials';
|
import { renderSections, renderWidget } from './partials';
|
||||||
import { fetchServicesInfo } from '../../fetchers';
|
import { fetchServicesInfo } from '../../fetchers';
|
||||||
|
import { getClashApiSecret } from '../../methods/custom/getClashApiSecret';
|
||||||
|
|
||||||
// Fetchers
|
// Fetchers
|
||||||
|
|
||||||
@@ -38,8 +39,10 @@ async function fetchDashboardSections() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function connectToClashSockets() {
|
async function connectToClashSockets() {
|
||||||
|
const clashApiSecret = await getClashApiSecret();
|
||||||
|
|
||||||
socket.subscribe(
|
socket.subscribe(
|
||||||
`${getClashWsUrl()}/traffic?token=`,
|
`${getClashWsUrl()}/traffic?token=${clashApiSecret}`,
|
||||||
(msg) => {
|
(msg) => {
|
||||||
const parsedMsg = JSON.parse(msg);
|
const parsedMsg = JSON.parse(msg);
|
||||||
|
|
||||||
@@ -68,7 +71,7 @@ async function connectToClashSockets() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
socket.subscribe(
|
socket.subscribe(
|
||||||
`${getClashWsUrl()}/connections?token=`,
|
`${getClashWsUrl()}/connections?token=${clashApiSecret}`,
|
||||||
(msg) => {
|
(msg) => {
|
||||||
const parsedMsg = JSON.parse(msg);
|
const parsedMsg = JSON.parse(msg);
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ export namespace Podkop {
|
|||||||
export type ConfigSection = ConfigBaseSection & {
|
export type ConfigSection = ConfigBaseSection & {
|
||||||
'.name': string;
|
'.name': string;
|
||||||
'.type': 'settings' | 'section';
|
'.type': 'settings' | 'section';
|
||||||
|
yacd_secret_key?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface MethodSuccessResponse<T> {
|
export interface MethodSuccessResponse<T> {
|
||||||
|
|||||||
@@ -731,10 +731,18 @@ async function getDashboardSections() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// src/podkop/methods/custom/getClashApiSecret.ts
|
||||||
|
async function getClashApiSecret() {
|
||||||
|
const sections = await getConfigSections();
|
||||||
|
const settings = sections.find((section) => section[".type"] === "settings");
|
||||||
|
return settings?.yacd_secret_key || "";
|
||||||
|
}
|
||||||
|
|
||||||
// src/podkop/methods/custom/index.ts
|
// src/podkop/methods/custom/index.ts
|
||||||
var CustomPodkopMethods = {
|
var CustomPodkopMethods = {
|
||||||
getConfigSections,
|
getConfigSections,
|
||||||
getDashboardSections
|
getDashboardSections,
|
||||||
|
getClashApiSecret
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/constants.ts
|
// src/constants.ts
|
||||||
@@ -1876,8 +1884,9 @@ async function fetchDashboardSections() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function connectToClashSockets() {
|
async function connectToClashSockets() {
|
||||||
|
const clashApiSecret = await getClashApiSecret();
|
||||||
socket.subscribe(
|
socket.subscribe(
|
||||||
`${getClashWsUrl()}/traffic?token=`,
|
`${getClashWsUrl()}/traffic?token=${clashApiSecret}`,
|
||||||
(msg) => {
|
(msg) => {
|
||||||
const parsedMsg = JSON.parse(msg);
|
const parsedMsg = JSON.parse(msg);
|
||||||
store.set({
|
store.set({
|
||||||
@@ -1904,7 +1913,7 @@ async function connectToClashSockets() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
socket.subscribe(
|
socket.subscribe(
|
||||||
`${getClashWsUrl()}/connections?token=`,
|
`${getClashWsUrl()}/connections?token=${clashApiSecret}`,
|
||||||
(msg) => {
|
(msg) => {
|
||||||
const parsedMsg = JSON.parse(msg);
|
const parsedMsg = JSON.parse(msg);
|
||||||
store.set({
|
store.set({
|
||||||
|
|||||||
@@ -445,7 +445,7 @@ function createSectionContent(section) {
|
|||||||
);
|
);
|
||||||
o.value("disabled", _("Disabled"));
|
o.value("disabled", _("Disabled"));
|
||||||
o.value("dynamic", _("Dynamic List"));
|
o.value("dynamic", _("Dynamic List"));
|
||||||
o.value("text", _("Text List (comma/space/newline separated)"));
|
o.value("text", _("Text List"));
|
||||||
o.default = "disabled";
|
o.default = "disabled";
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
|
|
||||||
|
|||||||
@@ -240,6 +240,25 @@ function createSettingsContent(section) {
|
|||||||
o.default = "0";
|
o.default = "0";
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
|
|
||||||
|
o = section.option(
|
||||||
|
form.Flag,
|
||||||
|
"enable_yacd_wan_access",
|
||||||
|
_("Enable YACD WAN Access"),
|
||||||
|
_("Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."),
|
||||||
|
);
|
||||||
|
o.depends("enable_yacd", "1");
|
||||||
|
o.default = "0";
|
||||||
|
o.rmempty = false;
|
||||||
|
|
||||||
|
o = section.option(
|
||||||
|
form.Value,
|
||||||
|
"yacd_secret_key",
|
||||||
|
_("YACD Secret Key"),
|
||||||
|
_("Secret key for authenticating remote access to YACD when WAN access is enabled."),
|
||||||
|
);
|
||||||
|
o.depends("enable_yacd_wan_access", "1");
|
||||||
|
o.rmempty = false;
|
||||||
|
|
||||||
o = section.option(
|
o = section.option(
|
||||||
form.Flag,
|
form.Flag,
|
||||||
"disable_quic",
|
"disable_quic",
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PODKOP\n"
|
"Project-Id-Version: PODKOP\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-10-27 13:15+0200\n"
|
"POT-Creation-Date: 2025-11-06 16:19+0200\n"
|
||||||
"PO-Revision-Date: 2025-10-27 13:15+0200\n"
|
"PO-Revision-Date: 2025-11-06 16:19+0200\n"
|
||||||
"Last-Translator: divocat\n"
|
"Last-Translator: divocat\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
@@ -35,6 +35,9 @@ msgstr "Активные соединения"
|
|||||||
msgid "Additional marking rules found"
|
msgid "Additional marking rules found"
|
||||||
msgstr "Найдены дополнительные правила маркировки"
|
msgstr "Найдены дополнительные правила маркировки"
|
||||||
|
|
||||||
|
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
|
||||||
|
msgstr "Обеспечивает доступ к YACD из WAN. Убедитесь, что в брандмауэре открыт соответствующий порт."
|
||||||
|
|
||||||
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
||||||
msgstr "Применимо для SOCKS и Shadowsocks прокси"
|
msgstr "Применимо для SOCKS и Shadowsocks прокси"
|
||||||
|
|
||||||
@@ -206,6 +209,9 @@ msgstr "Включить смешанный прокси-сервер, разр
|
|||||||
msgid "Enable YACD"
|
msgid "Enable YACD"
|
||||||
msgstr "Включить YACD"
|
msgstr "Включить YACD"
|
||||||
|
|
||||||
|
msgid "Enable YACD WAN Access"
|
||||||
|
msgstr "Включить доступ YACD WAN"
|
||||||
|
|
||||||
msgid "Enter complete outbound configuration in JSON format"
|
msgid "Enter complete outbound configuration in JSON format"
|
||||||
msgstr "Введите полную конфигурацию исходящего соединения в формате JSON"
|
msgstr "Введите полную конфигурацию исходящего соединения в формате JSON"
|
||||||
|
|
||||||
@@ -497,6 +503,9 @@ msgstr "Запустить диагностику"
|
|||||||
msgid "Russia inside restrictions"
|
msgid "Russia inside restrictions"
|
||||||
msgstr "Ограничения Russia inside"
|
msgstr "Ограничения Russia inside"
|
||||||
|
|
||||||
|
msgid "Secret key for authenticating remote access to YACD when WAN access is enabled."
|
||||||
|
msgstr "Секретный ключ для аутентификации удаленного доступа к YACD при включенном доступе через WAN."
|
||||||
|
|
||||||
msgid "Sections"
|
msgid "Sections"
|
||||||
msgstr "Секции"
|
msgstr "Секции"
|
||||||
|
|
||||||
@@ -681,10 +690,10 @@ msgid "URLTest Proxy Links"
|
|||||||
msgstr "Ссылки прокси для URLTest"
|
msgstr "Ссылки прокси для URLTest"
|
||||||
|
|
||||||
msgid "URLTest Testing URL"
|
msgid "URLTest Testing URL"
|
||||||
msgstr "URL для тестирования URLTest"
|
msgstr "URLTest ссылка для проверки"
|
||||||
|
|
||||||
msgid "URLTest Tolerance"
|
msgid "URLTest Tolerance"
|
||||||
msgstr "Порог переключения URLTest"
|
msgstr "URLTest допустимое отклонение"
|
||||||
|
|
||||||
msgid "User Domain List Type"
|
msgid "User Domain List Type"
|
||||||
msgstr "Тип пользовательского списка доменов"
|
msgstr "Тип пользовательского списка доменов"
|
||||||
@@ -722,5 +731,8 @@ msgstr "Предупреждение: %s нельзя использовать
|
|||||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
||||||
msgstr "Предупреждение: Russia inside может быть использован только с %s. %s уже есть в Russia inside и будет удален из выбранных."
|
msgstr "Предупреждение: Russia inside может быть использован только с %s. %s уже есть в Russia inside и будет удален из выбранных."
|
||||||
|
|
||||||
|
msgid "YACD Secret Key"
|
||||||
|
msgstr "Секретный ключ YACD"
|
||||||
|
|
||||||
msgid "You can select Output Network Interface, by default autodetect"
|
msgid "You can select Output Network Interface, by default autodetect"
|
||||||
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
msgstr "Вы можете выбрать выходной сетевой интерфейс, по умолчанию он определяется автоматически."
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PODKOP\n"
|
"Project-Id-Version: PODKOP\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-10-27 11:15+0200\n"
|
"POT-Creation-Date: 2025-11-06 14:19+0200\n"
|
||||||
"PO-Revision-Date: 2025-10-27 11:15+0200\n"
|
"PO-Revision-Date: 2025-11-06 14:19+0200\n"
|
||||||
"Last-Translator: divocat <divocatt@gmail.com>\n"
|
"Last-Translator: divocat <divocatt@gmail.com>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"Language: \n"
|
"Language: \n"
|
||||||
@@ -40,6 +40,10 @@ msgstr ""
|
|||||||
msgid "Additional marking rules found"
|
msgid "Additional marking rules found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247
|
||||||
|
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:175
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:175
|
||||||
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
msgid "Applicable for SOCKS and Shadowsocks proxy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -72,11 +76,11 @@ msgstr ""
|
|||||||
msgid "Browser is using FakeIP correctly"
|
msgid "Browser is using FakeIP correctly"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:329
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:348
|
||||||
msgid "Cache File Path"
|
msgid "Cache File Path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:343
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:362
|
||||||
msgid "Cache file path cannot be empty"
|
msgid "Cache file path cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -119,7 +123,7 @@ msgstr ""
|
|||||||
msgid "Community Lists"
|
msgid "Community Lists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:316
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:335
|
||||||
msgid "Config File Path"
|
msgid "Config File Path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -175,11 +179,11 @@ msgstr ""
|
|||||||
msgid "Disable autostart"
|
msgid "Disable autostart"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:265
|
||||||
msgid "Disable QUIC"
|
msgid "Disable QUIC"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:247
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:266
|
||||||
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -228,7 +232,7 @@ msgstr ""
|
|||||||
msgid "Domain Resolver"
|
msgid "Domain Resolver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:307
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:326
|
||||||
msgid "Dont Touch My DHCP!"
|
msgid "Dont Touch My DHCP!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -241,16 +245,16 @@ msgstr ""
|
|||||||
msgid "Download"
|
msgid "Download"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:269
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:288
|
||||||
msgid "Download Lists via Proxy/VPN"
|
msgid "Download Lists via Proxy/VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:278
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:297
|
||||||
msgid "Download Lists via specific proxy section"
|
msgid "Download Lists via specific proxy section"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:289
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:279
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:298
|
||||||
msgid "Downloading all lists via specific Proxy/VPN"
|
msgid "Downloading all lists via specific Proxy/VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -283,6 +287,10 @@ msgstr ""
|
|||||||
msgid "Enable YACD"
|
msgid "Enable YACD"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:246
|
||||||
|
msgid "Enable YACD WAN Access"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:65
|
||||||
msgid "Enter complete outbound configuration in JSON format"
|
msgid "Enter complete outbound configuration in JSON format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -315,11 +323,11 @@ msgstr ""
|
|||||||
msgid "Every 5 minutes"
|
msgid "Every 5 minutes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:365
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:384
|
||||||
msgid "Exclude NTP"
|
msgid "Exclude NTP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:385
|
||||||
msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN"
|
msgid "Exclude NTP protocol traffic from the tunnel to prevent it from being routed through the proxy or VPN"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -503,7 +511,7 @@ msgstr ""
|
|||||||
msgid "Latest"
|
msgid "Latest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:276
|
||||||
msgid "List Update Frequency"
|
msgid "List Update Frequency"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -585,15 +593,15 @@ msgstr ""
|
|||||||
msgid "Path cannot be empty"
|
msgid "Path cannot be empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:347
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:366
|
||||||
msgid "Path must be absolute (start with /)"
|
msgid "Path must be absolute (start with /)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:356
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:375
|
||||||
msgid "Path must contain at least one directory (like /tmp/cache.db)"
|
msgid "Path must contain at least one directory (like /tmp/cache.db)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:351
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:370
|
||||||
msgid "Path must end with cache.db"
|
msgid "Path must end with cache.db"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -613,7 +621,7 @@ msgstr ""
|
|||||||
msgid "Podkop Settings"
|
msgid "Podkop Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:308
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:327
|
||||||
msgid "Podkop will not modify your DHCP configuration"
|
msgid "Podkop will not modify your DHCP configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -653,7 +661,7 @@ msgstr ""
|
|||||||
msgid "Router DNS is routed through sing-box"
|
msgid "Router DNS is routed through sing-box"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:376
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:395
|
||||||
msgid "Routing Excluded IPs"
|
msgid "Routing Excluded IPs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -689,6 +697,10 @@ msgstr ""
|
|||||||
msgid "Russia inside restrictions"
|
msgid "Russia inside restrictions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:257
|
||||||
|
msgid "Secret key for authenticating remote access to YACD when WAN access is enabled."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:36
|
||||||
msgid "Sections"
|
msgid "Sections"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -705,7 +717,7 @@ msgstr ""
|
|||||||
msgid "Select DNS protocol to use"
|
msgid "Select DNS protocol to use"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:258
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:277
|
||||||
msgid "Select how often the domain or subnet lists are updated automatically"
|
msgid "Select how often the domain or subnet lists are updated automatically"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -722,11 +734,11 @@ msgstr ""
|
|||||||
msgid "Select or enter DNS server address"
|
msgid "Select or enter DNS server address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:330
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:349
|
||||||
msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing"
|
msgid "Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:317
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:336
|
||||||
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
|
msgid "Select path for sing-box config file. Change this ONLY if you know what you are doing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -799,7 +811,7 @@ msgstr ""
|
|||||||
msgid "Source Network Interface"
|
msgid "Source Network Interface"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:377
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:396
|
||||||
msgid "Specify a local IP address to be excluded from routing"
|
msgid "Specify a local IP address to be excluded from routing"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -1014,6 +1026,10 @@ msgstr ""
|
|||||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:256
|
||||||
|
msgid "YACD Secret Key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127
|
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:127
|
||||||
msgid "You can select Output Network Interface, by default autodetect"
|
msgid "You can select Output Network Interface, by default autodetect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ check_required_file "$PODKOP_LIB/helpers.sh"
|
|||||||
check_required_file "$PODKOP_LIB/sing_box_config_manager.sh"
|
check_required_file "$PODKOP_LIB/sing_box_config_manager.sh"
|
||||||
check_required_file "$PODKOP_LIB/sing_box_config_facade.sh"
|
check_required_file "$PODKOP_LIB/sing_box_config_facade.sh"
|
||||||
check_required_file "$PODKOP_LIB/logging.sh"
|
check_required_file "$PODKOP_LIB/logging.sh"
|
||||||
|
check_required_file "$PODKOP_LIB/rulesets.sh"
|
||||||
. /lib/config/uci.sh
|
. /lib/config/uci.sh
|
||||||
. /lib/functions.sh
|
. /lib/functions.sh
|
||||||
. "$PODKOP_LIB/constants.sh"
|
. "$PODKOP_LIB/constants.sh"
|
||||||
@@ -26,6 +27,7 @@ check_required_file "$PODKOP_LIB/logging.sh"
|
|||||||
. "$PODKOP_LIB/sing_box_config_manager.sh"
|
. "$PODKOP_LIB/sing_box_config_manager.sh"
|
||||||
. "$PODKOP_LIB/sing_box_config_facade.sh"
|
. "$PODKOP_LIB/sing_box_config_facade.sh"
|
||||||
. "$PODKOP_LIB/logging.sh"
|
. "$PODKOP_LIB/logging.sh"
|
||||||
|
. "$PODKOP_LIB/rulesets.sh"
|
||||||
|
|
||||||
config_load "$PODKOP_CONFIG"
|
config_load "$PODKOP_CONFIG"
|
||||||
|
|
||||||
@@ -123,19 +125,16 @@ start_main() {
|
|||||||
|
|
||||||
# base
|
# base
|
||||||
route_table_rule_mark
|
route_table_rule_mark
|
||||||
create_nft_table
|
create_nft_rules
|
||||||
sing_box_uci
|
sing_box_configure_service
|
||||||
|
|
||||||
# sing-box
|
# sing-box
|
||||||
sing_box_init_config
|
sing_box_init_config
|
||||||
config_foreach add_cron_job "section"
|
config_foreach add_cron_job "section"
|
||||||
/etc/init.d/sing-box start
|
/etc/init.d/sing-box start
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
local exclude_ntp
|
echolog "Failed to start sing-box service"
|
||||||
config_get_bool exclude_ntp "settings" "exclude_ntp" "0"
|
exit 1
|
||||||
if [ "$exclude_ntp" -eq 1 ]; then
|
|
||||||
log "NTP traffic exclude for proxy"
|
|
||||||
nft insert rule inet "$NFT_TABLE_NAME" mangle udp dport 123 return
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Nice"
|
log "Nice"
|
||||||
@@ -143,16 +142,6 @@ start_main() {
|
|||||||
echo $! > /var/run/podkop_list_update.pid
|
echo $! > /var/run/podkop_list_update.pid
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
|
||||||
start_main
|
|
||||||
config_get_bool dont_touch_dhcp "settings" "dont_touch_dhcp" 0
|
|
||||||
if [ "$dont_touch_dhcp" -eq 0 ]; then
|
|
||||||
dnsmasq_add_resolver
|
|
||||||
fi
|
|
||||||
uci_set "podkop" "settings" "shutdown_correctly" 0
|
|
||||||
uci commit "podkop" && config_load "$PODKOP_CONFIG"
|
|
||||||
}
|
|
||||||
|
|
||||||
stop_main() {
|
stop_main() {
|
||||||
log "Stopping the podkop"
|
log "Stopping the podkop"
|
||||||
|
|
||||||
@@ -188,13 +177,27 @@ stop_main() {
|
|||||||
/etc/init.d/sing-box stop
|
/etc/init.d/sing-box stop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
start_main
|
||||||
|
|
||||||
|
config_get_bool dont_touch_dhcp "settings" "dont_touch_dhcp" 0
|
||||||
|
if [ "$dont_touch_dhcp" -eq 0 ]; then
|
||||||
|
dnsmasq_configure
|
||||||
|
fi
|
||||||
|
|
||||||
|
uci_set "podkop" "settings" "shutdown_correctly" 0
|
||||||
|
uci commit "podkop" && config_load "$PODKOP_CONFIG"
|
||||||
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
local dont_touch_dhcp
|
local dont_touch_dhcp
|
||||||
config_get_bool dont_touch_dhcp "settings" "dont_touch_dhcp" 0
|
config_get_bool dont_touch_dhcp "settings" "dont_touch_dhcp" 0
|
||||||
if [ "$dont_touch_dhcp" -eq 0 ]; then
|
if [ "$dont_touch_dhcp" -eq 0 ]; then
|
||||||
dnsmasq_restore
|
dnsmasq_restore
|
||||||
fi
|
fi
|
||||||
|
|
||||||
stop_main
|
stop_main
|
||||||
|
|
||||||
uci_set "podkop" "settings" "shutdown_correctly" 1
|
uci_set "podkop" "settings" "shutdown_correctly" 1
|
||||||
uci commit "podkop" && config_load "$PODKOP_CONFIG"
|
uci commit "podkop" && config_load "$PODKOP_CONFIG"
|
||||||
}
|
}
|
||||||
@@ -279,7 +282,7 @@ nft_init_interfaces_set() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
create_nft_table() {
|
create_nft_rules() {
|
||||||
log "Create nft table"
|
log "Create nft table"
|
||||||
nft_create_table "$NFT_TABLE_NAME"
|
nft_create_table "$NFT_TABLE_NAME"
|
||||||
|
|
||||||
@@ -327,6 +330,13 @@ create_nft_table() {
|
|||||||
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "@$NFT_COMMON_SET_NAME" meta l4proto udp meta mark set 0x105 counter
|
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "@$NFT_COMMON_SET_NAME" meta l4proto udp meta mark set 0x105 counter
|
||||||
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "$SB_FAKEIP_INET4_RANGE" meta l4proto tcp meta mark set 0x105 counter
|
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "$SB_FAKEIP_INET4_RANGE" meta l4proto tcp meta mark set 0x105 counter
|
||||||
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "$SB_FAKEIP_INET4_RANGE" meta l4proto tcp meta mark set 0x105 counter
|
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "$SB_FAKEIP_INET4_RANGE" meta l4proto tcp meta mark set 0x105 counter
|
||||||
|
|
||||||
|
local exclude_ntp
|
||||||
|
config_get_bool exclude_ntp "settings" "exclude_ntp" "0"
|
||||||
|
if [ "$exclude_ntp" -eq 1 ]; then
|
||||||
|
log "NTP traffic exclude for proxy"
|
||||||
|
nft insert rule inet "$NFT_TABLE_NAME" mangle udp dport 123 return
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
backup_dnsmasq_config_option() {
|
backup_dnsmasq_config_option() {
|
||||||
@@ -340,7 +350,7 @@ backup_dnsmasq_config_option() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsmasq_add_resolver() {
|
dnsmasq_configure() {
|
||||||
local shutdown_correctly
|
local shutdown_correctly
|
||||||
config_get shutdown_correctly "settings" "shutdown_correctly"
|
config_get shutdown_correctly "settings" "shutdown_correctly"
|
||||||
if [ "$shutdown_correctly" -eq 0 ]; then
|
if [ "$shutdown_correctly" -eq 0 ]; then
|
||||||
@@ -472,42 +482,55 @@ remove_cron_job() {
|
|||||||
list_update() {
|
list_update() {
|
||||||
echolog "🔄 Starting lists update..."
|
echolog "🔄 Starting lists update..."
|
||||||
|
|
||||||
|
local nslookup_timeout=3
|
||||||
|
local nslookup_attempts=10
|
||||||
|
local curl_timeout=5
|
||||||
|
local curl_attempts=10
|
||||||
|
local curl_max_timeout=10
|
||||||
|
local delay=3
|
||||||
local i
|
local i
|
||||||
|
|
||||||
for i in $(seq 1 60); do
|
# DNS Check
|
||||||
if nslookup -timeout=1 openwrt.org > /dev/null 2>&1; then
|
for i in $(seq 1 $nslookup_timeout); do
|
||||||
|
if nslookup -timeout=$nslookup_timeout openwrt.org > /dev/null 2>&1; then
|
||||||
echolog "✅ DNS check passed"
|
echolog "✅ DNS check passed"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
log "DNS is unavailable [$i/60]"
|
echolog "DNS is unavailable [$i/$nslookup_attempts]"
|
||||||
sleep 3
|
sleep $delay
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$i" -eq 60 ]; then
|
if [ "$i" -eq $nslookup_attempts ]; then
|
||||||
echolog "❌ DNS check failed after 60 attempts"
|
echolog "❌ DNS check failed after $nslookup_attempts attempts"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for i in $(seq 1 60); do
|
# Github Check
|
||||||
config_get_bool download_lists_via_proxy "settings" "download_lists_via_proxy" "0"
|
for i in $(seq 1 $curl_attempts); do
|
||||||
if [ "$download_lists_via_proxy" -eq 1 ]; then
|
local service_proxy_address
|
||||||
if http_proxy="http://127.0.0.1:4534" https_proxy="http://127.0.0.1:4534" curl -s -m 3 https://github.com > /dev/null; then
|
service_proxy_address="$(get_service_proxy_address)"
|
||||||
|
|
||||||
|
if [ -n "$http_proxy_address" ]; then
|
||||||
|
if curl -s -x "http://$service_proxy_address" -m $curl_timeout https://github.com > /dev/null; then
|
||||||
echolog "✅ GitHub connection check passed (via proxy)"
|
echolog "✅ GitHub connection check passed (via proxy)"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if curl -s -m 3 https://github.com > /dev/null; then
|
if curl -s -m $curl_timeout https://github.com > /dev/null; then
|
||||||
echolog "✅ GitHub connection check passed"
|
echolog "✅ GitHub connection check passed"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echolog "GitHub is unavailable [$i/60]"
|
echolog "GitHub is unavailable [$i/$curl_attempts] (max-timeout=$curl_timeout)"
|
||||||
sleep 3
|
if [ "$curl_timeout" -lt $curl_max_timeout ]; then
|
||||||
|
curl_timeout=$((curl_timeout + 1))
|
||||||
|
fi
|
||||||
|
sleep $delay
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$i" -eq 60 ]; then
|
if [ "$i" -eq $curl_attempts ]; then
|
||||||
echolog "❌ GitHub connection check failed after 60 attempts"
|
echolog "❌ GitHub connection check failed after $curl_attempts attempts"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -525,30 +548,30 @@ list_update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# sing-box funcs
|
# sing-box funcs
|
||||||
|
sing_box_configure_service() {
|
||||||
sing_box_uci() {
|
|
||||||
local sing_box_enabled sing_box_user sing_box_config_path sing_box_conffile
|
local sing_box_enabled sing_box_user sing_box_config_path sing_box_conffile
|
||||||
sing_box_enabled=$(uci get "sing-box.main.enabled")
|
sing_box_enabled="$(uci_get "sing-box" "main" "enabled")"
|
||||||
sing_box_user=$(uci get "sing-box.main.user")
|
sing_box_user="$(uci_get "sing-box" "main" "user")"
|
||||||
|
|
||||||
if [ "$sing_box_enabled" -ne 1 ]; then
|
if [ "$sing_box_enabled" -ne 1 ]; then
|
||||||
uci set "sing-box.main.enabled=1"
|
uci_set "sing-box" "main" "enabled" 1
|
||||||
uci commit "sing-box"
|
uci_commit "sing-box"
|
||||||
log "sing-box service has been enabled"
|
log "sing-box service has been enabled"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$sing_box_user" != "root" ]; then
|
if [ "$sing_box_user" != "root" ]; then
|
||||||
uci set "sing-box.main.user=root"
|
uci_set "sing-box" "main" "user" "root"
|
||||||
uci commit "sing-box"
|
uci_commit "sing-box"
|
||||||
log "sing-box service user has been changed to root"
|
log "sing-box service user has been changed to root"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
config_get sing_box_config_path "settings" "config_path"
|
config_get sing_box_config_path "settings" "config_path"
|
||||||
sing_box_conffile=$(uci get "sing-box.main.conffile")
|
sing_box_conffile="$(uci_get "sing-box" "main" "conffile")"
|
||||||
log "sing-box config path: $sing_box_config_path" "debug"
|
log "sing-box config path: $sing_box_config_path" "debug"
|
||||||
log "sing-box service conffile: $sing_box_conffile" "debug"
|
log "sing-box service conffile: $sing_box_conffile" "debug"
|
||||||
if [ "$sing_box_conffile" != "$sing_box_config_path" ]; then
|
if [ "$sing_box_conffile" != "$sing_box_config_path" ]; then
|
||||||
uci set "sing-box.main.conffile=$sing_box_config_path"
|
uci_set "sing-box" "main" "conffile" "$sing_box_config_path"
|
||||||
uci commit "sing-box"
|
uci_commit "sing-box"
|
||||||
log "Configuration file path has been set to $sing_box_config_path"
|
log "Configuration file path has been set to $sing_box_config_path"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -865,66 +888,37 @@ configure_routing_for_section_lists() {
|
|||||||
|
|
||||||
if [ "$user_domain_list_type" != "disabled" ]; then
|
if [ "$user_domain_list_type" != "disabled" ]; then
|
||||||
log "Processing user domains routing rules for '$section' section"
|
log "Processing user domains routing rules for '$section' section"
|
||||||
prepare_common_ruleset "$section" "domains" "$route_rule_tag"
|
configure_user_domain_list "$section" "$route_rule_tag"
|
||||||
configure_user_domain_or_subnets_list "$section" "domains" "$route_rule_tag"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$user_subnet_list_type" != "disabled" ]; then
|
if [ "$user_subnet_list_type" != "disabled" ]; then
|
||||||
log "Processing user subnets routing rules for '$section' section"
|
log "Processing user subnets routing rules for '$section' section"
|
||||||
prepare_common_ruleset "$section" "subnets" "$route_rule_tag"
|
configure_user_subnet_list "$section" "$route_rule_tag"
|
||||||
configure_user_domain_or_subnets_list "$section" "subnets" "$route_rule_tag"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$local_domain_lists" ]; then
|
if [ -n "$local_domain_lists" ]; then
|
||||||
log "Processing local domains routing rules for '$section' section"
|
log "Processing local domains routing rules for '$section' section"
|
||||||
configure_local_domain_or_subnet_lists "$section" "domains" "$route_rule_tag"
|
configure_local_domain_lists "$section" "$route_rule_tag"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$local_subnet_lists" ]; then
|
if [ -n "$local_subnet_lists" ]; then
|
||||||
log "Processing local subnets routing rules for '$section' section"
|
log "Processing local subnets routing rules for '$section' section"
|
||||||
configure_local_domain_or_subnet_lists "$section" "subnets" "$route_rule_tag"
|
configure_local_subnet_lists "$section" "$route_rule_tag"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$remote_domain_lists" ]; then
|
if [ -n "$remote_domain_lists" ]; then
|
||||||
log "Processing remote domains routing rules for '$section' section"
|
log "Processing remote domains routing rules for '$section' section"
|
||||||
prepare_common_ruleset "$section" "domains" "$route_rule_tag"
|
|
||||||
config_list_foreach "$section" "remote_domain_lists" configure_remote_domain_or_subnet_list_handler \
|
config_list_foreach "$section" "remote_domain_lists" configure_remote_domain_or_subnet_list_handler \
|
||||||
"domains" "$section" "$route_rule_tag"
|
"domains" "$section" "$route_rule_tag"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$remote_subnet_lists" ]; then
|
if [ -n "$remote_subnet_lists" ]; then
|
||||||
log "Processing remote subnets routing rules for '$section' section"
|
log "Processing remote subnets routing rules for '$section' section"
|
||||||
prepare_common_ruleset "$section" "subnets" "$route_rule_tag"
|
|
||||||
config_list_foreach "$section" "remote_subnet_lists" configure_remote_domain_or_subnet_list_handler \
|
config_list_foreach "$section" "remote_subnet_lists" configure_remote_domain_or_subnet_list_handler \
|
||||||
"subnets" "$section" "$route_rule_tag"
|
"subnets" "$section" "$route_rule_tag"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare_common_ruleset() {
|
|
||||||
local section="$1"
|
|
||||||
local type="$2"
|
|
||||||
local route_rule_tag="$3"
|
|
||||||
|
|
||||||
log "Preparing a common $type ruleset for '$section' section" "debug"
|
|
||||||
ruleset_tag=$(get_ruleset_tag "$section" "common" "$type")
|
|
||||||
ruleset_filename="$ruleset_tag.json"
|
|
||||||
ruleset_filepath="$TMP_RULESET_FOLDER/$ruleset_filename"
|
|
||||||
if file_exists "$ruleset_filepath"; then
|
|
||||||
log "Ruleset $ruleset_filepath already exists. Skipping." "debug"
|
|
||||||
else
|
|
||||||
sing_box_cm_create_local_source_ruleset "$ruleset_filepath"
|
|
||||||
config=$(sing_box_cm_add_local_ruleset "$config" "$ruleset_tag" "source" "$ruleset_filepath")
|
|
||||||
config=$(sing_box_cm_patch_route_rule "$config" "$route_rule_tag" "rule_set" "$ruleset_tag")
|
|
||||||
case "$type" in
|
|
||||||
domains)
|
|
||||||
config=$(sing_box_cm_patch_dns_route_rule "$config" "$SB_FAKEIP_DNS_RULE_TAG" "rule_set" "$ruleset_tag")
|
|
||||||
;;
|
|
||||||
subnets) ;;
|
|
||||||
*) log "Unsupported remote rule set type: $type" "error" ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
configure_community_list_handler() {
|
configure_community_list_handler() {
|
||||||
local tag="$1"
|
local tag="$1"
|
||||||
local section="$2"
|
local section="$2"
|
||||||
@@ -942,99 +936,113 @@ configure_community_list_handler() {
|
|||||||
config=$(sing_box_cm_patch_dns_route_rule "$config" "$SB_FAKEIP_DNS_RULE_TAG" "rule_set" "$ruleset_tag")
|
config=$(sing_box_cm_patch_dns_route_rule "$config" "$SB_FAKEIP_DNS_RULE_TAG" "rule_set" "$ruleset_tag")
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_user_domain_or_subnets_list() {
|
prepare_source_ruleset() {
|
||||||
local section="$1"
|
local section="$1"
|
||||||
local type="$2"
|
local name="$2"
|
||||||
|
local type="$3"
|
||||||
|
local route_rule_tag="$4"
|
||||||
|
|
||||||
local items ruleset_tag ruleset_filename ruleset_filepath json_array
|
log "Preparing a $name $type rule set for '$section' section" "debug"
|
||||||
case "$type" in
|
ruleset_tag=$(get_ruleset_tag "$section" "$name" "$type")
|
||||||
domains)
|
ruleset_filepath="$TMP_RULESET_FOLDER/$ruleset_tag.json"
|
||||||
local user_domain_list_type
|
create_source_rule_set "$ruleset_filepath"
|
||||||
config_get user_domain_list_type "$section" "user_domain_list_type"
|
case $? in
|
||||||
case "$user_domain_list_type" in
|
0)
|
||||||
dynamic) config_get items "$section" "user_domains" ;;
|
config=$(sing_box_cm_add_local_ruleset "$config" "$ruleset_tag" "source" "$ruleset_filepath")
|
||||||
text) config_get items "$section" "user_domains_text" ;;
|
config=$(sing_box_cm_patch_route_rule "$config" "$route_rule_tag" "rule_set" "$ruleset_tag")
|
||||||
esac
|
case "$type" in
|
||||||
;;
|
domains)
|
||||||
subnets)
|
config=$(sing_box_cm_patch_dns_route_rule "$config" "$SB_FAKEIP_DNS_RULE_TAG" "rule_set" "$ruleset_tag")
|
||||||
local user_subnet_list_type
|
;;
|
||||||
config_get user_subnet_list_type "$section" "user_subnet_list_type"
|
subnets) ;;
|
||||||
case "$user_subnet_list_type" in
|
*)
|
||||||
dynamic) config_get items "$section" "user_subnets" ;;
|
log "Unsupported remote rule set type: $type" "error"
|
||||||
text) config_get items "$section" "user_subnets_text" ;;
|
return 1
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
3) log "Source rule set $ruleset_filepath already exists, skipping." "debug" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_user_domain_list() {
|
||||||
|
local section="$1"
|
||||||
|
local route_rule_tag="$2"
|
||||||
|
|
||||||
|
prepare_source_ruleset "$section" "user" "domains" "$route_rule_tag"
|
||||||
|
|
||||||
|
local user_domain_list_type items json_array
|
||||||
|
config_get user_domain_list_type "$section" "user_domain_list_type"
|
||||||
|
case "$user_domain_list_type" in
|
||||||
|
dynamic) config_get items "$section" "user_domains" ;;
|
||||||
|
text) config_get items "$section" "user_domains_text" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
ruleset_tag=$(get_ruleset_tag "$section" "common" "$type")
|
items="$(parse_domain_or_subnet_string_to_commas_string "$items" "domains")"
|
||||||
ruleset_filename="$ruleset_tag.json"
|
|
||||||
ruleset_filepath="$TMP_RULESET_FOLDER/$ruleset_filename"
|
|
||||||
items="$(parse_domain_or_subnet_string_to_commas_string "$items" "$type")"
|
|
||||||
json_array="$(comma_string_to_json_array "$items")"
|
json_array="$(comma_string_to_json_array "$items")"
|
||||||
case "$type" in
|
patch_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$json_array"
|
||||||
domains) sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$json_array" ;;
|
|
||||||
subnets)
|
|
||||||
sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$json_array"
|
|
||||||
nft_add_set_elements "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME" "$items"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_local_domain_or_subnet_lists() {
|
configure_user_subnet_list() {
|
||||||
local section="$1"
|
local section="$1"
|
||||||
local type="$2"
|
local route_rule_tag="$2"
|
||||||
local route_rule_tag="$3"
|
|
||||||
|
|
||||||
local ruleset_tag ruleset_filename ruleset_filepath
|
prepare_source_ruleset "$section" "user" "subnets" "$route_rule_tag"
|
||||||
ruleset_tag="$(get_ruleset_tag "$section" "local" "$type")"
|
|
||||||
ruleset_filename="$ruleset_tag.json"
|
|
||||||
ruleset_filepath="$TMP_RULESET_FOLDER/$ruleset_filename"
|
|
||||||
|
|
||||||
sing_box_cm_create_local_source_ruleset "$ruleset_filepath"
|
local user_subnet_list_type items json_array
|
||||||
config=$(sing_box_cm_add_local_ruleset "$config" "$ruleset_tag" "source" "$ruleset_filepath")
|
config_get user_subnet_list_type "$section" "user_subnet_list_type"
|
||||||
config=$(sing_box_cm_patch_route_rule "$config" "$route_rule_tag" "rule_set" "$ruleset_tag")
|
case "$user_subnet_list_type" in
|
||||||
|
dynamic) config_get items "$section" "user_subnets" ;;
|
||||||
case "$type" in
|
text) config_get items "$section" "user_subnets_text" ;;
|
||||||
domains)
|
|
||||||
config_list_foreach "$section" "local_domain_lists" import_local_domain_or_subnet_list "$type" \
|
|
||||||
"$section" "$ruleset_filepath"
|
|
||||||
config=$(sing_box_cm_patch_dns_route_rule "$config" "$SB_FAKEIP_DNS_RULE_TAG" "rule_set" "$ruleset_tag")
|
|
||||||
;;
|
|
||||||
subnets)
|
|
||||||
config_list_foreach "$section" "local_subnet_lists" import_local_domain_or_subnet_list "$type" \
|
|
||||||
"$section" "$ruleset_filepath"
|
|
||||||
;;
|
|
||||||
*) log "Unsupported local rule set type: $type" "error" ;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
items="$(parse_domain_or_subnet_string_to_commas_string "$items" "subnets")"
|
||||||
|
json_array="$(comma_string_to_json_array "$items")"
|
||||||
|
patch_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$json_array"
|
||||||
|
nft_add_set_elements "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME" "$items"
|
||||||
}
|
}
|
||||||
|
|
||||||
import_local_domain_or_subnet_list() {
|
configure_local_domain_lists() {
|
||||||
local filepath="$1"
|
local section="$1"
|
||||||
local type="$2"
|
local route_rule_tag="$2"
|
||||||
local section="$3"
|
|
||||||
local ruleset_filepath="$4"
|
|
||||||
|
|
||||||
if ! file_exists "$filepath"; then
|
prepare_source_ruleset "$section" "local" "domains" "$route_rule_tag"
|
||||||
log "File $filepath not found" "error"
|
|
||||||
|
config_list_foreach "$section" "local_domain_lists" import_local_domain_list_handler "$ruleset_filepath"
|
||||||
|
}
|
||||||
|
|
||||||
|
import_local_domain_list_handler() {
|
||||||
|
local local_domain_list_filepath="$1"
|
||||||
|
local ruleset_filepath="$2"
|
||||||
|
|
||||||
|
if ! file_exists "$local_domain_list_filepath"; then
|
||||||
|
log "Local domain list file $local_domain_list_filepath not found" "error"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local items json_array
|
import_plain_domain_list_to_local_source_ruleset_chunked "$local_domain_list_filepath" "$ruleset_filepath"
|
||||||
items="$(parse_domain_or_subnet_file_to_comma_string "$filepath" "$type")"
|
}
|
||||||
|
|
||||||
if [ -z "$items" ]; then
|
configure_local_subnet_lists() {
|
||||||
log "No valid $type found in $filepath" "warn"
|
local section="$1"
|
||||||
return 0
|
local route_rule_tag="$2"
|
||||||
|
|
||||||
|
prepare_source_ruleset "$section" "local" "subnets" "$route_rule_tag"
|
||||||
|
|
||||||
|
config_list_foreach "$section" "local_subnet_lists" import_local_subnets_list_handler "$ruleset_filepath"
|
||||||
|
}
|
||||||
|
|
||||||
|
import_local_subnets_list_handler() {
|
||||||
|
local local_subnet_list_filepath="$1"
|
||||||
|
local ruleset_filepath="$2"
|
||||||
|
|
||||||
|
if ! file_exists "$local_subnet_list_filepath"; then
|
||||||
|
log "Local subnet list file $local_subnet_list_filepath not found" "error"
|
||||||
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
json_array="$(comma_string_to_json_array "$items")"
|
import_plain_subnet_list_to_local_source_ruleset_chunked "$local_subnet_list_filepath" "$ruleset_filepath"
|
||||||
case "$type" in
|
nft_add_set_elements_from_file_chunked "$local_subnet_list_filepath" "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME"
|
||||||
domains) sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$json_array" ;;
|
|
||||||
subnets)
|
|
||||||
sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$json_array"
|
|
||||||
nft_add_set_elements_from_file_chunked "$filepath" "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_remote_domain_or_subnet_list_handler() {
|
configure_remote_domain_or_subnet_list_handler() {
|
||||||
@@ -1045,9 +1053,10 @@ configure_remote_domain_or_subnet_list_handler() {
|
|||||||
|
|
||||||
local file_extension
|
local file_extension
|
||||||
file_extension=$(url_get_file_extension "$url")
|
file_extension=$(url_get_file_extension "$url")
|
||||||
|
log "Detected file extension: '$file_extension'" "debug"
|
||||||
case "$file_extension" in
|
case "$file_extension" in
|
||||||
json | srs)
|
json | srs)
|
||||||
log "Detected file extension: '$file_extension' → proceeding with processing" "debug"
|
log "Creating a remote $type ruleset from the source URL" "info"
|
||||||
local basename ruleset_tag format detour update_interval
|
local basename ruleset_tag format detour update_interval
|
||||||
basename=$(url_get_basename "$url")
|
basename=$(url_get_basename "$url")
|
||||||
ruleset_tag=$(get_ruleset_tag "$section" "$basename" "remote-$type")
|
ruleset_tag=$(get_ruleset_tag "$section" "$basename" "remote-$type")
|
||||||
@@ -1066,7 +1075,7 @@ configure_remote_domain_or_subnet_list_handler() {
|
|||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
log "Detected file extension: '$file_extension' → no processing needed, managed on list_update" "debug"
|
prepare_source_ruleset "$section" "remote" "$type" "$route_rule_tag"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -1079,16 +1088,39 @@ sing_box_configure_experimental() {
|
|||||||
config_get cache_file "settings" "cache_path" "/tmp/sing-box/cache.db"
|
config_get cache_file "settings" "cache_path" "/tmp/sing-box/cache.db"
|
||||||
config=$(sing_box_cm_configure_cache_file "$config" true "$cache_file" true)
|
config=$(sing_box_cm_configure_cache_file "$config" true "$cache_file" true)
|
||||||
|
|
||||||
local enable_yacd external_controller_ui
|
|
||||||
config_get_bool enable_yacd "settings" "enable_yacd" 0
|
|
||||||
log "Configuring Clash API"
|
log "Configuring Clash API"
|
||||||
|
local enable_yacd enable_yacd_wan_access clash_api_controller_address
|
||||||
|
config_get_bool enable_yacd "settings" "enable_yacd" 0
|
||||||
|
config_get_bool enable_yacd_wan_access "settings" "enable_yacd_wan_access" 0
|
||||||
|
|
||||||
|
if [ "$enable_yacd" -eq 1 ] && [ "$enable_yacd_wan_access" -eq 1 ]; then
|
||||||
|
clash_api_controller_address="0.0.0.0"
|
||||||
|
else
|
||||||
|
clash_api_controller_address="$(get_service_listen_address)"
|
||||||
|
if [ -z "$clash_api_controller_address" ]; then
|
||||||
|
log "Could not determine the listening IP address for the Clash API controller. It will run only on localhost." "warn"
|
||||||
|
clash_api_controller_address="127.0.0.1"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$enable_yacd" -eq 1 ]; then
|
if [ "$enable_yacd" -eq 1 ]; then
|
||||||
log "YACD is enabled, enabling Clash API with downloadable YACD" "debug"
|
log "YACD is enabled, enabling Clash API with downloadable YACD" "debug"
|
||||||
local external_controller_ui="ui"
|
local yacd_secret_key external_controller_ui
|
||||||
config=$(sing_box_cm_configure_clash_api "$config" "$SB_CLASH_API_CONTROLLER" "$external_controller_ui")
|
config_get yacd_secret_key "settings" "yacd_secret_key"
|
||||||
|
external_controller_ui="ui"
|
||||||
|
|
||||||
|
config=$(
|
||||||
|
sing_box_cm_configure_clash_api \
|
||||||
|
"$config" \
|
||||||
|
"$clash_api_controller_address:$SB_CLASH_API_CONTROLLER_PORT" \
|
||||||
|
"$external_controller_ui" \
|
||||||
|
"$yacd_secret_key"
|
||||||
|
)
|
||||||
else
|
else
|
||||||
log "YACD is disabled, enabling Clash API in online mode" "debug"
|
log "YACD is disabled, enabling Clash API in online mode" "debug"
|
||||||
config=$(sing_box_cm_configure_clash_api "$config" "$SB_CLASH_API_CONTROLLER")
|
config=$(
|
||||||
|
sing_box_cm_configure_clash_api "$config" "$clash_api_controller_address:$SB_CLASH_API_CONTROLLER_PORT"
|
||||||
|
)
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1117,8 +1149,13 @@ sing_box_additional_inbounds() {
|
|||||||
configure_section_mixed_proxy() {
|
configure_section_mixed_proxy() {
|
||||||
local section="$1"
|
local section="$1"
|
||||||
|
|
||||||
local mixed_inbound_enabled mixed_proxy_port mixed_inbound_tag mixed_outbound_tag
|
local mixed_inbound_enabled mixed_proxy_port mixed_inbound_tag mixed_outbound_tag mixed_proxy_address
|
||||||
config_get_bool mixed_inbound_enabled "$section" "mixed_proxy_enabled" 0
|
config_get_bool mixed_inbound_enabled "$section" "mixed_proxy_enabled" 0
|
||||||
|
mixed_proxy_address="$(get_service_listen_address)"
|
||||||
|
if [ -z "$mixed_proxy_address" ]; then
|
||||||
|
log "Could not determine the listening IP address for the Mixed Proxy. The proxy will not be created." "warn"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
config_get mixed_proxy_port "$section" "mixed_proxy_port"
|
config_get mixed_proxy_port "$section" "mixed_proxy_port"
|
||||||
if [ "$mixed_inbound_enabled" -eq 1 ]; then
|
if [ "$mixed_inbound_enabled" -eq 1 ]; then
|
||||||
mixed_inbound_tag="$(get_inbound_tag_by_section "$section-mixed")"
|
mixed_inbound_tag="$(get_inbound_tag_by_section "$section-mixed")"
|
||||||
@@ -1127,7 +1164,7 @@ configure_section_mixed_proxy() {
|
|||||||
sing_box_cf_add_mixed_inbound_and_route_rule \
|
sing_box_cf_add_mixed_inbound_and_route_rule \
|
||||||
"$config" \
|
"$config" \
|
||||||
"$mixed_inbound_tag" \
|
"$mixed_inbound_tag" \
|
||||||
"$SB_MIXED_INBOUND_ADDRESS" \
|
"$mixed_proxy_address" \
|
||||||
"$mixed_proxy_port" \
|
"$mixed_proxy_port" \
|
||||||
"$mixed_outbound_tag"
|
"$mixed_outbound_tag"
|
||||||
)
|
)
|
||||||
@@ -1251,17 +1288,41 @@ import_domains_from_remote_domain_list_handler() {
|
|||||||
|
|
||||||
local file_extension
|
local file_extension
|
||||||
file_extension=$(url_get_file_extension "$url")
|
file_extension=$(url_get_file_extension "$url")
|
||||||
|
log "Detected file extension: '$file_extension'" "debug"
|
||||||
case "$file_extension" in
|
case "$file_extension" in
|
||||||
json | srs)
|
json | srs)
|
||||||
log "Detected file extension: '$file_extension' → no update needed, sing-box manages updates" "debug"
|
log "No update needed - sing-box manages updates automatically."
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
log "Detected file extension: '$file_extension' → proceeding with processing" "debug"
|
log "Import domains from a remote plain-text list"
|
||||||
import_domains_or_subnets_from_remote_file "$url" "$section" "domains"
|
import_domains_from_remote_plain_file "$url" "$section"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import_domains_from_remote_plain_file() {
|
||||||
|
local url="$1"
|
||||||
|
local section="$2"
|
||||||
|
|
||||||
|
local tmpfile http_proxy_address items json_array
|
||||||
|
tmpfile=$(mktemp)
|
||||||
|
http_proxy_address="$(get_service_proxy_address)"
|
||||||
|
|
||||||
|
download_to_file "$url" "$tmpfile" "$http_proxy_address"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ] || [ ! -s "$tmpfile" ]; then
|
||||||
|
log "Download $url list failed" "error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
convert_crlf_to_lf "$tmpfile"
|
||||||
|
ruleset_tag=$(get_ruleset_tag "$section" "remote" "domains")
|
||||||
|
ruleset_filepath="$TMP_RULESET_FOLDER/$ruleset_tag.json"
|
||||||
|
import_plain_domain_list_to_local_source_ruleset_chunked "$tmpfile" "$ruleset_filepath"
|
||||||
|
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
}
|
||||||
|
|
||||||
import_subnets_from_remote_subnet_lists() {
|
import_subnets_from_remote_subnet_lists() {
|
||||||
local section="$1"
|
local section="$1"
|
||||||
local remote_subnet_lists
|
local remote_subnet_lists
|
||||||
@@ -1280,61 +1341,23 @@ import_subnets_from_remote_subnet_list_handler() {
|
|||||||
|
|
||||||
local file_extension
|
local file_extension
|
||||||
file_extension="$(url_get_file_extension "$url")"
|
file_extension="$(url_get_file_extension "$url")"
|
||||||
|
log "Detected file extension: '$file_extension'" "debug"
|
||||||
case "$file_extension" in
|
case "$file_extension" in
|
||||||
json)
|
json)
|
||||||
log "Detected file extension: '$file_extension' → proceeding with processing" "debug"
|
log "Import subnets from a remote JSON list" "info"
|
||||||
import_subnets_from_remote_json_file "$url"
|
import_subnets_from_remote_json_file "$url"
|
||||||
;;
|
;;
|
||||||
srs)
|
srs)
|
||||||
log "Detected file extension: '$file_extension' → proceeding with processing" "debug"
|
log "Import subnets from a remote SRS list" "info"
|
||||||
import_subnets_from_remote_srs_file "$url"
|
import_subnets_from_remote_srs_file "$url"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
log "Detected file extension: '$file_extension' → proceeding with processing" "debug"
|
log "Import subnets from a remote plain-text list" "info"
|
||||||
import_domains_or_subnets_from_remote_file "$url" "$section" "subnets"
|
import_subnets_from_remote_plain_file "$url" "$section"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
import_domains_or_subnets_from_remote_file() {
|
|
||||||
local url="$1"
|
|
||||||
local section="$2"
|
|
||||||
local type="$3"
|
|
||||||
|
|
||||||
local tmpfile http_proxy_address items json_array
|
|
||||||
tmpfile=$(mktemp)
|
|
||||||
http_proxy_address="$(get_service_proxy_address)"
|
|
||||||
|
|
||||||
download_to_file "$url" "$tmpfile" "$http_proxy_address"
|
|
||||||
|
|
||||||
if [ $? -ne 0 ] || [ ! -s "$tmpfile" ]; then
|
|
||||||
log "Download $url list failed" "error"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
convert_crlf_to_lf "$tmpfile"
|
|
||||||
items="$(parse_domain_or_subnet_file_to_comma_string "$tmpfile" "$type")"
|
|
||||||
|
|
||||||
if [ -z "$items" ]; then
|
|
||||||
log "No valid $type found in $url" "warn"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
ruleset_tag=$(get_ruleset_tag "$section" "common" "$type")
|
|
||||||
ruleset_filename="$ruleset_tag.json"
|
|
||||||
ruleset_filepath="$TMP_RULESET_FOLDER/$ruleset_filename"
|
|
||||||
json_array="$(comma_string_to_json_array "$items")"
|
|
||||||
case "$type" in
|
|
||||||
domains) sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$json_array" ;;
|
|
||||||
subnets)
|
|
||||||
sing_box_cm_patch_local_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$json_array"
|
|
||||||
nft_add_set_elements_from_file_chunked "$tmpfile" "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
rm -f "$tmpfile"
|
|
||||||
}
|
|
||||||
|
|
||||||
import_subnets_from_remote_json_file() {
|
import_subnets_from_remote_json_file() {
|
||||||
local url="$1"
|
local url="$1"
|
||||||
local json_tmpfile subnets_tmpfile http_proxy_address
|
local json_tmpfile subnets_tmpfile http_proxy_address
|
||||||
@@ -1370,8 +1393,8 @@ import_subnets_from_remote_srs_file() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! decompile_srs_file "$binary_tmpfile" "$json_tmpfile"; then
|
if ! decompile_binary_ruleset "$binary_tmpfile" "$json_tmpfile"; then
|
||||||
log "Failed to decompile SRS file" "error"
|
log "Failed to decompile binary rule set file" "error"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1380,6 +1403,31 @@ import_subnets_from_remote_srs_file() {
|
|||||||
rm -f "$binary_tmpfile" "$json_tmpfile" "$subnets_tmpfile"
|
rm -f "$binary_tmpfile" "$json_tmpfile" "$subnets_tmpfile"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import_subnets_from_remote_plain_file() {
|
||||||
|
local url="$1"
|
||||||
|
local section="$2"
|
||||||
|
|
||||||
|
local tmpfile http_proxy_address items json_array
|
||||||
|
tmpfile=$(mktemp)
|
||||||
|
http_proxy_address="$(get_service_proxy_address)"
|
||||||
|
|
||||||
|
download_to_file "$url" "$tmpfile" "$http_proxy_address"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ] || [ ! -s "$tmpfile" ]; then
|
||||||
|
log "Download $url list failed" "error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
convert_crlf_to_lf "$tmpfile"
|
||||||
|
|
||||||
|
ruleset_tag=$(get_ruleset_tag "$section" "remote" "subnets")
|
||||||
|
ruleset_filepath="$TMP_RULESET_FOLDER/$ruleset_tag.json"
|
||||||
|
import_plain_subnet_list_to_local_source_ruleset_chunked "$tmpfile" "$ruleset_filepath"
|
||||||
|
nft_add_set_elements_from_file_chunked "$tmpfile" "$NFT_TABLE_NAME" "$NFT_COMMON_SET_NAME"
|
||||||
|
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
}
|
||||||
|
|
||||||
## Support functions
|
## Support functions
|
||||||
get_service_proxy_address() {
|
get_service_proxy_address() {
|
||||||
local download_lists_via_proxy
|
local download_lists_via_proxy
|
||||||
@@ -1460,6 +1508,23 @@ section_has_enabled_lists() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_service_listen_address() {
|
||||||
|
local service_listen_address
|
||||||
|
|
||||||
|
service_listen_address="$(uci_get "network" "lan" "ipaddr")"
|
||||||
|
|
||||||
|
if [ -z "$service_listen_address" ]; then
|
||||||
|
config_get service_listen_address "settings" "service_listen_address" # TODO(ampetelin): Remove after testing
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$service_listen_address" ]; then
|
||||||
|
log "Failed to determine the listening IP address. Please open an issue to report this problem: https://github.com/itdoginfo/podkop/issues" "error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$service_listen_address"
|
||||||
|
}
|
||||||
|
|
||||||
## nftables
|
## nftables
|
||||||
nft_list_all_traffic_from_ip() {
|
nft_list_all_traffic_from_ip() {
|
||||||
local ip="$1"
|
local ip="$1"
|
||||||
@@ -1471,46 +1536,6 @@ nft_list_all_traffic_from_ip() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
nft_add_set_elements_from_file_chunked() {
|
|
||||||
local filepath="$1"
|
|
||||||
local nft_table_name="$2"
|
|
||||||
local nft_set_name="$3"
|
|
||||||
local chunk_size="${4:-5000}"
|
|
||||||
|
|
||||||
local array count
|
|
||||||
count=0
|
|
||||||
while IFS= read -r line; do
|
|
||||||
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
||||||
|
|
||||||
[ -z "$line" ] && continue
|
|
||||||
|
|
||||||
if ! is_ipv4 "$line" && ! is_ipv4_cidr "$line"; then
|
|
||||||
log "'$line' is not IPv4 or IPv4 CIDR" "debug"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$array" ]; then
|
|
||||||
array="$line"
|
|
||||||
else
|
|
||||||
array="$array,$line"
|
|
||||||
fi
|
|
||||||
|
|
||||||
count=$((count + 1))
|
|
||||||
|
|
||||||
if [ "$count" = "$chunk_size" ]; then
|
|
||||||
log "Adding $count elements to nft set $nft_set_name" "debug"
|
|
||||||
nft_add_set_elements "$nft_table_name" "$nft_set_name" "$array"
|
|
||||||
array=""
|
|
||||||
count=0
|
|
||||||
fi
|
|
||||||
done < "$filepath"
|
|
||||||
|
|
||||||
if [ -n "$array" ]; then
|
|
||||||
log "Adding $count elements to nft set $nft_set_name" "debug"
|
|
||||||
nft_add_set_elements "$nft_table_name" "$nft_set_name" "$array"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Diagnotics
|
# Diagnotics
|
||||||
check_proxy() {
|
check_proxy() {
|
||||||
local sing_box_config_path
|
local sing_box_config_path
|
||||||
@@ -1671,7 +1696,7 @@ check_logs() {
|
|||||||
nolog "Logs not found"
|
nolog "Logs not found"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
ы
|
|
||||||
# Find the last occurrence of "Starting podkop"
|
# Find the last occurrence of "Starting podkop"
|
||||||
local start_line
|
local start_line
|
||||||
start_line=$(echo "$logs" | grep -n "podkop.*Starting podkop" | tail -n 1 | cut -d: -f1)
|
start_line=$(echo "$logs" | grep -n "podkop.*Starting podkop" | tail -n 1 | cut -d: -f1)
|
||||||
@@ -1733,6 +1758,7 @@ show_config() {
|
|||||||
-e 's/\(list urltest_proxy_links\).*/\1 '\''MASKED'\''/g' \
|
-e 's/\(list urltest_proxy_links\).*/\1 '\''MASKED'\''/g' \
|
||||||
-e "s@\\(option dns_server '[^/]*\\)/[^']*'@\\1/MASKED'@g" \
|
-e "s@\\(option dns_server '[^/]*\\)/[^']*'@\\1/MASKED'@g" \
|
||||||
-e "s@\\(option domain_resolver_dns_server '[^/]*\\)/[^']*'@\\1/MASKED'@g" \
|
-e "s@\\(option domain_resolver_dns_server '[^/]*\\)/[^']*'@\\1/MASKED'@g" \
|
||||||
|
-e 's/\(option yacd_secret_key\).*/\1 '\''MASKED'\''/g' \
|
||||||
"$PODKOP_CONFIG" > "$tmp_config"
|
"$PODKOP_CONFIG" > "$tmp_config"
|
||||||
|
|
||||||
cat "$tmp_config"
|
cat "$tmp_config"
|
||||||
@@ -2112,13 +2138,28 @@ check_fakeip() {
|
|||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
clash_api() {
|
clash_api() {
|
||||||
local CLASH_URL="127.0.0.1:9090"
|
|
||||||
local TEST_URL="https://www.gstatic.com/generate_204"
|
|
||||||
local action="$1"
|
local action="$1"
|
||||||
|
local clash_api_controller_address CLASH_URL TEST_URL
|
||||||
|
clash_api_controller_address="$(get_service_listen_address)"
|
||||||
|
if [ -z "$clash_api_controller_address" ]; then
|
||||||
|
clash_api_controller_address="127.0.0.1"
|
||||||
|
fi
|
||||||
|
CLASH_URL="$clash_api_controller_address:$SB_CLASH_API_CONTROLLER_PORT"
|
||||||
|
TEST_URL="https://www.gstatic.com/generate_204"
|
||||||
|
|
||||||
|
local enable_yacd_wan_access yacd_secret_key auth_header
|
||||||
|
config_get_bool enable_yacd_wan_access "settings" "enable_yacd_wan_access" 0
|
||||||
|
config_get yacd_secret_key "settings" "yacd_secret_key"
|
||||||
|
|
||||||
|
if [ "$enable_yacd_wan_access" -eq 1 ]; then
|
||||||
|
auth_header="Authorization: Bearer $yacd_secret_key"
|
||||||
|
else
|
||||||
|
auth_header=""
|
||||||
|
fi
|
||||||
|
|
||||||
case "$action" in
|
case "$action" in
|
||||||
get_proxies)
|
get_proxies)
|
||||||
curl -s "$CLASH_URL/proxies" | jq .
|
curl -s --header "$auth_header" "$CLASH_URL/proxies" | jq .
|
||||||
;;
|
;;
|
||||||
|
|
||||||
get_proxy_latency)
|
get_proxy_latency)
|
||||||
@@ -2131,6 +2172,7 @@ clash_api() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
curl -G -s "$CLASH_URL/proxies/$proxy_tag/delay" \
|
curl -G -s "$CLASH_URL/proxies/$proxy_tag/delay" \
|
||||||
|
--header "$auth_header" \
|
||||||
--data-urlencode "url=$TEST_URL" \
|
--data-urlencode "url=$TEST_URL" \
|
||||||
--data-urlencode "timeout=$timeout" | jq .
|
--data-urlencode "timeout=$timeout" | jq .
|
||||||
;;
|
;;
|
||||||
@@ -2145,6 +2187,7 @@ clash_api() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
curl -G -s "$CLASH_URL/group/$group_tag/delay" \
|
curl -G -s "$CLASH_URL/group/$group_tag/delay" \
|
||||||
|
--header "$auth_header" \
|
||||||
--data-urlencode "url=$TEST_URL" \
|
--data-urlencode "url=$TEST_URL" \
|
||||||
--data-urlencode "timeout=$timeout" | jq .
|
--data-urlencode "timeout=$timeout" | jq .
|
||||||
;;
|
;;
|
||||||
@@ -2159,8 +2202,11 @@ clash_api() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local response
|
local response
|
||||||
response=$(curl -X PUT -s -w "\n%{http_code}" "$CLASH_URL/proxies/$group_tag" \
|
response=$(
|
||||||
--data-raw "{\"name\":\"$proxy_tag\"}")
|
curl -X PUT -s -w "\n%{http_code}" "$CLASH_URL/proxies/$group_tag" \
|
||||||
|
--header "$auth_header" \
|
||||||
|
--data-raw "{\"name\":\"$proxy_tag\"}"
|
||||||
|
)
|
||||||
|
|
||||||
local http_code
|
local http_code
|
||||||
local body
|
local body
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ SB_TPROXY_INBOUND_PORT=1602
|
|||||||
SB_DNS_INBOUND_TAG="dns-in"
|
SB_DNS_INBOUND_TAG="dns-in"
|
||||||
SB_DNS_INBOUND_ADDRESS="127.0.0.42"
|
SB_DNS_INBOUND_ADDRESS="127.0.0.42"
|
||||||
SB_DNS_INBOUND_PORT=53
|
SB_DNS_INBOUND_PORT=53
|
||||||
SB_MIXED_INBOUND_ADDRESS="0.0.0.0" # TODO(ampetelin): maybe to determine address?
|
|
||||||
SB_SERVICE_MIXED_INBOUND_TAG="service-mixed-in"
|
SB_SERVICE_MIXED_INBOUND_TAG="service-mixed-in"
|
||||||
SB_SERVICE_MIXED_INBOUND_ADDRESS="127.0.0.1"
|
SB_SERVICE_MIXED_INBOUND_ADDRESS="127.0.0.1"
|
||||||
SB_SERVICE_MIXED_INBOUND_PORT=4534
|
SB_SERVICE_MIXED_INBOUND_PORT=4534
|
||||||
@@ -47,7 +46,7 @@ SB_DIRECT_OUTBOUND_TAG="direct-out"
|
|||||||
# Route
|
# Route
|
||||||
SB_REJECT_RULE_TAG="reject-rule-tag"
|
SB_REJECT_RULE_TAG="reject-rule-tag"
|
||||||
# Experimental
|
# Experimental
|
||||||
SB_CLASH_API_CONTROLLER="0.0.0.0:9090"
|
SB_CLASH_API_CONTROLLER_PORT=9090
|
||||||
|
|
||||||
## Lists
|
## Lists
|
||||||
GITHUB_RAW_URL="https://raw.githubusercontent.com/itdoginfo/allow-domains/main"
|
GITHUB_RAW_URL="https://raw.githubusercontent.com/itdoginfo/allow-domains/main"
|
||||||
|
|||||||
@@ -105,37 +105,6 @@ get_domain_resolver_tag() {
|
|||||||
echo "$section-$postfix"
|
echo "$section-$postfix"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Constructs and returns a ruleset tag using section, name, optional type, and a fixed postfix
|
|
||||||
get_ruleset_tag() {
|
|
||||||
local section="$1"
|
|
||||||
local name="$2"
|
|
||||||
local type="$3"
|
|
||||||
local postfix="ruleset"
|
|
||||||
|
|
||||||
if [ -n "$type" ]; then
|
|
||||||
echo "$section-$name-$type-$postfix"
|
|
||||||
else
|
|
||||||
echo "$section-$name-$postfix"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Determines the ruleset format based on the file extension (json → source, srs → binary)
|
|
||||||
get_ruleset_format_by_file_extension() {
|
|
||||||
local file_extension="$1"
|
|
||||||
|
|
||||||
local format
|
|
||||||
case "$file_extension" in
|
|
||||||
json) format="source" ;;
|
|
||||||
srs) format="binary" ;;
|
|
||||||
*)
|
|
||||||
log "Unsupported file extension: .$file_extension" "error"
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "$format"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Converts a comma-separated string into a JSON array string
|
# Converts a comma-separated string into a JSON array string
|
||||||
comma_string_to_json_array() {
|
comma_string_to_json_array() {
|
||||||
local input="$1"
|
local input="$1"
|
||||||
@@ -300,25 +269,6 @@ convert_crlf_to_lf() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Decompiles a sing-box SRS binary file into a JSON ruleset file
|
|
||||||
decompile_srs_file() {
|
|
||||||
local binary_filepath="$1"
|
|
||||||
local output_filepath="$2"
|
|
||||||
|
|
||||||
log "Decompiling $binary_filepath to $output_filepath" "debug"
|
|
||||||
|
|
||||||
if ! file_exists "$binary_filepath"; then
|
|
||||||
log "File $binary_filepath not found" "error"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
sing-box rule-set decompile "$binary_filepath" -o "$output_filepath"
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
log "Decompilation command failed for $binary_filepath" "error"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Parses a whitespace-separated string, validates items as either domains
|
# Parses a whitespace-separated string, validates items as either domains
|
||||||
# or IPv4 addresses/subnets, and returns a comma-separated string of valid items.
|
# or IPv4 addresses/subnets, and returns a comma-separated string of valid items.
|
||||||
@@ -387,18 +337,4 @@ parse_domain_or_subnet_file_to_comma_string() {
|
|||||||
done < "$filepath"
|
done < "$filepath"
|
||||||
|
|
||||||
echo "$result"
|
echo "$result"
|
||||||
}
|
|
||||||
|
|
||||||
# Extracts all ip_cidr entries from a JSON ruleset file and writes them to an output file.
|
|
||||||
extract_ip_cidr_from_json_ruleset_to_file() {
|
|
||||||
local json_file="$1"
|
|
||||||
local output_file="$2"
|
|
||||||
|
|
||||||
if [ ! -f "$json_file" ]; then
|
|
||||||
log "JSON file not found: $json_file" "error"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "Extracting ip_cidr entries from $json_file to $output_file" "debug"
|
|
||||||
jq -r '.rules[].ip_cidr[]' "$json_file" > "$output_file"
|
|
||||||
}
|
}
|
||||||
@@ -27,4 +27,44 @@ nft_add_set_elements() {
|
|||||||
local elements="$3"
|
local elements="$3"
|
||||||
|
|
||||||
nft add element inet "$table" "$set" "{ $elements }"
|
nft add element inet "$table" "$set" "{ $elements }"
|
||||||
|
}
|
||||||
|
|
||||||
|
nft_add_set_elements_from_file_chunked() {
|
||||||
|
local filepath="$1"
|
||||||
|
local nft_table_name="$2"
|
||||||
|
local nft_set_name="$3"
|
||||||
|
local chunk_size="${4:-5000}"
|
||||||
|
|
||||||
|
local array count
|
||||||
|
count=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
|
||||||
|
if ! is_ipv4 "$line" && ! is_ipv4_cidr "$line"; then
|
||||||
|
log "'$line' is not IPv4 or IPv4 CIDR" "debug"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$array" ]; then
|
||||||
|
array="$line"
|
||||||
|
else
|
||||||
|
array="$array,$line"
|
||||||
|
fi
|
||||||
|
|
||||||
|
count=$((count + 1))
|
||||||
|
|
||||||
|
if [ "$count" = "$chunk_size" ]; then
|
||||||
|
log "Adding $count elements to nft set $nft_set_name" "debug"
|
||||||
|
nft_add_set_elements "$nft_table_name" "$nft_set_name" "$array"
|
||||||
|
array=""
|
||||||
|
count=0
|
||||||
|
fi
|
||||||
|
done < "$filepath"
|
||||||
|
|
||||||
|
if [ -n "$array" ]; then
|
||||||
|
log "Adding $count elements to nft set $nft_set_name" "debug"
|
||||||
|
nft_add_set_elements "$nft_table_name" "$nft_set_name" "$array"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
180
podkop/files/usr/lib/rulesets.sh
Normal file
180
podkop/files/usr/lib/rulesets.sh
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
# Constructs and returns a ruleset tag using section, name, optional type, and a fixed postfix
|
||||||
|
get_ruleset_tag() {
|
||||||
|
local section="$1"
|
||||||
|
local name="$2"
|
||||||
|
local type="$3"
|
||||||
|
local postfix="ruleset"
|
||||||
|
|
||||||
|
if [ -n "$type" ]; then
|
||||||
|
echo "$section-$name-$type-$postfix"
|
||||||
|
else
|
||||||
|
echo "$section-$name-$postfix"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Creates a new ruleset JSON file if it doesn't already exist
|
||||||
|
create_source_rule_set() {
|
||||||
|
local ruleset_filepath="$1"
|
||||||
|
|
||||||
|
if file_exists "$ruleset_filepath"; then
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
jq -n '{version: 3, rules: []}' > "$ruleset_filepath"
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Patch a source ruleset JSON file for sing-box by appending a new ruleset object containing the provided key
|
||||||
|
# and value.
|
||||||
|
# Arguments:
|
||||||
|
# filepath: path to the JSON file to patch
|
||||||
|
# key: the ruleset key to insert (e.g., "ip_cidr")
|
||||||
|
# value: a JSON array of values to assign to the key
|
||||||
|
# Example:
|
||||||
|
# patch_source_ruleset_rules "/tmp/sing-box/ruleset.json" "ip_cidr" '["1.1.1.1","2.2.2.2"]'
|
||||||
|
#######################################
|
||||||
|
patch_source_ruleset_rules() {
|
||||||
|
local filepath="$1"
|
||||||
|
local key="$2"
|
||||||
|
local value="$3"
|
||||||
|
|
||||||
|
local tmpfile=$(mktemp)
|
||||||
|
|
||||||
|
jq --arg key "$key" --argjson value "$value" \
|
||||||
|
'( .rules | map(has($key)) | index(true) ) as $idx |
|
||||||
|
if $idx != null then
|
||||||
|
.rules[$idx][$key] = (.rules[$idx][$key] + $value | unique)
|
||||||
|
else
|
||||||
|
.rules += [{ ($key): $value }]
|
||||||
|
end' "$filepath" > "$tmpfile"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv "$tmpfile" "$filepath"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Imports a plain domain list into a ruleset in chunks, validating domains and appending them as domain_suffix rules
|
||||||
|
import_plain_domain_list_to_local_source_ruleset_chunked() {
|
||||||
|
local plain_list_filepath="$1"
|
||||||
|
local ruleset_filepath="$2"
|
||||||
|
local chunk_size="${3:-5000}"
|
||||||
|
|
||||||
|
local array count json_array
|
||||||
|
count=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
|
||||||
|
if ! is_domain_suffix "$line"; then
|
||||||
|
log "'$line' is not a valid domain" "debug"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$array" ]; then
|
||||||
|
array="$line"
|
||||||
|
else
|
||||||
|
array="$array,$line"
|
||||||
|
fi
|
||||||
|
|
||||||
|
count=$((count + 1))
|
||||||
|
|
||||||
|
if [ "$count" = "$chunk_size" ]; then
|
||||||
|
log "Adding $count elements to rule set at $ruleset_filepath" "debug"
|
||||||
|
json_array="$(comma_string_to_json_array "$array")"
|
||||||
|
patch_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$json_array"
|
||||||
|
array=""
|
||||||
|
count=0
|
||||||
|
fi
|
||||||
|
done < "$plain_list_filepath"
|
||||||
|
|
||||||
|
if [ -n "$array" ]; then
|
||||||
|
log "Adding $count elements to rule set at $ruleset_filepath" "debug"
|
||||||
|
json_array="$(comma_string_to_json_array "$array")"
|
||||||
|
patch_source_ruleset_rules "$ruleset_filepath" "domain_suffix" "$json_array"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Imports a plain IPv4/CIDR list into a ruleset in chunks, validating entries and appending them as ip_cidr rules
|
||||||
|
import_plain_subnet_list_to_local_source_ruleset_chunked() {
|
||||||
|
local plain_list_filepath="$1"
|
||||||
|
local ruleset_filepath="$2"
|
||||||
|
local chunk_size="${3:-5000}"
|
||||||
|
|
||||||
|
local array count json_array
|
||||||
|
count=0
|
||||||
|
while IFS= read -r line; do
|
||||||
|
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
|
||||||
|
if ! is_ipv4 "$line" && ! is_ipv4_cidr "$line"; then
|
||||||
|
log "'$line' is not IPv4 or IPv4 CIDR" "debug"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$array" ]; then
|
||||||
|
array="$line"
|
||||||
|
else
|
||||||
|
array="$array,$line"
|
||||||
|
fi
|
||||||
|
|
||||||
|
count=$((count + 1))
|
||||||
|
|
||||||
|
if [ "$count" = "$chunk_size" ]; then
|
||||||
|
log "Adding $count elements to ruleset at $ruleset_filepath" "debug"
|
||||||
|
json_array="$(comma_string_to_json_array "$array")"
|
||||||
|
patch_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$json_array"
|
||||||
|
array=""
|
||||||
|
count=0
|
||||||
|
fi
|
||||||
|
done < "$plain_list_filepath"
|
||||||
|
|
||||||
|
if [ -n "$array" ]; then
|
||||||
|
log "Adding $count elements to ruleset at $ruleset_filepath" "debug"
|
||||||
|
json_array="$(comma_string_to_json_array "$array")"
|
||||||
|
patch_source_ruleset_rules "$ruleset_filepath" "ip_cidr" "$json_array"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determines the ruleset format based on the file extension (json → source, srs → binary)
|
||||||
|
get_ruleset_format_by_file_extension() {
|
||||||
|
local file_extension="$1"
|
||||||
|
|
||||||
|
local format
|
||||||
|
case "$file_extension" in
|
||||||
|
json) format="source" ;;
|
||||||
|
srs) format="binary" ;;
|
||||||
|
*)
|
||||||
|
log "Unsupported file extension: .$file_extension" "error"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "$format"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Decompiles a sing-box SRS binary file into a JSON ruleset file
|
||||||
|
decompile_binary_ruleset() {
|
||||||
|
local binary_filepath="$1"
|
||||||
|
local output_filepath="$2"
|
||||||
|
|
||||||
|
log "Decompiling $binary_filepath to $output_filepath" "debug"
|
||||||
|
sing-box rule-set decompile "$binary_filepath" -o "$output_filepath"
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
log "Decompilation command failed for $binary_filepath" "error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extracts all ip_cidr entries from a JSON ruleset file and writes them to an output file.
|
||||||
|
extract_ip_cidr_from_json_ruleset_to_file() {
|
||||||
|
local json_file="$1"
|
||||||
|
local output_file="$2"
|
||||||
|
|
||||||
|
log "Extracting ip_cidr entries from $json_file to $output_file" "debug"
|
||||||
|
jq -r '.rules[].ip_cidr[]' "$json_file" > "$output_file"
|
||||||
|
}
|
||||||
@@ -1339,9 +1339,10 @@ sing_box_cm_configure_cache_file() {
|
|||||||
#######################################
|
#######################################
|
||||||
# Configure the experimental clash_api section of a sing-box JSON configuration.
|
# Configure the experimental clash_api section of a sing-box JSON configuration.
|
||||||
# Arguments:
|
# Arguments:
|
||||||
# config: JSON configuration (string)
|
# config: string, JSON configuration
|
||||||
# external_controller: API listening address; Clash API will be disabled if empty
|
# external_controller: string, API listening address; Clash API will be disabled if empty
|
||||||
# external_ui: Optional path to static web resources to serve at http://{{external-controller}}/ui
|
# external_ui: string, Optional path to static web resources to serve at http://{{external-controller}}/ui
|
||||||
|
# secret: string, Optional secret for the RESTful API Authenticate by specifying HTTP header
|
||||||
# Outputs:
|
# Outputs:
|
||||||
# Writes updated JSON configuration to stdout
|
# Writes updated JSON configuration to stdout
|
||||||
# Example:
|
# Example:
|
||||||
@@ -1351,59 +1352,17 @@ sing_box_cm_configure_clash_api() {
|
|||||||
local config="$1"
|
local config="$1"
|
||||||
local external_controller="$2"
|
local external_controller="$2"
|
||||||
local external_ui="$3"
|
local external_ui="$3"
|
||||||
|
local secret="$4"
|
||||||
|
|
||||||
echo "$config" | jq \
|
echo "$config" | jq \
|
||||||
--arg external_controller "$external_controller" \
|
--arg external_controller "$external_controller" \
|
||||||
--arg external_ui "$external_ui" \
|
--arg external_ui "$external_ui" \
|
||||||
|
--arg secret "$secret" \
|
||||||
'.experimental.clash_api = {
|
'.experimental.clash_api = {
|
||||||
external_controller: $external_controller,
|
external_controller: $external_controller,
|
||||||
}
|
}
|
||||||
+ (if $external_ui != "" then { external_ui: $external_ui } else {} end)'
|
+ (if $external_ui != "" then { external_ui: $external_ui } else {} end)
|
||||||
}
|
+ (if $secret != "" then { secret: $secret } else {} end)'
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Create a local source ruleset JSON file for sing-box.
|
|
||||||
# Arguments:
|
|
||||||
# filepath: path to the JSON file to create
|
|
||||||
# Example:
|
|
||||||
# sing_box_cm_create_local_source_ruleset "/tmp/sing-box/ruleset.json"
|
|
||||||
#######################################
|
|
||||||
sing_box_cm_create_local_source_ruleset() {
|
|
||||||
local filepath="$1"
|
|
||||||
|
|
||||||
jq -n '{version: 3, rules: []}' > "$filepath"
|
|
||||||
}
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Patch a local source ruleset JSON file for sing-box by adding unique! values to a given key.
|
|
||||||
# Arguments:
|
|
||||||
# filepath: path to the JSON file to patch
|
|
||||||
# key: the ruleset key to update (e.g., "ip_cidr")
|
|
||||||
# value: a JSON array of values to add to the key
|
|
||||||
# Example:
|
|
||||||
# sing_box_cm_patch_local_source_ruleset_rules "/tmp/sing-box/ruleset.json" "ip_cidr" '["1.1.1.1","2.2.2.2"]'
|
|
||||||
#######################################
|
|
||||||
sing_box_cm_patch_local_source_ruleset_rules() {
|
|
||||||
local filepath="$1"
|
|
||||||
local key="$2"
|
|
||||||
local value="$3"
|
|
||||||
|
|
||||||
value=$(_normalize_arg "$value")
|
|
||||||
|
|
||||||
local content
|
|
||||||
content="$(cat "$filepath")"
|
|
||||||
|
|
||||||
echo "$content" | jq \
|
|
||||||
--arg key "$key" \
|
|
||||||
--argjson value "$value" '
|
|
||||||
([.rules[]?[$key][]] | unique) as $existing
|
|
||||||
| ($value - $existing) as $value
|
|
||||||
| if ($value | length) > 0 then
|
|
||||||
.rules += [{($key): $value}]
|
|
||||||
else
|
|
||||||
.
|
|
||||||
end
|
|
||||||
' > "$filepath"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
|
|||||||
Reference in New Issue
Block a user