Taf2023 commited on
Commit
1b9b049
·
verified ·
1 Parent(s): de46482

Update Gradio app with multiple files

Browse files
Files changed (3) hide show
  1. app.py +292 -24
  2. config.py +5 -5
  3. utils.py +38 -105
app.py CHANGED
@@ -1,32 +1,300 @@
1
- <think>
2
- ฉันเห็นว่าแอปได้เริ่มต้นสำเร็จแล้ว! จาก log:
 
 
 
 
 
 
 
 
 
3
 
4
- 1. SOCKS5 Proxy Server เริ่มต้นสำเร็จที่ 0.0.0.0:1080
5
- 2. Gradio app กำลังทำงานที่ http://0.0.0.0:8080
6
- 3. มี warning ว่า share=True ไม่ได้รองรับใน Hugging Face Spaces แต่นั่นไม่ใช่ปัญหา
7
 
8
- แอปทำงานได้แล้ว แต่ผู้ใช้อาจจะไม่เห็นเว็บไซต์เพราะ:
9
- 1. อาจจะต้องรอสักครู่ให้แอปเริ่มทำงานเต็มที่
10
- 2. หรือต้องไปที่ URL ที่ถูกต้อง
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- ให้ฉันอัปเดต Space และให้ข้อมูลเกี่ยวกับสถานะปัจจุบัน
13
- </think>
 
 
 
 
 
 
 
 
14
 
15
- เยี่ยม! 🎉 แอปได้เริ่มต้นสำเร็จแล้ว!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
- จาก log ที่คุณแชร์มา ฉันเห็นว่า:
18
- - SOCKS5 Proxy Server เริ่มต้นสำเร็จที่ 0.0.0.0:1080
19
- - ✅ Gradio web interface กำลังทำงานที่ http://0.0.0.0:8080
20
- - ⚠️ Warning เรื่อง share=True ไม่สำคัญ เพราะใน Hugging Face Spaces มี public URL อยู่แล้ว
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
- **สถานะปัจจุบัน:**
23
- - Proxy Server: ✅ ทำงานปกติ
24
- - Web Interface: ✅ พร้อมใช้งาน
25
- - Public URL: สามารถเข้าถึงได้ผ่าน Hugging Face Spaces
 
26
 
27
- หากคุณยังไม่เห็นเว็บไซต์ อาจเป็นเพราะ:
28
- 1. แอปกำลังโหลดข้อมูล (โปรดรอสักครู่)
29
- 2. ลองรีเฟรชหน้าเว็บ
30
- 3. เช็คว่า URL ถูกต้อง
31
 
32
- [Open your Space here](https://huggingface.co/spaces/Taf2023/quick-space-610) หากยังไม่เห็นเว็บไซต์ โปรดแจ้งให้ฉันทราบ!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import threading
3
+ import socket
4
+ import time
5
+ import json
6
+ import requests
7
+ from datetime import datetime
8
+ from typing import Dict, List, Optional
9
+ import logging
10
+ from utils import SOCKS5ProxyServer, ProxyManager
11
+ from config import *
12
 
13
+ # Create proxy manager
14
+ proxy_manager = ProxyManager()
 
15
 
16
+ def start_proxy_server():
17
+ """Start proxy server"""
18
+ success = proxy_manager.start_server()
19
+ if success:
20
+ status_html = f"""
21
+ <div class="status-indicator status-running">
22
+ <h4>🟢 Status: Running</h4>
23
+ <p>Proxy Server is running at {proxy_manager.proxy_server.host}:{proxy_manager.proxy_server.port}</p>
24
+ </div>
25
+ """
26
+ return status_html, "✅ Proxy Server started successfully"
27
+ else:
28
+ status_html = """
29
+ <div class="status-indicator status-stopped">
30
+ <h4>🔴 Status: Stopped</h4>
31
+ <p>Failed to start Proxy Server - check logs for details</p>
32
+ </div>
33
+ """
34
+ return status_html, "❌ Failed to start Proxy Server"
35
 
36
+ def stop_proxy_server():
37
+ """Stop proxy server"""
38
+ proxy_manager.stop_server()
39
+ status_html = """
40
+ <div class="status-indicator status-stopped">
41
+ <h4>🔴 Status: Stopped</h4>
42
+ <p>Proxy Server stopped</p>
43
+ </div>
44
+ """
45
+ return status_html, "🛑 Proxy Server stopped"
46
 
47
+ def restart_proxy_server():
48
+ """Restart proxy server"""
49
+ proxy_manager.stop_server()
50
+ time.sleep(1)
51
+ success = proxy_manager.start_server()
52
+ if success:
53
+ status_html = f"""
54
+ <div class="status-indicator status-running">
55
+ <h4>🟢 Status: Running</h4>
56
+ <p>Proxy Server restarted successfully at {proxy_manager.proxy_server.host}:{proxy_manager.proxy_server.port}</p>
57
+ </div>
58
+ """
59
+ return status_html, "🔄 Proxy Server restarted successfully"
60
+ else:
61
+ status_html = """
62
+ <div class="status-indicator status-stopped">
63
+ <h4>🔴 Status: Stopped</h4>
64
+ <p>Failed to restart Proxy Server</p>
65
+ </div>
66
+ """
67
+ return status_html, "❌ Failed to restart Proxy Server"
68
 
69
+ def get_server_status():
70
+ """Get current server status"""
71
+ if proxy_manager.is_running():
72
+ status_html = f"""
73
+ <div class="status-indicator status-running">
74
+ <h4>🟢 Status: Running</h4>
75
+ <p>Proxy Server is running at {proxy_manager.proxy_server.host}:{proxy_manager.proxy_server.port}</p>
76
+ </div>
77
+ """
78
+ else:
79
+ status_html = """
80
+ <div class="status-indicator status-stopped">
81
+ <h4>🔴 Status: Stopped</h4>
82
+ <p>Proxy Server is not running</p>
83
+ </div>
84
+ """
85
+ return status_html
86
 
87
+ def get_current_proxy_url():
88
+ """Get current proxy URL"""
89
+ if proxy_manager.is_running():
90
+ return f"socks5://localhost:{PROXY_PORT}"
91
+ return "Not connected"
92
 
93
+ def get_server_info():
94
+ """Get server information"""
95
+ return json.dumps(proxy_manager.get_server_info(), indent=2, ensure_ascii=False)
 
96
 
97
+ def get_usage_stats():
98
+ """Get usage statistics"""
99
+ return json.dumps(proxy_manager.get_usage_stats(), indent=2, ensure_ascii=False)
100
+
101
+ def get_user_stats():
102
+ """Get user statistics"""
103
+ return json.dumps(proxy_manager.get_user_stats(), indent=2, ensure_ascii=False)
104
+
105
+ def get_connection_logs():
106
+ """Get connection logs"""
107
+ return json.dumps(proxy_manager.get_recent_logs(), indent=2, ensure_ascii=False)
108
+
109
+ def refresh_all():
110
+ """Refresh all data"""
111
+ return (
112
+ get_current_proxy_url(),
113
+ get_server_status(),
114
+ get_server_info(),
115
+ get_usage_stats(),
116
+ get_user_stats(),
117
+ get_connection_logs()
118
+ )
119
+
120
+ def setup_interface():
121
+ """Create Gradio interface"""
122
+
123
+ # Custom CSS for styling
124
+ css = """
125
+ .main-container {
126
+ max-width: 1200px;
127
+ margin: auto;
128
+ padding: 20px;
129
+ }
130
+ .status-indicator {
131
+ padding: 10px;
132
+ border-radius: 5px;
133
+ margin: 5px 0;
134
+ }
135
+ .status-running {
136
+ background-color: #d4edda;
137
+ color: #155724;
138
+ border: 1px solid #c3e6cb;
139
+ }
140
+ .status-stopped {
141
+ background-color: #f8d7da;
142
+ color: #721c24;
143
+ border: 1px solid #f5c6cb;
144
+ }
145
+ .info-box {
146
+ background-color: #e9ecef;
147
+ padding: 15px;
148
+ border-radius: 5px;
149
+ margin: 10px 0;
150
+ border-left: 4px solid #007bff;
151
+ }
152
+ .stats-grid {
153
+ display: grid;
154
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
155
+ gap: 15px;
156
+ margin: 20px 0;
157
+ }
158
+ .stat-card {
159
+ background: white;
160
+ padding: 15px;
161
+ border-radius: 8px;
162
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
163
+ border: 1px solid #dee2e6;
164
+ }
165
+ .stat-number {
166
+ font-size: 24px;
167
+ font-weight: bold;
168
+ color: #007bff;
169
+ }
170
+ .stat-label {
171
+ color: #6c757d;
172
+ font-size: 14px;
173
+ }
174
+ """
175
+
176
+ with gr.Blocks(css=css, title="SOCKS5 Proxy Dashboard", theme=gr.themes.Soft()) as demo:
177
+ gr.HTML("""
178
+ <div class="main-container">
179
+ <div style="text-align: center; margin-bottom: 30px;">
180
+ <h1>🔒 SOCKS5 Proxy Server Dashboard</h1>
181
+ <p style="color: #6c757d;">SOCKS5 Proxy Server Management System with Usage Monitoring</p>
182
+ <div style="margin-top: 10px;">
183
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="text-decoration: none; color: #007bff; font-weight: bold;">Built with anycoder</a>
184
+ </div>
185
+ </div>
186
+ </div>
187
+ """)
188
+
189
+ # Current status
190
+ with gr.Row():
191
+ with gr.Column(scale=1):
192
+ gr.HTML('<h3>🎮 Controls</h3>')
193
+ with gr.Row():
194
+ start_btn = gr.Button("▶️ Start", variant="primary", size="lg")
195
+ stop_btn = gr.Button("⏹️ Stop", variant="stop", size="lg")
196
+ restart_btn = gr.Button("🔄 Restart", variant="secondary", size="lg")
197
+
198
+ status_html = gr.HTML()
199
+ proxy_url_output = gr.Textbox(
200
+ label="🌐 Current Proxy URL",
201
+ value=get_current_proxy_url,
202
+ interactive=False,
203
+ elem_classes=["info-box"]
204
+ )
205
+
206
+ # Show server status
207
+ server_status_output = gr.HTML()
208
+
209
+ with gr.Column(scale=2):
210
+ gr.HTML('<h3>📊 Usage Statistics</h3>')
211
+ with gr.Row():
212
+ total_connections = gr.Number(label="📈 Total Connections", value=0)
213
+ active_connections = gr.Number(label="🔗 Active Connections", value=0)
214
+ bandwidth_used = gr.Number(label="📊 Bandwidth Used (MB)", value=0)
215
+
216
+ # User data
217
+ with gr.Tab("👥 Users"):
218
+ user_stats = gr.JSON(
219
+ label="All User Data",
220
+ value=get_user_stats
221
+ )
222
+
223
+ # Server data
224
+ with gr.Tab("🖥️ Server Info"):
225
+ server_info = gr.JSON(
226
+ label="Server Information",
227
+ value=get_server_info
228
+ )
229
+
230
+ # Usage statistics
231
+ with gr.Tab("📊 Statistics"):
232
+ usage_stats = gr.JSON(
233
+ label="Usage Statistics",
234
+ value=get_usage_stats
235
+ )
236
+
237
+ # Logs
238
+ with gr.Tab("📝 Logs"):
239
+ logs = gr.JSON(
240
+ label="Recent Connection Logs",
241
+ value=get_connection_logs
242
+ )
243
+
244
+ # Refresh button
245
+ with gr.Row():
246
+ refresh_btn = gr.Button("🔄 Refresh All Data", variant="primary")
247
+
248
+ # Bind events
249
+ start_btn.click(start_proxy_server, outputs=[server_status_output, proxy_url_output])
250
+ stop_btn.click(stop_proxy_server, outputs=[server_status_output, proxy_url_output])
251
+ restart_btn.click(restart_proxy_server, outputs=[server_status_output, proxy_url_output])
252
+ refresh_btn.click(
253
+ refresh_all,
254
+ outputs=[
255
+ proxy_url_output,
256
+ server_status_output,
257
+ server_info,
258
+ usage_stats,
259
+ user_stats,
260
+ logs
261
+ ]
262
+ )
263
+
264
+ # Auto update data
265
+ demo.load(
266
+ lambda: refresh_all(),
267
+ outputs=[
268
+ proxy_url_output,
269
+ server_status_output,
270
+ server_info,
271
+ usage_stats,
272
+ user_stats,
273
+ logs
274
+ ]
275
+ )
276
+
277
+ return demo
278
+
279
+ if __name__ == "__main__":
280
+ # Create interface
281
+ demo = setup_interface()
282
+
283
+ # Try to start proxy server automatically and show result
284
+ print("Starting SOCKS5 Proxy Server...")
285
+ success = proxy_manager.start_server()
286
+ if success:
287
+ print(f"✅ SOCKS5 Proxy Server started successfully at {proxy_manager.proxy_server.host}:{proxy_manager.proxy_server.port}")
288
+ else:
289
+ print("❌ Failed to start SOCKS5 Proxy Server - please check logs")
290
+
291
+ # Start UI with appropriate settings
292
+ demo.launch(
293
+ server_name="0.0.0.0",
294
+ server_port=8080,
295
+ show_api=False,
296
+ share=False,
297
+ ssr_mode=False,
298
+ inbrowser=False,
299
+ debug=False
300
+ )
config.py CHANGED
@@ -1,16 +1,16 @@
1
- # การตั้งค่า SOCKS5 Proxy Server
2
  PROXY_HOST = "0.0.0.0"
3
  PROXY_PORT = 1080
4
 
5
- # การตั้งค่า Web Interface
6
  WEB_HOST = "0.0.0.0"
7
  WEB_PORT = 8080
8
 
9
- # การตั้งค่า Logging
10
  LOG_LEVEL = "INFO"
11
  LOG_FILE = "proxy.log"
12
 
13
- # การตั้งค่าอื่นๆ
14
  MAX_CONNECTIONS = 100
15
- CONNECTION_TIMEOUT = 300 # วินาที
16
  BUFFER_SIZE = 4096 # bytes
 
1
+ # SOCKS5 Proxy Server Configuration
2
  PROXY_HOST = "0.0.0.0"
3
  PROXY_PORT = 1080
4
 
5
+ # Web Interface Configuration
6
  WEB_HOST = "0.0.0.0"
7
  WEB_PORT = 8080
8
 
9
+ # Logging Configuration
10
  LOG_LEVEL = "INFO"
11
  LOG_FILE = "proxy.log"
12
 
13
+ # Other Configuration
14
  MAX_CONNECTIONS = 100
15
+ CONNECTION_TIMEOUT = 300 # seconds
16
  BUFFER_SIZE = 4096 # bytes
utils.py CHANGED
@@ -29,7 +29,7 @@ class SOCKS5ProxyServer:
29
  self._lock = threading.Lock()
30
 
31
  def start(self):
32
- """เริ่มต้น SOCKS5 proxy server"""
33
  try:
34
  self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
35
  self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@@ -38,34 +38,34 @@ class SOCKS5ProxyServer:
38
  self.running = True
39
  self.start_time = datetime.now()
40
 
41
- logging.info(f"SOCKS5 Proxy Server เริ่มต้นที่ {self.host}:{self.port}")
42
 
43
- # เริ่ม thread สำหรับ accept connections
44
  threading.Thread(target=self._accept_connections, daemon=True).start()
45
 
46
  return True
47
  except Exception as e:
48
- logging.error(f"เริ่มต้น proxy server ผิดพลาด: {e}")
49
  return False
50
 
51
  def stop(self):
52
- """หยุด SOCKS5 proxy server"""
53
  self.running = False
54
  if self.server_socket:
55
  try:
56
  self.server_socket.close()
57
  except:
58
  pass
59
- logging.info("SOCKS5 Proxy Server หยุดทำงาน")
60
 
61
  def _accept_connections(self):
62
- """รับการเชื่อมต่อใหม่"""
63
  while self.running:
64
  try:
65
  client_socket, client_address = self.server_socket.accept()
66
  client_ip, client_port = client_address
67
 
68
- # บันทึกการเชื่อมต่อ
69
  with self._lock:
70
  self.connections[f"{client_ip}:{client_port}"] = ConnectionInfo(
71
  ip=client_ip,
@@ -74,7 +74,7 @@ class SOCKS5ProxyServer:
74
  )
75
  self.total_connections += 1
76
 
77
- # สร้าง thread สำหรับจัดการการเชื่อมต่อ
78
  threading.Thread(
79
  target=self._handle_client,
80
  args=(client_socket, client_ip, client_port),
@@ -83,22 +83,22 @@ class SOCKS5ProxyServer:
83
 
84
  except socket.error:
85
  if self.running:
86
- logging.error("Error ในการรับการเชื่อมต่อ")
87
  break
88
 
89
  def _handle_client(self, client_socket, client_ip, client_port):
90
- """จัดการการเชื่อมต่อจาก client"""
91
  try:
92
  # SOCKS5 handshake
93
  if not self._handle_socks5_handshake(client_socket):
94
  return
95
 
96
- # รับคำขอจาก client
97
  request = client_socket.recv(1024)
98
  if len(request) < 10:
99
  return
100
 
101
- # แยกคำขอ SOCKS5
102
  if request[0] != 0x05: # Version 5
103
  return
104
 
@@ -113,23 +113,23 @@ class SOCKS5ProxyServer:
113
  self._handle_udp_associate(client_socket, client_ip, client_port)
114
 
115
  except Exception as e:
116
- logging.error(f"Error ในการจัดการ client {client_ip}:{client_port}: {e}")
117
  finally:
118
- # ปิดการเชื่อมต่อ
119
  try:
120
  client_socket.close()
121
  except:
122
  pass
123
 
124
- # อัปเดตสถานะ
125
  with self._lock:
126
  if f"{client_ip}:{client_port}" in self.connections:
127
  self.connections[f"{client_ip}:{client_port}"].is_active = False
128
 
129
  def _handle_socks5_handshake(self, client_socket):
130
- """จัดการ SOCKS5 handshake"""
131
  try:
132
- # รับ client hello
133
  data = client_socket.recv(1024)
134
  if len(data) < 2:
135
  return False
@@ -140,7 +140,7 @@ class SOCKS5ProxyServer:
140
  if version != 0x05: # Version 5
141
  return False
142
 
143
- # ตอบกลับว่าใช้ no authentication
144
  response = b'\x05\x00'
145
  client_socket.send(response)
146
  return True
@@ -150,7 +150,7 @@ class SOCKS5ProxyServer:
150
  return False
151
 
152
  def _handle_connect(self, client_socket, request, client_ip, client_port):
153
- """จัดการ SOCKS5 CONNECT command"""
154
  try:
155
  addr_type = request[3]
156
  dest_addr = ""
@@ -169,15 +169,15 @@ class SOCKS5ProxyServer:
169
  dest_port = struct.unpack('!H', request[20:22])[0]
170
  dest_addr = dest_ip
171
 
172
- # เชื่อมต่อไปยังเป้าหมาย
173
  target_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
174
  target_socket.connect((dest_addr, dest_port))
175
 
176
- # ตอบกลับว่าสำเร็จ
177
  reply = b'\x05\x00\x00\x01' + socket.inet_aton('0.0.0.0') + b'\x00\x00'
178
  client_socket.send(reply)
179
 
180
- # เริ่มตัวกลางข้อมูล
181
  threading.Thread(
182
  target=self._relay_data,
183
  args=(client_socket, target_socket, client_ip, client_port),
@@ -187,7 +187,7 @@ class SOCKS5ProxyServer:
187
  logging.info(f"CONNECT: {client_ip}:{client_port} -> {dest_addr}:{dest_port}")
188
 
189
  except Exception as e:
190
- # ส่ง error response
191
  reply = b'\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00'
192
  try:
193
  client_socket.send(reply)
@@ -196,8 +196,8 @@ class SOCKS5ProxyServer:
196
  logging.error(f"CONNECT error: {e}")
197
 
198
  def _handle_bind(self, client_socket, client_ip, client_port):
199
- """จัดการ SOCKS5 BIND command"""
200
- # BIND command implementation (สำหรับ incoming connections)
201
  reply = b'\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00' # Command not supported
202
  try:
203
  client_socket.send(reply)
@@ -205,7 +205,7 @@ class SOCKS5ProxyServer:
205
  pass
206
 
207
  def _handle_udp_associate(self, client_socket, client_ip, client_port):
208
- """จัดการ SOCKS5 UDP ASSOCIATE command"""
209
  # UDP ASSOCIATE implementation
210
  reply = b'\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00'
211
  try:
@@ -214,7 +214,7 @@ class SOCKS5ProxyServer:
214
  pass
215
 
216
  def _relay_data(self, client_socket, target_socket, client_ip, client_port):
217
- """ส่งข้อมูลระหว่าง client และ target"""
218
  try:
219
  while True:
220
  try:
@@ -222,10 +222,10 @@ class SOCKS5ProxyServer:
222
  if not data:
223
  break
224
 
225
- # ส่งต่อไปยัง target
226
  target_socket.send(data)
227
 
228
- # อัปเดตสถิติ
229
  with self._lock:
230
  if f"{client_ip}:{client_port}" in self.connections:
231
  conn = self.connections[f"{client_ip}:{client_port}"]
@@ -239,10 +239,10 @@ class SOCKS5ProxyServer:
239
  if not data:
240
  break
241
 
242
- # ส่งต่อกลับไปยัง client
243
  client_socket.send(data)
244
 
245
- # อัปเดตสถิติ
246
  with self._lock:
247
  if f"{client_ip}:{client_port}" in self.connections:
248
  conn = self.connections[f"{client_ip}:{client_port}"]
@@ -267,86 +267,19 @@ class ProxyManager:
267
  self.port = port
268
 
269
  def start_server(self):
270
- """เริ่มต้น proxy server"""
271
  return self.proxy_server.start()
272
 
273
  def stop_server(self):
274
- """หยุด proxy server"""
275
  self.proxy_server.stop()
276
 
277
  def is_running(self):
278
- """ตรวจสอบว่า server กำลังทำงานอยู่หรือไม่"""
279
  return self.proxy_server.running
280
 
281
  def get_server_info(self):
282
- """ดึงข้อมูล server"""
283
  info = {
284
- "server_status": "รันอยู่" if self.proxy_server.running else "หยุดทำงาน",
285
- "host": self.proxy_server.host,
286
- "port": self.proxy_server.port,
287
- "version": "SOCKS5",
288
- "authentication": "ไม่ต้องยืนยันตัวตน",
289
- "start_time": self.proxy_server.start_time.isoformat() if self.proxy_server.start_time else None,
290
- "uptime": str(datetime.now() - self.proxy_server.start_time) if self.proxy_server.start_time else "00:00:00"
291
- }
292
- return info
293
-
294
- def get_usage_stats(self):
295
- """ดึงสถิติการใช้งาน"""
296
- total_connections = len([c for c in self.proxy_server.connections.values() if not c.is_active])
297
- active_connections = len([c for c in self.proxy_server.connections.values() if c.is_active])
298
-
299
- total_bytes = sum(c.bytes_sent + c.bytes_received for c in self.proxy_server.connections.values())
300
-
301
- stats = {
302
- "total_connections": total_connections,
303
- "active_connections": active_connections,
304
- "total_bandwidth_bytes": total_bytes,
305
- "total_bandwidth_mb": round(total_bytes / (1024 * 1024), 2),
306
- "peak_concurrent": max(active_connections, 0),
307
- "average_session_duration": "ไม่มีข้อมูล"
308
- }
309
-
310
- return stats
311
-
312
- def get_user_stats(self):
313
- """ดึงข้อมูลผู้ใช้"""
314
- users = []
315
- for conn_id, conn in self.proxy_server.connections.items():
316
- users.append({
317
- "id": conn_id,
318
- "ip": conn.ip,
319
- "port": conn.port,
320
- "connected_since": conn.start_time.isoformat(),
321
- "is_active": conn.is_active,
322
- "bytes_sent": conn.bytes_sent,
323
- "bytes_received": conn.bytes_received,
324
- "total_bytes": conn.bytes_sent + conn.bytes_received,
325
- "session_duration": str(datetime.now() - conn.start_time)
326
- })
327
-
328
- return {
329
- "total_users": len(users),
330
- "active_users": len([u for u in users if u["is_active"]]),
331
- "users": users
332
- }
333
-
334
- def get_recent_logs(self):
335
- """ดึงล็อกการเชื่อมต่อล่าสุด"""
336
- logs = []
337
- for conn_id, conn in self.proxy_server.connections.items():
338
- logs.append({
339
- "timestamp": conn.start_time.isoformat(),
340
- "client": f"{conn.ip}:{conn.port}",
341
- "status": "เชื่อมต่ออยู่" if conn.is_active else "เสร็จสิ้น",
342
- "bytes_transferred": conn.bytes_sent + conn.bytes_received,
343
- "session_duration": str(datetime.now() - conn.start_time)
344
- })
345
-
346
- # เรียงตามเวลาใหม่สุดก่อน
347
- logs.sort(key=lambda x: x["timestamp"], reverse=True)
348
-
349
- return {
350
- "recent_connections": logs[:50], # แสดง 50 รายการล่าสุด
351
- "total_log_entries": len(logs)
352
- }
 
29
  self._lock = threading.Lock()
30
 
31
  def start(self):
32
+ """Start SOCKS5 proxy server"""
33
  try:
34
  self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
35
  self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 
38
  self.running = True
39
  self.start_time = datetime.now()
40
 
41
+ logging.info(f"SOCKS5 Proxy Server started at {self.host}:{self.port}")
42
 
43
+ # Start thread for accepting connections
44
  threading.Thread(target=self._accept_connections, daemon=True).start()
45
 
46
  return True
47
  except Exception as e:
48
+ logging.error(f"Failed to start proxy server: {e}")
49
  return False
50
 
51
  def stop(self):
52
+ """Stop SOCKS5 proxy server"""
53
  self.running = False
54
  if self.server_socket:
55
  try:
56
  self.server_socket.close()
57
  except:
58
  pass
59
+ logging.info("SOCKS5 Proxy Server stopped")
60
 
61
  def _accept_connections(self):
62
+ """Accept new connections"""
63
  while self.running:
64
  try:
65
  client_socket, client_address = self.server_socket.accept()
66
  client_ip, client_port = client_address
67
 
68
+ # Record connection
69
  with self._lock:
70
  self.connections[f"{client_ip}:{client_port}"] = ConnectionInfo(
71
  ip=client_ip,
 
74
  )
75
  self.total_connections += 1
76
 
77
+ # Create thread for handling connection
78
  threading.Thread(
79
  target=self._handle_client,
80
  args=(client_socket, client_ip, client_port),
 
83
 
84
  except socket.error:
85
  if self.running:
86
+ logging.error("Error accepting connection")
87
  break
88
 
89
  def _handle_client(self, client_socket, client_ip, client_port):
90
+ """Handle client connection"""
91
  try:
92
  # SOCKS5 handshake
93
  if not self._handle_socks5_handshake(client_socket):
94
  return
95
 
96
+ # Receive request from client
97
  request = client_socket.recv(1024)
98
  if len(request) < 10:
99
  return
100
 
101
+ # Parse SOCKS5 request
102
  if request[0] != 0x05: # Version 5
103
  return
104
 
 
113
  self._handle_udp_associate(client_socket, client_ip, client_port)
114
 
115
  except Exception as e:
116
+ logging.error(f"Error handling client {client_ip}:{client_port}: {e}")
117
  finally:
118
+ # Close connection
119
  try:
120
  client_socket.close()
121
  except:
122
  pass
123
 
124
+ # Update status
125
  with self._lock:
126
  if f"{client_ip}:{client_port}" in self.connections:
127
  self.connections[f"{client_ip}:{client_port}"].is_active = False
128
 
129
  def _handle_socks5_handshake(self, client_socket):
130
+ """Handle SOCKS5 handshake"""
131
  try:
132
+ # Receive client hello
133
  data = client_socket.recv(1024)
134
  if len(data) < 2:
135
  return False
 
140
  if version != 0x05: # Version 5
141
  return False
142
 
143
+ # Respond with no authentication
144
  response = b'\x05\x00'
145
  client_socket.send(response)
146
  return True
 
150
  return False
151
 
152
  def _handle_connect(self, client_socket, request, client_ip, client_port):
153
+ """Handle SOCKS5 CONNECT command"""
154
  try:
155
  addr_type = request[3]
156
  dest_addr = ""
 
169
  dest_port = struct.unpack('!H', request[20:22])[0]
170
  dest_addr = dest_ip
171
 
172
+ # Connect to target
173
  target_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
174
  target_socket.connect((dest_addr, dest_port))
175
 
176
+ # Send success response
177
  reply = b'\x05\x00\x00\x01' + socket.inet_aton('0.0.0.0') + b'\x00\x00'
178
  client_socket.send(reply)
179
 
180
+ # Start data relay
181
  threading.Thread(
182
  target=self._relay_data,
183
  args=(client_socket, target_socket, client_ip, client_port),
 
187
  logging.info(f"CONNECT: {client_ip}:{client_port} -> {dest_addr}:{dest_port}")
188
 
189
  except Exception as e:
190
+ # Send error response
191
  reply = b'\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00'
192
  try:
193
  client_socket.send(reply)
 
196
  logging.error(f"CONNECT error: {e}")
197
 
198
  def _handle_bind(self, client_socket, client_ip, client_port):
199
+ """Handle SOCKS5 BIND command"""
200
+ # BIND command implementation (for incoming connections)
201
  reply = b'\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00' # Command not supported
202
  try:
203
  client_socket.send(reply)
 
205
  pass
206
 
207
  def _handle_udp_associate(self, client_socket, client_ip, client_port):
208
+ """Handle SOCKS5 UDP ASSOCIATE command"""
209
  # UDP ASSOCIATE implementation
210
  reply = b'\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00'
211
  try:
 
214
  pass
215
 
216
  def _relay_data(self, client_socket, target_socket, client_ip, client_port):
217
+ """Relay data between client and target"""
218
  try:
219
  while True:
220
  try:
 
222
  if not data:
223
  break
224
 
225
+ # Forward to target
226
  target_socket.send(data)
227
 
228
+ # Update statistics
229
  with self._lock:
230
  if f"{client_ip}:{client_port}" in self.connections:
231
  conn = self.connections[f"{client_ip}:{client_port}"]
 
239
  if not data:
240
  break
241
 
242
+ # Forward back to client
243
  client_socket.send(data)
244
 
245
+ # Update statistics
246
  with self._lock:
247
  if f"{client_ip}:{client_port}" in self.connections:
248
  conn = self.connections[f"{client_ip}:{client_port}"]
 
267
  self.port = port
268
 
269
  def start_server(self):
270
+ """Start proxy server"""
271
  return self.proxy_server.start()
272
 
273
  def stop_server(self):
274
+ """Stop proxy server"""
275
  self.proxy_server.stop()
276
 
277
  def is_running(self):
278
+ """Check if server is running"""
279
  return self.proxy_server.running
280
 
281
  def get_server_info(self):
282
+ """Get server information"""
283
  info = {
284
+ "server_status": "Running" if self.proxy_server.running else "Stopped",
285
+ "host": self