mirror of
https://github.com/lush2020/edgetunnel.git
synced 2026-03-24 00:48:39 +08:00
enhance logic
This commit is contained in:
@@ -1,55 +1,83 @@
|
||||
import { serve } from 'https://deno.land/std@0.167.0/http/server.ts';
|
||||
import { buildRawHttp500, isVaildateReq } from './helper.ts';
|
||||
const userID = Deno.env.get('UUID');
|
||||
|
||||
const handler = async (request: Request): Promise<Response> => {
|
||||
const headers = request.headers;
|
||||
const serverAddress = headers.get('x-host') || '';
|
||||
const remotePort = headers.get('x-port') || 443;
|
||||
const uuid = headers.get('x-uuid');
|
||||
// console.log('--------start--------');
|
||||
try {
|
||||
const headers = request.headers;
|
||||
const serverAddress = headers.get('x-host') || '';
|
||||
const remotePort = headers.get('x-port') || 443;
|
||||
const isHttp = headers.get('x-http') === 'true';
|
||||
const uuid = request.headers.get('x-uuid');
|
||||
|
||||
if (!serverAddress || !remotePort || !userID) {
|
||||
return new Response(
|
||||
`Version 0.0.1-2022/12/04!!
|
||||
if (!serverAddress || !remotePort || !userID) {
|
||||
return new Response(
|
||||
`Version 0.0.1-2022/12/04!!
|
||||
${userID ? 'has UUID env' : 'no UUID env'}
|
||||
感谢 deno deploy 严肃对待 web standard。支持 HTTP request & response streaming。
|
||||
`,
|
||||
{
|
||||
status: 200,
|
||||
{
|
||||
status: 200,
|
||||
headers: {},
|
||||
}
|
||||
);
|
||||
}
|
||||
if (uuid !== userID) {
|
||||
return new Response(buildRawHttp500('Do not send right UUID!'), {
|
||||
status: 403,
|
||||
headers: {},
|
||||
}
|
||||
);
|
||||
}
|
||||
console.log(
|
||||
`want to proxy to server address ${serverAddress}, and port ${remotePort}`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (uuid !== userID) {
|
||||
return new Response('Do not send right UUID!', {
|
||||
status: 403,
|
||||
if (!isVaildateReq(request)) {
|
||||
return new Response(
|
||||
buildRawHttp500(
|
||||
'request is not vaild due to lcoalip or request body is null'
|
||||
),
|
||||
{
|
||||
status: 500,
|
||||
headers: {},
|
||||
}
|
||||
);
|
||||
}
|
||||
console.log(
|
||||
`want to proxy to server address ${serverAddress}, and port ${remotePort}`
|
||||
);
|
||||
|
||||
const connection = await Deno.connect({
|
||||
port: Number(remotePort),
|
||||
hostname: serverAddress,
|
||||
});
|
||||
|
||||
// const proxyResp = request.body?.pipeThrough(connection);
|
||||
// 1. request.body readablestream end casue socket to be end, this will casue socket send FIN package early
|
||||
// and casue deno can't get TCP pcakge.
|
||||
// 2. current soluction for this, let proxy client wait for few ms and then end readablestream
|
||||
// 3. this is only inpact HTTP proxy not https
|
||||
let readablestreamRsp = connection.readable;
|
||||
if (isHttp) {
|
||||
// if is http, we need wait for request read, or we can warpper into async function
|
||||
for await (let chunk of request.body || []) {
|
||||
// console.log(new TextDecoder().decode(chunk));
|
||||
connection.write(chunk);
|
||||
}
|
||||
readablestreamRsp = connection.readable;
|
||||
} else {
|
||||
readablestreamRsp = request.body!.pipeThrough(connection);
|
||||
}
|
||||
|
||||
return new Response(readablestreamRsp, {
|
||||
status: 200,
|
||||
headers: {},
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return new Response(buildRawHttp500('has error'), {
|
||||
status: 500,
|
||||
headers: {},
|
||||
});
|
||||
}
|
||||
const connection = await Deno.connect({
|
||||
port: Number(remotePort),
|
||||
hostname: serverAddress,
|
||||
});
|
||||
|
||||
// const proxyResp = request.body?.pipeThrough(connection);
|
||||
// 1. request.body readablestream end casue socket to be end, this will casue socket send FIN package early
|
||||
// and casue deno can't get TCP pcakge.
|
||||
// 2. current soluction for this, let proxy client wait for few ms and then end readablestream
|
||||
// 3. this is only inpact HTTP proxy not https
|
||||
(async () => {
|
||||
for await (let chunk of request.body || []) {
|
||||
// console.log(new TextDecoder().decode(chunk));
|
||||
connection.write(chunk);
|
||||
}
|
||||
})();
|
||||
|
||||
return new Response(connection.readable, {
|
||||
status: 200,
|
||||
headers: {},
|
||||
});
|
||||
};
|
||||
|
||||
serve(handler, { port: 8080, hostname: '0.0.0.0' });
|
||||
|
||||
48
apps/deno-bypass/src/helper.ts
Normal file
48
apps/deno-bypass/src/helper.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { EOL } from 'https://deno.land/std@0.110.0/node/os.ts';
|
||||
function isPrivateIP(ip: string) {
|
||||
if (ip === 'localhost') {
|
||||
return true;
|
||||
}
|
||||
const parts = ip.split('.');
|
||||
return (
|
||||
parts[0] === '10' ||
|
||||
(parts[0] === '172' &&
|
||||
parseInt(parts[1], 10) >= 16 &&
|
||||
parseInt(parts[1], 10) <= 31) ||
|
||||
(parts[0] === '192' && parts[1] === '168')
|
||||
);
|
||||
}
|
||||
|
||||
function buildRawHttp500(message: string) {
|
||||
const body = new TextEncoder().encode(`${message}`);
|
||||
return new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(
|
||||
new TextEncoder().encode(`HTTP/1.1 500 Internal Server Error${EOL}`)
|
||||
);
|
||||
controller.enqueue(
|
||||
new TextEncoder().encode(`content-length: ${body.length}${EOL}`)
|
||||
);
|
||||
controller.enqueue(
|
||||
new TextEncoder().encode(
|
||||
`content-type: text/plain;charset=UTF-8${EOL}${EOL}`
|
||||
)
|
||||
);
|
||||
controller.enqueue(body);
|
||||
controller.close();
|
||||
},
|
||||
cancel() {},
|
||||
});
|
||||
}
|
||||
|
||||
function isVaildateReq(request: Request) {
|
||||
const serverAddress = request.headers.get('x-host') || '';
|
||||
let isVaild = true;
|
||||
if (isPrivateIP(serverAddress) || !request.body) {
|
||||
console.log('lcoal ip or request.body is null');
|
||||
isVaild = false;
|
||||
}
|
||||
return isVaild;
|
||||
}
|
||||
|
||||
export { isPrivateIP, buildRawHttp500, isVaildateReq };
|
||||
14
apps/deno-bypass/src/test/bypass-backup.ts
Normal file
14
apps/deno-bypass/src/test/bypass-backup.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// (async () => {
|
||||
// try {
|
||||
// for await (let chunk of request.body || []) {
|
||||
// // console.log(new TextDecoder().decode(chunk));
|
||||
// connection.write(chunk);
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.log(error);
|
||||
// return new Response('has error', {
|
||||
// status: 500,
|
||||
// headers: {},
|
||||
// });
|
||||
// }
|
||||
// })();
|
||||
@@ -21,12 +21,12 @@ const handler = async (request: Request): Promise<Response> => {
|
||||
});
|
||||
|
||||
// for await (const chunk of body2) {
|
||||
// console.log('11');
|
||||
// console.log('11', new TextDecoder().decode(chunk));
|
||||
// }
|
||||
const proxyResp = body2?.pipeThrough(connection);
|
||||
|
||||
for await (const chunk of proxyResp) {
|
||||
console.log('11');
|
||||
console.log('11', new TextDecoder().decode(chunk));
|
||||
}
|
||||
return new Response('111', {
|
||||
status: 200,
|
||||
|
||||
Reference in New Issue
Block a user