Compare commits

...

25 Commits

Author SHA1 Message Date
itdoginfo
e86bffb720 v0.3.8 2025-02-17 16:04:34 +03:00
itdoginfo
fb65b63639 Merge pull request #25 from VizzleTF/main
docs(ru): add new translations for podkop configuration
2025-02-17 15:51:19 +03:00
itdoginfo
daf7e30ed1 dnsmasq add 8.8.8.8. Validate domain_list 2025-02-17 15:22:55 +03:00
itdoginfo
dd62ecfbeb Check sing-box 2025-02-17 13:20:28 +03:00
Ivan K
41cb8cd650 Merge branch 'itdoginfo:main' into main 2025-02-17 13:08:35 +03:00
Ivan K
b7ad256986 docs(ru): add new translations for podkop configuration 2025-02-17 13:07:11 +03:00
itdoginfo
f88ffa1893 Fix install logic 2025-02-17 12:44:48 +03:00
itdoginfo
6f604ca765 Update 2025-02-16 17:53:14 +03:00
itdoginfo
52c6eeae12 Fix version 2025-02-16 17:52:57 +03:00
itdoginfo
778f2897bc Fix check iptables 2025-02-16 17:41:58 +03:00
itdoginfo
ca7bb77356 Fix 2025-02-16 16:57:16 +03:00
itdoginfo
da8195b795 Fix migrate 2025-02-16 15:59:07 +03:00
itdoginfo
98129720bb rm until 2025-02-16 14:29:50 +03:00
itdoginfo
3c1865c8a3 Expanding checkes. DNS 127.0.0.42. QUIC disable. Some fixes 2025-02-16 14:18:19 +03:00
itdoginfo
77ac728d47 Check sing-box 2025-02-16 12:16:43 +03:00
itdoginfo
1b5cfa3371 Move check sing-box to start 2025-02-15 23:32:18 +03:00
itdoginfo
590e040958 v0.3.4 2025-02-15 22:23:55 +03:00
itdoginfo
2323d426dd tmp check br-lan 2025-02-15 22:12:25 +03:00
itdoginfo
9bcc80f2be Checking file uploads 2025-02-15 19:17:59 +03:00
itdoginfo
bfde7518fb Merge pull request #20 from VizzleTF/main
feat(podkop): add show config + version features
2025-02-15 18:21:47 +03:00
Ivan K
18d466e166 feat(podkop): add version display in UI
- Added version display in Podkop UI
- Updated init script to fetch and display version
2025-02-15 17:58:39 +03:00
Ivan K
a30752d2e9 fix(init.d): decode URL-encoded characters in get_param
- Replaced `uhttpd` with `sed` for URL decoding
2025-02-15 17:47:09 +03:00
Ivan K
eb18537370 feat(podkop): add show_version command
- Update init script to include show_version command
- Add show_version function to display current version
- Update EXTRA_COMMANDS to include show_version
- Remove version from web and config
2025-02-15 17:30:14 +03:00
Ivan K
aa86445332 feat(podkop): add show config feature
- Add new button to show config with masked sensitive data
- Update init script with new command `show_config`
- Implement `show_config` function to mask sensitive data
- Update version in config file to 0.3.3
- Update proxy check logic for better error handling
2025-02-15 16:55:51 +03:00
itdoginfo
f1e7bfc377 Added procd instance 2025-02-15 14:32:40 +03:00
9 changed files with 520 additions and 154 deletions

View File

@@ -2,11 +2,13 @@
- Это альфа версия, которая находится в активной разработке. Из версии в версию что-то может меняться. - Это альфа версия, которая находится в активной разработке. Из версии в версию что-то может меняться.
- Основной функционал работает, но побочные штуки сейчас могут сбоить. - Основной функционал работает, но побочные штуки сейчас могут сбоить.
- При обновлении всегда заходите в конфигурацию и проверяйте свои настройки. Конфигурация может измениться. - При обновлении **обязатально** сбрасывайте кэш LuCI.
- Также при обновлении всегда заходите в конфигурацию и проверяйте свои настройки. Конфигурация может измениться.
- Необходимо минимум 15МБ свободного места на роутере. Роутерами с флешками на 16МБ сразу мимо. - Необходимо минимум 15МБ свободного места на роутере. Роутерами с флешками на 16МБ сразу мимо.
- При старте программы редактируется конфиг Dnsmasq. - При старте программы редактируется конфиг Dnsmasq.
- Podkop редактирует конфиг sing-box. Обязательно сохраните ваш конфиг sing-box перед установкой, если он вам нужен. - Podkop редактирует конфиг sing-box. Обязательно сохраните ваш конфиг sing-box перед установкой, если он вам нужен.
- Информация здесь может быть устаревшей. Все изменения фиксируются в телеграм-чате https://t.me/itdogchat - топик **Podkop**. - Информация здесь может быть устаревшей. Все изменения фиксируются в телеграм-чате https://t.me/itdogchat - топик **Podkop**.
- Если у вас не что-то не работает, то следуюет сходить в телеграм чат, прочитать закрепы и выполнить что там написано..
- Если у вас установлен Getdomains, его следует удалить. - Если у вас установлен Getdomains, его следует удалить.
# Удаление GetDomains скриптом # Удаление GetDomains скриптом
@@ -18,7 +20,8 @@ sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/domain-routing-openwr
# Установка Podkop # Установка Podkop
Пакет работает на всех архитектурах. Пакет работает на всех архитектурах.
Тестировался на OpenWrt 23.05 и OpenWrt 24.10. Тестировался на **ванильной** OpenWrt 23.05 и OpenWrt 24.10.
На FriendlyWrt 23.05 присуствуют зависимости от iptables, которые ломают tproxy. Если у вас появляется warning про это в логах, следуйте инструкции по приведённой там ссылке.
Поддержки APK на данный момент нет. APK будет сделан после того как разгребу основное. Поддержки APK на данный момент нет. APK будет сделан после того как разгребу основное.
@@ -148,6 +151,8 @@ Luci: Services/podkop
- [ ] Диагностика: podkop_domains: 0 elements как проверять что доходят запросы при fakeip? Мб врубать логи dnsmasq и их чекать. - [ ] Диагностика: podkop_domains: 0 elements как проверять что доходят запросы при fakeip? Мб врубать логи dnsmasq и их чекать.
- [ ] Сделать галку запрещающую подкопу редачить dhcp. Допилить в исключение вместе с пустыми полями proxy и vpn - [ ] Сделать галку запрещающую подкопу редачить dhcp. Допилить в исключение вместе с пустыми полями proxy и vpn
- [ ] Валидации предустановленных значений. Если прописаны другие, то вывод в лог о неизвестной переменной и продолжение работы - [ ] Валидации предустановленных значений. Если прописаны другие, то вывод в лог о неизвестной переменной и продолжение работы
- [ ] Добавление в список доменов домены первого уровня (LuCI)
- [ ] Проверка, что версия в makefile совпадает с тегом
Приоритет 2 Приоритет 2
- [x] Списки доменов и подсетей с роутера - [x] Списки доменов и подсетей с роутера

View File

@@ -4,24 +4,21 @@ REPO="https://api.github.com/repos/itdoginfo/podkop/releases/latest"
IS_SHOULD_RESTART_NETWORK= IS_SHOULD_RESTART_NETWORK=
DOWNLOAD_DIR="/tmp/podkop" DOWNLOAD_DIR="/tmp/podkop"
COUNT=3
rm -rf "$DOWNLOAD_DIR"
mkdir -p "$DOWNLOAD_DIR" mkdir -p "$DOWNLOAD_DIR"
main() { main() {
check_system check_system
sing_box
wget -qO- "$REPO" | grep -o 'https://[^"]*\.ipk' | while read -r url; do
filename=$(basename "$url")
echo "Download $filename..."
wget -q -O "$DOWNLOAD_DIR/$filename" "$url"
done
echo "opkg update"
opkg update opkg update
if [ -f "/etc/init.d/podkop" ]; then if [ -f "/etc/init.d/podkop" ]; then
printf "\033[32;1mPodkop is already installed. Just upgrade it? (y/n)\033[0m\n" printf "\033[32;1mPodkop is already installed. Just upgrade it? (y/n)\033[0m\n"
printf "\033[32;1my - Only upgrade podkop\033[0m\n" printf "\033[32;1my - Only upgrade podkop\033[0m\n"
printf "\033[32;1mn - Upgrade and install proxy or tunnels\033[0m\n" printf "\033[32;1mn - Upgrade and install tunnels (WG, AWG, OpenVPN, OC)\033[0m\n"
while true; do while true; do
read -r -p '' UPDATE read -r -p '' UPDATE
@@ -46,28 +43,59 @@ main() {
add_tunnel add_tunnel
fi fi
opkg install $DOWNLOAD_DIR/podkop*.ipk wget -qO- "$REPO" | grep -o 'https://[^"[:space:]]*\.ipk' | while read -r url; do
opkg install $DOWNLOAD_DIR/luci-app-podkop*.ipk filename=$(basename "$url")
filepath="$DOWNLOAD_DIR/$filename"
echo "Русский язык интерфейса ставим? y/n (Need a Russian translation?)" attempt=0
while true; do while [ $attempt -lt $COUNT ]; do
read -r -p '' RUS if [ -f "$filepath" ] && [ -s "$filepath" ]; then
case $RUS in echo "$filename has already been uploaded"
y) break
opkg install $DOWNLOAD_DIR/luci-i18n-podkop-ru*.ipk fi
break
;;
n) echo "Download $filename (count $((attempt+1)))..."
break wget -q -O "$filepath" "$url"
;;
if [ -s "$filepath" ]; then
*) echo "$filename successfully downloaded"
echo "Please enter y or n" else
;; echo "Download error $filename. Retry..."
esac rm -f "$filepath"
fi
attempt=$((attempt+1))
done
done done
for pkg in podkop luci-app-podkop; do
file=$(ls "$DOWNLOAD_DIR" | grep "^$pkg" | head -n 1)
if [ -n "$file" ]; then
echo "Installing $file"
opkg install "$DOWNLOAD_DIR/$file"
fi
done
ru=$(ls "$DOWNLOAD_DIR" | grep "luci-i18n-podkop-ru" | head -n 1)
if [ -n "$ru" ]; then
printf "\033[32;1mРусский язык интерфейса ставим? y/n (Need a Russian translation?)\033[0m "
while true; do
read -r -p '' RUS
case $RUS in
y)
opkg install "$DOWNLOAD_DIR/$ru"
break
;;
n)
break
;;
*)
echo "Введите y или n"
;;
esac
done
fi
rm -f $DOWNLOAD_DIR/podkop*.ipk $DOWNLOAD_DIR/luci-app-podkop*.ipk $DOWNLOAD_DIR/luci-i18n-podkop-ru*.ipk 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
@@ -77,7 +105,7 @@ main() {
} }
add_tunnel() { add_tunnel() {
echo "Will you be using Wireguard, AmneziaWG, OpenVPN, OpenConnect? If yes, select a number and they will be automatically installed" printf "\033[32;1mWill you be using Wireguard, AmneziaWG, OpenVPN, OpenConnect? If yes, select a number and they will be automatically installed\033[0m "
echo "1) Wireguard" echo "1) Wireguard"
echo "2) AmneziaWG" echo "2) AmneziaWG"
echo "3) OpenVPN" echo "3) OpenVPN"
@@ -129,7 +157,7 @@ add_tunnel() {
;; ;;
5) 5)
echo "Skip. Use this if you're installing an upgrade." echo "Installation without additional dependencies."
break break
;; ;;
@@ -367,18 +395,37 @@ check_system() {
echo "Router model: $MODEL" echo "Router model: $MODEL"
# Check available space # Check available space
AVAILABLE_SPACE=$(df /tmp | awk 'NR==2 {print $4}') AVAILABLE_SPACE=$(df /overlay | awk 'NR==2 {print $4}')
REQUIRED_SPACE=15360 # 15MB in KB REQUIRED_SPACE=15360 # 15MB in KB
echo "Available space: $((AVAILABLE_SPACE/1024))MB"
echo "Required space: $((REQUIRED_SPACE/1024))MB"
if [ "$AVAILABLE_SPACE" -lt "$REQUIRED_SPACE" ]; then if [ "$AVAILABLE_SPACE" -lt "$REQUIRED_SPACE" ]; then
echo "Error: Insufficient space in /tmp" printf "\033[31;1mError: Insufficient space in flash\033[0m\n"
echo "Available: $((AVAILABLE_SPACE/1024))MB" echo "Available: $((AVAILABLE_SPACE/1024))MB"
echo "Required: $((REQUIRED_SPACE/1024))MB" echo "Required: $((REQUIRED_SPACE/1024))MB"
exit 1 exit 1
fi fi
if ! nslookup google.com >/dev/null 2>&1; then
log "DNS not working"
exit 1
fi
if opkg list-installed | grep -qE "iptables|kmod-iptab"; then
printf "\033[31;1mFound incompatible iptables packages. If you're using FriendlyWrt: https://t.me/itdogchat/44512/181082\033[0m\n"
fi
}
sing_box() {
if ! opkg list-installed | grep -q "^sing-box"; then
return
fi
sing_box_version=$(sing-box version | head -n 1 | awk '{print $3}')
required_version="1.11.1"
if [ "$(echo -e "$sing_box_version\n$required_version" | sort -V | head -n 1)" != "$required_version" ]; then
opkg remove sing-box
fi
} }
main main

View File

@@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-podkop PKG_NAME:=luci-app-podkop
PKG_VERSION:=0.3.2 PKG_VERSION:=0.3.8
PKG_RELEASE:=1 PKG_RELEASE:=1
LUCI_TITLE:=LuCI podkop app LUCI_TITLE:=LuCI podkop app

View File

@@ -7,10 +7,20 @@
return view.extend({ return view.extend({
async render() { async render() {
document.getElementsByTagName('head')[0].insertAdjacentHTML('beforeend', `
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
`);
var m, s, o; var m, s, o;
m = new form.Map('podkop', _('Podkop configuration'), null, ['main', 'second']); m = new form.Map('podkop', _('Podkop configuration'), null, ['main', 'second']);
fs.exec('/etc/init.d/podkop', ['show_version']).then(function (res) {
if (res.stdout) {
m.title = _('Podkop') + ' v' + res.stdout.trim();
}
});
s = m.section(form.TypedSection, 'main'); s = m.section(form.TypedSection, 'main');
s.anonymous = true; s.anonymous = true;
@@ -394,13 +404,16 @@ return view.extend({
o = s.taboption('additional', form.Flag, 'yacd', _('Yacd enable'), _('http://openwrt.lan:9090/ui')); 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.rmempty = false; o.rmempty = false;
o.ucisection = 'main'; o.ucisection = 'main';
o = s.taboption('additional', 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.rmempty = false;
o.ucisection = 'main';
o = s.taboption('additional', form.Flag, 'quic_disable', _('QUIC disable'), _('For issues with the video stream'));
o.default = '0';
o.rmempty = false; o.rmempty = false;
o.ucisection = 'main'; o.ucisection = 'main';
@@ -552,6 +565,50 @@ return view.extend({
}); });
}; };
o = s.taboption('diagnostics', form.Button, '_show_config');
o.title = _('Show Config');
o.description = _('Show current podkop configuration with masked sensitive data');
o.inputtitle = _('Show Config');
o.inputstyle = 'apply';
o.onclick = function () {
return fs.exec('/etc/init.d/podkop', ['show_config'])
.then(function (res) {
const formattedOutput = formatDiagnosticOutput(res.stdout || _('No output'));
const modalElement = ui.showModal(_('Podkop Configuration'), [
E('div', { class: 'cbi-section' }, [
E('pre', { class: 'cbi-value-field' }, formattedOutput)
]),
E('div', { style: 'display: flex; justify-content: space-between; margin-top: 1em;' }, [
E('button', {
'class': 'btn cbi-button-save',
'click': function () {
const textarea = document.createElement('textarea');
textarea.value = '```\n' + formattedOutput + '\n```';
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
ui.hideModal();
} catch (err) {
ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message));
}
document.body.removeChild(textarea);
}
}, _('Copy to Clipboard')),
E('button', {
'class': 'btn cbi-button-neutral',
'click': ui.hideModal
}, _('Close'))
])
], 'large');
if (modalElement && modalElement.parentElement) {
modalElement.parentElement.classList.add('modal-overlay-large');
}
});
};
o = s.taboption('diagnostics', form.Button, '_list_update'); o = s.taboption('diagnostics', form.Button, '_list_update');
o.title = _('Update lists'); o.title = _('Update lists');
o.description = _('Update all lists in config'); o.description = _('Update all lists in config');

View File

@@ -329,4 +329,55 @@ msgid "View Logs"
msgstr "Просмотр логов" msgstr "Просмотр логов"
msgid "Failed to copy logs: " msgid "Failed to copy logs: "
msgstr "Ошибка копирования логов: " msgstr "Ошибка копирования логов: "
msgid "Show Config"
msgstr "Показать конфигурацию"
msgid "Show current podkop configuration with masked sensitive data"
msgstr "Показать текущую конфигурацию podkop с маскированными конфиденциальными данными"
msgid "Podkop Configuration"
msgstr "Конфигурация Podkop"
msgid "Update lists"
msgstr "Обновить списки"
msgid "Update all lists in config"
msgstr "Обновить все списки в конфигурации"
msgid "List Update"
msgstr "Обновление списков"
msgid "Lists will be updated in background. You can check the progress in system logs."
msgstr "Списки будут обновлены в фоновом режиме. Вы можете проверить прогресс в системных логах."
msgid "Extra configurations"
msgstr "Дополнительные конфигурации"
msgid "Extra configuration"
msgstr "Дополнительная конфигурация"
msgid "Add Section"
msgstr "Добавить раздел"
msgid "QUIC disable"
msgstr "Отключить QUIC"
msgid "For issues with the video stream"
msgstr "Для проблем с видеопотоком"
msgid "Community Lists"
msgstr "Списки сообщества"
msgid "Local Domain Lists"
msgstr "Локальные списки доменов"
msgid "Use the list from the router filesystem"
msgstr "Использовать список из файловой системы роутера"
msgid "Local Domain Lists Path"
msgstr "Путь к локальным спискам доменов"
msgid "Enter to the list file path"
msgstr "Введите путь к файлу списка"

View File

@@ -329,4 +329,55 @@ msgid "View Logs"
msgstr "" msgstr ""
msgid "Failed to copy logs: " msgid "Failed to copy logs: "
msgstr ""
msgid "Show Config"
msgstr ""
msgid "Show current podkop configuration with masked sensitive data"
msgstr ""
msgid "Podkop Configuration"
msgstr ""
msgid "Update lists"
msgstr ""
msgid "Update all lists in config"
msgstr ""
msgid "List Update"
msgstr ""
msgid "Lists will be updated in background. You can check the progress in system logs."
msgstr ""
msgid "Extra configurations"
msgstr ""
msgid "Extra configuration"
msgstr ""
msgid "Add Section"
msgstr ""
msgid "QUIC disable"
msgstr ""
msgid "For issues with the video stream"
msgstr ""
msgid "Community Lists"
msgstr ""
msgid "Local Domain Lists"
msgstr ""
msgid "Use the list from the router filesystem"
msgstr ""
msgid "Local Domain Lists Path"
msgstr ""
msgid "Enter to the list file path"
msgstr "" msgstr ""

View File

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

View File

@@ -28,5 +28,6 @@ config main 'main'
option yacd '0' option yacd '0'
option socks5 '0' option socks5 '0'
option exclude_ntp '0' option exclude_ntp '0'
option quic_disable '0'
option update_interval '1d' option update_interval '1d'
option custom_domains_text option custom_domains_text

View File

@@ -7,7 +7,7 @@ script=$(readlink "$initscript")
NAME="$(basename ${script:-$initscript})" NAME="$(basename ${script:-$initscript})"
config_load "$NAME" config_load "$NAME"
EXTRA_COMMANDS="list_update check_proxy check_nft check_github check_logs check_all check_three" EXTRA_COMMANDS="list_update check_proxy check_nft check_github check_logs check_all check_three main show_config show_version"
EXTRA_HELP=" list_update Updating domain and subnet lists EXTRA_HELP=" list_update Updating domain and subnet lists
sing_box_config_vless For test vless string sing_box_config_vless For test vless string
check_proxy Check if sing-box proxy works correctly check_proxy Check if sing-box proxy works correctly
@@ -15,7 +15,10 @@ EXTRA_HELP=" list_update Updating domain and subnet lists
check_github Check GitHub connectivity and lists availability check_github Check GitHub connectivity and lists availability
check_logs Show podkop logs from system journal check_logs Show podkop logs from system journal
check_all Run all checks check_all Run all checks
check_three Run check_proxy, check_nft and check_github" check_three Run check_proxy, check_nft and check_github
main Main function
show_config Show current configuration with masked sensitive data
show_version Show current version"
[ ! -L /usr/sbin/podkop ] && ln -s /etc/init.d/podkop /usr/sbin/podkop [ ! -L /usr/sbin/podkop ] && ln -s /etc/init.d/podkop /usr/sbin/podkop
@@ -32,6 +35,7 @@ SUBNETS_TELERAM="${GITHUB_RAW_URL}/Subnets/IPv4/telegram.lst"
SING_BOX_CONFIG="/etc/sing-box/config.json" SING_BOX_CONFIG="/etc/sing-box/config.json"
CACHE_FILE_PATH="/tmp/cache.db" CACHE_FILE_PATH="/tmp/cache.db"
FAKEIP="198.18.0.0/15" FAKEIP="198.18.0.0/15"
VALID_SERVICES="russia_inside russia_outside ukraine_inside geoblock block porn news anime youtube discord meta twitter hdrezka tiktok telegram"
start_service() { start_service() {
log "Start podkop" log "Start podkop"
@@ -40,80 +44,28 @@ start_service() {
required_version="1.11.1" required_version="1.11.1"
if [ "$(echo -e "$sing_box_version\n$required_version" | sort -V | head -n 1)" != "$required_version" ]; then if [ "$(echo -e "$sing_box_version\n$required_version" | sort -V | head -n 1)" != "$required_version" ]; then
echo "The version of sing-box ($sing_box_version) is lower than the minimum version. Update sing-box: opkg update && opkg install sing-box" echo "The version of sing-box ($sing_box_version) is lower than the minimum version. Update sing-box: opkg update && opkg remove sing-box && opkg install sing-box"
exit 1
fi
if opkg list-installed | grep -qE "iptables|kmod-iptab"; then
printf "\033[31;1mFound incompatible iptables packages. If you're using FriendlyWrt: https://t.me/itdogchat/44512/181082\033[0m\n"
fi
if ! ip addr | grep -q "br-lan"; then
log "Interface br-lan not found"
exit 1 exit 1
fi fi
migration migration
# S99sing-box issue
if sing-box -c $SING_BOX_CONFIG check >/dev/null 2>&1; then
/etc/init.d/sing-box start
fi
sleep 5 config_foreach process_validate_service
config_foreach wget_github procd_open_instance
procd_set_param command /bin/sh -c "/etc/init.d/podkop main &"
mkdir -p /tmp/podkop procd_set_param stdout 1
procd_set_param stderr 1
# base procd_close_instance
route_table_rule_mark
create_nft_table
sing_box_uci
# sing-box
sing_box_inbound_proxy 1602
sing_box_dns
sing_box_dns_rule_fakeip
sing_box_rule_dns
sing_box_cache_file
process_socks5
# sing-box outbounds and rules
config_foreach sing_box_outdound
config_foreach process_domains_for_section
config_foreach process_remote_ruleset
config_foreach sing_box_rule_preset
config_foreach process_domains_list_local
config_foreach process_domains_list_url
config_foreach process_subnet_for_section
config_foreach process_subnet_for_section_remote
config_foreach process_all_traffic_for_section
config_foreach add_cron_job
#Future: exclude at the fakeip?
config_get_bool exclude_from_ip_enabled "main" "exclude_from_ip_enabled" "0"
if [ "$exclude_from_ip_enabled" -eq 1 ]; then
log "Adding an IP for exclusion"
config_list_foreach main exclude_traffic_ip sing_box_rules_source_ip_cidr $exclude_traffic_ip direct-out
fi
config_get_bool yacd "main" "yacd" "0"
if [ "$yacd" -eq 1 ]; then
log "Yacd enable"
jq '.experimental.clash_api = {
"external_ui": "ui",
"external_controller": "0.0.0.0:9090"
}' $SING_BOX_CONFIG >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json $SING_BOX_CONFIG
fi
config_get_bool exclude_ntp "main" "exclude_ntp" "0"
if [ "$exclude_ntp" -eq 1 ]; then
log "NTP traffic exclude for proxy"
nft insert rule inet PodkopTable mangle udp dport 123 return
fi
sing_box_config_check
/etc/init.d/sing-box restart
/etc/init.d/sing-box enable
config_get proxy_string "main" "proxy_string"
config_get interface "main" "interface"
if [ -n "$proxy_string" ] || [ -n "$interface" ]; then
dnsmasq_add
fi
} }
stop_service() { stop_service() {
@@ -180,18 +132,141 @@ nolog() {
echo -e "${CYAN}[$timestamp]${RESET} ${GREEN}$message${RESET}" echo -e "${CYAN}[$timestamp]${RESET} ${GREEN}$message${RESET}"
} }
# Migrations funcs main() {
sleep 5
config_foreach wget_github
mkdir -p /tmp/podkop
# base
route_table_rule_mark
create_nft_table
sing_box_uci
# sing-box
sing_box_inbound_proxy 1602
sing_box_dns
sing_box_dns_rule_fakeip
sing_box_rule_dns
sing_box_cache_file
process_socks5
# sing-box outbounds and rules
config_foreach sing_box_outdound
config_foreach process_domains_for_section
config_foreach process_remote_ruleset
config_foreach sing_box_rule_preset
config_foreach process_domains_list_local
config_foreach process_domains_list_url
config_foreach process_subnet_for_section
config_foreach process_subnet_for_section_remote
config_foreach process_all_traffic_for_section
config_foreach add_cron_job
# Future: exclude at the fakeip?
config_get_bool exclude_from_ip_enabled "main" "exclude_from_ip_enabled" "0"
if [ "$exclude_from_ip_enabled" -eq 1 ]; then
log "Adding an IP for exclusion"
config_list_foreach main exclude_traffic_ip sing_box_rules_source_ip_cidr $exclude_traffic_ip direct-out
fi
config_get_bool yacd "main" "yacd" "0"
if [ "$yacd" -eq 1 ]; then
log "Yacd enable"
jq '.experimental.clash_api = {
"external_ui": "ui",
"external_controller": "0.0.0.0:9090"
}' $SING_BOX_CONFIG >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json $SING_BOX_CONFIG
fi
config_get_bool exclude_ntp "main" "exclude_ntp" "0"
if [ "$exclude_ntp" -eq 1 ]; then
log "NTP traffic exclude for proxy"
nft insert rule inet PodkopTable mangle udp dport 123 return
fi
config_get_bool quic_disable "main" "quic_disable" "0"
if [ "$quic_disable" -eq 1 ]; then
log "Rule for disable QUIC"
sing_box_quic_reject
fi
sing_box_config_check
/etc/init.d/sing-box restart
/etc/init.d/sing-box enable
config_get proxy_string "main" "proxy_string"
config_get interface "main" "interface"
if [ -n "$proxy_string" ] || [ -n "$interface" ]; then
dnsmasq_add
fi
}
# Migrations and validation funcs
migration() { migration() {
# list migrate # list migrate
grep -q "list domain_list 'ru_inside'" /etc/config/podkop && sed -i "s/list domain_list 'ru_inside'/list domain_list 'russia_inside'/" /etc/config/podkop local CONFIG="/etc/config/podkop"
grep -q "list domain_list 'ru_outside'" /etc/config/podkop && sed -i "s/list domain_list 'ru_outside'/list domain_list 'russia_outside'/" /etc/config/podkop
grep -q "list domain_list 'ua'" /etc/config/podkop && sed -i "s/list domain_list 'ua'/list domain_list 'ukraine_inside'/" /etc/config/podkop if grep -q "ru_inside" $CONFIG; then
log "Depricated list found: ru_inside"
sed -i '/ru_inside/d' $CONFIG
fi
if grep -q "list domain_list 'ru_outside'" $CONFIG; then
log "Depricated list found: sru_outside"
sed -i '/ru_outside/d' $CONFIG
fi
if grep -q "list domain_list 'ua'" $CONFIG; then
log "Depricated list found: ua"
sed -i '/ua/d' $CONFIG
fi
# Subnet list
if grep -q "list subnets" $CONFIG; then
log "Depricated second section found"
sed -i '/list subnets/d' $CONFIG
fi
# second remove # second remove
grep -q "config second 'second'" /etc/config/podkop && sed -i '/second/d' /etc/config/podkop if grep -q "config second 'second'" $CONFIG; then
log "Depricated second section found"
sed -i '/second/d' $CONFIG
fi
# cron update # cron update
grep -qE "^\s*option update_interval '[0-9*/,-]+( [0-9*/,-]+){4}'" /etc/config/podkop && sed -i "s|^\(\s*option update_interval\) '[0-9*/,-]\+\( [0-9*/,-]\+\)\{4\}'|\1 '1d'|" /etc/config/podkop if grep -qE "^\s*option update_interval '[0-9*/,-]+( [0-9*/,-]+){4}'" $CONFIG; then
log "Depricated update_interval"
sed -i "s|^\(\s*option update_interval\) '[0-9*/,-]\+\( [0-9*/,-]\+\)\{4\}'|\1 '1d'|" $CONFIG
fi
# dnsmasq https
if grep -q "^filter-rr=HTTPS" "/etc/dnsmasq.conf"; then
log "Found and removed filter-rr=HTTPS in dnsmasq config"
sed -i '/^filter-rr=HTTPS/d' "/etc/dnsmasq.conf"
fi
}
validate_service() {
local domain="$1"
for valid_service in $VALID_SERVICES; do
if [ "$domain" = "$valid_service" ]; then
return 0
fi
done
log "Invalid service in domain_list: $domain. Exiting. Check config and LuCI cache"
exit 1
}
process_validate_service() {
config_get_bool domain_list_enabled "$section" "domain_list_enabled" "0"
if [ "$domain_list_enabled" -eq 1 ]; then
config_list_foreach "$section" domain_list validate_service
fi
} }
# Main funcs # Main funcs
@@ -242,12 +317,10 @@ dnsmasq_add() {
uci set dhcp.@dnsmasq[0].filter_aaaa="1" uci set dhcp.@dnsmasq[0].filter_aaaa="1"
uci set dhcp.@dnsmasq[0].cachesize="0" uci set dhcp.@dnsmasq[0].cachesize="0"
uci -q delete dhcp.@dnsmasq[0].server uci -q delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server="127.0.0.1#5353" uci add_list dhcp.@dnsmasq[0].server="127.0.0.42"
uci add_list dhcp.@dnsmasq[0].server='/use-application-dns.net/' uci add_list dhcp.@dnsmasq[0].server='/use-application-dns.net/'
uci commit dhcp uci commit dhcp
grep -q "filter-rr=HTTPS" /etc/dnsmasq.conf || echo "filter-rr=HTTPS" >> /etc/dnsmasq.conf
/etc/init.d/dnsmasq restart /etc/init.d/dnsmasq restart
} }
@@ -257,10 +330,9 @@ dnsmasq_rm() {
uci set dhcp.@dnsmasq[0].filter_aaaa="0" uci set dhcp.@dnsmasq[0].filter_aaaa="0"
uci set dhcp.@dnsmasq[0].cachesize="1000" uci set dhcp.@dnsmasq[0].cachesize="1000"
uci -q delete dhcp.@dnsmasq[0].server uci -q delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server="8.8.8.8"
uci commit dhcp uci commit dhcp
sed -i '/filter-rr=HTTPS/d' /etc/dnsmasq.conf
/etc/init.d/dnsmasq restart /etc/init.d/dnsmasq restart
} }
@@ -302,7 +374,8 @@ process_subnets_text() {
} }
wget_github() { wget_github() {
local count=0 local count_nslookup=0
local count_curl=0
config_get domain_list_enabled "$section" "domain_list_enabled" config_get domain_list_enabled "$section" "domain_list_enabled"
config_get subnets_list_enabled "$section" "subnets_list_enabled" config_get subnets_list_enabled "$section" "subnets_list_enabled"
@@ -312,24 +385,40 @@ wget_github() {
if [ "$domain_list_enabled" -eq 1 ] || [ "$subnets_list_enabled" -eq 1 ] || if [ "$domain_list_enabled" -eq 1 ] || [ "$subnets_list_enabled" -eq 1 ] ||
[ "$custom_download_domains_list_enabled" -eq 1 ] || [ "$custom_download_subnets_list_enabled" -eq 1 ] ; then [ "$custom_download_domains_list_enabled" -eq 1 ] || [ "$custom_download_subnets_list_enabled" -eq 1 ] ; then
if ! nslookup google.com >/dev/null 2>&1; then
log "DNS not work"
exit 1
fi
while true; do while true; do
if ! curl -m 3 github.com; then if ! nslookup google.com >/dev/null 2>&1; then
log "GitHub is not available. Check the internet availability [$count sec]" log "DNS not working. Retrying... [$count_nslookup sec]"
count=$((count + 1)) count_nslookup=$((count_nslookup + 1))
else else
return return
fi fi
if [ $count -lt 30 ]; then if [ $count_nslookup -lt 30 ]; then
sleep_interval=1 sleep_interval=1
elif [ $count -ge 30 ] && [ $count -lt 60 ]; then elif [ $count_nslookup -ge 30 ] && [ $count_nslookup -lt 60 ]; then
sleep_interval=5 sleep_interval=5
elif [ $count -ge 60 ] && [ $count -lt 90 ]; then elif [ $count_nslookup -ge 60 ] && [ $count_nslookup -lt 90 ]; then
sleep_interval=10
else
sleep_interval=30
fi
sleep $sleep_interval
done
while true; do
if ! curl -m 3 github.com; then
log "GitHub is not available. Check the internet availability [$count_curl sec]"
count_curl=$((count_curl + 1))
else
return
fi
if [ $count_curl -lt 30 ]; then
sleep_interval=1
elif [ $count_curl -ge 30 ] && [ $count_curl -lt 60 ]; then
sleep_interval=5
elif [ $count_curl -ge 60 ] && [ $count_curl -lt 90 ]; then
sleep_interval=10 sleep_interval=10
else else
sleep_interval=30 sleep_interval=30
@@ -457,8 +546,8 @@ sing_box_inbound_proxy() {
{ {
"tag": "dns-in", "tag": "dns-in",
"type": "direct", "type": "direct",
"listen": "127.0.0.1", "listen": "127.0.0.42",
"listen_port": 5353 "listen_port": 53
} }
], ],
"outbounds": [ "outbounds": [
@@ -499,6 +588,12 @@ sing_box_dns_rule_fakeip() {
jq \ jq \
'.dns += { '.dns += {
"rules": [ "rules": [
{
"query_type": [
"HTTPS"
],
"action": "reject"
},
{ {
"server": "fakeip-server", "server": "fakeip-server",
"rule_set": [] "rule_set": []
@@ -659,8 +754,8 @@ sing_box_config_outbound_json() {
{ {
"tag": "dns-in", "tag": "dns-in",
"type": "direct", "type": "direct",
"listen": "127.0.0.1", "listen": "127.0.0.42",
"listen_port": 5353 "listen_port": 53
} }
], ],
"outbounds": [], "outbounds": [],
@@ -1060,7 +1155,7 @@ sing_box_rules() {
local rule_set="$1" local rule_set="$1"
local outbound="$2" local outbound="$2"
# Check if there is an outbound rule for tproxy-in # Check if there is an outbound rule for "tproxy-in"
local rule_exists=$(jq -r '.route.rules[] | select(.outbound == "'"$outbound"'" and .inbound == ["tproxy-in"])' "$SING_BOX_CONFIG") local rule_exists=$(jq -r '.route.rules[] | select(.outbound == "'"$outbound"'" and .inbound == ["tproxy-in"])' "$SING_BOX_CONFIG")
if [[ -n "$rule_exists" ]]; then if [[ -n "$rule_exists" ]]; then
@@ -1084,6 +1179,25 @@ sing_box_rules() {
fi fi
} }
sing_box_quic_reject() {
local quic_rule_exists=$(jq -e '.route.rules[] | select(.protocol == "quic" and .action == "reject")' "$SING_BOX_CONFIG")
if [[ -z "$quic_rule_exists" ]]; then
jq '
.route.rules |= (
reduce .[] as $rule ([];
if $rule.protocol == "dns" and $rule.action == "hijack-dns" then
. + [$rule, {"protocol": "quic", "action": "reject"}]
else
. + [$rule]
end
)
)' "$SING_BOX_CONFIG" >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json "$SING_BOX_CONFIG"
log "QUIC reject rule added successfully"
fi
}
process_remote_ruleset() { process_remote_ruleset() {
config_get_bool domain_list_enabled "$section" "domain_list_enabled" "0" config_get_bool domain_list_enabled "$section" "domain_list_enabled" "0"
if [ "$domain_list_enabled" -eq 1 ]; then if [ "$domain_list_enabled" -eq 1 ]; then
@@ -1288,18 +1402,31 @@ check_proxy() {
nolog "Checking proxy connection..." nolog "Checking proxy connection..."
for attempt in `seq 1 5`; do
response=$(sing-box tools fetch ifconfig.me -D /etc/sing-box 2>/dev/null)
if ! echo "$response" | grep -q "403 Forbidden"; then
nolog "Proxy check completed successfully"
#echo "$response" | sed 's/\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)/XXX.\2.\3.\4/'
echo "$response" | sed -n 's/^[0-9]\+\.[0-9]\+\.[0-9]\+\.\([0-9]\+\)$/X.X.X.\1/p'
return 0
fi
done
nolog "Failed to get a non-403 response after 5 attempts" for attempt in `seq 1 5`; do
return 1 response=$(sing-box tools fetch ifconfig.me -D /etc/sing-box 2>/dev/null)
if echo "$response" | grep -q "^<html\|403 Forbidden"; then
continue
fi
if [[ $response =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
ip=$(echo "$response" | sed -n 's/^[0-9]\+\.[0-9]\+\.[0-9]\+\.\([0-9]\+\)$/X.X.X.\1/p')
nolog "$ip - should match proxy IP"
return 0
elif echo "$response" | grep -q "^[0-9a-fA-F:]*::[0-9a-fA-F:]*$\|^[0-9a-fA-F:]\+$"; then
ip=$(echo "$response" | sed 's/\([0-9a-fA-F]\+:[0-9a-fA-F]\+:[0-9a-fA-F]\+\):.*/\1:XXXX:XXXX:XXXX/')
nolog "$ip - should match proxy IP"
return 0
fi
if [ $attempt -eq 5 ]; then
nolog "Failed to get valid IP address after 5 attempts"
if [ -z "$response" ]; then
nolog "Error: Empty response"
else
nolog "Error response: $response"
fi
return 1
fi
done
} }
check_nft() { check_nft() {
@@ -1310,7 +1437,6 @@ check_nft() {
nolog "Checking PodkopTable rules..." nolog "Checking PodkopTable rules..."
# Список всех возможных сетов
local sets="podkop_domains podkop_subnets podkop_subnets_discord localv4" local sets="podkop_domains podkop_subnets podkop_subnets_discord localv4"
nolog "Sets statistics:" nolog "Sets statistics:"
@@ -1323,7 +1449,6 @@ check_nft() {
fi fi
done done
# Показываем правила с счетчиками
nolog "Current chains and rules:" nolog "Current chains and rules:"
nft list table inet PodkopTable | grep "chain\|counter" nft list table inet PodkopTable | grep "chain\|counter"
@@ -1356,7 +1481,6 @@ check_logs() {
nolog "Showing podkop logs from system journal..." nolog "Showing podkop logs from system journal..."
if command -v logread >/dev/null 2>&1; then if command -v logread >/dev/null 2>&1; then
# Попытка получить последние 50 записей
logread -e "podkop" | tail -n 50 logread -e "podkop" | tail -n 50
else else
nolog "Error: logread command not found" nolog "Error: logread command not found"
@@ -1385,3 +1509,33 @@ check_all() {
check_three check_three
} }
show_config() {
nolog "Current podkop configuration:"
if [ ! -f /etc/config/podkop ]; then
nolog "Configuration file not found"
return 1
fi
tmp_config=$(mktemp)
cat /etc/config/podkop | sed \
-e 's/\(option proxy_string\).*/\1 '\''MASKED'\''/g' \
-e 's/\(option outbound_json\).*/\1 '\''MASKED'\''/g' \
-e 's/\(option second_proxy_string\).*/\1 '\''MASKED'\''/g' \
-e 's/\(option second_outbound_json\).*/\1 '\''MASKED'\''/g' \
-e 's/\(vless:\/\/[^@]*@\)/vless:\/\/MASKED@/g' \
-e 's/\(ss:\/\/[^@]*@\)/ss:\/\/MASKED@/g' \
-e 's/\(pbk=[^&]*\)/pbk=MASKED/g' \
-e 's/\(sid=[^&]*\)/sid=MASKED/g' \
> "$tmp_config"
cat "$tmp_config"
rm -f "$tmp_config"
}
show_version() {
local version=$(opkg info podkop | grep -m 1 "Version:" | cut -d' ' -f2)
echo "$version"
}