summaryrefslogtreecommitdiff
path: root/scripts/example-proxy.js
diff options
context:
space:
mode:
authorOlcan <[email protected]>2025-06-10 08:58:37 -0700
committerGitHub <[email protected]>2025-06-10 08:58:37 -0700
commite38d2078cc70b0453ef70523a8ad38279941aca2 (patch)
treeb5a4024d1c006a2d116631ac7a51bb5b0eaf34a6 /scripts/example-proxy.js
parent895c1f132f9d1cc88bd56584e461fd22a5f23394 (diff)
restricted networking for all sandboxing methods, new seatbelt profiles, updated docs, fixes to sandbox build, debugging through sandbox (#891)
Diffstat (limited to 'scripts/example-proxy.js')
-rwxr-xr-xscripts/example-proxy.js74
1 files changed, 74 insertions, 0 deletions
diff --git a/scripts/example-proxy.js b/scripts/example-proxy.js
new file mode 100755
index 00000000..284a2eed
--- /dev/null
+++ b/scripts/example-proxy.js
@@ -0,0 +1,74 @@
+#!/usr/bin/env node
+
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// Example proxy server that listens on 0.0.0.0:8877 and only allows HTTPS connections to example.com.
+// Set `GEMINI_SANDBOX_PROXY_COMMAND=scripts/example-proxy.js` to run proxy alongside sandbox
+// Test via `curl https://example.com` inside sandbox (in shell mode or via shell tool)
+
+import http from 'http';
+import net from 'net';
+import { URL } from 'url';
+import console from 'console';
+
+const PROXY_PORT = 8877;
+const ALLOWED_DOMAINS = ['example.com', 'googleapis.com'];
+const ALLOWED_PORT = '443';
+
+const server = http.createServer((req, res) => {
+ // Deny all requests other than CONNECT for HTTPS
+ console.log(
+ `[PROXY] Denying non-CONNECT request for: ${req.method} ${req.url}`,
+ );
+ res.writeHead(405, { 'Content-Type': 'text/plain' });
+ res.end('Method Not Allowed');
+});
+
+server.on('connect', (req, clientSocket, head) => {
+ // req.url will be in the format "hostname:port" for a CONNECT request.
+ const { port, hostname } = new URL(`http://${req.url}`);
+
+ console.log(`[PROXY] Intercepted CONNECT request for: ${hostname}:${port}`);
+
+ if (
+ ALLOWED_DOMAINS.some(
+ (domain) => hostname == domain || hostname.endsWith(`.${domain}`),
+ ) &&
+ port === ALLOWED_PORT
+ ) {
+ console.log(`[PROXY] Allowing connection to ${hostname}:${port}`);
+
+ // Establish a TCP connection to the original destination.
+ const serverSocket = net.connect(port, hostname, () => {
+ clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
+ // Create a tunnel by piping data between the client and the destination server.
+ serverSocket.write(head);
+ serverSocket.pipe(clientSocket);
+ clientSocket.pipe(serverSocket);
+ });
+
+ serverSocket.on('error', (err) => {
+ console.error(`[PROXY] Error connecting to destination: ${err.message}`);
+ clientSocket.end(`HTTP/1.1 502 Bad Gateway\r\n\r\n`);
+ });
+ } else {
+ console.log(`[PROXY] Denying connection to ${hostname}:${port}`);
+ clientSocket.end('HTTP/1.1 403 Forbidden\r\n\r\n');
+ }
+
+ clientSocket.on('error', (err) => {
+ // This can happen if the client hangs up.
+ console.error(`[PROXY] Client socket error: ${err.message}`);
+ });
+});
+
+server.listen(PROXY_PORT, '0.0.0.0', () => {
+ console.log(`[PROXY] Proxy listening on 0.0.0.0:${PROXY_PORT}`);
+ console.log(
+ `[PROXY] Allowing HTTPS connections to domains: ${ALLOWED_DOMAINS.join(', ')}`,
+ );
+});