mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-07 12:06:56 +03:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
590e040958 | ||
|
|
2323d426dd | ||
|
|
9bcc80f2be | ||
|
|
bfde7518fb | ||
|
|
18d466e166 | ||
|
|
a30752d2e9 | ||
|
|
eb18537370 | ||
|
|
aa86445332 |
@@ -148,6 +148,7 @@ Luci: Services/podkop
|
|||||||
- [ ] Диагностика: podkop_domains: 0 elements как проверять что доходят запросы при fakeip? Мб врубать логи dnsmasq и их чекать.
|
- [ ] Диагностика: podkop_domains: 0 elements как проверять что доходят запросы при fakeip? Мб врубать логи dnsmasq и их чекать.
|
||||||
- [ ] Сделать галку запрещающую подкопу редачить dhcp. Допилить в исключение вместе с пустыми полями proxy и vpn
|
- [ ] Сделать галку запрещающую подкопу редачить dhcp. Допилить в исключение вместе с пустыми полями proxy и vpn
|
||||||
- [ ] Валидации предустановленных значений. Если прописаны другие, то вывод в лог о неизвестной переменной и продолжение работы
|
- [ ] Валидации предустановленных значений. Если прописаны другие, то вывод в лог о неизвестной переменной и продолжение работы
|
||||||
|
- [ ] Добавление в список доменов домены первого уровня (LuCI)
|
||||||
|
|
||||||
Приоритет 2
|
Приоритет 2
|
||||||
- [x] Списки доменов и подсетей с роутера
|
- [x] Списки доменов и подсетей с роутера
|
||||||
|
|||||||
28
install.sh
28
install.sh
@@ -4,15 +4,37 @@ 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
|
||||||
|
|
||||||
wget -qO- "$REPO" | grep -o 'https://[^"]*\.ipk' | while read -r url; do
|
wget -qO- "$REPO" | grep -o 'https://[^"[:space:]]*\.ipk' | while read -r url; do
|
||||||
filename=$(basename "$url")
|
filename=$(basename "$url")
|
||||||
echo "Download $filename..."
|
filepath="$DOWNLOAD_DIR/$filename"
|
||||||
wget -q -O "$DOWNLOAD_DIR/$filename" "$url"
|
|
||||||
|
attempt=0
|
||||||
|
while [ $attempt -lt $COUNT ]; do
|
||||||
|
if [ -f "$filepath" ] && [ -s "$filepath" ]; then
|
||||||
|
echo "$filename has already been uploaded"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Download $filename (count $((attempt+1)))..."
|
||||||
|
wget -q -O "$filepath" "$url"
|
||||||
|
|
||||||
|
if [ -s "$filepath" ]; then
|
||||||
|
echo "$filename successfully downloaded"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
echo "Download error $filename. Retry..."
|
||||||
|
rm -f "$filepath"
|
||||||
|
fi
|
||||||
|
attempt=$((attempt+1))
|
||||||
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "opkg update"
|
echo "opkg update"
|
||||||
|
|||||||
@@ -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.3
|
PKG_VERSION:=0.3.4
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
LUCI_TITLE:=LuCI podkop app
|
LUCI_TITLE:=LuCI podkop app
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -552,6 +562,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');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=podkop
|
PKG_NAME:=podkop
|
||||||
PKG_VERSION:=0.3.3
|
PKG_VERSION:=0.3.4
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_MAINTAINER:=ITDog <podkop@itdog.info>
|
PKG_MAINTAINER:=ITDog <podkop@itdog.info>
|
||||||
|
|||||||
@@ -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 main"
|
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
|
||||||
@@ -16,7 +16,9 @@ EXTRA_HELP=" list_update Updating domain and subnet lists
|
|||||||
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"
|
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
|
||||||
|
|
||||||
@@ -125,6 +127,10 @@ main() {
|
|||||||
|
|
||||||
mkdir -p /tmp/podkop
|
mkdir -p /tmp/podkop
|
||||||
|
|
||||||
|
if ! ip addr | grep -q "br-lan"; then
|
||||||
|
log "Interface br-lan not found"
|
||||||
|
fi
|
||||||
|
|
||||||
# base
|
# base
|
||||||
route_table_rule_mark
|
route_table_rule_mark
|
||||||
create_nft_table
|
create_nft_table
|
||||||
@@ -1081,7 +1087,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
|
||||||
@@ -1309,18 +1315,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() {
|
||||||
@@ -1331,7 +1350,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:"
|
||||||
@@ -1344,7 +1362,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"
|
||||||
|
|
||||||
@@ -1377,7 +1394,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"
|
||||||
@@ -1406,3 +1422,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"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user