Compare commits

...

31 Commits

Author SHA1 Message Date
mercury 1a593100b7 update version 2025-02-02 14:24:05 +04:00
mercury 414a67c10d Revert "update singbox 1.11 windows x64"
This reverts commit 284b025881.
2025-02-02 13:29:51 +04:00
mercury f92b484011 Revert "fix singbox template"
This reverts commit 86261e6b76.
2025-02-02 11:52:02 +04:00
mercury 7af0276944 Revert "Migrate to sing-box 1.11"
This reverts commit 6d1ab0cb3a.
2025-02-02 01:56:15 +04:00
mercury 24aaa8756c update version 2025-02-02 00:05:02 +04:00
mercury 07e2beff9b xray stats improve 2025-01-31 18:15:48 +04:00
mercury 86261e6b76 fix singbox template 2025-01-31 12:30:45 +04:00
Konstantin d816582e6f Merge pull request #34 from legiz-ru/dev
Migrate to sing-box 1.11
2025-01-30 19:04:30 +04:00
legiz-ru 6d1ab0cb3a Migrate to sing-box 1.11 2025-01-30 17:55:27 +03:00
legiz-ru 284b025881 update singbox 1.11 windows x64 2025-01-30 17:51:19 +03:00
mercury 0ca93b56a3 vless: ~email~ tag in subscription 2025-01-29 18:18:28 +04:00
mercury 7bcd8de007 vless: reset stats user 2025-01-29 11:04:06 +04:00
mercury 34eb950852 ip-cidr route 2025-01-24 22:09:05 +04:00
mercury 46021855a5 improve wg client menu 2025-01-23 00:55:44 +04:00
mercury 29c18ceb9d update readme 2025-01-20 01:04:24 +04:00
mercury 49d0827b9e update version 2025-01-18 23:39:39 +04:00
mercury 07e04c384a Merge branch 'dev' of github.com:mercurykd/vpnbot into dev 2025-01-18 23:33:29 +04:00
mercury 579457b4f4 show xray stats 2025-01-18 23:33:00 +04:00
mercury 3dac9416ca fix download mihomo template 2025-01-18 23:32:31 +04:00
mercury 5b4d3b5627 reality degenerate pattern improve 2025-01-18 23:31:58 +04:00
mercury 658e125cd8 show group id 2025-01-18 23:31:01 +04:00
Konstantin 1840555573 Merge pull request #33 from legiz-ru/dev
update singbox 1.10.7 windows x64
2025-01-18 18:23:20 +04:00
legiz-ru ecdc028226 update singbox 1.10.7 windows x64 2025-01-18 16:57:39 +03:00
mercury d432bf82f2 force inclusion of xray statistics 2025-01-16 01:04:33 +04:00
mercury 211e2c079d collect xray metrics 2025-01-13 15:32:54 +04:00
Konstantin 1696c4da7b Merge pull request #32 from legiz-ru/dev
v2ray(xray) client templates update
2025-01-12 02:23:56 +04:00
legiz-ru b8d5700eba v2ray(xray) client update
return warp+block domain routes
replace rule for directing
2025-01-12 01:17:23 +03:00
mercury 7e20c14299 update version 2025-01-07 21:02:43 +04:00
mercury b9155cf674 fix show ports on start 2025-01-07 21:00:06 +04:00
mercury 159f775e12 port accounting for shadowsocks 2025-01-07 18:30:57 +04:00
mercury ae672439be return shadowsocks 2025-01-07 18:01:44 +04:00
13 changed files with 579 additions and 131 deletions
+266 -47
View File
@@ -238,6 +238,7 @@ class Bot
break;
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'], $this->input['chat'], $this->input['message_id']);
break;
case preg_match('~^/adguardChBr$~', $this->input['callback'], $m):
$this->adguardChBr();
@@ -296,7 +297,7 @@ class Bot
case preg_match('~^/delLog (?P<arg>\d+(?:_(?:-)?\d+)?)$~', $this->input['callback'], $m):
$this->delLog(...explode('_', $m['arg']));
break;
case preg_match('~^/debug$~', $this->input['callback'], $m):
case preg_match('~^/debug$~', $this->input['message'], $m):
$this->debug();
break;
case preg_match('~^/backup$~', $this->input['callback'], $m):
@@ -377,6 +378,9 @@ class Bot
case preg_match('~^/renameXrUser (\d+)$~', $this->input['callback'], $m):
$this->renameXrUser($m[1]);
break;
case preg_match('~^/resetXrUser (\d+)$~', $this->input['callback'], $m):
$this->resetXrUser($m[1]);
break;
case preg_match('~^/v2ray$~', $this->input['callback'], $m):
$this->v2ray();
break;
@@ -540,6 +544,9 @@ class Bot
case preg_match('~^/xtlsprocess(?: (\d+))?$~', $this->input['callback'], $m):
$this->xtlsprocess($m[1] ?: 0);
break;
case preg_match('~^/xtlssubnet(?: (\d+))?$~', $this->input['callback'], $m):
$this->xtlssubnet($m[1] ?: 0);
break;
case preg_match('~^/xtlsrulesset(?: (\d+))?$~', $this->input['callback'], $m):
$this->xtlsrulesset($m[1] ?: 0);
break;
@@ -667,13 +674,75 @@ class Bot
}
}
public function restartXray($c)
public function restartXray($c, $norestart = false)
{
$c['inbounds'][0]['settings']['clients'] = array_values($c['inbounds'][0]['settings']['clients']);
$c['log']['access'] = '/logs/xray';
$this->ssh('pkill xray', 'xr');
file_put_contents('/config/xray.json', json_encode($c, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$this->ssh('xray run -config /xray.json > /dev/null 2>&1 &', 'xr');
foreach ($c['inbounds'] as $v) {
if ($v['tag'] == 'api') {
$inbound = true;
break;
}
}
if (empty($inbound)) {
$c['inbounds'][] = [
"listen" => "127.0.0.1",
"port" => 8080,
"protocol" => "dokodemo-door",
"settings" => [
"address" => "127.0.0.1"
],
"tag" => "api"
];
}
foreach ($c['routing']['rules'] as $v) {
if ($v['outboundTag'] == 'api') {
$rule = true;
break;
}
}
if (empty($rule)) {
$c['routing']['rules'][] = [
"inboundTag" => ["api"],
"outboundTag" => "api",
"type" => "field"
];
}
$c['stats'] = new stdClass();
$c['api'] = [
'services' => ['StatsService'],
'tag' => 'api'
];
$l = new stdClass();
$l->{'0'} = [
"statsUserUplink" => true,
"statsUserDownlink" => true
];
$c['policy']['levels'] = $l;
$c['policy']['system'] = [
"statsInboundUplink" => true,
"statsInboundDownlink" => true,
"statsOutboundUplink" => true,
"statsOutboundDownlink" => true
];
if (empty($norestart)) {
$c = $this->collectSession($c);
file_put_contents('/config/xray.json', json_encode($c, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$this->ssh('pkill xray', 'xr');
$this->ssh('xray run -config /xray.json > /dev/null 2>&1 &', 'xr');
} else {
file_put_contents('/config/xray.json', json_encode($c, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
}
}
public function collectSession($c) {
foreach ($c['inbounds'][0]['settings']['clients'] as $k => $v) {
$c['inbounds'][0]['settings']['clients'][$k]['global']['download'] += $v['session']['download'];
$c['inbounds'][0]['settings']['clients'][$k]['session']['download'] = 0;
$c['inbounds'][0]['settings']['clients'][$k]['global']['upload'] += $v['session']['upload'];
$c['inbounds'][0]['settings']['clients'][$k]['session']['upload'] = 0;
}
return $c;
}
public function linkMtproto()
@@ -1251,10 +1320,30 @@ class Bot
$this->checkBackup($period);
$this->checkCert();
$this->autoAnalyzeLogs();
$this->xrayStatsUser();
sleep($period);
}
}
public function xrayStatsUser()
{
try {
$x = $this->getXray();
if (!empty($users = $x['inbounds'][0]['settings']['clients'])) {
foreach ($users as $k => $v) {
$d = json_decode($this->ssh('xray api stats --server=127.0.0.1:8080 -name "user>>>' . $v['email'] . '>>>traffic>>>downlink" 2>&1', 'xr'), true)['stat']['value'] ?: 0;
$u = json_decode($this->ssh('xray api stats --server=127.0.0.1:8080 -name "user>>>' . $v['email'] . '>>>traffic>>>uplink" 2>&1', 'xr'), true)['stat']['value'] ?: 0;
$x['inbounds'][0]['settings']['clients'][$k]['session'] = [
'download' => $d,
'upload' => $u,
];
}
$this->restartXray($x, norestart: 1);
}
} catch (\Throwable $th) {
}
}
public function autoAnalyzeLogs()
{
try {
@@ -1531,6 +1620,8 @@ class Bot
'xray' => $this->getXray(),
'oc' => file_get_contents('/config/ocserv.conf'),
'ocu' => file_get_contents('/config/ocserv.passwd'),
'ss' => $this->getSSConfig(),
'sl' => $this->getSSLocalConfig(),
];
return json_encode($conf, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
@@ -1612,6 +1703,22 @@ class Bot
yaml_emit_file($this->adguard, $json['ad']);
$this->startAd();
}
// ss
if (!empty($json['ss'])) {
$out[] = 'update shadowsocks server';
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
$this->ssh('pkill ssserver', 'ss');
file_put_contents('/config/ssserver.json', json_encode($json['ss'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$this->ssh('ssserver -v -d -c /config.json', 'ss');
}
// sl
if (!empty($json['sl'])) {
$out[] = 'update shadowsocks proxy';
$this->update($this->input['chat'], $this->input['message_id'], implode("\n", $out));
$this->ssh('pkill sslocal', 'proxy');
file_put_contents('/config/sslocal.json', json_encode($json['sl'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
$this->ssh('sslocal -v -d -c /config.json', 'proxy');
}
// mtproto
if (!empty($json['mtproto'])) {
$out[] = 'update mtproto';
@@ -2594,15 +2701,15 @@ DNS-over-HTTPS with IP:
$this->xtlswarp();
break;
case 'processlist':
$this->xrayUpdateRules();
$this->xtlsprocess();
break;
case 'packagelist':
$this->xrayUpdateRules();
$this->xtlsapp();
break;
case 'subnetlist':
$this->xtlssubnet();
break;
case 'rulessetlist':
$this->xrayUpdateRules();
$this->xtlsrulesset();
break;
case 'white':
@@ -3417,8 +3524,6 @@ DNS-over-HTTPS with IP:
'text' => $this->i18n('delete'),
'callback_data' => "/delete {$client}_$page",
],
],
[
[
'text' => $this->i18n('back'),
'callback_data' => "/menu wg $page",
@@ -3652,6 +3757,12 @@ DNS-over-HTTPS with IP:
case 'packagelist':
$dir = 'PACKAGE';
break;
case 'processlist':
$dir = 'PROCESS';
break;
case 'subnetlist':
$dir = 'SUBNET';
break;
case 'rulessetlist':
$dir = 'rulesset';
break;
@@ -3698,6 +3809,22 @@ DNS-over-HTTPS with IP:
],
];
break;
case 'processlist':
$data[] = [
[
'text' => $this->i18n('back'),
'callback_data' => "/xtlsprocess",
],
];
break;
case 'subnetlist':
$data[] = [
[
'text' => $this->i18n('back'),
'callback_data' => "/xtlssubnet",
],
];
break;
case 'rulessetlist':
$data[] = [
[
@@ -3845,7 +3972,25 @@ DNS-over-HTTPS with IP:
$text[] = "Menu -> " . $this->i18n('xray') . ' -> ' . $this->i18n('routes') . ' -> process list';
[$data] = $this->listPac('processlist', $page, 'xtlsprocess');
$p = $this->getPacConf();
$data[] = [
[
'text' => $this->i18n('back'),
'callback_data' => "/routes",
],
];
$this->update(
$this->input['chat'],
$this->input['message_id'],
implode("\n", $text ?: ['...']),
$data ?: false,
);
}
public function xtlssubnet($page = 0)
{
$text[] = "Menu -> " . $this->i18n('xray') . ' -> ' . $this->i18n('routes') . ' -> subnet';
[$data] = $this->listPac('subnetlist', $page, 'xtlssubnet');
$data[] = [
[
'text' => $this->i18n('back'),
@@ -3901,7 +4046,7 @@ DNS-over-HTTPS with IP:
}
$data[] = [
[
'text' => $this->i18n($v ? 'on' : 'off') . ' ' . ($basename ? basename($k) . ' ' : '') . (in_array($type, ['rulessetlist', 'packagelist', 'processlist']) ? $k : idn_to_utf8($k)),
'text' => $this->i18n($v ? 'on' : 'off') . ' ' . ($basename ? basename($k) . ' ' : '') . (in_array($type, ['rulessetlist', 'packagelist', 'processlist', 'subnetlist']) ? $k : idn_to_utf8($k)),
'callback_data' => "/change$type " . ($i + $page * $this->limit),
],
[
@@ -3995,14 +4140,12 @@ DNS-over-HTTPS with IP:
public function menuSS()
{
$conf = $this->getPacConf();
$ip = $this->ip;
$hash = $this->getHashBot();
$domain = $this->getDomain();
$scheme = empty($ssl = $this->nginxGetTypeCert()) ? 'http' : 'https';
$ss = $this->getSSConfig();
$v2ray = !empty($ss['plugin']) ? 'ON' : 'OFF';
$port = !empty($ss['plugin']) ? (!empty($ssl) ? 443 : 80) : getenv('SSPORT');
$options = !empty($ssl) && !empty($ss['plugin']) ? "tls;fast-open;path=/v2ray;host=$domain" : "path=/v2ray;host=$domain";
$port = !empty($ss['plugin']) ? 443 : getenv('SSPORT');
$options = !empty($ss['plugin']) ? "tls;fast-open;path=/v2ray$hash;host=$domain" : "path=/v2ray$hash;host=$domain";
$text = "Menu -> ShadowSocks";
$data[] = [
@@ -4011,7 +4154,7 @@ DNS-over-HTTPS with IP:
'callback_data' => "/sspswd",
],
];
$ss_link = preg_replace('~==~', '', 'ss://' . base64_encode("{$ss['method']}:{$ss['password']}")) . "@$domain:$port" . (!empty($ss['plugin']) ? '?plugin=' . urlencode("v2ray-plugin;path=/v2ray;host=$domain" . (!empty($ssl) ? ';tls' : '')) : '');
$ss_link = preg_replace('~==~', '', 'ss://' . base64_encode("{$ss['method']}:{$ss['password']}")) . "@$domain:$port" . (!empty($ss['plugin']) ? '?plugin=' . urlencode("v2ray-plugin;path=/v2ray$hash;host=$domain;tls") : '');
$text .= "\n\n<code>$ss_link</code>\n";
$text .= "\n\npassword: <span class='tg-spoiler'>{$ss['password']}</span>";
$text .= "\n\nserver: <code>$domain:$port</code>";
@@ -4089,6 +4232,7 @@ DNS-over-HTTPS with IP:
$main[] = $this->i18n($c['wg1'] ? 'on' : 'off') . ' ' . getenv('WG1PORT') . ' Wireguard 1';
$main[] = $this->i18n($c['tg'] ? 'on' : 'off') . ' ' . getenv('TGPORT') . ' MTProto';
$main[] = $this->i18n($c['ad'] ? 'on' : 'off') . ' 853 AdguardHome DoT';
$main[] = $this->i18n($c['ss'] ? 'on' : 'off') . ' 8388 Shadowsocks';
if (!empty($conf['domain'])) {
$main[] = '';
$oc = $this->getHashSubdomain('oc');
@@ -4102,12 +4246,6 @@ DNS-over-HTTPS with IP:
'main' => [
'text' => implode("\n", $main ?: []),
'data' => [
[
[
'text' => $this->i18n('config'),
'callback_data' => "/menu config",
],
],
[
[
'text' => $this->i18n($this->getPacConf()['amnezia'] ? 'amnezia' : 'wg_title'),
@@ -4149,15 +4287,25 @@ DNS-over-HTTPS with IP:
],
],
[
[
'text' => $this->i18n('sh_title'),
'callback_data' => "/menu ss",
],
[
'text' => $this->i18n('pac'),
'callback_data' => "/pacMenu 0",
],
],
[
[
'text' => $this->i18n('config'),
'callback_data' => "/menu config",
],
],
[
[
'text' => $this->i18n('chat'),
'url' => "https://t.me/+Wfxg6-nrokBlMmYy",
'url' => base64_decode('aHR0cHM6Ly90Lm1lLytXZnhnNi1ucm9rQmxNbVl5'),
],
[
'text' => $this->i18n('donate'),
@@ -4405,7 +4553,6 @@ DNS-over-HTTPS with IP:
}
$t = [
$this->suspicious('~\d+\.\d+\.\d+\.\d+.+200\s\d+\s0$~', '/logs/upstream_access', $xr, 'possibly a Reality Degenerate'),
$this->suspicious($this->reg, '/logs/nginx_default_access', $xr, 'possibly a scanner', true),
$this->suspicious($this->reg, '/logs/nginx_domain_access', $xr, 'possibly a scanner', true),
];
@@ -4417,6 +4564,15 @@ DNS-over-HTTPS with IP:
}
}
$r = $this->suspicious('~\d+\.\d+\.\d+\.\d+.+200\s\d+\s0$~', '/logs/upstream_access', $xr, 'possibly a Reality Degenerate');
if (!empty($r)) {
foreach ($r as $k => $v) {
if (count($v) > 30) {
$ip[$k] = $v;
}
}
}
if (!empty($return)) {
return $ip;
}
@@ -5116,15 +5272,15 @@ DNS-over-HTTPS with IP:
public function setTimerXr($time, $i)
{
$time = strtotime($time);
if ($time === false) {
$this->send($this->input['chat'], 'wrong format');
return;
}
$c = $this->getXray();
if (empty($time)) {
unset($c['inbounds'][0]['settings']['clients'][$i]['time']);
} else {
$time = strtotime($time);
if ($time === false) {
$this->send($this->input['chat'], 'wrong format');
return;
}
if (!empty($c['inbounds'][0]['settings']['clients'][$i]['off'])) {
$this->switchXr($i, 1);
$c = $this->getXray();
@@ -5161,6 +5317,17 @@ DNS-over-HTTPS with IP:
$this->userXr($i);
}
public function resetXrUser($i)
{
$c = $this->getXray();
$c['inbounds'][0]['settings']['clients'][$i]['global'] = [
'download' => 0,
'upload' => 0,
];
$this->restartXray($c);
$this->userXr($i);
}
public function listXr($i)
{
$c = $this->getPacConf();
@@ -5293,14 +5460,7 @@ DNS-over-HTTPS with IP:
public function downloadOrigin($type)
{
switch ($type) {
case 'sing':
$f = new \CURLFile('/config/sing.json', 'application/json', 'origin.json');
break;
case 'v2ray':
$f = new \CURLFile('/config/v2ray.json', 'application/json', 'origin.json');
break;
}
$f = new \CURLFile("/config/$type.json", 'application/json', 'origin.json');
$this->sendFile($this->input['chat'], $f);
}
@@ -5334,6 +5494,7 @@ DNS-over-HTTPS with IP:
<code>~pac~</code>
<code>~package~</code>
<code>~process~</code>
<code>~subnet~</code>
<code>~block~</code>
<code>~warp~</code>
<code>~dns~</code>
@@ -5342,6 +5503,7 @@ DNS-over-HTTPS with IP:
<code>~directdomain~</code>
<code>~cdndomain~</code>
<code>~short_id~</code>
<code>~email~</code>
<code>~public_key~</code>
<code>~server_name~</code>
<code>~ip~</code>
@@ -5435,6 +5597,25 @@ DNS-over-HTTPS with IP:
$this->xray();
}
public function getBytes($bytes)
{
$t = [
'B',
'KB',
'MB',
'GB',
'TB',
];
foreach ($t as $k => $v) {
if ($k == 0) {
continue;
}
if ($bytes / (1024 ** $k) < 1) {
return round($bytes / (1024 ** ($k - 1)), 2) . " {$t[$k - 1]}";
}
}
}
public function xray($page = 0)
{
if (!$this->ssh('pgrep xray', 'xr')) {
@@ -5517,10 +5698,12 @@ DNS-over-HTTPS with IP:
$page = $page == -2 ? $all - 1 : $page;
$clients = $page != -1 ? array_slice($clients, $page * $this->limit, $this->limit, true) : $clients;
foreach ($clients as $k => $v) {
$time = $v['time'] ? $this->getTime($v['time']) : '';
$data[] = [
$download = $this->getBytes($v['global']['download'] + $v['session']['download']);
$upload = $this->getBytes($v['global']['upload'] + $v['session']['upload']);
$time = $v['time'] ? $this->getTime($v['time']) : '';
$data[] = [
[
'text' => "{$v['email']}" . ($time ? ": $time" : ''),
'text' => "{$v['email']}" . ($time ? ": $time" : '') . " (↓$download$upload)",
'callback_data' => "/userXr $k",
],
];
@@ -5570,9 +5753,6 @@ DNS-over-HTTPS with IP:
{
$text[] = "Menu -> " . $this->i18n('xray') . ' -> routes';
$p = $this->getPacConf();
$outbound = $p['outbound'] ?: 'proxy';
$data = [
[[
'text' => $this->i18n('block'),
@@ -5586,6 +5766,10 @@ DNS-over-HTTPS with IP:
'text' => 'domains',
'callback_data' => "/xtlsproxy",
]],
[[
'text' => "subnet",
'callback_data' => "/xtlssubnet",
]],
[[
'text' => 'process',
'callback_data' => "/xtlsprocess",
@@ -5864,6 +6048,14 @@ DNS-over-HTTPS with IP:
'callback_data' => "/qrXray {$i}_2",
],
];
$download = $this->getBytes($c['global']['download'] + $c['session']['download']);
$upload = $this->getBytes($c['global']['upload'] + $c['session']['upload']);
$data[] = [
[
'text' => $this->i18n('reset stats') . ": ↓$download$upload",
'callback_data' => "/resetXrUser $i",
],
];
$data[] = [
[
'text' => $this->i18n('rename'),
@@ -6104,12 +6296,14 @@ DNS-over-HTTPS with IP:
'"~warp~"' => json_encode(array_keys(array_filter($pac['warplist'] ?: []))),
'"~process~"' => json_encode(array_keys(array_filter($pac['processlist'] ?: []))),
'"~package~"' => json_encode(array_keys(array_filter($pac['packagelist'] ?: []))),
'"~subnet~"' => json_encode(array_keys(array_filter($pac['subnetlist'] ?: []))),
'~dns~' => "https://$domain/dns-query$hash/$uid",
'~uid~' => $uid,
'~domain~' => $domain,
'~directdomain~' => $pac['domain'],
'~cdndomain~' => $pac['linkdomain'],
'~short_id~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['shortIds'][0],
'~email~' => $email,
'~public_key~' => $pac['xray'],
'~server_name~' => $xr['inbounds'][0]['streamSettings']['realitySettings']['serverNames'][0],
'~ip~' => $this->ip,
@@ -6213,6 +6407,9 @@ DNS-over-HTTPS with IP:
case 'domain':
echo yaml_emit(['payload' => array_map(fn($e) => "+.$e", $v['list'])]);
break;
case 'ipcidr':
echo yaml_emit(['payload' => array_map(fn($e) => $e, $v['list'])]);
break;
default:
echo yaml_emit(['payload' => array_map(fn($e) => "PROCESS-NAME,$e", $v['list'])]);
@@ -6440,7 +6637,7 @@ DNS-over-HTTPS with IP:
location
CONF;
$template = preg_replace('~(location /adguard.+?})\s*location~s', $r, $template);
$template = preg_replace('~(/webapp|/pac|/adguard|/ws|location /dns-query)~', '${1}' . $h, $template);
$template = preg_replace('~(/webapp|/pac|/adguard|/ws|/v2ray|location /dns-query)~', '${1}' . $h, $template);
file_put_contents('/config/nginx.conf', $template);
$x = $this->getXray();
if (!empty($x['inbounds'][0]['streamSettings']['wsSettings']['path'])) {
@@ -6808,6 +7005,8 @@ DNS-over-HTTPS with IP:
'text' => $this->i18n('Ports'),
'callback_data' => "/ports",
],
];
$data[] = [
[
'text' => $this->i18n('IP ban & Logs'),
'callback_data' => "/ipMenu",
@@ -6898,6 +7097,7 @@ DNS-over-HTTPS with IP:
$text[] = 'Settings -> Ports';
$f = '/docker/compose';
$c = yaml_parse_file($f)['services'];
$pac = $this->getPacConf();
$data = [
[[
'text' => $this->i18n($c['wg'] ? 'on' : 'off') . ' ' . getenv('WGPORT') . ' Wireguard',
@@ -6915,7 +7115,19 @@ DNS-over-HTTPS with IP:
'text' => $this->i18n($c['ad'] ? 'on' : 'off') . ' 853 AdguardHome DoT',
'callback_data' => "/hidePort ad",
]],
[[
'text' => $this->i18n($c['ss'] ? 'on' : 'off') . ' 8388 Shadowsocks',
'callback_data' => "/hidePort ss",
]],
];
if (!empty($pac['restart'])) {
$data[] = [
[
'text' => $this->i18n('restart'),
'callback_data' => "/restart",
],
];
}
$data[] = [
[
'text' => $this->i18n('back'),
@@ -6937,6 +7149,7 @@ DNS-over-HTTPS with IP:
'wg1' => getenv('WG1PORT') . ':' . getenv('WG1PORT') . '/udp',
'tg' => getenv('TGPORT') . ':' . getenv('TGPORT'),
'ad' => '853:853',
'ss' => '8388:8388',
];
$f = '/docker/compose';
$c = yaml_parse_file($f);
@@ -6950,7 +7163,10 @@ DNS-over-HTTPS with IP:
} else {
yaml_emit_file($f, $c);
}
$this->restart();
$pac = $this->getPacConf();
$pac['restart'] = 1;
$this->setPacConf($pac);
$this->ports();
}
public function branches()
@@ -7087,6 +7303,9 @@ DNS-over-HTTPS with IP:
}
file_put_contents('/update/message', '');
file_put_contents('/update/reload_message', '');
$pac = $this->getPacConf();
unset($pac['restart']);
$this->setPacConf($pac);
}
public function backup()
+1 -1
View File
@@ -30,7 +30,7 @@ $i = [
'ru' => 'PAC',
],
'chat' => [
'en' => 'discussion group',
'en' => 'chat',
'ru' => 'чат поддержки',
],
'back' => [
+1
View File
@@ -13,6 +13,7 @@ if ($c['debug']) {
$bot = new Bot($c['key'], $i);
$bot->selfUpdate();
$bot->ssPswdCheck();
$bot->restartTG();
if (!empty($bot->selfupdate)) {
$bot->offWarp();
+8
View File
@@ -133,6 +133,14 @@
"behavior": "domain",
"name": "pac"
},
{
"type": "RULE-SET",
"list": "~subnet~",
"action": "PROXY",
"interval": 30,
"behavior": "ipcidr",
"name": "subnet"
},
{
"type": "MATCH",
"action": "DIRECT"
+24
View File
@@ -97,6 +97,18 @@ http {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 5d;
}
location /v2ray {
access_log /logs/nginx_v2ray_access;
proxy_redirect off;
proxy_buffering off;
proxy_http_version 1.1;
proxy_pass http://ss:8388/;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /dns-query {
access_log /logs/nginx_doh_access;
proxy_http_version 1.1;
@@ -162,6 +174,17 @@ http {
# proxy_pass http://php;
# }
# location /v2ray {
# access_log /logs/nginx_v2ray_access;
# proxy_redirect off;
# proxy_buffering off;
# proxy_http_version 1.1;
# proxy_pass http://ss:8388/;
# proxy_set_header Host $http_host;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";
# }
# location /ws {
# proxy_pass http://xr:443;
# proxy_redirect off;
@@ -173,6 +196,7 @@ http {
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_read_timeout 5d;
# }
# location /dns-query {
# access_log /logs/nginx_doh_access;
# proxy_http_version 1.1;
+24
View File
@@ -97,6 +97,18 @@ http {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 5d;
}
location /v2ray {
access_log /logs/nginx_v2ray_access;
proxy_redirect off;
proxy_buffering off;
proxy_http_version 1.1;
proxy_pass http://ss:8388/;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /dns-query {
access_log /logs/nginx_doh_access;
proxy_http_version 1.1;
@@ -162,6 +174,17 @@ http {
# proxy_pass http://php;
# }
# location /v2ray {
# access_log /logs/nginx_v2ray_access;
# proxy_redirect off;
# proxy_buffering off;
# proxy_http_version 1.1;
# proxy_pass http://ss:8388/;
# proxy_set_header Host $http_host;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";
# }
# location /ws {
# proxy_pass http://xr:443;
# proxy_redirect off;
@@ -173,6 +196,7 @@ http {
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_read_timeout 5d;
# }
# location /dns-query {
# access_log /logs/nginx_doh_access;
# proxy_http_version 1.1;
+15
View File
@@ -129,6 +129,21 @@
],
"outbound": "~outbound~"
},
{
"addruleset": true,
"createruleset": [
{
"name": "subnet",
"interval": "30s",
"rules": [
{
"ip_cidr": "~subnet~"
}
]
}
],
"outbound": "~outbound~"
},
{
"addruleset": true,
"createruleset": [
+111 -81
View File
@@ -4,92 +4,122 @@
"error": "",
"loglevel": "warning"
},
"inbounds": [{
"tag": "socks",
"port": 10808,
"listen": "127.0.0.1",
"protocol": "socks",
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"],
"routeOnly": false
},
"settings": {
"auth": "noauth",
"udp": true,
"allowTransparent": false
}
}, {
"tag": "http",
"port": 10809,
"listen": "127.0.0.1",
"protocol": "http",
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"],
"routeOnly": false
},
"settings": {
"auth": "noauth",
"udp": true,
"allowTransparent": false
}
}],
"outbounds": [{
"tag": "~outbound~",
"protocol": "vless",
"settings": {
"vnext": [{
"address": "~domain~",
"port": 443,
"users": [{
"id": "~uid~",
"alterId": 0,
"email": "t@t.tt",
"security": "auto",
"encryption": "none",
"flow": "xtls-rprx-vision"
}]
}]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "~server_name~",
"fingerprint": "chrome",
"show": false,
"publicKey": "~public_key~",
"shortId": "~short_id~",
"spiderX": ""
"inbounds": [
{
"tag": "socks",
"port": 10808,
"listen": "127.0.0.1",
"protocol": "socks",
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
],
"routeOnly": false
},
"settings": {
"auth": "noauth",
"udp": true,
"allowTransparent": false
}
},
"mux": {
"enabled": false,
"concurrency": -1
}
}, {
"tag": "direct",
"protocol": "freedom"
}, {
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "http"
{
"tag": "http",
"port": 10809,
"listen": "127.0.0.1",
"protocol": "http",
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
],
"routeOnly": false
},
"settings": {
"auth": "noauth",
"udp": true,
"allowTransparent": false
}
}
}],
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "~outbound~",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "~domain~",
"port": 443,
"users": [
{
"id": "~uid~",
"alterId": 0,
"email": "t@t.tt",
"security": "auto",
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "~server_name~",
"fingerprint": "chrome",
"show": false,
"publicKey": "~public_key~",
"shortId": "~short_id~",
"spiderX": ""
}
},
"mux": {
"enabled": false,
"concurrency": -1
}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "http"
}
}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [{
"type": "field",
"outboundTag": "~outbound~",
"domain": "~pac~"
}, {
"type": "field",
"port": "0-65535",
"outboundTag": "direct"
}]
"rules": [
{
"type": "field",
"outboundTag": "block",
"domain": "~block~"
},
{
"type": "field",
"outboundTag": "~outbound~",
"domain": "~pac~"
},
{
"type": "field",
"outboundTag": "~outbound~",
"ip": "~subnet~"
},
{
"type": "field",
"outboundTag": "~outbound~",
"domain": "~warp~"
}
]
}
}
+39 -1
View File
@@ -22,6 +22,15 @@
}
},
"tag": "vless_tls"
},
{
"listen": "127.0.0.1",
"port": 8080,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1"
},
"tag": "api"
}
],
"log": {
@@ -40,6 +49,35 @@
],
"routing": {
"domainStrategy": "AsIs",
"rules": []
"rules": [
{
"inboundTag": [
"api"
],
"outboundTag": "api",
"type": "field"
}
]
},
"stats": {},
"api": {
"services": [
"StatsService"
],
"tag": "api"
},
"policy": {
"levels": {
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
"system": {
"statsInboundUplink": true,
"statsInboundDownlink": true,
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
}
}
+63
View File
@@ -44,6 +44,8 @@ services:
condition: service_healthy
ad:
condition: service_started
ss:
condition: service_started
env_file:
- path: ./.env
required: true # default
@@ -162,6 +164,7 @@ services:
- ./update:/update
- ./.git:/.git
- ./scripts/start_service.sh:/start_service.sh
- ./docker-compose.override.yml:/docker/compose
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
IP: ${IP}
@@ -192,6 +195,8 @@ services:
- xr
- oc
- np
- proxy
- ss
wg:
image: mercurykd/vpnbot-wg:1.1
build:
@@ -460,3 +465,61 @@ services:
default:
ipv4_address: 10.10.0.13
logging: *default-logging
proxy:
image: mercurykd/vpnbot-ss:1.2
build:
dockerfile: dockerfile/shadowsocks.dockerfile
args:
image: ${IMAGE}
volumes:
- ./config/.profile:/root/.ashrc:ro
- ./config/sslocal.json:/config.json
- ./ssh:/ssh
- ./config/sshd_config:/etc/ssh/sshd_config
- ./scripts/start_proxy.sh:/start_proxy.sh
hostname: proxy
container_name: proxy-${VER}
depends_on:
php:
condition: service_healthy
networks:
default:
ipv4_address: 10.10.0.3
environment:
TZ: ${TZ}
env_file:
- path: ./.env
required: true # default
- path: ./override.env
required: false
stop_grace_period: 1s
command: ["/bin/sh", "/start_proxy.sh"]
logging: *default-logging
ss:
image: mercurykd/vpnbot-ss:1.2
build:
dockerfile: dockerfile/shadowsocks.dockerfile
args:
image: ${IMAGE}
volumes:
- ./config/.profile:/root/.ashrc:ro
- ./config/ssserver.json:/config.json
- ./ssh:/ssh
- ./config/sshd_config:/etc/ssh/sshd_config
- ./scripts/start_ss.sh:/start_ss.sh
hostname: shadowsocks
container_name: shadowsocks-${VER}
depends_on:
php:
condition: service_healthy
env_file:
- path: ./.env
required: true # default
- path: ./override.env
required: false
stop_grace_period: 1s
command: ["/bin/sh", "/start_ss.sh"]
networks:
default:
ipv4_address: 10.10.0.6
logging: *default-logging
+10 -1
View File
@@ -13,8 +13,17 @@ telegram bot to manage servers (inside the bot)
---
environment: ubuntu 22.04/24.04, debian 11/12
### Install:
## Install:
```shell
wget -O- https://raw.githubusercontent.com/mercurykd/vpnbot/master/scripts/init.sh | sh -s YOUR_TELEGRAM_BOT_KEY master
```
#### Restart:
```shell
make r
```
#### autoload:
```shell
crontab -e
```
add `@reboot cd /root/vpnbot && make r` and save
Binary file not shown.
+17
View File
@@ -1,3 +1,20 @@
02.02.2025 v2.9
- откат sing-box 1.11
02.02.2025 v2.8
- vless: корректировка статы юзера
- sing-box 1.11
29.01.2025 v2.7
- vless: сброс статистики юзера
24.01.2025 v2.6
- правки меню
- vless:добавлена возможность маршрутизировать список ip-сетей
18.01.2025 v2.5
- фикс скачивания шаблона михомо
- обновлен singbox.exe
- вывод статистики vless пользователей
- смягчил паттерн поиска reality degenerate в логах
07.01.2025 v2.4
- вернул shadowsocks (спасибо за донат)
04.01.2025
- возможность установить нужную версию с нуля
- корректировка автосканера под новую версию