//这个是指向斗鱼直播的网站。只要把第130行 www.douyu.com改成想要指向的网站就可以了。然后复制以下代码到搭建的服务器work中。
// version base on commit 43fad05dcdae3b723c53c226f8181fc5bd47223e, time is 2023-06-22 15:20:02 UTC .
// @ts-ignore
import { connect } from ‘cloudflare:sockets’;
// import { connectdb } from ‘@planetscale/database’;
// How to generate your own UUID:
// [Windows] Press “Win + R”, input cmd and run: Powershell -NoExit -Command “[guid]::NewGuid()”
let userID = ‘441a9713-54e8-44b7-81bf-4ff5076b641d’;
const proxyIPs = [‘cdn-all.xn–b6gac.eu.org’, ‘cdn.xn–b6gac.eu.org’, ‘cdn-b100.xn–b6gac.eu.org’, ‘edgetunnel.anycast.eu.org’, ‘cdn.anycast.eu.org’];
let proxyIP = proxyIPs[Math.floor(Math.random() * proxyIPs.length)];
let dohURL = ‘https://sky.rethinkdns.com/1:-Pf_____9_8A_AMAIgE8kMABVDDmKOHTAKg=’; // https://cloudflare-dns.com/dns-query or https://dns.google/dns-query
// v2board api environment variables (optional)
// now deprecated, please use planetscale.com instead
let nodeId = ‘’; // 1
let apiToken = ‘’; //abcdefghijklmnopqrstuvwxyz123456
let apiHost = ‘’; // api.v2board.com
if (!isValidUUID(userID)) {
throw new Error(‘uuid is invalid’);
}
export default {
/**
* @param {import(“@cloudflare/workers-types”).Request} request
* @param {
{UUID: string, PROXYIP: string, DNS_RESOLVER_URL: string, NODE_ID: int, API_HOST: string, API_TOKEN: string}} env
* @param {import(“@cloudflare/workers-types”).ExecutionContext} ctx
* @returns {Promise}
*/
async fetch(request, env, ctx) {
try {
userID = env.UUID || userID;
proxyIP = env.PROXYIP || proxyIP;
dohURL = env.DNS_RESOLVER_URL || dohURL;
nodeId = env.NODE_ID || nodeId;
apiToken = env.API_TOKEN || apiToken;
apiHost = env.API_HOST || apiHost;
let userID_Path = userID;
if (userID.includes(‘,’)) {
userID_Path = userID.split(‘,’)[0];
}
const upgradeHeader = request.headers.get(‘Upgrade’);
if (!upgradeHeader || upgradeHeader !== ‘websocket’) {
const url = new URL(request.url);
switch (url.pathname) {
case ‘/cf’:
return new Response(JSON.stringify(request.cf, null, 4), {
status: 200,
headers: {
“Content-Type”: “application/json;charset=utf-8”,
},
});
case ‘/connect’: // for test connect to cf socket
const [hostname, port] = [‘cloudflare.com’, ‘80’];
console.log(Connecting to ${hostname}:${port}...
);
try {
const socket = await connect({
hostname: hostname,
port: parseInt(port, 10),
});
const writer = socket.writable.getWriter();
try {
await writer.write(new TextEncoder().encode('GET / HTTP/1.1\r\nHost: ' + hostname + '\r\n\r\n'));
} catch (writeError) {
writer.releaseLock();
await socket.close();
return new Response(writeError.message, { status: 500 });
}
writer.releaseLock();
const reader = socket.readable.getReader();
let value;
try {
const result = await reader.read();
value = result.value;
} catch (readError) {
await reader.releaseLock();
await socket.close();
return new Response(readError.message, { status: 500 });
}
await reader.releaseLock();
await socket.close();
return new Response(new TextDecoder().decode(value), { status: 200 });
} catch (connectError) {
return new Response(connectError.message, { status: 500 });
}
case `/${userID_Path}`: {
const vlessConfig = getVLESSConfig(userID, request.headers.get('Host'));
return new Response(`${vlessConfig}`, {
status: 200,
headers: {
"Content-Type": "text/html; charset=utf-8",
}
});
}
case `/sub/${userID_Path}`: {
const url = new URL(request.url);
const searchParams = url.searchParams;
let vlessConfig = createVLESSSub(userID, request.headers.get('Host'));
// If 'format' query param equals to 'clash', convert config to base64
if (searchParams.get('format') === 'clash') {
vlessConfig = btoa(vlessConfig);
}
// Construct and return response object
return new Response(vlessConfig, {
status: 200,
headers: {
"Content-Type": "text/plain;charset=utf-8",
}
});
}
default:
// return new Response('Not found', { status: 404 });
// For any other path, reverse proxy to 'www.fmprc.gov.cn' and return the original response
url.hostname = 'www.douyu.com' ;
url.protocol = 'https:';
request = new Request(url, request);
return await fetch(request);
}
} else {
return await vlessOverWSHandler(request);
}
} catch (err) {
/** @type {Error} */ let e = err;
return new Response(e.toString());
}
},
};
/**
- Creates a PlanetScale connection object and returns it.
- @param { {DATABASE_HOST: string, DATABASE_USERNAME: string, DATABASE_PASSWORD: string}} env The environment variables containing the database connection information.
- @returns {Promise} A Promise that resolves to the PlanetScale connection object.
*/
function getPlanetScaleConnection(env) {
const config = {
host: env.DATABASE_HOST,
username: env.DATABASE_USERNAME,
password: env.DATABASE_PASSWORD,
fetch: (url, init) => {
delete (init)[“cache”];
return fetch(url, init);
}
}
return connectdb(config)
}
/**
-
Handles VLESS over WebSocket requests by creating a WebSocket pair, accepting the WebSocket connection, and processing the VLESS header.
-
@param {import(“@cloudflare/workers-types”).Request} request The incoming request object.
-
@returns {Promise} A Promise that resolves to a WebSocket response object.
*/
async function vlessOverWSHandler(request) {
const webSocketPair = new WebSocketPair();
const [client, webSocket] = Object.values(webSocketPair);
webSocket.accept();let address = ‘’;
let portWithRandomLog = ‘’;
const log = (/** @type {string} / info, /* @type {string | undefined} */ event) => {
console.log([${address}:${portWithRandomLog}] ${info}
, event || ‘’);
};
const earlyDataHeader = request.headers.get(‘sec-websocket-protocol’) || ‘’;const readableWebSocketStream = makeReadableWebSocketStream(webSocket, earlyDataHeader, log);
/** @type { { value: import(“@cloudflare/workers-types”).Socket | null}}*/
let remoteSocketWapper = {
value: null,
};
let udpStreamWrite = null;
let isDns = false;// ws --> remote
readableWebSocketStream.pipeTo(new WritableStream({
async write(chunk, controller) {
if (isDns && udpStreamWrite) {
return udpStreamWrite(chunk);
}
if (remoteSocketWapper.value) {
const writer = remoteSocketWapper.value.writable.getWriter()
await writer.write(chunk);
writer.releaseLock();
return;
}const { hasError, message, portRemote = 443, addressRemote = '', rawDataIndex, vlessVersion = new Uint8Array([0, 0]), isUDP, } = processVlessHeader(chunk, userID); address = addressRemote; portWithRandomLog = `${portRemote} ${isUDP ? 'udp' : 'tcp'} `; if (hasError) { // controller.error(message); throw new Error(mess