Compare commits

...

8 Commits

Author SHA1 Message Date
mercury e2441eb9fd update version 2025-07-16 17:18:18 +04:00
mercury 269d0e9956 mirror shell-script 2025-07-13 23:34:11 +04:00
mercury 8ba85164aa fix empty warp status 2025-07-11 20:55:38 +04:00
mercury e7cc7b66e2 add configs to subs page 2025-07-04 18:33:04 +04:00
mercury 54fa8d35b1 update version 2025-07-04 17:48:15 +04:00
mercury ffe6bb4ba8 subscription page 2025-07-04 17:45:50 +04:00
mercury 6be95533c4 improve vless menu 2025-07-04 16:42:47 +04:00
mercury 8d13bee021 improve /id 2025-07-04 16:38:39 +04:00
8 changed files with 138 additions and 66 deletions
+2
View File
@@ -26,3 +26,5 @@ docker-compose.override.yml
backup.json backup.json
app/webapp/override/ app/webapp/override/
.rest .rest
subscription.php
+72 -27
View File
@@ -244,8 +244,7 @@ class Bot
$this->addLinkDomain(); $this->addLinkDomain();
break; break;
case preg_match('~^/id$~', $this->input['message'], $m): case preg_match('~^/id$~', $this->input['message'], $m):
$this->send($this->input['chat'], $this->input['from'], $this->input['message_id']); $this->send($this->input['chat'], "your id: {$this->input['from']}\nchat id: {$this->input['chat']}", $this->input['message_id']);
$this->send($this->input['chat'], $this->input['chat'], $this->input['message_id']);
break; break;
case preg_match('~^/adguardChBr$~', $this->input['callback'], $m): case preg_match('~^/adguardChBr$~', $this->input['callback'], $m):
$this->adguardChBr(); $this->adguardChBr();
@@ -5310,35 +5309,21 @@ DNS-over-HTTPS with IP:
public function getMirror() public function getMirror()
{ {
unlink('/config/mirror.tar.gz');
unlink('/config/mirror.tar');
$s = file_get_contents('/mirror/start_socat.sh'); $s = file_get_contents('/mirror/start_socat.sh');
$t = preg_replace([ $t = str_replace([
'~{ip}~', '~ip~',
'~{tg}~', '~tg~',
'~{ss}~', '~ss~',
'~{wg}~', '~wg1~',
'~wg2~',
], [ ], [
getenv('IP'), getenv('IP'),
getenv('TGPORT'), getenv('TGPORT'),
getenv('SSPORT'), getenv('SSPORT'),
getenv('WGPORT'), getenv('WGPORT'),
getenv('WG1PORT'),
], $s); ], $s);
file_put_contents('/mirror/start_socat.sh', $t); $this->sendFile($this->input['from'], new CURLStringFile($t, 'socat.sh', 'application/x-sh'));
$a = new PharData('/config/mirror.tar');
$a->buildFromDirectory('/mirror');
$a->compress(Phar::GZ);
if (!empty($this->input)) {
$this->sendFile($this->input['from'], curl_file_create('/config/mirror.tar.gz'));
} else {
header('Content-Disposition: attachment; filename=mirror.tar.gz');
header('Content-Type: application/tar+gzip');
echo file_get_contents('/config/mirror.tar.gz');
exit;
}
unlink('/config/mirror.tar.gz');
unlink('/config/mirror.tar');
file_put_contents('/mirror/start_socat.sh', $s);
} }
public function ocMenu() public function ocMenu()
@@ -5885,9 +5870,10 @@ DNS-over-HTTPS with IP:
$st = $this->getXrayStats(); $st = $this->getXrayStats();
$td = $this->getBytes($st['global']['download'] + $st['session']['download']); $td = $this->getBytes($st['global']['download'] + $st['session']['download']);
$tu = $this->getBytes($st['global']['upload'] + $st['session']['upload']); $tu = $this->getBytes($st['global']['upload'] + $st['session']['upload']);
$text[] = "$td$tu";
$data[] = [ $data[] = [
[ [
'text' => $this->i18n('reset stats') . ": ↓$td$tu", 'text' => $this->i18n('reset stats'),
'callback_data' => '/resetXrStats', 'callback_data' => '/resetXrStats',
], ],
[ [
@@ -6110,7 +6096,7 @@ DNS-over-HTTPS with IP:
if (!empty($this->ssh('pgrep warp-svc', 'wp'))) { if (!empty($this->ssh('pgrep warp-svc', 'wp'))) {
$st = $this->ssh('curl -m 1 -x socks5://127.0.0.1:40000 https://cloudflare.com/cdn-cgi/trace', 'wp'); $st = $this->ssh('curl -m 1 -x socks5://127.0.0.1:40000 https://cloudflare.com/cdn-cgi/trace', 'wp');
preg_match('~warp=(\w+)~', $st, $m); preg_match('~warp=(\w+)~', $st, $m);
return $m[1]; return trim($m[1]) ?: 'off';
} }
return 'off'; return 'off';
} }
@@ -6316,6 +6302,9 @@ DNS-over-HTTPS with IP:
$hash = $this->getHashBot(); $hash = $this->getHashBot();
$text[] = "Menu -> " . $this->i18n('xray') . " -> {$c['email']}\n"; $text[] = "Menu -> " . $this->i18n('xray') . " -> {$c['email']}\n";
if (file_exists(__DIR__ . '/subscription.php')) {
$text[] = "<a href='$scheme://{$domain}/pac$hash/sub?id={$c['id']}'>subscription</a>";
}
$text[] = "<pre><code>{$this->linkXray($i)}</code></pre>\n"; $text[] = "<pre><code>{$this->linkXray($i)}</code></pre>\n";
$text[] = "<a href='$scheme://{$domain}/pac$hash?t=s&r=v&s={$c['id']}#{$c['email']}'>import://v2rayng</a>"; $text[] = "<a href='$scheme://{$domain}/pac$hash?t=s&r=v&s={$c['id']}#{$c['email']}'>import://v2rayng</a>";
@@ -6443,7 +6432,57 @@ DNS-over-HTTPS with IP:
return $c['domain'] ?: $this->ip; return $c['domain'] ?: $this->ip;
} }
public function subscription() public function sub()
{
$xr = $this->getXray();
$pac = $this->getPacConf();
$st = $this->getXrayStats();
$domain = $_GET['cdn'] ?: ($_SERVER['SERVER_NAME'] ?: $this->getDomain($pac['transport'] != 'Reality'));
$scheme = empty($this->nginxGetTypeCert()) ? 'http' : 'https';
$hash = $this->getHashBot();
$flag = true;
foreach ($xr['inbounds'][0]['settings']['clients'] as $k => $v) {
if ($v['id'] == $_GET['id']) {
if (empty($v['off'])) {
$flag = false;
}
$uid = $v['id'];
$email = $v['email'];
break;
}
}
$download = $this->getBytes($st['users'][$k]['global']['download'] + $st['users'][$k]['session']['download']);
$upload = $this->getBytes($st['users'][$k]['global']['upload'] + $st['users'][$k]['session']['upload']);
$singbox = "$scheme://{$domain}/pac$hash/" . base64_encode(serialize([
'h' => $hash,
't' => 'si',
's' => $uid,
]));
$xray = "$scheme://{$domain}/pac$hash/" . base64_encode(serialize([
'h' => $hash,
't' => 's',
's' => $uid,
]));
$clash = "$scheme://{$domain}/pac$hash/" . base64_encode(serialize([
'h' => $hash,
't' => 'cl',
's' => $uid,
]));
$vless = $this->linkXray($k);
$windows = "$scheme://{$domain}/pac$hash?t=si&r=w&s=$uid";
$_GET['s'] = $uid;
foreach ([
'xray' => 's',
'singbox' => 'si',
'clash' => 'cl'
] as $k => $v) {
$_GET['t'] = $v;
$configs[$k] = $this->subscription(1);
}
require __DIR__ . '/subscription.php';
}
public function subscription($return = false)
{ {
switch ($_GET['t']) { switch ($_GET['t']) {
case 's': case 's':
@@ -6697,6 +6736,12 @@ DNS-over-HTTPS with IP:
} }
break; break;
} }
if (!empty($return)) {
if ($_GET['t'] == 'cl') {
return yaml_emit($c);
}
return json_encode($c);
}
if ($_GET['t'] == 'cl') { if ($_GET['t'] == 'cl') {
header('Content-type: text/yaml'); header('Content-type: text/yaml');
+4
View File
@@ -42,6 +42,10 @@ switch (true) {
echo "/adguard$hash/"; echo "/adguard$hash/";
break; break;
case preg_match('~^' . preg_quote("/pac$hash/sub") . '~', $_SERVER['REQUEST_URI']) && file_exists(__DIR__ . '/subscription.php'):
$bot->sub();
exit;
// subs & pac // subs & pac
case preg_match('~^' . preg_quote("/pac$hash") . '~', $_SERVER['REQUEST_URI']): case preg_match('~^' . preg_quote("/pac$hash") . '~', $_SERVER['REQUEST_URI']):
if (!empty($t = unserialize(base64_decode(explode('/', $_SERVER['REQUEST_URI'])[2])))) { // fix sing-box import if (!empty($t = unserialize(base64_decode(explode('/', $_SERVER['REQUEST_URI'])[2])))) { // fix sing-box import
-18
View File
@@ -1,18 +0,0 @@
version: "3"
services:
socat:
build:
dockerfile: ./dockerfile
ports:
- 80:80
- 443:443
- 853:853
- ${TGPORT}:${TGPORT}
- ${SSPORT}:${SSPORT}
- ${SSPORT}:${SSPORT}/udp
- ${WGPORT}:${WGPORT}/udp
volumes:
- ./start_socat.sh:/start_socat.sh
command: /bin/sh /start_socat.sh
stop_grace_period: 1s
-2
View File
@@ -1,2 +0,0 @@
FROM alpine:3.18
RUN apk add socat htop net-tools
-11
View File
@@ -1,11 +0,0 @@
b:
docker compose build --no-cache
u:
docker compose up -d --build
d:
docker compose down
ps:
docker compose ps
e:
docker compose exec socat sh
r: d u
+53 -8
View File
@@ -1,8 +1,53 @@
socat TCP-LISTEN:80,fork TCP:{ip}:80 & #!/bin/bash
socat TCP-LISTEN:443,fork TCP:{ip}:443 &
socat TCP-LISTEN:853,fork TCP:{ip}:853 & # Параметры (можно менять)
socat TCP-LISTEN:{tg},fork TCP:{ip}:{tg} & PORTS=(80 443 853 ~tg~ ~ss~ ~wg1~ ~wg2~) # Прослушиваемые порты
socat TCP-LISTEN:{ss},fork TCP:{ip}:{ss} & TARGET="~ip~" # Куда перенаправляем трафик
socat UDP-LISTEN:{ss},fork UDP:{ip}:{ss} & TCP_CMD="socat TCP-LISTEN:{PORT},fork,reuseaddr TCP:$TARGET:{PORT}"
socat UDP-LISTEN:{wg},fork UDP:{ip}:{wg} & UDP_CMD="socat UDP-LISTEN:{PORT},fork,reuseaddr UDP:$TARGET:{PORT}"
tail -f /dev/null
# Проверяем, установлен ли socat
if ! command -v socat &> /dev/null; then
echo "socat не установлен. Устанавливаем..."
if [[ -f /etc/debian_version ]]; then
sudo apt update && sudo apt install -y socat
elif [[ -f /etc/redhat-release ]]; then
sudo yum install -y socat
else
echo "Ошибка: Неизвестный дистрибутив. Установите socat вручную."
exit 1
fi
fi
# Проверяем, заняты ли порты (TCP и UDP)
for PORT in "${PORTS[@]}"; do
# Проверка TCP
if ss -tulnp | grep -q ":$PORT "; then
PROCESS=$(ss -tulnp | grep ":$PORT " | awk '{print $7}')
echo "Ошибка: Порт $PORT (TCP) занят процессом: $PROCESS"
exit 1
fi
# Проверка UDP
if ss -ulnp | grep -q ":$PORT "; then
PROCESS=$(ss -ulnp | grep ":$PORT " | awk '{print $6}')
echo "Ошибка: Порт $PORT (UDP) занят процессом: $PROCESS"
exit 1
fi
done
# Запускаем socat для каждого порта (TCP и UDP)
for PORT in "${PORTS[@]}"; do
# TCP
CMD_TCP=$(echo "$TCP_CMD" | sed "s/{PORT}/$PORT/g")
echo "Запуск (TCP): $CMD_TCP"
eval "$CMD_TCP &" # Запускаем в фоне
# UDP
CMD_UDP=$(echo "$UDP_CMD" | sed "s/{PORT}/$PORT/g")
echo "Запуск (UDP): $CMD_UDP"
eval "$CMD_UDP &" # Запускаем в фоне
done
echo "socat запущен для портов: ${PORTS[*]} (TCP и UDP)"
echo "Трафик перенаправляется на: $TARGET"
echo "Для остановки выполните: pkill socat"
+7
View File
@@ -1,3 +1,10 @@
16.07.2025 v2.23
- фикс зависания бота из-за пустого статуса warp
- скрипт socat.sh для мостов /mirror
04.07.2025 v2.23
- фикс двойного /id
- фикс отображения статы vless на мобилке
- страница подписок app/subscription.php
18.06.2025 v2.22 18.06.2025 v2.22
- фикс определения айпи при запуске - фикс определения айпи при запуске
11.06.2025 v2.21 11.06.2025 v2.21