Compare commits

..

27 Commits

Author SHA1 Message Date
itdoginfo
c46984b1e1 0.2.4 2024-11-13 15:43:16 +03:00
itdoginfo
fcb03ff51e Added install rus translate 2024-11-13 15:41:57 +03:00
itdoginfo
34ef7e074b Fix value #6 2024-11-13 15:41:21 +03:00
itdoginfo
be1db9626d Fixed alternative 2024-11-13 00:47:34 +03:00
itdoginfo
d232023140 Nft move br-lan to mark, renamed secondary, fixed po template 2024-11-13 00:44:26 +03:00
itdoginfo
a5d6b202a9 Update todo 2024-11-12 18:31:35 +03:00
itdoginfo
6cf88e319b Some fixes for #6 2024-11-12 18:11:44 +03:00
itdoginfo
f82503de0e Merge pull request #6 from VizzleTF/main
Вкладки + cron + перевод + ci
2024-11-12 16:09:15 +03:00
Ivan Kvashonkin
f520270864 refactor: Extract version from tag and add to translate ipk file 2024-11-11 21:23:25 +03:00
Ivan Kvashonkin
66c7eb0ccb feat: Improve custom routing options 2024-11-11 19:59:04 +03:00
Ivan Kvashonkin
52483887f4 fix: Rollout podkop init.d configuration 2024-11-11 19:08:06 +03:00
Ivan Kvashonkin
5195dfa715 feat: Add language translation package correct version 2024-11-11 18:51:34 +03:00
Ivan Kvashonkin
47699ee0d6 refactor: Optimize VPN/Proxy configuration messages 2024-11-11 18:46:52 +03:00
Ivan Kvashonkin
b6f1c4e747 refactor: Rename and update settings tab 2024-11-11 18:38:05 +03:00
Ivan Kvashonkin
b3678323ca feat: Consolidate settings into basic tab 2024-11-11 18:28:58 +03:00
Ivan Kvashonkin
d8a860fb2f fix: second proxy configuration fixing 2024-11-10 18:39:14 +03:00
Ivan Kvashonkin
56e93a3d5f refactor: Add ucisection attribute to taboptions 2024-11-10 17:40:23 +03:00
Ivan Kvashonkin
1ac1aa8f74 ci: Update CI build configuration 2024-11-10 16:11:03 +03:00
Ivan Kvashonkin
79761d9ba7 Merge branch 'main' of github.com:VizzleTF/podkop 2024-11-10 16:08:30 +03:00
Ivan Kvashonkin
6179306da9 fix: Fix secondary route configuration 2024-11-10 16:07:59 +03:00
Ivan K
8794fc72ed Update README.md 2024-11-09 20:29:13 +03:00
Ivan Kvashonkin
20d0d00620 docs: Remove GitHub link from description 2024-11-09 00:41:44 +03:00
Ivan K
9f5e99ab52 Streamline build (#1)
feat: Добавлена группировка по вкладкам
feat: Выбор частоты обновления списков по cron на вкладке Дополнительные настройки
feat: Перевод на русский язык
cicd: Добавлена поддержка пакета luci-i18n-podkop-ru
2024-11-09 00:04:17 +03:00
itdoginfo
f4485ba0b5 Merge pull request #3 from Slava-Shchipunov/main
Заменил инпут proxy string на textarea
2024-11-08 11:26:40 +03:00
Slava-Shchipunov
795ea2e384 feat: replace proxy string input to textarea 2024-11-08 02:10:33 +07:00
itdoginfo
4ba30ea117 Merge pull request #2 from Slava-Shchipunov/main
Добавил валидацию поля для ввода домена
2024-11-07 11:32:55 +03:00
Slava-Shchipunov
853af95404 feat: add domain input validation 2024-11-07 11:33:32 +07:00
12 changed files with 815 additions and 142 deletions

View File

@@ -1,5 +1,4 @@
name: Build packages name: Build packages
on: on:
push: push:
tags: tags:
@@ -9,7 +8,6 @@ jobs:
build: build:
name: Build podkop and luci-app-podkop name: Build podkop and luci-app-podkop
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4.2.1 - uses: actions/checkout@v4.2.1
@@ -27,10 +25,20 @@ jobs:
docker cp podkop:/builder/bin/packages/x86_64/utilites/. ./bin/ docker cp podkop:/builder/bin/packages/x86_64/utilites/. ./bin/
docker cp podkop:/builder/bin/packages/x86_64/luci/. ./bin/ docker cp podkop:/builder/bin/packages/x86_64/luci/. ./bin/
- name: Filter IPK files
run: |
# Извлекаем версию из тега, убирая префикс 'v'
VERSION=${GITHUB_REF#refs/tags/v}
mkdir -p ./filtered-bin
cp ./bin/luci-i18n-podkop-ru_*.ipk "./filtered-bin/luci-i18n-podkop-ru_${VERSION}.ipk"
cp ./bin/podkop_*.ipk ./filtered-bin/
cp ./bin/luci-app-podkop_*.ipk ./filtered-bin/
- name: Remove Docker container - name: Remove Docker container
run: docker rm podkop run: docker rm podkop
- name: Release - name: Release
uses: softprops/action-gh-release@v2.0.8 uses: softprops/action-gh-release@v2.0.8
with: with:
files: ./bin/*.ipk files: ./filtered-bin/*.ipk

View File

@@ -1,6 +1,6 @@
FROM openwrt/sdk:x86_64-v23.05.5 FROM openwrt/sdk:x86_64-v23.05.5
RUN ./scripts/feeds update -a && mkdir -p /builder/package/feeds/utilites/ && mkdir -p /builder/package/feeds/luci/ RUN ./scripts/feeds update -a && ./scripts/feeds install luci-base && mkdir -p /builder/package/feeds/utilites/ && mkdir -p /builder/package/feeds/luci/
COPY ./podkop /builder/package/feeds/utilites/podkop COPY ./podkop /builder/package/feeds/utilites/podkop
COPY ./luci-app-podkop /builder/package/feeds/luci/luci-app-podkop COPY ./luci-app-podkop /builder/package/feeds/luci/luci-app-podkop

View File

@@ -33,6 +33,11 @@ sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/mai
opkg remove luci-app-podkop podkop opkg remove luci-app-podkop podkop
``` ```
Если был установлен русский язык
```
opkg remove luci-i18n-podkop-ru
```
# Использование # Использование
Конфиг: /etc/config/podkop Конфиг: /etc/config/podkop
@@ -69,8 +74,10 @@ opkg update && opkg install sing-box
- [x] Не работает proxy при режимах main vpn, second proxy - [x] Не работает proxy при режимах main vpn, second proxy
- [x] Не всегда отрабатывает ucitrack (применение настроек из luci). Не удаётся повторить - [x] Не всегда отрабатывает ucitrack (применение настроек из luci). Не удаётся повторить
- [x] All traffic for IP ломает инет на клиенте. Proxy mode - [x] All traffic for IP ломает инет на клиенте. Proxy mode
- [ ] Не отрабатывает рестарт, при awg и не применяются изменения при awg - [x] Не отрабатывает рестарт, при awg и не применяются изменения при awg
- [ ] awg работает не стабильно - [x] awg работает не стабильно
- [ ] Сеть рестартится при любом раскладе
- [ ] Выкл-вкл wg через luci не отрабатывает поднятие маршрута
# ToDo # ToDo
Сделано Сделано
@@ -89,28 +96,34 @@ opkg update && opkg install sing-box
- [x] Вернуть две цепочки nft - [x] Вернуть две цепочки nft
- [x] Ntp (порт 123) делать маркировку 0x0. По галке - [x] Ntp (порт 123) делать маркировку 0x0. По галке
- [x] Открытый прокси порт на роутере для браузеров - [x] Открытый прокси порт на роутере для браузеров
- [x] Автонастройка wireguard по примеру getdomains
Приоритет 1 - [x] Автонастройка awg по примеру getdomains
- [x] RU перевод
- [x] Переделать на PROCD и выкинуть ucitrack. - [x] Переделать на PROCD и выкинуть ucitrack.
- [x] Нужен дебаг. Restart ucitrack в отдельный скрипт postinst, не отрабатывает. - [x] Нужен дебаг. Restart ucitrack в отдельный скрипт postinst, не отрабатывает.
- [x] Закомментировать дефолтные значения у list. interface поставить в пустое. - [x] Закомментировать дефолтные значения у list. interface поставить в пустое.
- [x] Скрипт установки: проверка установлен ли уже podkop. Если да, то просто предлагать обновится без установки тунелей и прокси. - [x] Скрипт установки: проверка установлен ли уже podkop. Если да, то просто предлагать обновится без установки тунелей и прокси.
Приоритет 1
- [x] Изменить название "Alternative Config"
- [x] "domain_service_enabled" Добавить _second
- [ ] Установка Ru пакета в install.sh
- [x] Правка nft mark, tproxy
- [x] Правка перевода минимальная
Приоритет 2 Приоритет 2
- [ ] Списки доменов и подсетей с роутера - [ ] Списки доменов и подсетей с роутера
- [ ] Кнопка обновления списка доменов и подсетей - [ ] Кнопка обновления списка доменов и подсетей
- [ ] IPv6 - [ ] IPv6
- [ ] Придумать автонастройку DNS через stubby итд. Как лучше это реализовать. - [ ] Придумать автонастройку DNS через stubby итд. Как лучше это реализовать.
- [ ] Удаление подсетей CF из domain sets раз в N часов - [ ] Удаление подсетей CF из domain sets раз в N часов
- [x] Автонастройка wireguard по примеру getdomains
- [x] Автонастройка awg по примеру getdomains
Wiki Wiki
- [x] Тема - [x] Тема
- [x] Изначальное наполнение - [x] Изначальное наполнение
Низкий приоритет Низкий приоритет
- [ ] Переменная, раз во сколько часов обновлять списки - [x] Переменная, раз во сколько часов обновлять списки
- [ ] Галочка, которая режет доступ к doh серверам - [ ] Галочка, которая режет доступ к doh серверам
- [ ] Свой конфиг sing-box - [ ] Свой конфиг sing-box
@@ -120,7 +133,6 @@ Wiki
- [ ] Формирование json для sing-box на уровне jq, а не шаблонов - [ ] Формирование json для sing-box на уровне jq, а не шаблонов
- [ ] Unit тесты (BATS) - [ ] Unit тесты (BATS)
- [ ] Интеграционые тесты бекенда (OpenWrt rootfs + BATS) - [ ] Интеграционые тесты бекенда (OpenWrt rootfs + BATS)
- [ ] RU перевод
Хз как сделать Хз как сделать
- [ ] Добавить label от конфига vless\ss\etc в luci. - [ ] Добавить label от конфига vless\ss\etc в luci.

View File

@@ -2,7 +2,7 @@
REPO="https://api.github.com/repos/itdoginfo/podkop/releases/latest" REPO="https://api.github.com/repos/itdoginfo/podkop/releases/latest"
IS_SHOULD_RESTART_NETWORK=false IS_SHOULD_RESTART_NETWORK=
DOWNLOAD_DIR="/tmp/podkop" DOWNLOAD_DIR="/tmp/podkop"
mkdir -p "$DOWNLOAD_DIR" mkdir -p "$DOWNLOAD_DIR"
@@ -54,7 +54,20 @@ fi
opkg install $DOWNLOAD_DIR/podkop*.ipk opkg install $DOWNLOAD_DIR/podkop*.ipk
opkg install $DOWNLOAD_DIR/luci-app-podkop*.ipk opkg install $DOWNLOAD_DIR/luci-app-podkop*.ipk
rm -f $DOWNLOAD_DIR/podkop*.ipk $DOWNLOAD_DIR/luci-app-podkop*.ipk echo "Русский язык интерфейса ставим? y/n (Need a Russian translation?)
while true; do
read -r -p '' RUS
case $RUS in
y)
opkg install $DOWNLOAD_DIR/luci-i18n-podkop-ru*.ipk
break
;;
esac
done
rm -f $DOWNLOAD_DIR/podkop*.ipk $DOWNLOAD_DIR/luci-app-podkop*.ipk $DOWNLOAD_DIR/luci-i18n-podkop-ru*.ipk
if [ "$IS_SHOULD_RESTART_NETWORK" ]; then if [ "$IS_SHOULD_RESTART_NETWORK" ]; then
printf "\033[32;1mRestart network\033[0m\n" printf "\033[32;1mRestart network\033[0m\n"

View File

@@ -1,19 +1,20 @@
# See /LICENSE for more information.
# This is free software, licensed under the GNU General Public License v2.
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-podkop PKG_NAME:=luci-app-podkop
PKG_VERSION:=0.2.3 PKG_VERSION:=0.2.4
PKG_RELEASE:=1 PKG_RELEASE:=1
LUCI_TITLE:=LuCI podkop app LUCI_TITLE:=LuCI podkop app
LUCI_DEPENDS:=+luci-base +podkop LUCI_DEPENDS:=+luci-base +podkop
LUCI_PKGARCH:=all LUCI_PKGARCH:=all
LUCI_LANG.ru:=Русский (Russian)
LUCI_LANG.en:=English
PKG_LICENSE:=GPL-2.0-or-later PKG_LICENSE:=GPL-2.0-or-later
PKG_MAINTAINER:=ITDog <podkop@itdog.info> PKG_MAINTAINER:=ITDog <podkop@itdog.info>
LUCI_LANGUAGES:=en ru
include $(TOPDIR)/feeds/luci/luci.mk include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature # call BuildPackage - OpenWrt buildroot signature

View File

@@ -8,28 +8,30 @@ return view.extend({
async render() { async render() {
var m, s, o; var m, s, o;
m = new form.Map('podkop', _('Podkop configuration')); m = new form.Map('podkop', _('Podkop configuration'), null, ['main', 'second']);
s = m.section(form.TypedSection, 'main'); s = m.section(form.TypedSection, 'main');
s.anonymous = true; s.anonymous = true;
o = s.tab('main', _('Main')); // Basic Settings Tab
o = s.tab('basic', _('Basic Settings'));
o = s.taboption('main', form.ListValue, 'mode', _('Mode'), _('Select VPN or Proxy')); o = s.taboption('basic', form.ListValue, 'mode', _('Connection Type'), _('Select between VPN and Proxy connection methods for traffic routing'));
o.value('vpn', ('VPN')); o.value('vpn', ('VPN'));
o.value('proxy', ('Proxy')); o.value('proxy', ('Proxy'));
o.ucisection = 'main';
o = s.taboption('main', form.Value, 'proxy_string', _('Proxy String'), _('String vless:// or ss://')); o = s.taboption('basic', form.TextValue, 'proxy_string', _('Proxy Configuration URL'), _('Enter connection string starting with vless:// or ss:// for proxy configuration'));
o.depends('mode', 'proxy'); o.depends('mode', 'proxy');
o.rows = 5;
o.ucisection = 'main';
// Get all interface o = s.taboption('basic', form.ListValue, 'interface', _('Network Interface'), _('Select network interface for VPN connection'));
o = s.taboption('main', form.ListValue, 'interface', _('Interface'), _('Specify the interface'));
o.depends('mode', 'vpn'); o.depends('mode', 'vpn');
o.ucisection = 'main';
try { try {
const devices = await network.getDevices(); const devices = await network.getDevices();
const excludeInterfaces = ['br-lan', 'eth0', 'eth1', 'wan', 'phy0-ap0', 'phy1-ap0']; const excludeInterfaces = ['br-lan', 'eth0', 'eth1', 'wan', 'phy0-ap0', 'phy1-ap0'];
devices.forEach(function (device) { devices.forEach(function (device) {
@@ -40,141 +42,289 @@ return view.extend({
if (!isExcluded) { if (!isExcluded) {
o.value(deviceName, deviceName); o.value(deviceName, deviceName);
} }
} else {
console.warn('Device name is undefined or empty');
} }
}); });
} catch (error) { } catch (error) {
console.error('Error fetching devices:', error); console.error('Error fetching devices:', error);
} }
o = s.taboption('main', form.Flag, 'domain_list_enabled', _('Domain list enable'), _('<a href="https://github.com/itdoginfo/allow-domains" target="_blank">github.com/itdoginfo/allow-domains</a>')); o = s.taboption('basic', form.Flag, 'domain_list_enabled', _('Community Domain Lists'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.ListValue, 'domain_list', _('Domain list'), _('Select a list')); o = s.taboption('basic', form.ListValue, 'domain_list', _('Domain List'), _('Select a list') + ' <a href="https://github.com/itdoginfo/allow-domains" target="_blank">github.com/itdoginfo/allow-domains</a>');
o.placeholder = 'placeholder'; o.placeholder = 'placeholder';
o.value('ru_inside', 'Russia inside'); o.value('ru_inside', 'Russia inside');
o.value('ru_outside', 'Russia outside'); o.value('ru_outside', 'Russia outside');
o.value('ua', 'Ukraine'); o.value('ua', 'Ukraine');
o.depends('domain_list_enabled', '1'); o.depends('domain_list_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.Flag, 'delist_domains_enabled', _('Delist domains from main list enable')); o = s.taboption('basic', form.Flag, 'delist_domains_enabled', _('Domain Exclusions'), _('Exclude specific domains from routing rules'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o.depends('domain_list_enabled', '1');
o = s.taboption('main', form.DynamicList, 'delist_domains', _('Delist domains'), _('Domains to be excluded')); o = s.taboption('basic', form.DynamicList, 'delist_domains', _('Excluded Domains'), _('Domains to be excluded from routing'));
o.placeholder = 'Delist domains'; o.placeholder = 'Delist domains';
o.depends('delist_domains_enabled', '1'); o.depends('delist_domains_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.Flag, 'subnets_list_enabled', _('Subnets list enable')); o = s.taboption('basic', form.Flag, 'subnets_list_enabled', _('Community Subnet Lists'), _('Enable routing for popular services like Twitter, Meta, and Discord'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.DynamicList, 'subnets', _('Subnets specify option')); o = s.taboption('basic', form.DynamicList, 'subnets', _('Service Networks'), _('Select predefined service networks for routing'));
o.placeholder = 'Subnet list'; o.placeholder = 'Service network list';
o.value('twitter', 'Twitter(x.com)'); o.value('twitter', 'Twitter(x.com)');
o.value('meta', 'Meta'); o.value('meta', 'Meta');
o.value('discord', 'Discord(voice)'); o.value('discord', 'Discord(voice)');
o.depends('subnets_list_enabled', '1'); o.depends('subnets_list_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.Flag, 'custom_domains_list_enabled', _('Custom domains enable')); o = s.taboption('basic', form.Flag, 'custom_domains_list_enabled', _('User Domain List'), _('Enable and manage your custom list of domains for selective routing'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.DynamicList, 'custom_domains', _('Your domains')); o = s.taboption('basic', form.DynamicList, 'custom_domains', _('User Domains'), _('Enter domain names without protocols (example: sub.example.com or example.com)'));
o.placeholder = 'Domains list'; o.placeholder = 'Domains list';
o.depends('custom_domains_list_enabled', '1'); o.depends('custom_domains_list_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o.validate = function (section_id, value) {
if (!value || value.length === 0) {
return true;
}
o = s.taboption('main', form.Flag, 'custom_download_domains_list_enabled', _('URL domains enable')); const domainRegex = /^(?!-)[A-Za-z0-9-]+([-.][A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
if (!domainRegex.test(value)) {
return _('Invalid domain format. Enter domain without protocol (example: sub.example.com)');
}
return true;
};
o = s.taboption('basic', form.Flag, 'custom_download_domains_list_enabled', _('Remote Domain Lists'), _('Download and use domain lists from remote URLs'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.DynamicList, 'custom_download_domains', _('Your URL domains')); o = s.taboption('basic', form.DynamicList, 'custom_download_domains', _('Remote Domain URLs'), _('Enter full URLs starting with http:// or https://'));
o.placeholder = 'URL'; o.placeholder = 'URL';
o.depends('custom_download_domains_list_enabled', '1'); o.depends('custom_download_domains_list_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o.validate = function (section_id, value) {
if (!value || value.length === 0) {
return true;
}
o = s.taboption('main', form.Flag, 'custom_subnets_list_enabled', _('Custom subnets enable')); try {
const url = new URL(value);
if (!['http:', 'https:'].includes(url.protocol)) {
return _('URL must use http:// or https:// protocol');
}
return true;
} catch (e) {
return _('Invalid URL format. URL must start with http:// or https://');
}
};
o = s.taboption('basic', form.Flag, 'custom_subnets_list_enabled', _('User Subnet List'), _('Enable and manage your custom list of IP subnets for selective routing'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.DynamicList, 'custom_subnets', _('Your subnet')); o = s.taboption('basic', form.DynamicList, 'custom_subnets', _('User Subnets'), _('Enter subnet in CIDR notation (example: 103.21.244.0/22)'));
o.placeholder = 'Subnets list'; o.placeholder = 'Subnets list';
o.depends('custom_subnets_list_enabled', '1'); o.depends('custom_subnets_list_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o.validate = function (section_id, value) {
if (!value || value.length === 0) {
return true;
}
o = s.taboption('main', form.Flag, 'custom_download_subnets_list_enabled', _('URL subnets enable')); const subnetRegex = /^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/;
if (!subnetRegex.test(value)) {
return _('Invalid subnet format. Use format: X.X.X.X/Y (like 103.21.244.0/22)');
}
const [ip, cidr] = value.split('/');
const ipParts = ip.split('.');
const cidrNum = parseInt(cidr);
for (const part of ipParts) {
const num = parseInt(part);
if (num < 0 || num > 255) {
return _('IP address parts must be between 0 and 255');
}
}
if (cidrNum < 0 || cidrNum > 32) {
return _('CIDR must be between 0 and 32');
}
return true;
};
o = s.taboption('basic', form.Flag, 'custom_download_subnets_list_enabled', _('Remote Subnet Lists'), _('Download and use subnet lists from remote URLs'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.DynamicList, 'custom_download_subnets', _('Your URL subnet')); o = s.taboption('basic', form.DynamicList, 'custom_download_subnets', _('Remote Subnet URLs'), _('Enter full URLs starting with http:// or https://'));
o.placeholder = 'URL'; o.placeholder = 'URL';
o.depends('custom_download_subnets_list_enabled', '1'); o.depends('custom_download_subnets_list_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o.validate = function (section_id, value) {
if (!value || value.length === 0) {
return true;
}
o = s.taboption('main', form.Flag, 'all_traffic_from_ip_enabled', _('IP for full redirection')); try {
const url = new URL(value);
if (!['http:', 'https:'].includes(url.protocol)) {
return _('URL must use http:// or https:// protocol');
}
return true;
} catch (e) {
return _('Invalid URL format. URL must start with http:// or https://');
}
};
o = s.taboption('basic', form.Flag, 'all_traffic_from_ip_enabled', _('IP for full redirection'), _('Specify local IP addresses whose traffic will always use the configured route'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.DynamicList, 'all_traffic_ip', _('Local IPs')); o = s.taboption('basic', form.DynamicList, 'all_traffic_ip', _('Local IPs'), _('Enter valid IPv4 addresses'));
o.placeholder = 'IP'; o.placeholder = 'IP';
o.depends('all_traffic_from_ip_enabled', '1'); o.depends('all_traffic_from_ip_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o.validate = function (section_id, value) {
if (!value || value.length === 0) {
return true;
}
o = s.taboption('main', form.Flag, 'exclude_from_ip_enabled', _('IP for full exclude')); const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/;
if (!ipRegex.test(value)) {
return _('Invalid IP format. Use format: X.X.X.X (like 192.168.1.1)');
}
const ipParts = value.split('.');
for (const part of ipParts) {
const num = parseInt(part);
if (num < 0 || num > 255) {
return _('IP address parts must be between 0 and 255');
}
}
return true;
};
o = s.taboption('basic', form.Flag, 'exclude_from_ip_enabled', _('IP for exclusion'), _('Specify local IP addresses that will never use the configured route'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.DynamicList, 'exclude_traffic_ip', _('Local IPs')); o = s.taboption('basic', form.DynamicList, 'exclude_traffic_ip', _('Local IPs'), _('Enter valid IPv4 addresses'));
o.placeholder = 'IP'; o.placeholder = 'IP';
o.depends('exclude_from_ip_enabled', '1'); o.depends('exclude_from_ip_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o.validate = function (section_id, value) {
if (!value || value.length === 0) {
return true;
}
o = s.taboption('main', form.Flag, 'yacd', _('Yacd enable'), _('http://openwrt.lan:9090/ui')); const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/;
if (!ipRegex.test(value)) {
return _('Invalid IP format. Use format: X.X.X.X (like 192.168.1.1)');
}
const ipParts = value.split('.');
for (const part of ipParts) {
const num = parseInt(part);
if (num < 0 || num > 255) {
return _('IP address parts must be between 0 and 255');
}
}
return true;
};
// Additional Settings Tab
o = s.tab('additional', _('Additional Settings'));
o = s.taboption('additional', form.Flag, 'yacd', _('Yacd enable'), _('http://openwrt.lan:9090/ui'));
o.default = '0'; o.default = '0';
o.depends('mode', 'proxy'); o.depends('mode', 'proxy');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.Flag, 'socks5', _('Mixed enable'), _('Browser port: 2080')); o = s.taboption('additional', form.Flag, 'socks5', _('Mixed enable'), _('Browser port: 2080'));
o.default = '0'; o.default = '0';
o.depends('mode', 'proxy'); o.depends('mode', 'proxy');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
o = s.taboption('main', form.Flag, 'exclude_ntp', _('Exclude NTP'), _('For issues with open connections sing-box')); o = s.taboption('additional', form.Flag, 'exclude_ntp', _('Exclude NTP'), _('For issues with open connections sing-box'));
o.default = '0'; o.default = '0';
o.depends('mode', 'proxy'); o.depends('mode', 'proxy');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main';
// Second section o = s.taboption('additional', form.ListValue, 'update_interval', _('List Update Frequency'), _('Select how often the lists will be updated'));
s = m.section(form.TypedSection, 'second'); o.value('0 */1 * * *', _('Every hour'));
s.anonymous = true; o.value('0 */2 * * *', _('Every 2 hours'));
o.value('0 */4 * * *', _('Every 4 hours'));
o.value('0 */6 * * *', _('Every 6 hours'));
o.value('0 */12 * * *', _('Every 12 hours'));
o.value('0 4 * * *', _('Once a day at 04:00'));
o.value('0 4 * * 0', _('Once a week on Sunday at 04:00'));
o.default = '0 4 * * *';
o.rmempty = false;
o.ucisection = 'main';
o = s.tab('second', _('Second')); // Secondary Settings Tab
o = s.taboption('second', form.Flag, 'second_enable', _('Second enable')); o = s.tab('secondary_config', _('Secondary Config'));
o = s.taboption('secondary_config', form.Flag, 'second_enable', _('Secondary VPN/Proxy Enable'), _('Enable secondary VPN/Proxy configuration'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'second';
o = s.taboption('second', form.ListValue, 'mode', _('Mode'), _('Select VPN or Proxy')); o = s.taboption('secondary_config', form.ListValue, 'second_mode', _('Connection Type'), _('Select between VPN and Proxy connection methods for traffic routing'));
o.value('vpn', ('VPN')); o.value('vpn', ('VPN'));
o.value('proxy', ('Proxy')); o.value('proxy', ('Proxy'));
o.depends('second_enable', '1'); o.depends('second_enable', '1');
o.ucisection = 'second';
o = s.taboption('second', form.Value, 'proxy_string', _('Proxy String'), _('String vless:// or ss://')); o = s.taboption('secondary_config', form.TextValue, 'second_proxy_string', _('Proxy Configuration URL'), _('Enter connection string starting with vless:// or ss:// for proxy configuration'));
o.depends('mode', 'proxy'); o.depends('second_mode', 'proxy');
o.ucisection = 'second';
// Get all interface o = s.taboption('secondary_config', form.ListValue, 'second_interface', _('Network Interface'), _('Select network interface for VPN connection'));
o = s.taboption('second', form.ListValue, 'interface', _('Interface'), _('Specify the interface')); o.depends('second_mode', 'vpn');
o.depends('mode', 'vpn'); o.ucisection = 'second';
try { try {
const devices = await network.getDevices(); const devices = await network.getDevices();
const excludeInterfaces = ['br-lan', 'eth0', 'eth1', 'wan', 'phy0-ap0', 'phy1-ap0']; const excludeInterfaces = ['br-lan', 'eth0', 'eth1', 'wan', 'phy0-ap0', 'phy1-ap0'];
devices.forEach(function (device) { devices.forEach(function (device) {
@@ -185,44 +335,88 @@ return view.extend({
if (!isExcluded) { if (!isExcluded) {
o.value(deviceName, deviceName); o.value(deviceName, deviceName);
} }
} else {
console.warn('Device name is undefined or empty');
} }
}); });
} catch (error) { } catch (error) {
console.error('Error fetching devices:', error); console.error('Error fetching devices:', error);
} }
o = s.taboption('second', form.Flag, 'domain_service_enabled', _('Domain service enable')); o = s.taboption('secondary_config', form.Flag, 'second_domain_service_enabled', _('Service Domain List Enable'), _('Enable predefined service domain lists for routing'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.depends('second_enable', '1'); o.depends('second_enable', '1');
o.ucisection = 'second';
o = s.taboption('second', form.ListValue, 'service_list', _('Service list'), _('Select a list')); o = s.taboption('secondary_config', form.ListValue, 'second_service_list', _('Service List'), _('Select predefined services for routing'));
o.placeholder = 'placeholder'; o.placeholder = 'placeholder';
o.value('youtube', 'Youtube'); o.value('youtube', 'Youtube');
o.depends('domain_service_enabled', '1'); o.depends('second_domain_service_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'second';
o = s.taboption('second', form.Flag, 'custom_domains_list_enabled', _('Custom domains enable')); o = s.taboption('secondary_config', form.Flag, 'second_custom_domains_list_enabled', _('User Domain List'), _('Enable and manage your custom list of domains for selective routing'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.depends('second_enable', '1'); o.depends('second_enable', '1');
o.ucisection = 'second';
o = s.taboption('second', form.DynamicList, 'custom_domains', _('Your domains')); o = s.taboption('secondary_config', form.DynamicList, 'second_custom_domains', _('User Domains'), _('Enter domain names without protocols (example: sub.example.com or example.com)'));
o.placeholder = 'Domains list'; o.placeholder = 'Domains list';
o.depends('custom_domains_list_enabled', '1'); o.depends('second_custom_domains_list_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'second';
o.validate = function (section_id, value) {
if (!value || value.length === 0) {
return true;
}
o = s.taboption('second', form.Flag, 'custom_subnets_list_enabled', _('Custom subnets enable')); const domainRegex = /^(?!-)[A-Za-z0-9-]+([-.][A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
if (!domainRegex.test(value)) {
return _('Invalid domain format. Enter domain without protocol (example: sub.example.com)');
}
return true;
};
o = s.taboption('secondary_config', form.Flag, 'second_custom_subnets_list_enabled', _('User Subnet List'), _('Enable and manage your custom list of IP subnets for selective routing'));
o.default = '0'; o.default = '0';
o.rmempty = false; o.rmempty = false;
o.depends('second_enable', '1'); o.depends('second_enable', '1');
o.ucisection = 'second';
o = s.taboption('second', form.DynamicList, 'custom_subnets', _('Your subnet')); o = s.taboption('secondary_config', form.DynamicList, 'second_custom_subnets', _('User Subnets'), _('Enter subnet in CIDR notation (example: 103.21.244.0/22)'));
o.placeholder = 'Subnets list'; o.placeholder = 'Subnets list';
o.depends('custom_subnets_list_enabled', '1'); o.depends('second_custom_subnets_list_enabled', '1');
o.rmempty = false; o.rmempty = false;
o.ucisection = 'second';
o.validate = function (section_id, value) {
if (!value || value.length === 0) {
return true;
}
const subnetRegex = /^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/;
if (!subnetRegex.test(value)) {
return _('Invalid subnet format. Use format: X.X.X.X/Y (like 103.21.244.0/22)');
}
const [ip, cidr] = value.split('/');
const ipParts = ip.split('.');
const cidrNum = parseInt(cidr);
for (const part of ipParts) {
const num = parseInt(part);
if (num < 0 || num > 255) {
return _('IP address parts must be between 0 and 255');
}
}
if (cidrNum < 0 || cidrNum > 32) {
return _('CIDR must be between 0 and 32');
}
return true;
};
return m.render(); return m.render();
} }

View File

@@ -0,0 +1,221 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Podkop configuration"
msgstr "Настройка Podkop"
msgid "Basic Settings"
msgstr "Основные настройки"
msgid "Additional Settings"
msgstr "Дополнительные настройки"
msgid "Secondary Config"
msgstr "Второй маршрут"
msgid "Secondary VPN/Proxy Enable"
msgstr "Включить второй VPN/Proxy"
msgid "Enable secondary VPN/Proxy configuration"
msgstr "Включить конфигурацию второго VPN/Proxy"
msgid "Connection Type"
msgstr "Тип подключения"
msgid "Select between VPN and Proxy connection methods for traffic routing"
msgstr "Выберите между VPN и Proxy методами для маршрутизации трафика"
msgid "Proxy Configuration URL"
msgstr "URL конфигурации прокси"
msgid "Enter connection string starting with vless:// or ss:// for proxy configuration"
msgstr "Введите строку подключения, начинающуюся с vless:// или ss:// для настройки прокси"
msgid "Network Interface"
msgstr "Сетевой интерфейс"
msgid "Select network interface for VPN connection"
msgstr "Выберите сетевой интерфейс для VPN подключения"
msgid "Community Domain Lists"
msgstr "Предустановленные списки доменов"
msgid "Domain List"
msgstr "Список доменов"
msgid "Select a list"
msgstr "Выберите список доменов"
msgid "Community Subnet Lists"
msgstr "Предустановленные сети сервисов"
msgid "Enable routing for popular services like Twitter, Meta, and Discord"
msgstr "Включить маршрутизацию для популярных сервисов, таких как Twitter, Meta и Discord"
msgid "Service Networks"
msgstr "Сети сервисов"
msgid "Select predefined service networks for routing"
msgstr "Выберите предустановленные сети сервисов для маршрутизации"
msgid "User Domain List"
msgstr "Пользовательский список доменов"
msgid "Enable and manage your custom list of domains for selective routing"
msgstr "Включить и управлять пользовательским списком доменов для выборочной маршрутизации"
msgid "User Domains"
msgstr "Пользовательские домены"
msgid "Enter domain names without protocols (example: sub.example.com or example.com)"
msgstr "Введите имена доменов без протоколов (пример: sub.example.com или example.com)"
msgid "Remote Domain Lists"
msgstr "Удаленные списки доменов"
msgid "Download and use domain lists from remote URLs"
msgstr "Загрузка и использование списков доменов с удаленных URL"
msgid "Remote Domain URLs"
msgstr "URL удаленных доменов"
msgid "Enter full URLs starting with http:// or https://"
msgstr "Введите полные URL, начинающиеся с http:// или https://"
msgid "User Subnet List"
msgstr "Пользовательский список подсетей"
msgid "Enable and manage your custom list of IP subnets for selective routing"
msgstr "Включить и управлять пользовательским списком IP-подсетей для выборочной маршрутизации"
msgid "User Subnets"
msgstr "Пользовательские подсети"
msgid "Enter subnet in CIDR notation (example: 103.21.244.0/22)"
msgstr "Введите подсеть в нотации CIDR (пример: 103.21.244.0/22)"
msgid "Remote Subnet Lists"
msgstr "Удаленные списки подсетей"
msgid "Download and use subnet lists from remote URLs"
msgstr "Загрузка и использование списков подсетей с удаленных URL"
msgid "Remote Subnet URLs"
msgstr "URL удаленных подсетей"
msgid "Domain Exclusions"
msgstr "Исключения доменов"
msgid "Exclude specific domains from routing rules"
msgstr "Исключить определенные домены из правил маршрутизации"
msgid "Excluded Domains"
msgstr "Исключенные домены"
msgid "Domains to be excluded from routing"
msgstr "Домены, которые будут исключены из маршрутизации"
msgid "IP for full redirection"
msgstr "Принудительные прокси IP"
msgid "Specify local IP addresses whose traffic will always use the configured route"
msgstr "Укажите локальные IP-адреса, трафик которых всегда будет использовать настроенный маршрут"
msgid "Local IPs"
msgstr "Локальные IP"
msgid "Enter valid IPv4 addresses"
msgstr "Введите действительные IPv4 адреса"
msgid "IP for exclusion"
msgstr "Исключения прокси IP"
msgid "Specify local IP addresses that will never use the configured route"
msgstr "Укажите локальные IP-адреса, которые никогда не будут использовать настроенный маршрут"
msgid "List Update Frequency"
msgstr "Частота обновления списков"
msgid "Select how often the lists will be updated"
msgstr "Выберите, как часто будут обновляться списки"
msgid "Every hour"
msgstr "Каждый час"
msgid "Every 2 hours"
msgstr "Каждые 2 часа"
msgid "Every 4 hours"
msgstr "Каждые 4 часа"
msgid "Every 6 hours"
msgstr "Каждые 6 часов"
msgid "Every 12 hours"
msgstr "Каждые 12 часов"
msgid "Once a day at 04:00"
msgstr "Раз в день в 04:00"
msgid "Once a week on Sunday at 04:00"
msgstr "Раз в неделю в воскресенье в 04:00"
msgid "Yacd enable"
msgstr "Включить Yacd"
msgid "Mixed enable"
msgstr "Включить смешанный режим"
msgid "Browser port: 2080"
msgstr "Порт браузера: 2080"
msgid "Exclude NTP"
msgstr "Исключить NTP"
msgid "For issues with open connections sing-box"
msgstr "Для проблем с открытыми соединениями sing-box"
msgid "Service Domain List Enable"
msgstr "Включить список доменов сервисов"
msgid "Enable predefined service domain lists for routing"
msgstr "Включить предустановленные списки доменов для маршрутизации"
msgid "Service List"
msgstr "Список сервисов"
msgid "Select predefined services for routing"
msgstr "Выберите предустановленные сервисы для маршрутизации"
msgid "Domains"
msgstr "Домены"
msgid "Subnet List"
msgstr "Список подсетей"
msgid "Configure custom subnets for routing"
msgstr "Настройка пользовательских подсетей для маршрутизации"
msgid "Subnets"
msgstr "Подсети"
msgid "Invalid domain format. Enter domain without protocol (example: sub.example.com)"
msgstr "Неверный формат домена. Введите домен без протокола (пример: sub.example.com)"
msgid "URL must use http:// or https:// protocol"
msgstr "URL должен использовать протокол http:// или https://"
msgid "Invalid URL format. URL must start with http:// or https://"
msgstr "Неверный формат URL. URL должен начинаться с http:// или https://"
msgid "Invalid subnet format. Use format: X.X.X.X/Y (like 192.168.1.0/24)"
msgstr "Неверный формат подсети. Используйте формат: X.X.X.X/Y (например: 192.168.1.0/24)"
msgid "IP address parts must be between 0 and 255"
msgstr "Части IP-адреса должны быть между 0 и 255"
msgid "CIDR must be between 0 and 32"
msgstr "CIDR должен быть между 0 и 32"
msgid "Invalid IP format. Use format: X.X.X.X (like 192.168.1.1)"
msgstr "Неверный формат IP. Используйте формат: X.X.X.X (например: 192.168.1.1)"

View File

@@ -0,0 +1,221 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Podkop configuration"
msgstr ""
msgid "Basic Settings"
msgstr ""
msgid "Additional Settings"
msgstr ""
msgid "Secondary Config"
msgstr ""
msgid "Secondary VPN/Proxy Enable"
msgstr ""
msgid "Enable secondary VPN/Proxy configuration"
msgstr ""
msgid "Connection Type"
msgstr ""
msgid "Select between VPN and Proxy connection methods for traffic routing"
msgstr ""
msgid "Proxy Configuration URL"
msgstr ""
msgid "Enter connection string starting with vless:// or ss:// for proxy configuration"
msgstr ""
msgid "Network Interface"
msgstr ""
msgid "Select network interface for VPN connection"
msgstr ""
msgid "Community Domain Lists"
msgstr ""
msgid "Domain List"
msgstr ""
msgid "Select a list"
msgstr ""
msgid "Community Subnet Lists"
msgstr ""
msgid "Enable routing for popular services like Twitter, Meta, and Discord"
msgstr ""
msgid "Service Networks"
msgstr ""
msgid "Select predefined service networks for routing"
msgstr ""
msgid "User Domain List"
msgstr ""
msgid "Enable and manage your custom list of domains for selective routing"
msgstr ""
msgid "User Domains"
msgstr ""
msgid "Enter domain names without protocols (example: sub.example.com or example.com)"
msgstr ""
msgid "Remote Domain Lists"
msgstr ""
msgid "Download and use domain lists from remote URLs"
msgstr ""
msgid "Remote Domain URLs"
msgstr ""
msgid "Enter full URLs starting with http:// or https://"
msgstr ""
msgid "User Subnet List"
msgstr ""
msgid "Enable and manage your custom list of IP subnets for selective routing"
msgstr ""
msgid "User Subnets"
msgstr ""
msgid "Enter subnet in CIDR notation (example: 103.21.244.0/22)"
msgstr ""
msgid "Remote Subnet Lists"
msgstr ""
msgid "Download and use subnet lists from remote URLs"
msgstr ""
msgid "Remote Subnet URLs"
msgstr ""
msgid "Domain Exclusions"
msgstr ""
msgid "Exclude specific domains from routing rules"
msgstr ""
msgid "Excluded Domains"
msgstr ""
msgid "Domains to be excluded from routing"
msgstr ""
msgid "IP for full redirection"
msgstr ""
msgid "Specify local IP addresses whose traffic will always use the configured route"
msgstr ""
msgid "Local IPs"
msgstr ""
msgid "Enter valid IPv4 addresses"
msgstr ""
msgid "IP for exclusion"
msgstr ""
msgid "Specify local IP addresses that will never use the configured route"
msgstr ""
msgid "List Update Frequency"
msgstr ""
msgid "Select how often the lists will be updated"
msgstr ""
msgid "Every hour"
msgstr ""
msgid "Every 2 hours"
msgstr ""
msgid "Every 4 hours"
msgstr ""
msgid "Every 6 hours"
msgstr ""
msgid "Every 12 hours"
msgstr ""
msgid "Once a day at 04:00"
msgstr ""
msgid "Once a week on Sunday at 04:00"
msgstr ""
msgid "Yacd enable"
msgstr ""
msgid "Mixed enable"
msgstr ""
msgid "Browser port: 2080"
msgstr ""
msgid "Exclude NTP"
msgstr ""
msgid "For issues with open connections sing-box"
msgstr ""
msgid "Service Domain List Enable"
msgstr ""
msgid "Enable predefined service domain lists for routing"
msgstr ""
msgid "Service List"
msgstr ""
msgid "Select predefined services for routing"
msgstr ""
msgid "Domains"
msgstr ""
msgid "Subnet List"
msgstr ""
msgid "Configure custom subnets for routing"
msgstr ""
msgid "Subnets"
msgstr ""
msgid "Invalid domain format. Enter domain without protocol (example: sub.example.com)"
msgstr ""
msgid "URL must use http:// or https:// protocol"
msgstr ""
msgid "Invalid URL format. URL must start with http:// or https://"
msgstr ""
msgid "Invalid subnet format. Use format: X.X.X.X/Y (like 103.21.244.0/22)"
msgstr ""
msgid "IP address parts must be between 0 and 255"
msgstr ""
msgid "CIDR must be between 0 and 32"
msgstr ""
msgid "Invalid IP format. Use format: X.X.X.X (like 192.168.1.1)"
msgstr ""

View File

@@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=podkop PKG_NAME:=podkop
PKG_VERSION:=0.2.3 PKG_VERSION:=0.2.4
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_MAINTAINER:=ITDog <podkop@itdog.info> PKG_MAINTAINER:=ITDog <podkop@itdog.info>

View File

@@ -23,15 +23,16 @@ config main 'main'
option yacd '0' option yacd '0'
option socks5 '0' option socks5 '0'
option exclude_ntp '0' option exclude_ntp '0'
option update_interval ''
config second 'second' config second 'second'
option second_enable '0' option second_enable '0'
option mode 'proxy' option second_mode 'proxy'
option interface 'wg1' option second_interface ''
option proxy_string '' option second_proxy_string ''
option domain_list_enabled '0' option second_domain_service_enabled '0'
#list domains 'youtube' #list second_service_list 'youtube'
option custom_domains_list_enabled '0' option second_custom_domains_list_enabled '0'
#list custom_domains 'ifconfig.io' #list second_custom_domains 'ifconfig.io'
option custom_subnets_list_enabled '0' option second_custom_subnets_list_enabled '0'
#list custom_subnets '' #list second_custom_subnets ''

View File

@@ -16,13 +16,13 @@ if [ "$mode" = "proxy" ]; then
fi fi
config_get second_enable "second" "second_enable" "0" config_get second_enable "second" "second_enable" "0"
config_get interface "second" "interface" "0" config_get second_interface "second" "second_interface" "0"
config_get "mode" "second" "mode" "0" config_get "second_mode" "second" "second_mode" "0"
if [ "$second_enable" -eq "1" ] && [ "$mode" = "vpn" ] && [ -n "$interface" ]; then if [ "$second_enable" -eq "1" ] && [ "$second_mode" = "vpn" ] && [ -n "$second_interface" ]; then
add_route_interface "$interface" "podkop2" add_route_interface "$second_interface" "podkop2"
fi fi
if [ "$second_enable" -eq "1" ] && [ "$mode" = "proxy" ]; then if [ "$second_enable" -eq "1" ] && [ "$second_mode" = "proxy" ]; then
echo "Add route for second tproxy" echo "Add route for second tproxy"
add_route_tproxy podkop2 add_route_tproxy podkop2
fi fi

View File

@@ -12,7 +12,8 @@ EXTRA_HELP=" list_update Updating domain and subnet lists
add_route_interface Adding route for interface add_route_interface Adding route for interface
sing_box_config_vless For test vless string" sing_box_config_vless For test vless string"
cron_job="0 4 * * * /etc/init.d/podkop list_update" config_get update_interval "main" "update_interval" "0 4 * * *"
cron_job="${update_interval} /etc/init.d/podkop list_update"
start_service() { start_service() {
log "Start podkop" log "Start podkop"
@@ -34,9 +35,9 @@ start_service() {
fi fi
config_get_bool second_enable "second" "second_enable" "0" config_get_bool second_enable "second" "second_enable" "0"
config_get mode "second" "mode" "0" config_get second_mode "second" "second_mode" "0"
if [ "$second_enable" -eq "1" ] && [ "$mode" = "proxy" ]; then if [ "$second_enable" -eq "1" ] && [ "$second_mode" = "proxy" ]; then
config_get proxy_string second "proxy_string" config_get proxy_string "second" "second_proxy_string"
if [[ "$proxy_string" =~ ^ss:// ]]; then if [[ "$proxy_string" =~ ^ss:// ]]; then
sing_box_config_shadowsocks "$proxy_string" "1603" sing_box_config_shadowsocks "$proxy_string" "1603"
elif [[ "$proxy_string" =~ ^vless:// ]]; then elif [[ "$proxy_string" =~ ^vless:// ]]; then
@@ -52,9 +53,9 @@ start_service() {
/etc/init.d/sing-box enable /etc/init.d/sing-box enable
fi fi
if [ "$second_enable" -eq "1" ] && [ "$mode" = "vpn" ]; then if [ "$second_enable" -eq "1" ] && [ "$second_mode" = "vpn" ]; then
log "VPN mode for second" log "VPN mode for second"
config_get interface "second" "interface" "0" config_get interface "second" "second_interface" "0"
if [ -n "$interface" ]; then if [ -n "$interface" ]; then
add_route_interface "$interface" "podkop2" add_route_interface "$interface" "podkop2"
else else
@@ -71,8 +72,8 @@ start_service() {
# Main - proxy, Second - proxy # Main - proxy, Second - proxy
config_get_bool second_enable "second" "second_enable" "0" config_get_bool second_enable "second" "second_enable" "0"
config_get mode "second" "mode" "0" config_get second_mode "second" "second_mode" "0"
if [ "$second_enable" -eq "1" ] && [ "$mode" = "proxy" ]; then if [ "$second_enable" -eq "1" ] && [ "$second_mode" = "proxy" ]; then
log "Two proxy enable" log "Two proxy enable"
outbound_main=$(mktemp) outbound_main=$(mktemp)
outbound_second=$(mktemp) outbound_second=$(mktemp)
@@ -87,7 +88,7 @@ start_service() {
return return
fi fi
config_get proxy_string second "proxy_string" config_get proxy_string "second" "second_proxy_string"
if [[ "$proxy_string" =~ ^ss:// ]]; then if [[ "$proxy_string" =~ ^ss:// ]]; then
sing_box_config_outbound_shadowsocks "$proxy_string" "$outbound_second" second sing_box_config_outbound_shadowsocks "$proxy_string" "$outbound_second" second
elif [[ "$proxy_string" =~ ^vless:// ]]; then elif [[ "$proxy_string" =~ ^vless:// ]]; then
@@ -108,8 +109,8 @@ start_service() {
# Main proxy, second disable/vpn # Main proxy, second disable/vpn
config_get_bool second_enable "second" "second_enable" "0" config_get_bool second_enable "second" "second_enable" "0"
config_get mode "second" "mode" "0" config_get second_mode "second" "second_mode" "0"
if [ "$second_enable" -eq "0" ] || [ "$mode" = "vpn" ]; then if [ "$second_enable" -eq "0" ] || [ "$second_mode" = "vpn" ]; then
config_get proxy_string main "proxy_string" config_get proxy_string main "proxy_string"
if [[ "$proxy_string" =~ ^ss:// ]]; then if [[ "$proxy_string" =~ ^ss:// ]]; then
sing_box_config_shadowsocks "$proxy_string" "1602" sing_box_config_shadowsocks "$proxy_string" "1602"
@@ -129,11 +130,11 @@ start_service() {
# Main proxy, Second VPN # Main proxy, Second VPN
config_get_bool second_enable "second" "second_enable" "0" config_get_bool second_enable "second" "second_enable" "0"
config_get mode "second" "mode" "0" config_get second_mode "second" "second_mode" "0"
if [ "$second_enable" -eq "1" ] && [ "$mode" = "vpn" ]; then if [ "$second_enable" -eq "1" ] && [ "$second_mode" = "vpn" ]; then
log "VPN mode for seconds" log "VPN mode for seconds"
log "You are using VPN mode, make sure you have installed all the necessary packages, configured, created the zone and forwarding." log "You are using VPN mode, make sure you have installed all the necessary packages, configured, created the zone and forwarding."
config_get interface "second" "interface" "0" config_get interface "second" "second_interface" "0"
if [ -n "$interface" ]; then if [ -n "$interface" ]; then
add_route_interface "$interface" "podkop2" add_route_interface "$interface" "podkop2"
else else
@@ -224,7 +225,7 @@ stop_service() {
log "Stop sing-box" log "Stop sing-box"
config_get mode_main "main" "mode" "0" config_get mode_main "main" "mode" "0"
config_get mode_second "second" "mode" "0" config_get mode_second "second" "second_mode" "0"
if [ "$mode_main" = "proxy" ] || [ "$mode_second" = "proxy" ]; then if [ "$mode_main" = "proxy" ] || [ "$mode_second" = "proxy" ]; then
/etc/init.d/sing-box stop /etc/init.d/sing-box stop
@@ -259,18 +260,16 @@ log() {
} }
add_cron_job() { add_cron_job() {
if ! crontab -l | grep -q "podkop"; then remove_cron_job
#echo "$cron_job" >>/etc/crontabs/root crontab -l | {
crontab -l | { cat
cat echo "$cron_job"
echo "$cron_job" } | crontab -
} | crontab - log "The cron job has been created: $cron_job"
log "The cron job has been created"
fi
} }
remove_cron_job() { remove_cron_job() {
sed -i "\|podkop|d" /etc/crontabs/root (crontab -l | grep -v "/etc/init.d/podkop list_update") | crontab -
log "The cron job removed" log "The cron job removed"
} }
@@ -311,27 +310,27 @@ list_update() {
/etc/init.d/dnsmasq restart /etc/init.d/dnsmasq restart
fi fi
config_get_bool custom_domains_list_enabled "second" "custom_domains_list_enabled" "0" config_get_bool second_custom_domains_list_enabled "second" "second_custom_domains_list_enabled" "0"
if [ "$custom_domains_list_enabled" -eq 1 ]; then if [ "$second_custom_domains_list_enabled" -eq 1 ]; then
log "Adding a custom domains list. Second podkop" log "Adding a custom domains list. Second podkop"
add_set "podkop2_domains" "second" add_set "podkop2_domains" "second"
rm -f /tmp/dnsmasq.d/podkop2-custom-domains.lst rm -f /tmp/dnsmasq.d/podkop2-custom-domains.lst
config_list_foreach second custom_domains "list_delist_domains" config_list_foreach second second_custom_domains "list_delist_domains"
config_list_foreach second custom_domains "list_custom_domains_create" "podkop2" config_list_foreach second second_custom_domains "list_custom_domains_create" "podkop2"
dnsmasq_config_check podkop2-custom-domains.lst dnsmasq_config_check podkop2-custom-domains.lst
fi fi
config_get_bool domain_service_enabled "second" "domain_service_enabled" "0" config_get_bool second_domain_service_enabled "second" "second_domain_service_enabled" "0"
if [ "$domain_service_enabled" -eq 1 ]; then if [ "$second_domain_service_enabled" -eq 1 ]; then
log "Adding a service for podkop2" log "Adding a service for podkop2"
add_set "podkop2_domains" "second" add_set "podkop2_domains" "second"
config_get service_list second "service_list" config_get second_service_list second "second_service_list"
lists_services_download "$service_list" lists_services_download "$second_service_list"
config_list_foreach second custom_domains "list_delist_domains" config_list_foreach second second_custom_domains "list_delist_domains"
dnsmasq_config_check podkop2-domains.lst dnsmasq_config_check podkop2-domains.lst
fi fi
if [ "$custom_domains_list_enabled" -eq 1 ] || [ "$domain_service_enabled" -eq 1 ]; then if [ "$second_custom_domains_list_enabled" -eq 1 ] || [ "$second_domain_service_enabled" -eq 1 ]; then
/etc/init.d/dnsmasq restart /etc/init.d/dnsmasq restart
fi fi
@@ -358,11 +357,11 @@ list_update() {
config_list_foreach main custom_subnets "list_custom_subnets_create" "podkop" config_list_foreach main custom_subnets "list_custom_subnets_create" "podkop"
fi fi
config_get_bool custom_subnets_list_enabled "second" "custom_subnets_list_enabled" "0" config_get_bool second_custom_subnets_list_enabled "second" "second_custom_subnets_list_enabled" "0"
if [ "$custom_subnets_list_enabled" -eq 1 ]; then if [ "$second_custom_subnets_list_enabled" -eq 1 ]; then
log "Adding a custom subnets list. Second" log "Adding a custom subnets list. Second"
add_set "podkop2_subnets" "second" add_set "podkop2_subnets" "second"
config_list_foreach second custom_subnets "list_custom_subnets_create" "podkop2" config_list_foreach second second_custom_subnets "list_custom_subnets_create" "podkop2"
fi fi
} }
@@ -391,14 +390,18 @@ add_set() {
log "Create set $set_name" log "Create set $set_name"
nft add chain inet PodkopTable mangle { type filter hook prerouting priority -150 \; policy accept \;} nft add chain inet PodkopTable mangle { type filter hook prerouting priority -150 \; policy accept \;}
nft add set inet PodkopTable "$set_name" { type ipv4_addr\; flags interval\; auto-merge\; } nft add set inet PodkopTable "$set_name" { type ipv4_addr\; flags interval\; auto-merge\; }
config_get mode "$connect" "mode" if [ "$connect" = "main" ]; then
config_get mode "$connect" "mode"
else
config_get mode "$connect" "second_mode"
fi
case "$mode" in case "$mode" in
"vpn") "vpn")
if ! nft list chain inet PodkopTable mangle | grep -q "ip daddr @"$set_name" meta mark set"; then if ! nft list chain inet PodkopTable mangle | grep -q "ip daddr @"$set_name" meta mark set"; then
if [ "$connect" = "main" ]; then if [ "$connect" = "main" ]; then
nft add rule inet PodkopTable mangle ip daddr @"$set_name" meta mark set 0x105 counter nft add rule inet PodkopTable mangle iifname "br-lan" ip daddr @"$set_name" meta mark set 0x105 counter
elif [ "$connect" = "second" ]; then elif [ "$connect" = "second" ]; then
nft add rule inet PodkopTable mangle ip daddr @"$set_name" meta mark set 0x106 counter nft add rule inet PodkopTable mangle iifname "br-lan" ip daddr @"$set_name" meta mark set 0x106 counter
fi fi
fi fi
;; ;;
@@ -410,18 +413,18 @@ add_set() {
else else
log "Added nft rule tproxy" log "Added nft rule tproxy"
if [ "$connect" = "main" ]; then if [ "$connect" = "main" ]; then
nft add rule inet PodkopTable mangle ip daddr @"$set_name" meta l4proto tcp meta mark set 0x105 counter nft add rule inet PodkopTable mangle iifname "br-lan" ip daddr @"$set_name" meta l4proto tcp meta mark set 0x105 counter
nft add rule inet PodkopTable mangle ip daddr @"$set_name" meta l4proto udp meta mark set 0x105 counter nft add rule inet PodkopTable mangle iifname "br-lan" ip daddr @"$set_name" meta l4proto udp meta mark set 0x105 counter
if ! ( nft list table inet PodkopTable | grep -q "meta mark 0x00000105 meta l4proto tcp tproxy" ); then if ! ( nft list table inet PodkopTable | grep -q "meta mark 0x00000105 meta l4proto tcp tproxy" ); then
nft add rule inet PodkopTable proxy iifname "br-lan" meta mark 0x105 meta l4proto tcp tproxy ip to :1602 counter nft add rule inet PodkopTable proxy meta mark 0x105 meta l4proto tcp tproxy ip to :1602 counter
nft add rule inet PodkopTable proxy iifname "br-lan" meta mark 0x105 meta l4proto udp tproxy ip to :1602 counter nft add rule inet PodkopTable proxy meta mark 0x105 meta l4proto udp tproxy ip to :1602 counter
fi fi
elif [ "$connect" = "second" ]; then elif [ "$connect" = "second" ]; then
nft add rule inet PodkopTable mangle ip daddr @"$set_name" meta l4proto tcp meta mark set 0x106 counter nft add rule inet PodkopTable mangle iifname "br-lan" ip daddr @"$set_name" meta l4proto tcp meta mark set 0x106 counter
nft add rule inet PodkopTable mangle ip daddr @"$set_name" meta l4proto udp meta mark set 0x106 counter nft add rule inet PodkopTable mangle iifname "br-lan" ip daddr @"$set_name" meta l4proto udp meta mark set 0x106 counter
if ! ( nft list table inet PodkopTable | grep -q "meta mark 0x00000106 meta l4proto tcp tproxy" ); then if ! ( nft list table inet PodkopTable | grep -q "meta mark 0x00000106 meta l4proto tcp tproxy" ); then
nft add rule inet PodkopTable proxy iifname "br-lan" meta mark 0x106 meta l4proto tcp tproxy ip to :1603 counter nft add rule inet PodkopTable proxy meta mark 0x106 meta l4proto tcp tproxy ip to :1603 counter
nft add rule inet PodkopTable proxy iifname "br-lan" meta mark 0x106 meta l4proto udp tproxy ip to :1603 counter nft add rule inet PodkopTable proxy meta mark 0x106 meta l4proto udp tproxy ip to :1603 counter
fi fi
fi fi
fi fi
@@ -659,7 +662,7 @@ list_all_traffic_from_ip() {
if ! nft list chain inet PodkopTable mangle | grep -q "ip saddr $ip"; then if ! nft list chain inet PodkopTable mangle | grep -q "ip saddr $ip"; then
config_get mode "main" "mode" "0" config_get mode "main" "mode" "0"
if [ "$mode" = "vpn" ]; then if [ "$mode" = "vpn" ]; then
nft insert rule inet PodkopTable mangle ip saddr $ip meta mark set 0x105 counter nft insert rule inet PodkopTable mangle iifname "br-lan" ip saddr $ip meta mark set 0x105 counter
elif [ "$mode" = "proxy" ]; then elif [ "$mode" = "proxy" ]; then
nft add set inet PodkopTable localv4 { type ipv4_addr\; flags interval\; } nft add set inet PodkopTable localv4 { type ipv4_addr\; flags interval\; }
nft add element inet PodkopTable localv4 { \ nft add element inet PodkopTable localv4 { \
@@ -677,7 +680,7 @@ list_all_traffic_from_ip() {
203.0.113.0/24, \ 203.0.113.0/24, \
224.0.0.0/4, \ 224.0.0.0/4, \
240.0.0.0-255.255.255.255 } 240.0.0.0-255.255.255.255 }
nft insert rule inet PodkopTable mangle ip saddr $ip meta l4proto { tcp, udp } meta mark set 0x105 counter nft insert rule inet PodkopTable mangle iifname "br-lan" ip saddr $ip meta l4proto { tcp, udp } meta mark set 0x105 counter
nft insert rule inet PodkopTable mangle ip saddr $ip ip daddr @localv4 return nft insert rule inet PodkopTable mangle ip saddr $ip ip daddr @localv4 return
fi fi
fi fi
@@ -840,7 +843,6 @@ sing_box_config_vless() {
end)' "$template_config" >/etc/sing-box/config.json end)' "$template_config" >/etc/sing-box/config.json
} }
# make one function for full and outbound only
sing_box_config_outbound_shadowsocks() { sing_box_config_outbound_shadowsocks() {
local STRING="$1" local STRING="$1"
local outbound="$2" local outbound="$2"