Skip to content

Instantly share code, notes, and snippets.

@ondras
Last active March 21, 2023 11:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ondras/463f4bb611578fbc4c487f620e560ef4 to your computer and use it in GitHub Desktop.
Save ondras/463f4bb611578fbc4c487f620e560ef4 to your computer and use it in GitHub Desktop.
HTTP/S proxy in Deno
import { serve, serveTls } from "https://deno.land/std@0.177.0/http/server.ts";
const TARGET = Deno.env.get("TARGET");
const PORT = Deno.env.has("PORT") ? Number(Deno.env.get("PORT")) : undefined;
const CERT_FILE = Deno.env.get("CERT_FILE");
const KEY_FILE = Deno.env.get("KEY_FILE");
if (!TARGET) {
console.log("Usage:", "TARGET=http://upstream:1234/ [CERT_FILE=/path/to/cert KEY_FILE=/path/key] deno run --allow-env --allow-net proxy.ts")
Deno.exit(1)
}
async function handler(request: Request) {
let upUrl = new URL(TARGET!, request.url);
console.log("-->", request.url, "-->", upUrl.href);
let upRequest = new Request(upUrl, {
method: request.method,
body: request.body,
headers: request.headers
});
return fetch(upRequest);
}
if (CERT_FILE && KEY_FILE) {
await serveTls(handler, {
port: PORT,
certFile: CERT_FILE,
keyFile: KEY_FILE
})
} else {
await serve(handler, {
port: PORT
})
}
@Robitx
Copy link

Robitx commented Mar 21, 2023

gpt 4 version

To create a TLS termination HTTP proxy in Deno, you'll first need to have Deno installed on your system. If you don't have it installed, visit https://deno.land/ for installation instructions. Once you have Deno installed, follow these steps:

Generate a TLS certificate and private key. For development purposes, you can use a self-signed certificate. For production, it's recommended to use a certificate from a trusted Certificate Authority (CA).

Create a new Deno project directory, and inside that directory, create a file named tls_termination_proxy.ts.

In tls_termination_proxy.ts, paste the following code:

// Import required modules
import { serve, ServerRequest, serveTLS } from "https://deno.land/std@0.113.0/http/server.ts";
import { parseAddrFromStr } from "https://deno.land/std@0.113.0/net/mod.ts";
import { copy } from "https://deno.land/std@0.113.0/io/util.ts";

const proxy = async (req: ServerRequest, targetAddr: string) => {
  try {
    const targetConn = await Deno.connect(parseAddrFromStr(targetAddr));
    const clientConn = await req.respond({ status: 101, headers: new Headers() });

    // Proxy traffic between client and target
    await Promise.all([copy(targetConn, clientConn), copy(clientConn, targetConn)]);

    // Close connections
    clientConn.close();
    targetConn.close();
  } catch (err) {
    console.error(`Proxy error: ${err}`);
    req.respond({ status: 500 });
  }
};

const main = async () => {
  const tlsOptions = {
    hostname: "localhost",
    port: 8443,
    certFile: "./cert.pem",
    keyFile: "./key.pem",
  };
  const targetAddr = "http://localhost:8000";

  const tlsServer = serveTLS(tlsOptions);
  console.log(`Listening on https://${tlsOptions.hostname}:${tlsOptions.port} for incoming TLS connections...`);

  for await (const req of tlsServer) {
    proxy(req, targetAddr);
  }
};

main();

Make sure to replace the paths in certFile and keyFile with the correct paths to your certificate and private key files.

Run the following command to start your TLS termination proxy:

deno run --allow-net --allow-read tls_termination_proxy.ts

This will start the proxy server on https://localhost:8443, and forward incoming connections to http://localhost:8000. You can change the target address by modifying the targetAddr variable in the code.

Remember to run your target server (the one you want to proxy the connections to) on the specified target address (in this example, http://localhost:8000).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment