anews9340 commited on
Commit
915f34a
·
verified ·
1 Parent(s): 7263496

Update simple-proxy.js

Browse files
Files changed (1) hide show
  1. simple-proxy.js +126 -78
simple-proxy.js CHANGED
@@ -5,22 +5,13 @@ import { URL } from 'node:url';
5
 
6
  // Configuration
7
  const CONFIG = {
8
- // Port - Hugging Face provides this via PORT environment variable
9
  PORT: process.env.PORT || 8080,
10
-
11
- // Allowed domains - customize this list for your needs
12
- ALLOWED_DOMAINS: [
13
- 'huggingface.co',
14
- 'googleapis.com',
15
- 'example.com',
16
- '*.example.com' // Allow subdomains
17
- ],
18
-
19
- // Enable logging
20
  LOG_REQUESTS: process.env.LOG_REQUESTS !== 'false',
21
-
22
- // Timeout settings (ms)
23
- CONNECT_TIMEOUT: 30000
24
  };
25
 
26
  // Logging helper
@@ -32,15 +23,20 @@ const logger = {
32
 
33
  // Check if domain is allowed
34
  function isDomainAllowed(hostname) {
 
 
35
  for (const pattern of CONFIG.ALLOWED_DOMAINS) {
36
- if (pattern.startsWith('*.')) {
37
- // Wildcard subdomain matching
38
- const baseDomain = pattern.slice(2);
 
 
 
 
 
39
  if (hostname === baseDomain || hostname.endsWith(`.${baseDomain}`)) {
40
  return true;
41
  }
42
- } else if (hostname === pattern) {
43
- return true;
44
  }
45
  }
46
  return false;
@@ -48,6 +44,25 @@ function isDomainAllowed(hostname) {
48
 
49
  // Create HTTP server
50
  const server = http.createServer((req, res) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  // Only CONNECT method is supported for HTTPS proxying
52
  res.writeHead(405, {
53
  'Content-Type': 'application/json',
@@ -55,77 +70,103 @@ const server = http.createServer((req, res) => {
55
  });
56
  res.end(JSON.stringify({
57
  error: 'Method Not Allowed',
58
- message: 'This proxy only supports CONNECT method for HTTPS tunneling'
 
59
  }));
60
  });
61
 
62
  // Handle CONNECT requests (HTTPS tunneling)
63
  server.on('connect', (req, clientSocket, head) => {
64
- const { hostname, port } = new URL(`http://${req.url}`);
65
- const targetPort = port || '443';
66
 
67
- if (CONFIG.LOG_REQUESTS) {
68
- logger.info(`CONNECT ${hostname}:${targetPort} from ${req.socket.remoteAddress}`);
69
- }
70
-
71
- // Security checks
72
- if (targetPort !== '443') {
73
- logger.warn(`Blocked non-HTTPS port: ${targetPort}`);
74
- clientSocket.end('HTTP/1.1 403 Forbidden\r\n\r\nNon-HTTPS ports not allowed');
75
- return;
76
- }
77
-
78
- if (!isDomainAllowed(hostname)) {
79
- logger.warn(`Blocked domain: ${hostname}`);
80
- clientSocket.end('HTTP/1.1 403 Forbidden\r\n\r\nDomain not allowed');
81
- return;
82
- }
83
-
84
- // Connect to target server
85
- const serverSocket = net.connect({
86
- host: hostname,
87
- port: targetPort,
88
- timeout: CONFIG.CONNECT_TIMEOUT
89
- });
90
-
91
- // Handle successful connection
92
- serverSocket.on('connect', () => {
93
- clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
94
- serverSocket.write(head);
95
-
96
- // Pipe data between client and server
97
- serverSocket.pipe(clientSocket);
98
- clientSocket.pipe(serverSocket);
99
 
100
  if (CONFIG.LOG_REQUESTS) {
101
- logger.info(`Connected to ${hostname}:${targetPort}`);
102
  }
103
- });
104
-
105
- // Handle errors
106
- serverSocket.on('error', (err) => {
107
- logger.error(`Connection error to ${hostname}:${targetPort} - ${err.message}`);
108
- clientSocket.end('HTTP/1.1 502 Bad Gateway\r\n\r\n');
109
- });
110
-
111
- clientSocket.on('error', (err) => {
112
- logger.error(`Client socket error: ${err.message}`);
113
- serverSocket.destroy();
114
- });
115
-
116
- // Handle timeouts
117
- serverSocket.setTimeout(CONFIG.CONNECT_TIMEOUT, () => {
118
- logger.warn(`Timeout connecting to ${hostname}:${targetPort}`);
119
- clientSocket.end('HTTP/1.1 504 Gateway Timeout\r\n\r\n');
120
- serverSocket.destroy();
121
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  });
123
 
124
  // Start server
125
- server.listen(CONFIG.PORT, () => {
126
- logger.info(`Secure HTTPS Proxy Server started on port ${CONFIG.PORT}`);
127
- logger.info(`Allowed domains: ${CONFIG.ALLOWED_DOMAINS.join(', ')}`);
128
- logger.info(`Ready to accept CONNECT requests`);
 
 
 
129
  });
130
 
131
  // Handle graceful shutdown
@@ -135,4 +176,11 @@ process.on('SIGTERM', () => {
135
  logger.info('Server closed');
136
  process.exit(0);
137
  });
 
 
 
 
 
 
 
138
  });
 
5
 
6
  // Configuration
7
  const CONFIG = {
 
8
  PORT: process.env.PORT || 8080,
9
+ ALLOWED_DOMAINS: process.env.ALLOWED_DOMAINS
10
+ ? process.env.ALLOWED_DOMAINS.split(',')
11
+ : ['huggingface.co', 'googleapis.com', 'gemini.google.com'],
 
 
 
 
 
 
 
12
  LOG_REQUESTS: process.env.LOG_REQUESTS !== 'false',
13
+ CONNECT_TIMEOUT: 30000,
14
+ MAX_REQUEST_SIZE: 1024 * 1024 * 10 // 10MB
 
15
  };
16
 
17
  // Logging helper
 
23
 
24
  // Check if domain is allowed
25
  function isDomainAllowed(hostname) {
26
+ if (CONFIG.ALLOWED_DOMAINS.includes('*')) return true;
27
+
28
  for (const pattern of CONFIG.ALLOWED_DOMAINS) {
29
+ const trimmedPattern = pattern.trim();
30
+
31
+ // Exact match
32
+ if (hostname === trimmedPattern) return true;
33
+
34
+ // Wildcard subdomain matching
35
+ if (trimmedPattern.startsWith('*.')) {
36
+ const baseDomain = trimmedPattern.slice(2);
37
  if (hostname === baseDomain || hostname.endsWith(`.${baseDomain}`)) {
38
  return true;
39
  }
 
 
40
  }
41
  }
42
  return false;
 
44
 
45
  // Create HTTP server
46
  const server = http.createServer((req, res) => {
47
+ // Basic info endpoint
48
+ if (req.url === '/' && req.method === 'GET') {
49
+ res.writeHead(200, {
50
+ 'Content-Type': 'application/json',
51
+ 'Access-Control-Allow-Origin': '*'
52
+ });
53
+ res.end(JSON.stringify({
54
+ service: 'HTTPS Proxy Server',
55
+ version: '1.0.0',
56
+ status: 'running',
57
+ allowed_domains: CONFIG.ALLOWED_DOMAINS,
58
+ endpoints: {
59
+ proxy: 'CONNECT method for HTTPS tunneling',
60
+ info: 'GET / for service information'
61
+ }
62
+ }));
63
+ return;
64
+ }
65
+
66
  // Only CONNECT method is supported for HTTPS proxying
67
  res.writeHead(405, {
68
  'Content-Type': 'application/json',
 
70
  });
71
  res.end(JSON.stringify({
72
  error: 'Method Not Allowed',
73
+ message: 'This proxy only supports CONNECT method for HTTPS tunneling',
74
+ allowed_methods: ['CONNECT', 'GET']
75
  }));
76
  });
77
 
78
  // Handle CONNECT requests (HTTPS tunneling)
79
  server.on('connect', (req, clientSocket, head) => {
80
+ const startTime = Date.now();
 
81
 
82
+ try {
83
+ const { hostname, port } = new URL(`http://${req.url}`);
84
+ const targetPort = port || '443';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  if (CONFIG.LOG_REQUESTS) {
87
+ logger.info(`CONNECT ${hostname}:${targetPort} from ${req.socket.remoteAddress}`);
88
  }
89
+
90
+ // Security checks
91
+ if (targetPort !== '443') {
92
+ logger.warn(`Blocked non-HTTPS port: ${targetPort}`);
93
+ clientSocket.end('HTTP/1.1 403 Forbidden\r\n\r\nNon-HTTPS ports not allowed');
94
+ return;
95
+ }
96
+
97
+ if (!isDomainAllowed(hostname)) {
98
+ logger.warn(`Blocked domain: ${hostname}`);
99
+ clientSocket.end('HTTP/1.1 403 Forbidden\r\n\r\nDomain not allowed');
100
+ return;
101
+ }
102
+
103
+ // Connect to target server
104
+ const serverSocket = net.connect({
105
+ host: hostname,
106
+ port: targetPort,
107
+ timeout: CONFIG.CONNECT_TIMEOUT
108
+ });
109
+
110
+ // Handle successful connection
111
+ serverSocket.on('connect', () => {
112
+ clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
113
+
114
+ if (head && head.length > 0) {
115
+ serverSocket.write(head);
116
+ }
117
+
118
+ // Pipe data between client and server
119
+ serverSocket.pipe(clientSocket);
120
+ clientSocket.pipe(serverSocket);
121
+
122
+ if (CONFIG.LOG_REQUESTS) {
123
+ const duration = Date.now() - startTime;
124
+ logger.info(`Connected to ${hostname}:${targetPort} in ${duration}ms`);
125
+ }
126
+ });
127
+
128
+ // Handle errors
129
+ serverSocket.on('error', (err) => {
130
+ logger.error(`Connection error to ${hostname}:${targetPort} - ${err.message}`);
131
+ clientSocket.end('HTTP/1.1 502 Bad Gateway\r\n\r\n');
132
+ });
133
+
134
+ clientSocket.on('error', (err) => {
135
+ logger.error(`Client socket error: ${err.message}`);
136
+ serverSocket.destroy();
137
+ });
138
+
139
+ // Handle timeouts
140
+ serverSocket.setTimeout(CONFIG.CONNECT_TIMEOUT, () => {
141
+ logger.warn(`Timeout connecting to ${hostname}:${targetPort}`);
142
+ clientSocket.end('HTTP/1.1 504 Gateway Timeout\r\n\r\n');
143
+ serverSocket.destroy();
144
+ });
145
+
146
+ // Handle socket close
147
+ clientSocket.on('close', () => {
148
+ serverSocket.end();
149
+ });
150
+
151
+ } catch (error) {
152
+ logger.error(`Request parsing error: ${error.message}`);
153
+ clientSocket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
154
+ }
155
+ });
156
+
157
+ // Error handling for server
158
+ server.on('error', (err) => {
159
+ logger.error(`Server error: ${err.message}`);
160
  });
161
 
162
  // Start server
163
+ server.listen(CONFIG.PORT, '0.0.0.0', () => {
164
+ logger.info(`=== HTTPS Proxy Server Started ===`);
165
+ logger.info(`Port: ${CONFIG.PORT}`);
166
+ logger.info(`Allowed Domains: ${CONFIG.ALLOWED_DOMAINS.join(', ')}`);
167
+ logger.info(`Logging: ${CONFIG.LOG_REQUESTS ? 'Enabled' : 'Disabled'}`);
168
+ logger.info(`Health Check: http://localhost:${CONFIG.PORT}/`);
169
+ logger.info(`================================`);
170
  });
171
 
172
  // Handle graceful shutdown
 
176
  logger.info('Server closed');
177
  process.exit(0);
178
  });
179
+ });
180
+
181
+ process.on('SIGINT', () => {
182
+ logger.info('Received SIGINT, shutting down');
183
+ server.close(() => {
184
+ process.exit(0);
185
+ });
186
  });