Skip to content

Commit

Permalink
Refactored.
Browse files Browse the repository at this point in the history
  • Loading branch information
bia-pain-bache committed Nov 2, 2024
1 parent aaab067 commit 53cb6a6
Show file tree
Hide file tree
Showing 15 changed files with 322 additions and 279 deletions.
64 changes: 58 additions & 6 deletions src/authentication/auth.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
import { SignJWT, jwtVerify } from 'jose';
import nacl from 'tweetnacl';
import { initializeParams, userID } from "../helpers/init.js";
import { initializeParams, userID, origin } from "../helpers/init";
import { renderLoginPage } from '../pages/loginPage';
import { renderErrorPage } from '../pages/errorPage';


export async function generateJWTToken (env, secretKey) {
await initializeParams(env);
async function generateJWTToken (request, env) {
await initializeParams(request, env);
const password = await request.text();
const savedPass = await env.bpb.get('pwd');
if (password !== savedPass) return new Response('Method Not Allowed', { status: 405 });
let secretKey = await env.bpb.get('secretKey');
if (!secretKey) {
secretKey = generateSecretKey();
await env.bpb.put('secretKey', secretKey);
}
const secret = new TextEncoder().encode(secretKey);
return await new SignJWT({ userID })
const jwtToken = await new SignJWT({ userID })
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime('24h')
.sign(secret);

return new Response('Success', {
status: 200,
headers: {
'Set-Cookie': `jwtToken=${jwtToken}; HttpOnly; Secure; Max-Age=${7 * 24 * 60 * 60}; Path=/; SameSite=Strict`,
'Content-Type': 'text/plain',
}
});
}

export function generateSecretKey () {
function generateSecretKey () {
const key = nacl.randomBytes(32);
return Array.from(key, byte => byte.toString(16).padStart(2, '0')).join('');
}
Expand All @@ -37,4 +54,39 @@ export async function Authenticate (request, env) {
console.log(error);
return false;
}
}

export function logout() {
return new Response('Success', {
status: 200,
headers: {
'Set-Cookie': 'jwtToken=; Secure; SameSite=None; Expires=Thu, 01 Jan 1970 00:00:00 GMT',
'Content-Type': 'text/plain'
}
});
}

export async function resetPassword(request, env) {
let auth = await Authenticate(request, env);
const oldPwd = await env.bpb.get('pwd');
if (oldPwd && !auth) return new Response('Unauthorized!', { status: 401 });
const newPwd = await request.text();
if (newPwd === oldPwd) return new Response('Please enter a new Password!', { status: 400 });
await env.bpb.put('pwd', newPwd);
return new Response('Success', {
status: 200,
headers: {
'Set-Cookie': 'jwtToken=; Path=/; Secure; SameSite=None; Expires=Thu, 01 Jan 1970 00:00:00 GMT',
'Content-Type': 'text/plain',
}
});
}

export async function login(request, env) {
await initializeParams(request, env);
if (typeof env.bpb !== 'object') return await renderErrorPage(request, env, 'KV Dataset is not properly set!', null, true);
const auth = await Authenticate(request, env);
if (auth) return Response.redirect(`${origin}/panel`, 302);
if (request.method === 'POST') return await generateJWTToken(request, env);
return await renderLoginPage(request, env);
}
34 changes: 27 additions & 7 deletions src/cores-configs/clash.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { getConfigAddresses, extractWireguardParams, generateRemark, randomUpperCase, getRandomPath, isIPv6 } from './helpers.js';
import { initializeParams, userID, trojanPassword, defaultHttpsPorts } from "../helpers/init.js";
import { getConfigAddresses, extractWireguardParams, generateRemark, randomUpperCase, getRandomPath, isIPv6 } from './helpers';
import { initializeParams, userID, trojanPassword, hostName, defaultHttpsPorts } from "../helpers/init";
import { getDataset } from '../kv/handlers';
import { renderErrorPage } from '../pages/errorPage';

async function buildClashDNS (proxySettings, isWarp) {
const {
Expand Down Expand Up @@ -279,7 +281,9 @@ function buildClashChainOutbound(chainProxyParams) {
return chainOutbound;
}

export async function getClashWarpConfig(proxySettings, warpConfigs) {
export async function getClashWarpConfig(request, env) {
const { kvNotFound, proxySettings, warpConfigs } = await getDataset(request, env);
if (kvNotFound) return await renderErrorPage(request, env, 'KV Dataset is not properly set!', null, true);
const { warpEndpoints, warpEnableIPv6 } = proxySettings;
let config = structuredClone(clashConfigTemp);
config.ipv6 = warpEnableIPv6;
Expand Down Expand Up @@ -308,11 +312,20 @@ export async function getClashWarpConfig(proxySettings, warpConfigs) {
});

selector.proxies.push(...warpRemarks, ...WoWRemarks);
return config;
return new Response(JSON.stringify(config, null, 4), {
status: 200,
headers: {
'Content-Type': 'text/plain;charset=utf-8',
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
'CDN-Cache-Control': 'no-store'
}
});
}

export async function getClashNormalConfig (env, hostName, proxySettings) {
await initializeParams(env);
export async function getClashNormalConfig (request, env) {
await initializeParams(request, env);
const { kvNotFound, proxySettings } = await getDataset(request, env);
if (kvNotFound) return await renderErrorPage(request, env, 'KV Dataset is not properly set!', null, true);
let chainProxy;
const {
cleanIPs,
Expand Down Expand Up @@ -418,7 +431,14 @@ export async function getClashNormalConfig (env, hostName, proxySettings) {
});
});

return config;
return new Response(JSON.stringify(config, null, 4), {
status: 200,
headers: {
'Content-Type': 'text/plain;charset=utf-8',
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
'CDN-Cache-Control': 'no-store'
}
});
}

const clashConfigTemp = {
Expand Down
2 changes: 1 addition & 1 deletion src/cores-configs/helpers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { resolveDNS, isDomain } from '../helpers/helpers.js';
import { resolveDNS, isDomain } from '../helpers/helpers';

export async function getConfigAddresses(hostName, cleanIPs, enableIPv6) {
const resolved = await resolveDNS(hostName);
Expand Down
22 changes: 17 additions & 5 deletions src/cores-configs/normalConfigs.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { getConfigAddresses, generateRemark, randomUpperCase, getRandomPath } from './helpers.js';
import { initializeParams, userID, trojanPassword, defaultHttpsPorts } from "../helpers/init.js";
import { getConfigAddresses, generateRemark, randomUpperCase, getRandomPath } from './helpers';
import { initializeParams, userID, trojanPassword, hostName, client, defaultHttpsPorts } from "../helpers/init";
import { getDataset } from '../kv/handlers';
import { renderErrorPage } from '../pages/errorPage';

export async function getNormalConfigs(env, hostName, proxySettings, client) {
await initializeParams(env);
export async function getNormalConfigs(request, env) {
await initializeParams(request, env);
const { kvNotFound, proxySettings } = await getDataset(request, env);
if (kvNotFound) return await renderErrorPage(request, env, 'KV Dataset is not properly set!', null, true);
const {
cleanIPs,
proxyIP,
Expand Down Expand Up @@ -66,5 +70,13 @@ export async function getNormalConfigs(env, hostName, proxySettings, client) {
}
}

return btoa(vlessConfs + trojanConfs + chainProxy);
const configs = btoa(vlessConfs + trojanConfs + chainProxy);
return new Response(JSON.stringify(configs, null, 4), {
status: 200,
headers: {
'Content-Type': 'text/plain;charset=utf-8',
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
'CDN-Cache-Control': 'no-store'
}
});
}
34 changes: 27 additions & 7 deletions src/cores-configs/sing-box.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { getConfigAddresses, extractWireguardParams, generateRemark, randomUpperCase, getRandomPath } from './helpers.js';
import { initializeParams, userID, trojanPassword, defaultHttpsPorts } from "../helpers/init.js";
import { getConfigAddresses, extractWireguardParams, generateRemark, randomUpperCase, getRandomPath } from './helpers';
import { initializeParams, userID, trojanPassword, hostName, defaultHttpsPorts } from "../helpers/init";
import { renderErrorPage } from '../pages/errorPage';
import { getDataset } from '../kv/handlers';

function buildSingBoxDNS (proxySettings, isChain, isWarp) {
const {
Expand Down Expand Up @@ -508,7 +510,9 @@ function buildSingBoxChainOutbound (chainProxyParams) {
return chainOutbound;
}

export async function getSingBoxWarpConfig (proxySettings, warpConfigs, client) {
export async function getSingBoxWarpConfig (request, env, client) {
const { kvNotFound, proxySettings, warpConfigs } = await getDataset(request, env);
if (kvNotFound) return await renderErrorPage(request, env, 'KV Dataset is not properly set!', null, true);
const { warpEndpoints } = proxySettings;
let config = structuredClone(singboxConfigTemp);
const dnsObject = buildSingBoxDNS(proxySettings, false, true);
Expand Down Expand Up @@ -543,11 +547,20 @@ export async function getSingBoxWarpConfig (proxySettings, warpConfigs, client)
});

selector.outbounds.push(...warpRemarks, ...WoWRemarks);
return config;
return new Response(JSON.stringify(config, null, 4), {
status: 200,
headers: {
'Content-Type': 'text/plain;charset=utf-8',
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
'CDN-Cache-Control': 'no-store'
}
});
}

export async function getSingBoxCustomConfig(env, hostName, proxySettings, isFragment) {
await initializeParams(env);
export async function getSingBoxCustomConfig(request, env, isFragment) {
await initializeParams(request, env);
const { kvNotFound, proxySettings } = await getDataset(request, env);
if (kvNotFound) return await renderErrorPage(request, env, 'KV Dataset is not properly set!', null, true);
let chainProxyOutbound;
const {
cleanIPs,
Expand Down Expand Up @@ -655,7 +668,14 @@ export async function getSingBoxCustomConfig(env, hostName, proxySettings, isFra
});
});

return config;
return new Response(JSON.stringify(config, null, 4), {
status: 200,
headers: {
'Content-Type': 'text/plain;charset=utf-8',
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
'CDN-Cache-Control': 'no-store'
}
});
}

const singboxConfigTemp = {
Expand Down
47 changes: 34 additions & 13 deletions src/cores-configs/xray.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { resolveDNS, isDomain } from '../helpers/helpers.js';
import { getConfigAddresses, extractWireguardParams, base64ToDecimal, generateRemark, randomUpperCase, getRandomPath } from './helpers.js';
import { initializeParams, userID, trojanPassword, defaultHttpsPorts } from "../helpers/init.js";

import { getConfigAddresses, extractWireguardParams, base64ToDecimal, generateRemark, randomUpperCase, getRandomPath } from './helpers';
import { initializeParams, userID, trojanPassword, hostName, defaultHttpsPorts } from "../helpers/init";
import { getDataset } from '../kv/handlers.js';
import { renderErrorPage } from '../pages/errorPage.js';

async function buildXrayDNS (proxySettings, outboundAddrs, domainToStaticIPs, isWorkerLess, isBalancer, isWarp) {
const {
Expand Down Expand Up @@ -632,8 +633,10 @@ async function buildXrayWorkerLessConfig(proxySettings) {
return config;
}

export async function getXrayCustomConfigs(env, hostName, proxySettings, isFragment) {
await initializeParams(env);
export async function getXrayCustomConfigs(request, env, isFragment) {
await initializeParams(request, env);
const { kvNotFound, proxySettings } = await getDataset(request, env);
if (kvNotFound) return await renderErrorPage(request, env, 'KV Dataset is not properly set!', null, true);
let configs = [];
let outbounds = [];
let protocols = [];
Expand Down Expand Up @@ -711,15 +714,25 @@ export async function getXrayCustomConfigs(env, hostName, proxySettings, isFragm
}

const bestPing = await buildXrayBestPingConfig(proxySettings, totalAddresses, chainProxy, outbounds, isFragment);
if (!isFragment) return [...configs, bestPing];
const bestFragment = await buildXrayBestFragmentConfig(proxySettings, hostName, chainProxy, outbounds);
const workerLessConfig = await buildXrayWorkerLessConfig(proxySettings);
configs.push(bestPing, bestFragment, workerLessConfig);

return configs;
let finalConfigs = [...configs, bestPing];
if (isFragment) {
const bestFragment = await buildXrayBestFragmentConfig(proxySettings, hostName, chainProxy, outbounds);
const workerLessConfig = await buildXrayWorkerLessConfig(proxySettings);
finalConfigs.push(bestFragment, workerLessConfig);
}
return new Response(JSON.stringify(finalConfigs, null, 4), {
status: 200,
headers: {
'Content-Type': 'text/plain;charset=utf-8',
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
'CDN-Cache-Control': 'no-store'
}
});
}

export async function getXrayWarpConfigs (proxySettings, warpConfigs, client) {
export async function getXrayWarpConfigs (request, env, client) {
const { kvNotFound, proxySettings, warpConfigs } = await getDataset(request, env);
if (kvNotFound) return await renderErrorPage(request, env, 'KV Dataset is not properly set!', null, true);
let xrayWarpConfigs = [];
let xrayWoWConfigs = [];
let xrayWarpOutbounds = [];
Expand Down Expand Up @@ -761,7 +774,15 @@ export async function getXrayWarpConfigs (proxySettings, warpConfigs, client) {
xrayWoWBestPing.dns = dnsObject;
xrayWoWBestPing.routing.rules = buildXrayRoutingRules(proxySettings, outboundDomains, true, true, false);
xrayWoWBestPing.outbounds.unshift(...xrayWoWOutbounds, ...xrayWarpOutbounds);
return [...xrayWarpConfigs, ...xrayWoWConfigs, xrayWarpBestPing, xrayWoWBestPing];
const configs = [...xrayWarpConfigs, ...xrayWoWConfigs, xrayWarpBestPing, xrayWoWBestPing];
return new Response(JSON.stringify(configs, null, 4), {
status: 200,
headers: {
'Content-Type': 'text/plain;charset=utf-8',
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
'CDN-Cache-Control': 'no-store'
}
});
}

const xrayConfigTemp = {
Expand Down
29 changes: 29 additions & 0 deletions src/helpers/helpers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import { Authenticate } from "../authentication/auth";
import { getDataset, updateDataset } from "../kv/handlers";
import { renderErrorPage } from "../pages/errorPage";
import { renderHomePage } from "../pages/homePage";
import { initializeParams, origin } from "./init";

export function isValidUUID(uuid) {
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
return uuidRegex.test(uuid);
Expand Down Expand Up @@ -36,4 +42,27 @@ export function isDomain(address) {
return domainPattern.test(address);
}

export async function handlePanel(request, env) {
await initializeParams(request, env);
const auth = await Authenticate(request, env);
if (request.method === 'POST') {
if (!auth) return new Response('Unauthorized or expired session!', { status: 401 });
await updateDataset(request, env);
return new Response('Success', { status: 200 });
}

const pwd = await env.bpb.get('pwd');
if (pwd && !auth) return Response.redirect(`${origin}/login`, 302);
const isPassSet = pwd?.length >= 8;
const { kvNotFound, proxySettings } = await getDataset(request, env);
if (kvNotFound) return await renderErrorPage(request, env, 'KV Dataset is not properly set!', null, true);
return await renderHomePage(request, env, proxySettings, isPassSet);
}

export async function fallback(request) {
const url = new URL(request.url);
url.hostname = 'www.speedtest.net';
url.protocol = 'https:';
request = new Request(url, request);
return await fetch(request);
}
18 changes: 12 additions & 6 deletions src/helpers/init.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { isValidUUID } from './helpers.js';
import { isValidUUID } from './helpers';
const proxyIPs = ['bpb.yousef.isegaro.com'];
let userID, dohURL, proxyIP, trojanPassword, defaultHttpPorts, defaultHttpsPorts, panelVersion;
let userID, dohURL, proxyIP, trojanPassword, defaultHttpPorts, defaultHttpsPorts, panelVersion, hostName, origin, client, pathName;

function initParams(env) {
function initParams(request, env) {
userID = env.UUID || '89b3cbba-e6ac-485a-9481-976a0415eab9';
if (!isValidUUID(userID)) throw new Error(`Invalid UUID: ${userID}`);
dohURL = env.DOH_URL || 'https://cloudflare-dns.com/dns-query';
Expand All @@ -11,11 +11,17 @@ function initParams(env) {
defaultHttpPorts = ['80', '8080', '2052', '2082', '2086', '2095', '8880'];
defaultHttpsPorts = ['443', '8443', '2053', '2083', '2087', '2096'];
panelVersion = '2.7.2';
hostName = request.headers.get('Host');
const url = new URL(request.url);
const searchParams = new URLSearchParams(url.search);
client = searchParams.get('app');
origin = url.origin;
pathName = url.pathname;
}

export function initializeParams(env) {
initParams(env);
export function initializeParams(request, env) {
initParams(request, env);
return Promise.resolve();
}

export { userID, dohURL, proxyIP, trojanPassword, defaultHttpPorts, defaultHttpsPorts, panelVersion };
export { userID, dohURL, proxyIP, trojanPassword, hostName, origin, client, pathName, defaultHttpPorts, defaultHttpsPorts, panelVersion };
Loading

0 comments on commit 53cb6a6

Please sign in to comment.