Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68f5f123ca | ||
|
|
fae43d0471 | ||
|
|
9d6dc45fdb | ||
|
|
9aa5a2d242 | ||
|
|
63dc86fca4 | ||
|
|
4d9cedaf4c |
@@ -22,6 +22,11 @@ https://podkop.net/
|
|||||||
sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/main/install.sh)
|
sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/main/install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Обновление
|
||||||
|
```
|
||||||
|
sh <(wget -qO- https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/main/install.sh) --upgrade
|
||||||
|
```
|
||||||
|
|
||||||
# ToDo
|
# ToDo
|
||||||
Этот раздел не означает задачи, которые нужно брать и делать. Это общий список хотелок. Если вы хотите помочь, пожалуйста, спросите сначала в телеграмме.
|
Этот раздел не означает задачи, которые нужно брать и делать. Это общий список хотелок. Если вы хотите помочь, пожалуйста, спросите сначала в телеграмме.
|
||||||
|
|
||||||
@@ -32,7 +37,5 @@ sh <(wget -O - https://raw.githubusercontent.com/itdoginfo/podkop/refs/heads/mai
|
|||||||
- [ ] IPv6. Только после наполнения Wiki
|
- [ ] IPv6. Только после наполнения Wiki
|
||||||
|
|
||||||
Рефактор
|
Рефактор
|
||||||
- [ ] Handle для sing-box
|
|
||||||
- [ ] Handle для dnsmasq
|
|
||||||
- [ ] Unit тесты (BATS)
|
- [ ] Unit тесты (BATS)
|
||||||
- [ ] Интеграционые тесты бекенда (OpenWrt rootfs + BATS)
|
- [ ] Интеграционые тесты бекенда (OpenWrt rootfs + BATS)
|
||||||
|
|||||||
@@ -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.44
|
PKG_VERSION:=0.3.47
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
LUCI_TITLE:=LuCI podkop app
|
LUCI_TITLE:=LuCI podkop app
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ function createConfigSection(section, map, network) {
|
|||||||
o = s.taboption('basic', form.ListValue, 'mode', _('Connection Type'), _('Select between VPN and Proxy connection methods for traffic routing'));
|
o = s.taboption('basic', form.ListValue, 'mode', _('Connection Type'), _('Select between VPN and Proxy connection methods for traffic routing'));
|
||||||
o.value('proxy', ('Proxy'));
|
o.value('proxy', ('Proxy'));
|
||||||
o.value('vpn', ('VPN'));
|
o.value('vpn', ('VPN'));
|
||||||
|
o.value('block', ('Block'));
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption('basic', form.ListValue, 'proxy_config_type', _('Configuration Type'), _('Select how to configure the proxy'));
|
o = s.taboption('basic', form.ListValue, 'proxy_config_type', _('Configuration Type'), _('Select how to configure the proxy'));
|
||||||
@@ -638,7 +639,7 @@ const showConfigModal = async (command, title) => {
|
|||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
||||||
|
|
||||||
const response = await fetch('https://fakeip.podkop.net/check', { signal: controller.signal });
|
const response = await fetch('https://fakeip.podkop.fyi/check', { signal: controller.signal });
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
@@ -652,9 +653,9 @@ const showConfigModal = async (command, title) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bypass check
|
// Bypass check
|
||||||
const bypassResponse = await fetch('https://fakeip.podkop.net/check', { signal: controller.signal });
|
const bypassResponse = await fetch('https://fakeip.podkop.fyi/check', { signal: controller.signal });
|
||||||
const bypassData = await bypassResponse.json();
|
const bypassData = await bypassResponse.json();
|
||||||
const bypassResponse2 = await fetch('https://ip.podkop.net/check', { signal: controller.signal });
|
const bypassResponse2 = await fetch('https://ip.podkop.fyi/check', { signal: controller.signal });
|
||||||
const bypassData2 = await bypassResponse2.json();
|
const bypassData2 = await bypassResponse2.json();
|
||||||
|
|
||||||
formattedOutput += '━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
|
formattedOutput += '━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
|
||||||
@@ -1313,7 +1314,7 @@ return view.extend({
|
|||||||
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('https://fakeip.podkop.net/check', { signal: controller.signal });
|
const response = await fetch('https://fakeip.podkop.fyi/check', { signal: controller.signal });
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
@@ -1352,7 +1353,7 @@ return view.extend({
|
|||||||
return resolve(createStatus('not_working', 'DNS not configured', 'ERROR'));
|
return resolve(createStatus('not_working', 'DNS not configured', 'ERROR'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await safeExec('nslookup', ['-timeout=2', 'fakeip.podkop.net', '127.0.0.42']);
|
const result = await safeExec('nslookup', ['-timeout=2', 'fakeip.podkop.fyi', '127.0.0.42']);
|
||||||
|
|
||||||
if (result.stdout && result.stdout.includes('198.18')) {
|
if (result.stdout && result.stdout.includes('198.18')) {
|
||||||
return resolve(createStatus('working', 'working on router', 'SUCCESS'));
|
return resolve(createStatus('working', 'working on router', 'SUCCESS'));
|
||||||
@@ -1401,7 +1402,7 @@ return view.extend({
|
|||||||
const controller1 = new AbortController();
|
const controller1 = new AbortController();
|
||||||
const timeoutId1 = setTimeout(() => controller1.abort(), 10000);
|
const timeoutId1 = setTimeout(() => controller1.abort(), 10000);
|
||||||
|
|
||||||
const response1 = await fetch('https://fakeip.podkop.net/check', { signal: controller1.signal });
|
const response1 = await fetch('https://fakeip.podkop.fyi/check', { signal: controller1.signal });
|
||||||
const data1 = await response1.json();
|
const data1 = await response1.json();
|
||||||
clearTimeout(timeoutId1);
|
clearTimeout(timeoutId1);
|
||||||
|
|
||||||
@@ -1416,7 +1417,7 @@ return view.extend({
|
|||||||
const controller2 = new AbortController();
|
const controller2 = new AbortController();
|
||||||
const timeoutId2 = setTimeout(() => controller2.abort(), 10000);
|
const timeoutId2 = setTimeout(() => controller2.abort(), 10000);
|
||||||
|
|
||||||
const response2 = await fetch('https://ip.podkop.net/check', { signal: controller2.signal });
|
const response2 = await fetch('https://ip.podkop.fyi/check', { signal: controller2.signal });
|
||||||
const data2 = await response2.json();
|
const data2 = await response2.json();
|
||||||
clearTimeout(timeoutId2);
|
clearTimeout(timeoutId2);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=podkop
|
PKG_NAME:=podkop
|
||||||
PKG_VERSION:=0.3.44
|
PKG_VERSION:=0.3.47
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_MAINTAINER:=ITDog <podkop@itdog.info>
|
PKG_MAINTAINER:=ITDog <podkop@itdog.info>
|
||||||
@@ -15,7 +15,7 @@ define Package/podkop
|
|||||||
DEPENDS:=+sing-box +curl +jq +kmod-nft-tproxy +coreutils-base64
|
DEPENDS:=+sing-box +curl +jq +kmod-nft-tproxy +coreutils-base64
|
||||||
CONFLICTS:=https-dns-proxy
|
CONFLICTS:=https-dns-proxy
|
||||||
TITLE:=Domain routing app
|
TITLE:=Domain routing app
|
||||||
URL:=https://itdog.info
|
URL:=https://podkop.net
|
||||||
PKGARCH:=all
|
PKGARCH:=all
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ SING_BOX_CONFIG="/etc/sing-box/config.json"
|
|||||||
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 cloudflare"
|
VALID_SERVICES="russia_inside russia_outside ukraine_inside geoblock block porn news anime youtube discord meta twitter hdrezka tiktok telegram cloudflare"
|
||||||
DNS_RESOLVERS="1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 9.9.9.9 9.9.9.11 94.140.14.14 94.140.15.15 208.67.220.220 208.67.222.222 77.88.8.1 77.88.8.8"
|
DNS_RESOLVERS="1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 9.9.9.9 9.9.9.11 94.140.14.14 94.140.15.15 208.67.220.220 208.67.222.222 77.88.8.1 77.88.8.8"
|
||||||
TEST_DOMAIN="fakeip.podkop.net"
|
TEST_DOMAIN="fakeip.podkop.fyi"
|
||||||
INTERFACES_LIST=""
|
INTERFACES_LIST=""
|
||||||
SRC_INTERFACE=""
|
SRC_INTERFACE=""
|
||||||
RESOLV_CONF="/etc/resolv.conf"
|
RESOLV_CONF="/etc/resolv.conf"
|
||||||
@@ -67,7 +67,10 @@ start_main() {
|
|||||||
|
|
||||||
config_foreach process_validate_service
|
config_foreach process_validate_service
|
||||||
|
|
||||||
sleep 3
|
# Sync time for DoH/DoT
|
||||||
|
/usr/sbin/ntpd -q -p 194.190.168.1 -p 216.239.35.0 -p 216.239.35.4 -p 162.159.200.1 -p 162.159.200.123
|
||||||
|
|
||||||
|
sleep 2
|
||||||
|
|
||||||
mkdir -p /tmp/podkop
|
mkdir -p /tmp/podkop
|
||||||
|
|
||||||
@@ -160,7 +163,7 @@ stop_main() {
|
|||||||
|
|
||||||
if [ -f /var/run/podkop_list_update.pid ]; then
|
if [ -f /var/run/podkop_list_update.pid ]; then
|
||||||
pid=$(cat /var/run/podkop_list_update.pid)
|
pid=$(cat /var/run/podkop_list_update.pid)
|
||||||
if kill -0 "$pid"; then
|
if kill -0 "$pid" 2>/dev/null; then
|
||||||
kill "$pid" 2>/dev/null
|
kill "$pid" 2>/dev/null
|
||||||
log "Stopped list_update"
|
log "Stopped list_update"
|
||||||
fi
|
fi
|
||||||
@@ -375,8 +378,6 @@ save_dnsmasq_config() {
|
|||||||
|
|
||||||
dnsmasq_add_resolver() {
|
dnsmasq_add_resolver() {
|
||||||
log "Save dnsmasq config"
|
log "Save dnsmasq config"
|
||||||
save_dnsmasq_config "dhcp.@dnsmasq[0].noresolv" "dhcp.@dnsmasq[0].podkop_noresolv"
|
|
||||||
save_dnsmasq_config "dhcp.@dnsmasq[0].cachesize" "dhcp.@dnsmasq[0].podkop_cachesize"
|
|
||||||
|
|
||||||
uci -q delete dhcp.@dnsmasq[0].podkop_server
|
uci -q delete dhcp.@dnsmasq[0].podkop_server
|
||||||
for server in $(uci get dhcp.@dnsmasq[0].server 2>/dev/null); do
|
for server in $(uci get dhcp.@dnsmasq[0].server 2>/dev/null); do
|
||||||
@@ -388,6 +389,9 @@ dnsmasq_add_resolver() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
save_dnsmasq_config "dhcp.@dnsmasq[0].noresolv" "dhcp.@dnsmasq[0].podkop_noresolv"
|
||||||
|
save_dnsmasq_config "dhcp.@dnsmasq[0].cachesize" "dhcp.@dnsmasq[0].podkop_cachesize"
|
||||||
|
|
||||||
log "Configure dnsmasq for sing-box"
|
log "Configure dnsmasq for sing-box"
|
||||||
uci set dhcp.@dnsmasq[0].noresolv="1"
|
uci set dhcp.@dnsmasq[0].noresolv="1"
|
||||||
uci set dhcp.@dnsmasq[0].cachesize="0"
|
uci set dhcp.@dnsmasq[0].cachesize="0"
|
||||||
@@ -793,7 +797,7 @@ sing_box_create_bypass_ruleset() {
|
|||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"domain_suffix": [
|
"domain_suffix": [
|
||||||
"ip.podkop.net"
|
"ip.podkop.fyi"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -939,6 +943,9 @@ sing_box_outdound() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
"block")
|
||||||
|
log "Block mode"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
log "Requires *vpn* or *proxy* value"
|
log "Requires *vpn* or *proxy* value"
|
||||||
return
|
return
|
||||||
@@ -1219,8 +1226,8 @@ sing_box_config_vless() {
|
|||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
log "Config VLESS created successfully"
|
log "Config VLESS created successfully"
|
||||||
else
|
else
|
||||||
log "Error: VLESS invalid JSON config generated"
|
log "[critical] Error: VLESS invalid JSON config generated"
|
||||||
return 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1458,27 +1465,54 @@ 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"
|
config_get mode "$section" "mode"
|
||||||
local rule_exists=$(jq -r '.route.rules[] | select(.outbound == "'"$outbound"'" and .inbound == ["tproxy-in"])' "$SING_BOX_CONFIG")
|
|
||||||
|
|
||||||
if [[ -n "$rule_exists" ]]; then
|
if [[ "$mode" == "block" ]]; then
|
||||||
# If a rule for tproxy-in exists, add a new rule_set to the existing rule
|
# Action reject
|
||||||
jq \
|
# Check if there is an rule with reject"
|
||||||
--arg rule_set "$rule_set" \
|
local rule_exists=$(jq -r '.route.rules[] | select(.inbound == ["tproxy-in"] and .action == "reject")' "$SING_BOX_CONFIG")
|
||||||
--arg outbound "$outbound" \
|
|
||||||
'(.route.rules[] | select(.outbound == $outbound and .inbound == ["tproxy-in"]) .rule_set) += [$rule_set]' \
|
if [[ -n "$rule_exists" ]]; then
|
||||||
"$SING_BOX_CONFIG" >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json "$SING_BOX_CONFIG"
|
# If a rule for rejectexists, add a new rule_set to the existing rule
|
||||||
|
jq \
|
||||||
|
--arg rule_set "$rule_set" \
|
||||||
|
'(.route.rules[] | select(.inbound == ["tproxy-in"] and .action == "reject") .rule_set) += [$rule_set]' \
|
||||||
|
"$SING_BOX_CONFIG" > /tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json "$SING_BOX_CONFIG"
|
||||||
|
else
|
||||||
|
# If there is no rule for reject, create a new one with rule_set
|
||||||
|
jq \
|
||||||
|
--arg rule_set "$rule_set" \
|
||||||
|
'.route.rules += [{
|
||||||
|
"inbound": ["tproxy-in"],
|
||||||
|
"rule_set": [$rule_set],
|
||||||
|
"action": "reject"
|
||||||
|
}]' "$SING_BOX_CONFIG" > /tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json "$SING_BOX_CONFIG"
|
||||||
|
fi
|
||||||
|
return
|
||||||
else
|
else
|
||||||
# If there is no rule for tproxy-in, create a new one with rule_set
|
# Action route
|
||||||
jq \
|
# Check if there is an outbound rule for "tproxy-in"
|
||||||
--arg rule_set "$rule_set" \
|
local rule_exists=$(jq -r '.route.rules[] | select(.outbound == "'"$outbound"'" and .inbound == ["tproxy-in"])' "$SING_BOX_CONFIG")
|
||||||
--arg outbound "$outbound" \
|
|
||||||
'.route.rules += [{
|
if [[ -n "$rule_exists" ]]; then
|
||||||
"inbound": ["tproxy-in"],
|
# If a rule for tproxy-in exists, add a new rule_set to the existing rule
|
||||||
"rule_set": [$rule_set],
|
jq \
|
||||||
"outbound": $outbound,
|
--arg rule_set "$rule_set" \
|
||||||
"action": "route"
|
--arg outbound "$outbound" \
|
||||||
}]' "$SING_BOX_CONFIG" >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json "$SING_BOX_CONFIG"
|
'(.route.rules[] | select(.outbound == $outbound and .inbound == ["tproxy-in"]) .rule_set) += [$rule_set]' \
|
||||||
|
"$SING_BOX_CONFIG" >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json "$SING_BOX_CONFIG"
|
||||||
|
else
|
||||||
|
# If there is no rule for tproxy-in, create a new one with rule_set
|
||||||
|
jq \
|
||||||
|
--arg rule_set "$rule_set" \
|
||||||
|
--arg outbound "$outbound" \
|
||||||
|
'.route.rules += [{
|
||||||
|
"inbound": ["tproxy-in"],
|
||||||
|
"rule_set": [$rule_set],
|
||||||
|
"outbound": $outbound,
|
||||||
|
"action": "route"
|
||||||
|
}]' "$SING_BOX_CONFIG" >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json "$SING_BOX_CONFIG"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user