mirror of
https://github.com/lush2020/edgetunnel.git
synced 2026-03-23 16:38:34 +08:00
init edge tunnel
This commit is contained in:
18
apps/edge-bypass-client/.eslintrc.json
Normal file
18
apps/edge-bypass-client/.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": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
16
apps/edge-bypass-client/jest.config.ts
Normal file
16
apps/edge-bypass-client/jest.config.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: 'edge-bypass-client',
|
||||
preset: '../../jest.preset.js',
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||
},
|
||||
},
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
'^.+\\.[tj]s$': 'ts-jest',
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '../../coverage/apps/edge-bypass-client',
|
||||
};
|
||||
67
apps/edge-bypass-client/project.json
Normal file
67
apps/edge-bypass-client/project.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "edge-bypass-client",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "apps/edge-bypass-client/src",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nrwl/webpack:webpack",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"options": {
|
||||
"target": "node",
|
||||
"compiler": "tsc",
|
||||
"outputPath": "dist/apps/edge-bypass-client",
|
||||
"main": "apps/edge-bypass-client/src/main.ts",
|
||||
"tsConfig": "apps/edge-bypass-client/tsconfig.app.json",
|
||||
"assets": ["apps/edge-bypass-client/src/assets"]
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"optimization": true,
|
||||
"extractLicenses": true,
|
||||
"inspect": false,
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "apps/edge-bypass-client/src/environments/environment.ts",
|
||||
"with": "apps/edge-bypass-client/src/environments/environment.prod.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "@nrwl/js:node",
|
||||
"options": {
|
||||
"buildTarget": "edge-bypass-client:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "edge-bypass-client:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pkg": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"command": "npx pkg dist/apps/edge-bypass-client/main.js --targets linux,linux-arm64,macos,win --compress GZip --output dist/pkg/edge-tunnel-client/edgetunnel"
|
||||
},
|
||||
"dependsOn": ["build"]
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/edge-bypass-client/**/*.ts"]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nrwl/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"options": {
|
||||
"jestConfig": "apps/edge-bypass-client/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
0
apps/edge-bypass-client/src/app/.gitkeep
Normal file
0
apps/edge-bypass-client/src/app/.gitkeep
Normal file
0
apps/edge-bypass-client/src/assets/.gitkeep
Normal file
0
apps/edge-bypass-client/src/assets/.gitkeep
Normal file
5
apps/edge-bypass-client/src/assets/config.json
Normal file
5
apps/edge-bypass-client/src/assets/config.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"port": "",
|
||||
"address": "",
|
||||
"uuid": ""
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export const environment = {
|
||||
production: true,
|
||||
};
|
||||
3
apps/edge-bypass-client/src/environments/environment.ts
Normal file
3
apps/edge-bypass-client/src/environments/environment.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const environment = {
|
||||
production: false,
|
||||
};
|
||||
9
apps/edge-bypass-client/src/helper.ts
Normal file
9
apps/edge-bypass-client/src/helper.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
async function* concatStreams(readables) {
|
||||
for (const readable of readables) {
|
||||
for await (const chunk of readable) {
|
||||
yield chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { concatStreams };
|
||||
127
apps/edge-bypass-client/src/main copy 2.ts
Normal file
127
apps/edge-bypass-client/src/main copy 2.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import { Socket } from 'node:net';
|
||||
import { createServer } from 'node:http';
|
||||
import { Duplex, pipeline, Readable } from 'node:stream';
|
||||
import { ReadableStream, WritableStream } from 'node:stream/web';
|
||||
import { Command } from 'commander';
|
||||
import { writeFileSync, existsSync, readFileSync } from 'fs';
|
||||
import { exit } from 'node:process';
|
||||
import * as url from 'node:url';
|
||||
import * as undici from 'undici';
|
||||
import { concatStreams } from './helper';
|
||||
|
||||
let config: {
|
||||
port: string;
|
||||
address: string;
|
||||
uuid: string;
|
||||
config: string;
|
||||
} = null;
|
||||
const program = new Command();
|
||||
program
|
||||
.command('run')
|
||||
.description('launch local http proxy for edge pass')
|
||||
.option(
|
||||
'--config <config>',
|
||||
'address of remote proxy, etc https://***.deno.dev/'
|
||||
)
|
||||
.option(
|
||||
'--address <address>',
|
||||
'address of remote proxy, etc https://***.deno.dev/'
|
||||
)
|
||||
.option('--port <port>', 'local port of http proxy proxy', '8134')
|
||||
.option('--uuid <uuid>', 'uuid')
|
||||
.option('--save', 'if this is pass, will save to config.json')
|
||||
.action((options) => {
|
||||
if (options.config) {
|
||||
if (existsSync(options.config)) {
|
||||
const content = readFileSync(options.config, {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
config = JSON.parse(content);
|
||||
return;
|
||||
} else {
|
||||
console.error('config not exsit!');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
config = options;
|
||||
if (options.save) {
|
||||
writeFileSync('./config.json', JSON.stringify(options), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
}
|
||||
});
|
||||
program.parse();
|
||||
|
||||
let httpProxyServer = createServer((req, resp) => {
|
||||
console.log('start');
|
||||
const reqUrl = url.parse(req.url);
|
||||
console.log('proxy for http request: ' + reqUrl.href);
|
||||
|
||||
req.pipe(resp);
|
||||
});
|
||||
|
||||
httpProxyServer.on('connect', (req, clientSocket, head) => {
|
||||
const reqUrl = url.parse('https://' + req.url);
|
||||
console.log(
|
||||
`Client Connected To Proxy, client http version is ${
|
||||
req.httpVersion
|
||||
}, client url is ${req.url},head is ${head.toString()}`
|
||||
);
|
||||
// We need only the data once, the starting packet
|
||||
clientSocket.write(
|
||||
`HTTP/${req.httpVersion} 200 Connection Established\r\n\r\n`
|
||||
);
|
||||
|
||||
pipeline(
|
||||
concatStreams([head, clientSocket]),
|
||||
undici.pipeline(
|
||||
config.address,
|
||||
{
|
||||
headers: {
|
||||
'x-host': reqUrl.hostname,
|
||||
'x-port': reqUrl.port,
|
||||
'x-uuid': config.uuid,
|
||||
// "Content-Type": "text/plain",
|
||||
},
|
||||
method: 'POST',
|
||||
},
|
||||
({ statusCode, headers, body }) => {
|
||||
console.log(
|
||||
`proxy to ${reqUrl.hostname}:${reqUrl.port} and remote return ${statusCode}`
|
||||
);
|
||||
// body.on();
|
||||
return pipeline(body, clientSocket, (error) => {
|
||||
console.log('server response to clientSocket return error', error);
|
||||
});
|
||||
}
|
||||
),
|
||||
(error) => {
|
||||
console.log('clientSocket request to server error', error);
|
||||
}
|
||||
);
|
||||
|
||||
clientSocket.on('error', (e) => {
|
||||
console.log('client socket error: ' + e);
|
||||
});
|
||||
clientSocket.on('end', () => {
|
||||
console.log('end-----');
|
||||
});
|
||||
});
|
||||
|
||||
httpProxyServer.on('error', (err) => {
|
||||
console.log('SERVER ERROR');
|
||||
console.log(err);
|
||||
throw err;
|
||||
});
|
||||
httpProxyServer.on('clientError', (err, clientSocket) => {
|
||||
console.log('client error: ' + err);
|
||||
clientSocket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
|
||||
});
|
||||
|
||||
httpProxyServer.on('close', () => {
|
||||
console.log('Client Disconnected');
|
||||
});
|
||||
|
||||
httpProxyServer.listen(Number(config.port), () => {
|
||||
console.log('Server runnig at http://localhost:' + config.port);
|
||||
});
|
||||
118
apps/edge-bypass-client/src/main copy 3.ts
Normal file
118
apps/edge-bypass-client/src/main copy 3.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { Socket } from 'node:net';
|
||||
import { createServer } from 'node:http';
|
||||
import { Duplex, pipeline, Readable, Writable } from 'node:stream';
|
||||
import { ReadableStream, WritableStream } from 'node:stream/web';
|
||||
import { Command } from 'commander';
|
||||
import { writeFileSync, existsSync, readFileSync } from 'fs';
|
||||
import { exit } from 'node:process';
|
||||
import * as url from 'node:url';
|
||||
import * as undici from 'undici';
|
||||
import { concatStreams } from './helper';
|
||||
import * as http from 'node:http';
|
||||
|
||||
let config: {
|
||||
port: string;
|
||||
address: string;
|
||||
uuid: string;
|
||||
config: string;
|
||||
} = null;
|
||||
const program = new Command();
|
||||
program
|
||||
.command('run')
|
||||
.description('launch local http proxy for edge pass')
|
||||
.option(
|
||||
'--config <config>',
|
||||
'address of remote proxy, etc https://***.deno.dev/'
|
||||
)
|
||||
.option(
|
||||
'--address <address>',
|
||||
'address of remote proxy, etc https://***.deno.dev/'
|
||||
)
|
||||
.option('--port <port>', 'local port of http proxy proxy', '8134')
|
||||
.option('--uuid <uuid>', 'uuid')
|
||||
.option('--save', 'if this is pass, will save to config.json')
|
||||
.action((options) => {
|
||||
if (options.config) {
|
||||
if (existsSync(options.config)) {
|
||||
const content = readFileSync(options.config, {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
config = JSON.parse(content);
|
||||
return;
|
||||
} else {
|
||||
console.error('config not exsit!');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
config = options;
|
||||
if (options.save) {
|
||||
writeFileSync('./config.json', JSON.stringify(options), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
}
|
||||
});
|
||||
program.parse();
|
||||
|
||||
let httpProxyServer = createServer((req, resp) => {
|
||||
console.log('start');
|
||||
const reqUrl = url.parse(req.url);
|
||||
console.log('proxy for http request: ' + reqUrl.href);
|
||||
|
||||
req.pipe(resp);
|
||||
});
|
||||
|
||||
httpProxyServer.on('connect', async (req, clientSocket, head) => {
|
||||
const reqUrl = url.parse('https://' + req.url);
|
||||
console.log(
|
||||
`Client Connected To Proxy, client http version is ${
|
||||
req.httpVersion
|
||||
}, client url is ${req.url},head is ${head.toString()}`
|
||||
);
|
||||
// We need only the data once, the starting packet
|
||||
clientSocket.write(
|
||||
`HTTP/${req.httpVersion} 200 Connection Established\r\n\r\n`
|
||||
);
|
||||
|
||||
const { body, headers, statusCode, trailers } = await undici.request(
|
||||
config.address,
|
||||
{
|
||||
headers: {
|
||||
'x-host': reqUrl.hostname,
|
||||
'x-port': reqUrl.port,
|
||||
'x-uuid': config.uuid,
|
||||
// "Content-Type": "text/plain",
|
||||
},
|
||||
method: 'POST',
|
||||
body: clientSocket,
|
||||
}
|
||||
);
|
||||
|
||||
body.pipe(clientSocket).on('error', (error) => {
|
||||
console.log('serever reponse to clientSocket: ' + error);
|
||||
});
|
||||
|
||||
clientSocket.on('error', (e) => {
|
||||
console.log('client socket error: ' + e);
|
||||
});
|
||||
clientSocket.on('end', () => {
|
||||
console.log('end-----');
|
||||
});
|
||||
});
|
||||
|
||||
httpProxyServer.on('error', (err) => {
|
||||
console.log('SERVER ERROR');
|
||||
console.log(err);
|
||||
throw err;
|
||||
});
|
||||
httpProxyServer.on('clientError', (err, clientSocket) => {
|
||||
console.log('client error: ' + err);
|
||||
clientSocket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
|
||||
});
|
||||
|
||||
httpProxyServer.on('close', () => {
|
||||
console.log('Client Disconnected');
|
||||
});
|
||||
|
||||
httpProxyServer.listen(Number(config.port), () => {
|
||||
console.log('Server runnig at http://localhost:' + config.port);
|
||||
});
|
||||
136
apps/edge-bypass-client/src/main copy.ts
Normal file
136
apps/edge-bypass-client/src/main copy.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import { createServer, Socket } from 'node:net';
|
||||
import { Duplex } from 'node:stream';
|
||||
import { fetch } from 'undici';
|
||||
import { ReadableStream, WritableStream } from 'node:stream/web';
|
||||
import { Command } from 'commander';
|
||||
import { writeFileSync, existsSync, readFileSync } from 'fs';
|
||||
import { exit } from 'node:process';
|
||||
|
||||
let config: {
|
||||
port: string;
|
||||
address: string;
|
||||
uuid: string;
|
||||
config: string;
|
||||
} = null;
|
||||
const program = new Command();
|
||||
program
|
||||
.command('run')
|
||||
.description('launch local http proxy for edge pass')
|
||||
.option(
|
||||
'--config <config>',
|
||||
'address of remote proxy, etc https://***.deno.dev/'
|
||||
)
|
||||
.option(
|
||||
'--address <address>',
|
||||
'address of remote proxy, etc https://***.deno.dev/'
|
||||
)
|
||||
.option('--port <port>', 'local port of http proxy proxy', '8134')
|
||||
.option('--uuid <uuid>', 'uuid')
|
||||
.option('--save', 'if this is pass, will save to config.json')
|
||||
.action((options) => {
|
||||
if (options.config) {
|
||||
if (existsSync(options.config)) {
|
||||
const content = readFileSync(options.config, {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
config = JSON.parse(content);
|
||||
return;
|
||||
} else {
|
||||
console.error('config not exsit!');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
config = options;
|
||||
if (options.save) {
|
||||
writeFileSync('./config.json', JSON.stringify(options), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
}
|
||||
});
|
||||
program.parse();
|
||||
|
||||
const server = createServer();
|
||||
server.on('connection', (clientToProxySocket: Socket) => {
|
||||
console.log('Client Connected To Proxy');
|
||||
// We need only the data once, the starting packet
|
||||
clientToProxySocket.once('data', async (data) => {
|
||||
// If you want to see the packet uncomment below
|
||||
// console.log(data.toString());
|
||||
let isTLSConnection = data.toString().indexOf('CONNECT') !== -1;
|
||||
let serverPort = '80';
|
||||
let serverAddress: string;
|
||||
if (isTLSConnection) {
|
||||
// Port changed if connection is TLS
|
||||
serverPort = data
|
||||
.toString()
|
||||
.split('CONNECT ')[1]
|
||||
.split(' ')[0]
|
||||
.split(':')[1];
|
||||
serverAddress = data
|
||||
.toString()
|
||||
.split('CONNECT ')[1]
|
||||
.split(' ')[0]
|
||||
.split(':')[0];
|
||||
} else {
|
||||
serverAddress = data.toString().split('Host: ')[1].split('\r\n')[0];
|
||||
}
|
||||
|
||||
const {
|
||||
readable: clientToProxySocketReadable,
|
||||
writable: clientToProxySocketWritable,
|
||||
} = Duplex.toWeb(clientToProxySocket) as any as {
|
||||
readable: ReadableStream;
|
||||
writable: WritableStream;
|
||||
};
|
||||
|
||||
// console.log(serverAddress);
|
||||
if (isTLSConnection) {
|
||||
clientToProxySocket.write('HTTP/1.1 200 OK\r\n\n');
|
||||
} else {
|
||||
// TODO
|
||||
// proxyToServerSocket.write(data);
|
||||
}
|
||||
|
||||
fetch(config.address, {
|
||||
headers: {
|
||||
'x-host': serverAddress,
|
||||
'x-port': serverPort,
|
||||
'x-uuid': config.uuid,
|
||||
// "Content-Type": "text/plain",
|
||||
},
|
||||
method: 'POST',
|
||||
// body: Uint8Array.from(chunks),
|
||||
body: clientToProxySocketReadable,
|
||||
duplex: 'half',
|
||||
})
|
||||
.then((resp) => {
|
||||
console.log(
|
||||
`proxy to ${serverAddress}:${serverPort} and remote return ${resp.status}`
|
||||
);
|
||||
resp.body.pipeTo(clientToProxySocketWritable).catch((error) => {
|
||||
console.error('pipe to', JSON.stringify(error));
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('fetch error', error);
|
||||
});
|
||||
clientToProxySocket.on('error', (err) => {
|
||||
console.log('CLIENT TO PROXY ERROR');
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
server.on('error', (err) => {
|
||||
console.log('SERVER ERROR');
|
||||
console.log(err);
|
||||
throw err;
|
||||
});
|
||||
|
||||
server.on('close', () => {
|
||||
console.log('Client Disconnected');
|
||||
});
|
||||
|
||||
server.listen(Number(config.port), () => {
|
||||
console.log('Server runnig at http://localhost:' + config.port);
|
||||
});
|
||||
118
apps/edge-bypass-client/src/main.ts
Normal file
118
apps/edge-bypass-client/src/main.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { Socket } from 'node:net';
|
||||
import { createServer } from 'node:http';
|
||||
import { Duplex, pipeline, Readable, Writable } from 'node:stream';
|
||||
import { ReadableStream, WritableStream } from 'node:stream/web';
|
||||
import { Command } from 'commander';
|
||||
import { writeFileSync, existsSync, readFileSync } from 'fs';
|
||||
import { exit } from 'node:process';
|
||||
import * as url from 'node:url';
|
||||
import * as undici from 'undici';
|
||||
import { concatStreams } from './helper';
|
||||
import * as http from 'node:http';
|
||||
|
||||
let config: {
|
||||
port: string;
|
||||
address: string;
|
||||
uuid: string;
|
||||
config: string;
|
||||
} = null;
|
||||
const program = new Command();
|
||||
program
|
||||
.command('run')
|
||||
.description('launch local http proxy for edge pass')
|
||||
.option(
|
||||
'--config <config>',
|
||||
'address of remote proxy, etc https://***.deno.dev/'
|
||||
)
|
||||
.option(
|
||||
'--address <address>',
|
||||
'address of remote proxy, etc https://***.deno.dev/'
|
||||
)
|
||||
.option('--port <port>', 'local port of http proxy proxy', '8134')
|
||||
.option('--uuid <uuid>', 'uuid')
|
||||
.option('--save', 'if this is pass, will save to config.json')
|
||||
.action((options) => {
|
||||
if (options.config) {
|
||||
if (existsSync(options.config)) {
|
||||
const content = readFileSync(options.config, {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
config = JSON.parse(content);
|
||||
return;
|
||||
} else {
|
||||
console.error('config not exsit!');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
config = options;
|
||||
if (options.save) {
|
||||
writeFileSync('./config.json', JSON.stringify(options), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
}
|
||||
});
|
||||
program.parse();
|
||||
|
||||
let httpProxyServer = createServer((req, resp) => {
|
||||
console.log('start');
|
||||
const reqUrl = url.parse(req.url);
|
||||
console.log('proxy for http request: ' + reqUrl.href);
|
||||
|
||||
req.pipe(resp);
|
||||
});
|
||||
|
||||
httpProxyServer.on('connect', async (req, clientSocket, head) => {
|
||||
const reqUrl = url.parse('https://' + req.url);
|
||||
console.log(
|
||||
`Client Connected To Proxy, client http version is ${
|
||||
req.httpVersion
|
||||
}, client url is ${req.url},head is ${head.toString()}`
|
||||
);
|
||||
// We need only the data once, the starting packet
|
||||
clientSocket.write(
|
||||
`HTTP/${req.httpVersion} 200 Connection Established\r\n\r\n`
|
||||
);
|
||||
|
||||
const { body, headers, statusCode, trailers } = await undici.request(
|
||||
config.address,
|
||||
{
|
||||
headers: {
|
||||
'x-host': reqUrl.hostname,
|
||||
'x-port': reqUrl.port,
|
||||
'x-uuid': config.uuid,
|
||||
// "Content-Type": "text/plain",
|
||||
},
|
||||
method: 'POST',
|
||||
body: clientSocket,
|
||||
}
|
||||
);
|
||||
|
||||
body.pipe(clientSocket).on('error', (error) => {
|
||||
console.log('serever reponse to clientSocket: ' + error);
|
||||
});
|
||||
|
||||
clientSocket.on('error', (e) => {
|
||||
console.log('client socket error: ' + e);
|
||||
});
|
||||
clientSocket.on('end', () => {
|
||||
console.log('end-----');
|
||||
});
|
||||
});
|
||||
|
||||
httpProxyServer.on('error', (err) => {
|
||||
console.log('SERVER ERROR');
|
||||
console.log(err);
|
||||
throw err;
|
||||
});
|
||||
httpProxyServer.on('clientError', (err, clientSocket) => {
|
||||
console.log('client error: ' + err);
|
||||
clientSocket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
|
||||
});
|
||||
|
||||
httpProxyServer.on('close', () => {
|
||||
console.log('Client Disconnected');
|
||||
});
|
||||
|
||||
httpProxyServer.listen(Number(config.port), () => {
|
||||
console.log('Server runnig at http://localhost:' + config.port);
|
||||
});
|
||||
87
apps/edge-bypass-client/src/proxy.js
Normal file
87
apps/edge-bypass-client/src/proxy.js
Normal file
@@ -0,0 +1,87 @@
|
||||
var net = require('net');
|
||||
var http = require('http');
|
||||
var url = require('url');
|
||||
|
||||
var proxyServer = http.createServer(httpOptions);
|
||||
|
||||
// handle http proxy requests
|
||||
function httpOptions(clientReq, clientRes) {
|
||||
var reqUrl = url.parse(clientReq.url);
|
||||
console.log('proxy for http request: ' + reqUrl.href);
|
||||
|
||||
var options = {
|
||||
hostname: reqUrl.hostname,
|
||||
port: reqUrl.port,
|
||||
path: reqUrl.path,
|
||||
method: clientReq.method,
|
||||
headers: clientReq.headers,
|
||||
};
|
||||
|
||||
// create socket connection on behalf of client, then pipe the response to client response (pass it on)
|
||||
var serverConnection = http.request(options, function (res) {
|
||||
clientRes.writeHead(res.statusCode, res.headers);
|
||||
res.pipe(clientRes);
|
||||
});
|
||||
|
||||
clientReq.pipe(serverConnection);
|
||||
|
||||
clientReq.on('error', (e) => {
|
||||
console.log('client socket error: ' + e);
|
||||
});
|
||||
|
||||
serverConnection.on('error', (e) => {
|
||||
console.log('server connection error: ' + e);
|
||||
});
|
||||
}
|
||||
|
||||
// handle https proxy requests (CONNECT method)
|
||||
proxyServer.on('connect', (clientReq, clientSocket, head) => {
|
||||
var reqUrl = url.parse('https://' + clientReq.url);
|
||||
console.log(
|
||||
'proxy for https request: ' + reqUrl.href + '(path encrypted by ssl)'
|
||||
);
|
||||
|
||||
var options = {
|
||||
port: reqUrl.port,
|
||||
host: reqUrl.hostname,
|
||||
};
|
||||
|
||||
// create socket connection for client, then pipe (redirect) it to client socket
|
||||
var serverSocket = net.connect(options, () => {
|
||||
clientSocket.write(
|
||||
'HTTP/' +
|
||||
clientReq.httpVersion +
|
||||
' 200 Connection Established\r\n' +
|
||||
'Proxy-agent: Node.js-Proxy\r\n' +
|
||||
'\r\n',
|
||||
'UTF-8',
|
||||
() => {
|
||||
// creating pipes in both ends
|
||||
serverSocket.write(head);
|
||||
serverSocket.pipe(clientSocket);
|
||||
clientSocket.pipe(serverSocket);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
clientSocket.on('error', (e) => {
|
||||
console.log('client socket error: ' + e);
|
||||
serverSocket.end();
|
||||
});
|
||||
|
||||
serverSocket.on('error', (e) => {
|
||||
console.log('forward proxy server connection error: ' + e);
|
||||
clientSocket.end();
|
||||
});
|
||||
});
|
||||
|
||||
proxyServer.on('clientError', (err, clientSocket) => {
|
||||
console.log('client error: ' + err);
|
||||
clientSocket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
|
||||
});
|
||||
|
||||
proxyServer.listen(2560);
|
||||
|
||||
console.log('forward proxy server started, listening on port 2560');
|
||||
|
||||
module.exports = proxyServer;
|
||||
31
apps/edge-bypass-client/src/test.mjs
Normal file
31
apps/edge-bypass-client/src/test.mjs
Normal file
@@ -0,0 +1,31 @@
|
||||
import * as undici from 'undici';
|
||||
import { pipeline, Readable, Writable } from 'node:stream';
|
||||
|
||||
pipeline(
|
||||
new Readable({
|
||||
read() {
|
||||
this.push(Buffer.from('undici'));
|
||||
this.push(null);
|
||||
},
|
||||
}),
|
||||
undici.pipeline(
|
||||
'http://localhost:1082',
|
||||
{
|
||||
method: 'POST',
|
||||
},
|
||||
({ statusCode, headers, body }) => {
|
||||
console.log(`response received ${statusCode}`);
|
||||
console.log('headers', headers);
|
||||
console.log('headers', body);
|
||||
return body;
|
||||
}
|
||||
),
|
||||
// new Writable({
|
||||
// write(chunk) {
|
||||
// console.log(chunk.toString());
|
||||
// },
|
||||
// }),
|
||||
(error) => {
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
10
apps/edge-bypass-client/tsconfig.app.json
Normal file
10
apps/edge-bypass-client/tsconfig.app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts"],
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
17
apps/edge-bypass-client/tsconfig.json
Normal file
17
apps/edge-bypass-client/tsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "NodeNext",
|
||||
"target": "ES2022"
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
9
apps/edge-bypass-client/tsconfig.spec.json
Normal file
9
apps/edge-bypass-client/tsconfig.spec.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user