mirror of
https://github.com/lush2020/edgetunnel.git
synced 2026-03-21 17:12:33 +08:00
add cf worker poc
This commit is contained in:
72
client-config/config-client-without-dns-lcoal.json
Normal file
72
client-config/config-client-without-dns-lcoal.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "debug"
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"listen": "0.0.0.0",
|
||||
"port": "4080",
|
||||
"protocol": "socks",
|
||||
"settings": {
|
||||
"auth": "noauth",
|
||||
"udp": true,
|
||||
"ip": "0.0.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"listen": "0.0.0.0",
|
||||
"port": "4081",
|
||||
"protocol": "http"
|
||||
}
|
||||
],
|
||||
"dns": {
|
||||
"servers": ["8.8.8.8"]
|
||||
},
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"vnext": [
|
||||
{
|
||||
"address": "127.0.0.1",
|
||||
"port": 8787,
|
||||
"users": [
|
||||
{
|
||||
"id": "1a403b79-039b-4dc2-9b45-1ad13197b99a",
|
||||
"encryption": "none",
|
||||
"level": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "ws"
|
||||
// "wsSettings": {
|
||||
// "path": "/node-vless"
|
||||
// }
|
||||
// "security": "tls"
|
||||
},
|
||||
"tag": "zizi-ws"
|
||||
},
|
||||
{
|
||||
"protocol": "freedom",
|
||||
"tag": "direct"
|
||||
}
|
||||
],
|
||||
"routing": {
|
||||
"domainStrategy": "IPIfNonMatch",
|
||||
"rules": [
|
||||
// {
|
||||
// "type": "field",
|
||||
// "ip": ["8.8.8.8"],
|
||||
// "outboundTag": "zizi-ws"
|
||||
// },
|
||||
{
|
||||
"type": "field",
|
||||
"ip": ["geoip:private"],
|
||||
"outboundTag": "zizi-ws"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
74
client-config/config-client.json
Normal file
74
client-config/config-client.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "debug"
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"listen": "0.0.0.0",
|
||||
"port": "4080",
|
||||
"protocol": "socks",
|
||||
"settings": {
|
||||
"auth": "noauth",
|
||||
"udp": true,
|
||||
"ip": "0.0.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"listen": "0.0.0.0",
|
||||
"port": "4081",
|
||||
"protocol": "http"
|
||||
}
|
||||
],
|
||||
"dns": {
|
||||
"servers": ["8.8.8.8"]
|
||||
},
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"vnext": [
|
||||
{
|
||||
"address": "192.203.230.111",
|
||||
"port": 80,
|
||||
"users": [
|
||||
{
|
||||
"id": "1a403b79-039b-4dc2-9b45-1ad13197b99a",
|
||||
"encryption": "none",
|
||||
"level": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "ws",
|
||||
"wsSettings": {
|
||||
"headers": {
|
||||
"Host": "vless-dev.121107.xyz"
|
||||
}
|
||||
}
|
||||
// "security": "tls"
|
||||
},
|
||||
"tag": "zizi-ws"
|
||||
},
|
||||
{
|
||||
"protocol": "freedom",
|
||||
"tag": "direct"
|
||||
}
|
||||
],
|
||||
"routing": {
|
||||
"domainStrategy": "AsIs",
|
||||
"rules": [
|
||||
// {
|
||||
// "type": "field",
|
||||
// "ip": ["8.8.8.8"],
|
||||
// "outboundTag": "zizi-ws"
|
||||
// },
|
||||
{
|
||||
"type": "field",
|
||||
"ip": ["geoip:private"],
|
||||
"outboundTag": "zizi-ws"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// @ts-ignore
|
||||
import { connect } from 'cloudflare:sockets';
|
||||
|
||||
export const onRequest: PagesFunction<Env> = async (context) => {
|
||||
export const onRequest: PagesFunction<any> = async (context) => {
|
||||
console.log('start fetch');
|
||||
const socket = connect({
|
||||
hostname: 'neverssl.com',
|
||||
|
||||
18
libs/cf-worker-vless/.eslintrc.json
Normal file
18
libs/cf-worker-vless/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
11
libs/cf-worker-vless/README.md
Normal file
11
libs/cf-worker-vless/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# cf-worker-vless
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Building
|
||||
|
||||
Run `nx build cf-worker-vless` to build the library.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `nx test cf-worker-vless` to execute the unit tests via [Jest](https://jestjs.io).
|
||||
10
libs/cf-worker-vless/jest.config.ts
Normal file
10
libs/cf-worker-vless/jest.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: 'cf-worker-vless',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '../../coverage/libs/cf-worker-vless',
|
||||
};
|
||||
5
libs/cf-worker-vless/package.json
Normal file
5
libs/cf-worker-vless/package.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "@edge-bypass/cf-worker-vless",
|
||||
"version": "0.0.1",
|
||||
"type": "commonjs"
|
||||
}
|
||||
40
libs/cf-worker-vless/project.json
Normal file
40
libs/cf-worker-vless/project.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "cf-worker-vless",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "libs/cf-worker-vless/src",
|
||||
"projectType": "library",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nx/js:tsc",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"options": {
|
||||
"outputPath": "dist/libs/cf-worker-vless",
|
||||
"main": "libs/cf-worker-vless/src/index.ts",
|
||||
"tsConfig": "libs/cf-worker-vless/tsconfig.lib.json",
|
||||
"assets": ["libs/cf-worker-vless/*.md"]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["libs/cf-worker-vless/**/*.ts"]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"options": {
|
||||
"jestConfig": "libs/cf-worker-vless/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"ci": true,
|
||||
"codeCoverage": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
140
libs/cf-worker-vless/src/index.ts
Normal file
140
libs/cf-worker-vless/src/index.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import {
|
||||
makeReadableWebSocketStream,
|
||||
processVlessHeader,
|
||||
vlessJs,
|
||||
} from 'vless-js';
|
||||
import { connect } from 'cloudflare:sockets';
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { validate } from 'uuid';
|
||||
|
||||
interface Env {
|
||||
UUID: string;
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
|
||||
let address = '';
|
||||
let portWithRandomLog = '';
|
||||
const userID = env.UUID;
|
||||
|
||||
const log = (info: string, event?: any) => {
|
||||
console.log(`[${address}:${portWithRandomLog}] ${info}`, event || '');
|
||||
};
|
||||
|
||||
const upgradeHeader = request.headers.get('Upgrade');
|
||||
if (!upgradeHeader || upgradeHeader !== 'websocket') {
|
||||
return new Response(`Expected Upgrade: websocket--uuid--${userID}`, {
|
||||
status: 426,
|
||||
});
|
||||
}
|
||||
|
||||
const webSocketPair = new WebSocketPair();
|
||||
const [client, webSocket] = Object.values(webSocketPair);
|
||||
|
||||
console.log(WebSocket.READY_STATE_OPEN);
|
||||
|
||||
const earlyDataHeader = request.headers.get('sec-websocket-protocol') || '';
|
||||
let remoteSocket: TransformStream = null;
|
||||
webSocket.accept();
|
||||
webSocket.addEventListener('message', async (event) => {
|
||||
if (remoteSocket) {
|
||||
const writer = remoteSocket.writable.getWriter();
|
||||
await writer.write(event.data);
|
||||
writer.releaseLock();
|
||||
return;
|
||||
}
|
||||
const vlessBuffer: ArrayBuffer = event.data as ArrayBuffer;
|
||||
const {
|
||||
hasError,
|
||||
message,
|
||||
portRemote,
|
||||
addressRemote,
|
||||
rawDataIndex,
|
||||
vlessVersion,
|
||||
isUDP,
|
||||
} = processVlessHeader(vlessBuffer, userID);
|
||||
address = addressRemote || '';
|
||||
portWithRandomLog = `${portRemote}--${Math.random()} ${
|
||||
isUDP ? 'udp ' : 'tcp '
|
||||
} `;
|
||||
log(`connecting`);
|
||||
if (hasError) {
|
||||
webSocket.close(); // server close will not casuse worker throw error
|
||||
}
|
||||
const vlessResponseHeader = new Uint8Array([vlessVersion![0], 0]);
|
||||
const rawClientData = vlessBuffer.slice(rawDataIndex!);
|
||||
remoteSocket = connect({
|
||||
hostname: addressRemote,
|
||||
port: portRemote,
|
||||
});
|
||||
log(`connected`);
|
||||
|
||||
const writer = remoteSocket.writable.getWriter();
|
||||
await writer.write(rawClientData); // first write, nomal is tls client hello
|
||||
writer.releaseLock();
|
||||
|
||||
remoteSocket.readable
|
||||
.pipeTo(
|
||||
new WritableStream({
|
||||
start() {
|
||||
if (webSocket.readyState === WebSocket.READY_STATE_OPEN) {
|
||||
webSocket.send(vlessResponseHeader!);
|
||||
}
|
||||
},
|
||||
async write(chunk: Uint8Array, controller) {
|
||||
if (webSocket.readyState === WebSocket.READY_STATE_OPEN) {
|
||||
webSocket.send(chunk);
|
||||
} else {
|
||||
controller.error(
|
||||
'webSocket.readyState is not open, maybe close'
|
||||
);
|
||||
}
|
||||
},
|
||||
close() {
|
||||
console.log(
|
||||
`[${address}:${portWithRandomLog}] remoteConnection!.readable is close`
|
||||
);
|
||||
},
|
||||
abort(reason) {
|
||||
console.error(
|
||||
`[${address}:${portWithRandomLog}] remoteConnection!.readable abort`,
|
||||
reason
|
||||
);
|
||||
},
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
console.error(
|
||||
`[${address}:${portWithRandomLog}] processWebSocket has exception `,
|
||||
error.stack || error
|
||||
);
|
||||
safeCloseWebSocket(webSocket);
|
||||
});
|
||||
|
||||
// end
|
||||
});
|
||||
|
||||
webSocket.addEventListener('close', async (event) => {
|
||||
console.log('-------------close-----------------', event);
|
||||
});
|
||||
|
||||
webSocket.addEventListener('error', () => {
|
||||
console.log('-------------error-----------------');
|
||||
});
|
||||
|
||||
return new Response(null, {
|
||||
status: 101,
|
||||
webSocket: client,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
function safeCloseWebSocket(ws: WebSocket) {
|
||||
try {
|
||||
if (ws.readyState === WebSocket.READY_STATE_OPEN) {
|
||||
ws.close();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('safeCloseWebSocket error', error);
|
||||
}
|
||||
}
|
||||
36
libs/cf-worker-vless/src/index2.ts
Normal file
36
libs/cf-worker-vless/src/index2.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { connect } from 'cloudflare:sockets';
|
||||
|
||||
interface Env {
|
||||
UUID: string;
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
|
||||
console.log('start fetch');
|
||||
const socket = connect({
|
||||
hostname: 'neverssl.com',
|
||||
port: 80,
|
||||
});
|
||||
|
||||
const writer = socket.writable.getWriter();
|
||||
const encoder = new TextEncoder();
|
||||
const encoded = encoder.encode(
|
||||
'GET / HTTP/1.1\r\nHost: neverssl.com\r\n\r\n'
|
||||
);
|
||||
await writer.write(encoded);
|
||||
|
||||
const reader = socket.readable.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let response = '';
|
||||
while (true) {
|
||||
const res = await reader.read();
|
||||
if (res.done) {
|
||||
console.log('Stream done, socket connection has been closed.');
|
||||
break;
|
||||
}
|
||||
response += decoder.decode(res.value);
|
||||
}
|
||||
|
||||
return new Response(response);
|
||||
},
|
||||
};
|
||||
11
libs/cf-worker-vless/tsconfig.json
Normal file
11
libs/cf-worker-vless/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"lib": ["esnext"],
|
||||
"types": ["@cloudflare/workers-types"],
|
||||
"paths": {
|
||||
"vless-js": ["../vless-js/src/index.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
10
libs/cf-worker-vless/tsconfig.lib.json
Normal file
10
libs/cf-worker-vless/tsconfig.lib.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"declaration": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
|
||||
}
|
||||
14
libs/cf-worker-vless/tsconfig.spec.json
Normal file
14
libs/cf-worker-vless/tsconfig.spec.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": [
|
||||
"jest.config.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
@@ -3,12 +3,21 @@ export function vlessJs(): string {
|
||||
return 'vless-js';
|
||||
}
|
||||
|
||||
const WS_READY_STATE_OPEN = 1;
|
||||
|
||||
export function delay(ms: number) {
|
||||
return new Promise((resolve, rej) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* we need make sure read websocket message in order
|
||||
* @param ws
|
||||
* @param earlyDataHeader
|
||||
* @param log
|
||||
* @returns
|
||||
*/
|
||||
export function makeReadableWebSocketStream(
|
||||
ws: WebSocket | any,
|
||||
earlyDataHeader: string,
|
||||
@@ -90,7 +99,7 @@ function base64ToArrayBuffer(base64Str: string) {
|
||||
|
||||
export function safeCloseWebSocket(socket: WebSocket | any) {
|
||||
try {
|
||||
if (socket.readyState === socket.OPEN) {
|
||||
if (socket.readyState === WS_READY_STATE_OPEN) {
|
||||
socket.close();
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
"node-vless:bunled": "nx build cf-page --configuration=production && nx build node-vless --skip-nx-cache --configurations=production -- --externalDependencies=none",
|
||||
"node-vless:start": "node dist/apps/node-vless/main.js",
|
||||
"deno-vless:bunled": "nx deno-bunled deno-vless",
|
||||
"test": "nx test"
|
||||
"test": "nx test",
|
||||
"cf-worker": "wrangler dev ./libs/cf-worker-vless/src/index.ts --experimental-local"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"skipDefaultLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@edge-bypass/cf-worker-vless": ["libs/cf-worker-vless/src/index.ts"],
|
||||
"edge-ui": ["libs/edge-ui/src/index.ts"],
|
||||
"vless-js": ["libs/vless-js/src/index.ts"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user