Compare commits

...

13 Commits

Author SHA1 Message Date
Kirill Sobakin
00db99723c Merge pull request #169 from itdoginfo/urltest
fix: Correct boolean value for interrupt_exist_connections in JSON
2025-09-16 15:14:43 +03:00
Andrey Petelin
5439504de7 fix: Correct boolean value for interrupt_exist_connections in JSON generation 2025-09-16 17:12:19 +05:00
Kirill Sobakin
c3072162de Merge pull request #168 from itdoginfo/urltest
feat: Add URLTest proxy configuration type with dynamic list support
2025-09-16 15:10:37 +03:00
Andrey Petelin
d021636f85 chore: Fix placeholder text typo in proxy links field 2025-09-16 17:09:37 +05:00
Andrey Petelin
a06aac0613 feat: Add URLTest proxy configuration type with dynamic list support 2025-09-16 16:58:39 +05:00
Kirill Sobakin
29159243ea Merge pull request #167 from itdoginfo/fix
Fix
2025-09-16 11:44:27 +03:00
Andrey Petelin
269123600a fix: Correct variable usage in domain/subnet parsing function (#165) 2025-09-16 13:39:40 +05:00
Andrey Petelin
49add27f81 fix: Improve domain validation to support suffix matching (#166) 2025-09-16 13:19:02 +05:00
itdoginfo
c929c74da5 DeepWiki 2025-09-15 23:29:04 +03:00
itdoginfo
bb91144a91 Update 2025-09-15 22:22:10 +03:00
itdoginfo
2291d9fb9d Check 23.05 2025-09-15 22:15:10 +03:00
Kirill Sobakin
f722a513d0 Merge pull request #163 from itdoginfo/fix
fix: Use correct variable for detour service address
2025-09-15 17:27:15 +03:00
Andrey Petelin
a71707f174 fix: Use correct variable for detour service address 2025-09-15 19:22:52 +05:00
6 changed files with 161 additions and 19 deletions

View File

@@ -4,12 +4,13 @@
- При возникновении проблем, нужен технически грамотный фидбэк в чат.
- При обновлении **обязательно** [сбрасывайте кэш LuCI](https://podkop.net/docs/clear-browser-cache/).
- Также при обновлении всегда заходите в конфигурацию и проверяйте свои настройки. Конфигурация может измениться.
- Необходимо минимум 15МБ свободного места на роутере. Роутеры с флешками на 16МБ сразу мимо.
- Необходимо минимум 25МБ свободного места на роутере. Роутеры с флешками на 16МБ сразу мимо.
- При старте программы редактируется конфиг Dnsmasq.
- Podkop редактирует конфиг sing-box. Обязательно сохраните ваш конфиг sing-box перед установкой, если он вам нужен.
- Информация здесь может быть устаревшей. Все изменения фиксируются в [телеграм-чате](https://t.me/itdogchat/81758/420321).
- [Если у вас не что-то не работает.](https://podkop.net/docs/diagnostics/)
- Если у вас установлен Getdomains, [его следует удалить](https://github.com/itdoginfo/domain-routing-openwrt?tab=readme-ov-file#%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82-%D0%B4%D0%BB%D1%8F-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F).
- Требуется версия OpenWrt 24.10.
# Документация
https://podkop.net/
@@ -28,17 +29,17 @@ sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/mai
Основные задачи в issues.
## Рефактор
- [ ] Очевидные повторения в `/usr/bin/podkop` загнать в переменые
- [x] Очевидные повторения в `/usr/bin/podkop` загнать в переменые
- [x] Возможно поменять структуру
## Списки
- [ ] CloudFront
- [ ] DO
- [ ] HODCA
- [x] CloudFront
- [x] DO
- [x] HODCA
## Будущее
- [ ] [Подписка](https://github.com/itdoginfo/podkop/issues/118). Здесь нужна реализация, чтоб для каждой секции помимо ручного выбора, был выбор фильтрации по тегу. Например, для main выбираем ключевые слова NL, DE, FI. А для extra секции фильтруем по RU. И создаётся outbound c urltest в которых перечислены outbound из фильтров.
- [ ] Опция, когда все запросы (с роутера в первую очередь), а не только br-lan идут в прокси. С этим связана #95. Требуется много переделать для nftables.
- [x] Опция, когда все запросы (с роутера в первую очередь), а не только br-lan идут в прокси. С этим связана #95. Требуется много переделать для nftables.
- [ ] Весь трафик в Proxy\VPN. Вопрос, что делать с экстрасекциями в этом случае. FakeIP здесь скорее не нужен, а значит только main секция остаётся. Всё что касается fakeip проверок, придётся выключать в этом режиме.
- [x] Поддержка Source format. Нужна расшифровка в json и если присуствуют подсети, заносить их в custom subnet nftset.
- [x] Переделывание функции формирования кастомных списков в JSON. Обрабатывать сразу скопом, а не по одному.
@@ -49,4 +50,6 @@ sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/mai
## Тесты
- [ ] Unit тесты (BATS)
- [ ] Интеграционые тесты бекенда (OpenWrt rootfs + BATS)
- [ ] Интеграционые тесты бекенда (OpenWrt rootfs + BATS)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/itdoginfo/podkop)

View File

@@ -108,6 +108,15 @@ check_system() {
MODEL=$(cat /tmp/sysinfo/model)
msg "Router model: $MODEL"
# Check OpenWrt version
openwrt_version=$(cat /etc/openwrt_release | grep DISTRIB_RELEASE | cut -d"'" -f2 | cut -d'.' -f1)
if [ "$openwrt_version" = "23" ]; then
msg "OpenWrt 23.05 не поддерживается начиная с podkop 0.5.0"
msg "Для OpenWrt 23.05 используйте podkop версии 0.4.11 или устанавливайте зависимости и podkop вручную"
msg "Подробности: https://podkop.net/docs/install/#%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-%d0%bd%d0%b0-2305"
exit 1
fi
# Check available space
AVAILABLE_SPACE=$(df /overlay | awk 'NR==2 {print $4}')
REQUIRED_SPACE=15360 # 15MB in KB
@@ -150,7 +159,7 @@ sing_box() {
fi
sing_box_version=$(sing-box version | head -n 1 | awk '{print $3}')
required_version="1.11.1"
required_version="1.12.4"
if [ "$(echo -e "$sing_box_version\n$required_version" | sort -V | head -n 1)" != "$required_version" ]; then
msg "sing-box version $sing_box_version is older than required $required_version"

View File

@@ -32,6 +32,7 @@ function createConfigSection(section, map, network) {
o = s.taboption('basic', form.ListValue, 'proxy_config_type', _('Configuration Type'), _('Select how to configure the proxy'));
o.value('url', _('Connection URL'));
o.value('outbound', _('Outbound Config'));
o.value('urltest', _('URLTest'));
o.default = 'url';
o.depends('mode', 'proxy');
o.ucisection = s.section;
@@ -205,6 +206,11 @@ function createConfigSection(section, map, network) {
}
};
o = s.taboption('basic', form.DynamicList, 'urltest_proxy_links', _('URLTest Proxy Links'));
o.depends('proxy_config_type', 'urltest');
o.placeholder = 'vless:// or ss:// link';
o.rmempty = false;
o = s.taboption('basic', form.Flag, 'ss_uot', _('Shadowsocks UDP over TCP'), _('Apply for SS2022'));
o.default = '0';
o.depends('mode', 'proxy');

View File

@@ -83,13 +83,14 @@ start_main() {
}
start() {
local proxy_string interface outbound_json dont_touch_dhcp
local proxy_string interface outbound_json urltest_proxy_links dont_touch_dhcp
config_get proxy_string "main" "proxy_string"
config_get interface "main" "interface"
config_get outbound_json "main" "outbound_json"
config_get urltest_proxy_links "main" "urltest_proxy_links"
if [ -z "$proxy_string" ] && [ -z "$interface" ] && [ -z "$outbound_json" ]; then
log "Podkop start aborted: required options (proxy_string, interface, outbound_json) are missing in 'main' section"
if [ -z "$proxy_string" ] && [ -z "$interface" ] && [ -z "$outbound_json" ] && [ -z "$urltest_proxy_links" ]; then
log "Required options (proxy_string, interface, outbound_json, urltest_proxy_links) are missing in 'main' section. Aborted." "fatal"
exit 1
fi
@@ -629,7 +630,7 @@ configure_outbound_handler() {
case "$proxy_config_type" in
url)
log "Detected proxy configuration type: url"
log "Detected proxy configuration type: url" "debug"
local proxy_string udp_over_tcp
config_get proxy_string "$section" "proxy_string"
config_get udp_over_tcp "$section" "ss_uot"
@@ -643,11 +644,42 @@ configure_outbound_handler() {
config=$(sing_box_cf_add_proxy_outbound "$config" "$section" "$active_proxy_string" "$udp_over_tcp")
;;
outbound)
log "Detected proxy configuration type: outbound"
log "Detected proxy configuration type: outbound" "debug"
local json_outbound
config_get json_outbound "$section" "outbound_json"
config=$(sing_box_cf_add_json_outbound "$config" "$section" "$json_outbound")
;;
urltest)
log "Detected proxy configuration type: urltest" "debug"
local urltest_proxy_links udp_over_tcp i urltest_tag selector_tag outbound_tag outbound_tags \
urltest_outbounds selector_outbounds
config_get urltest_proxy_links "$section" "urltest_proxy_links"
config_get udp_over_tcp "$section" "ss_uot"
if [ -z "$urltest_proxy_links" ]; then
log "URLTest proxy links is not set. Aborted." "fatal"
exit 1
fi
i=1
for link in $urltest_proxy_links; do
config="$(sing_box_cf_add_proxy_outbound "$config" "$section-$i" "$link" "$udp_over_tcp")"
outbound_tag="$(get_outbound_tag_by_section "$section-$i")"
if [ -z "$outbound_tags" ]; then
outbound_tags="$outbound_tag"
else
outbound_tags="$outbound_tags,$outbound_tag"
fi
i=$((i+1))
done
urltest_tag="$(get_outbound_tag_by_section "$section-urltest")"
selector_tag="$(get_outbound_tag_by_section "$section")"
urltest_outbounds="$(comma_string_to_json_array "$outbound_tags")"
selector_outbounds="$(comma_string_to_json_array "$outbound_tags,$urltest_tag")"
config="$(sing_box_cm_add_urltest_outbound "$config" "$urltest_tag" "$urltest_outbounds")"
config="$(sing_box_cm_add_selector_outbound "$config" "$selector_tag" "$selector_outbounds" "$urltest_tag")"
;;
*)
log "Unknown proxy configuration type: '$proxy_config_type'. Aborted." "fatal"
exit 1
@@ -1021,7 +1053,7 @@ import_local_domain_or_subnet_list() {
fi
local items json_array
items="$(parse_domain_or_subnet_file_to_comma_string "$tmpfile" "domains")"
items="$(parse_domain_or_subnet_file_to_comma_string "$filepath" "$type")"
if [ -z "$items" ]; then
log "No valid $type found in $filepath"
@@ -1375,7 +1407,7 @@ get_service_proxy_address() {
local detour
config_get_bool detour "main" "detour" 0
if [ "$detour" -eq 1 ]; then
echo "$SB_SERVICE_MIXED_INBOUND_TAG:$SB_SERVICE_MIXED_INBOUND_PORT"
echo "$SB_SERVICE_MIXED_INBOUND_ADDRESS:$SB_SERVICE_MIXED_INBOUND_PORT"
else
echo ""
fi

View File

@@ -16,10 +16,18 @@ is_ipv4_ip_or_ipv4_cidr() {
is_ipv4 "$1" || is_ipv4_cidr "$1"
}
# Check if string is valid domain
is_domain() {
local str="$1"
echo "$str" | grep -Eq '^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9]))+$'
local regex='^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$'
[[ "$str" =~ $regex ]]
}
is_domain_suffix() {
local str="$1"
local normalized="${str#.}"
is_domain "$normalized"
}
# Checks if the given string is a valid base64-encoded sequence
@@ -295,7 +303,7 @@ parse_domain_or_subnet_string_to_commas_string() {
for item in $string; do
case "$type" in
domains)
if ! is_domain "$item"; then
if ! is_domain_suffix "$item"; then
log "'$item' is not a valid domain" "debug"
continue
fi
@@ -341,7 +349,7 @@ parse_domain_or_subnet_file_to_comma_string() {
case "$type" in
domains)
if ! is_domain "$line"; then
if ! is_domain_suffix "$line"; then
log "'$line' is not a valid domain" "debug"
continue
fi

View File

@@ -832,6 +832,90 @@ sing_box_cm_add_raw_outbound() {
)]'
}
#######################################
# Add a URLTest outbound to the outbounds section of a sing-box JSON configuration.
# Arguments:
# config: JSON configuration
# tag: string, identifier for the URLTest outbound
# outbounds: JSON array of outbound tags to test
# url: URL to probe (optional)
# interval: test interval (e.g., "10s") (optional)
# tolerance: max latency difference tolerated (optional)
# idle_timeout: idle timeout duration (optional)
# interrupt_exist_connections: flag to interrupt existing connections ("true"/"false") (optional)
# Outputs:
# Writes updated JSON configuration to stdout
# Example:
# CONFIG=$(sing_box_cm_add_urltest_outbound "$CONFIG" "auto-select" '["proxy1","proxy2"]')
#######################################
sing_box_cm_add_urltest_outbound() {
local config="$1"
local tag="$2"
local outbounds="$3"
local url="$4"
local interval="$5"
local tolerance="$6"
local idle_timeout="$7"
local interrupt_exist_connections="$8"
echo "$config" | jq \
--arg tag "$tag" \
--argjson outbounds "$outbounds" \
--arg url "$url" \
--arg interval "$interval" \
--arg tolerance "$tolerance" \
--arg idle_timeout "$idle_timeout" \
--arg interrupt_exist_connections "$interrupt_exist_connections" \
'.outbounds += [
{
type: "urltest",
tag: $tag,
outbounds: $outbounds
}
+ (if $url != "" then {url: $url} else {} end)
+ (if $interval != "" then {interval: $interval} else {} end)
+ (if $tolerance != "" then {tolerance: ($tolerance | tonumber)} else {} end)
+ (if $idle_timeout != "" then {idle_timeout: $idle_timeout} else {} end)
+ (if $interrupt_exist_connections == "true" then {interrupt_exist_connections: true} else {} end)
]'
}
#######################################
# Add a Selector outbound to the outbounds section of a sing-box JSON configuration.
# Arguments:
# config: JSON configuration
# tag: string, identifier for the Selector outbound
# outbounds: JSON array of outbound tags to choose from
# default: default outbound tag if none selected (optional)
# interrupt_exist_connections: flag to interrupt existing connections ("true"/"false") (optional)
# Outputs:
# Writes updated JSON configuration to stdout
# Example:
# CONFIG=$(sing_box_cm_add_selector_outbound "$CONFIG" "select-proxy" '["proxy1","proxy2"]')
#######################################
sing_box_cm_add_selector_outbound() {
local config="$1"
local tag="$2"
local outbounds="$3"
local default="$4"
local interrupt_exist_connections="$5"
echo "$config" | jq \
--arg tag "$tag" \
--argjson outbounds "$outbounds" \
--arg default "$default" \
--arg interrupt_exist_connections "$interrupt_exist_connections" \
'.outbounds += [
{
type: "selector",
tag: $tag,
outbounds: $outbounds,
default: $default
}
+ (if $interrupt_exist_connections == "true" then {interrupt_exist_connections: true} else {} end)
]'
}
#######################################
# Configure the route section of a sing-box JSON configuration.
# Arguments: