zhuhai111 commited on
Commit
0174c7a
·
verified ·
1 Parent(s): 46e8836

Upload 2 files

Browse files
Files changed (2) hide show
  1. Dockerfile +32 -0
  2. main.py +122 -0
Dockerfile ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM nkpro/chrome-novnc
2
+
3
+ # 安装 Python3 和 pip
4
+ RUN apk update && \
5
+ apk add --no-cache python3 py3-pip && \
6
+ rm -rf /var/cache/apk/*
7
+
8
+ # 复制 main.py 到容器
9
+ COPY main.py /workspace/main.py
10
+
11
+ # 设置工作目录
12
+ WORKDIR /workspace
13
+
14
+ # 如有 requirements.txt 可取消注释以下两行
15
+ # COPY requirements.txt /workspace/requirements.txt
16
+ # RUN pip3 install -r requirements.txt
17
+
18
+ # 创建启动脚本,在原始启动命令后在后台执行main.py
19
+ RUN echo '#!/bin/sh \n\
20
+ # 启动原始的entrypoint脚本,在后台运行 \n\
21
+ /entrypoint.sh "$@" & \n\
22
+ # 等待VNC和noVNC完全启动 \n\
23
+ sleep 5 \n\
24
+ # 运行main.py \n\
25
+ cd /workspace && python3 main.py & \n\
26
+ # 保持容器运行 \n\
27
+ wait' > /start.sh && \
28
+ chmod +x /start.sh
29
+
30
+ # 设置新的启动命令
31
+ ENTRYPOINT ["/start.sh"]
32
+ CMD []
main.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # main.py
2
+ import asyncio
3
+ from fastapi import FastAPI, WebSocket
4
+ import uvicorn
5
+
6
+ # 创建 FastAPI 应用实例
7
+ app = FastAPI()
8
+
9
+ @app.websocket("/")
10
+ async def tunnel(websocket: WebSocket):
11
+ """
12
+ WebSocket 隧道入口:
13
+ 1. 接受客户端 WebSocket 连接;
14
+ 2. 等待客户端发送 CONNECT 请求,解析出目标主机及端口;
15
+ 3. 尝试与目标主机建立 TCP 连接;
16
+ 4. 返回 HTTP 200 成功建立隧道;
17
+ 5. 启动双向数据转发(TCP <--> WebSocket)。
18
+ """
19
+ await websocket.accept()
20
+ try:
21
+ # ---------------------------
22
+ # 1. 等待客户端发来的 CONNECT 请求
23
+ # ---------------------------
24
+ # CONNECT 请求格式示例:
25
+ # CONNECT destHost:destPort HTTP/1.1\r\nHost: destHost:destPort\r\n\r\n
26
+ request_text = await websocket.receive_text()
27
+ lines = request_text.splitlines()
28
+ if not lines:
29
+ await websocket.send_text("HTTP/1.1 400 Bad Request\r\n\r\n")
30
+ await websocket.close()
31
+ return
32
+
33
+ # 解析第一行
34
+ first_line = lines[0].strip()
35
+ parts = first_line.split()
36
+ if len(parts) < 3 or parts[0].upper() != "CONNECT":
37
+ await websocket.send_text("HTTP/1.1 400 Bad Request\r\n\r\n")
38
+ await websocket.close()
39
+ return
40
+
41
+ # 从第二个字段中获取目标主机及端口,如 destHost:destPort
42
+ dest = parts[1]
43
+ if ":" not in dest:
44
+ await websocket.send_text("HTTP/1.1 400 Bad Request\r\n\r\n")
45
+ await websocket.close()
46
+ return
47
+
48
+ dest_parts = dest.split(":", 1)
49
+ dest_host = dest_parts[0]
50
+ try:
51
+ dest_port = int(dest_parts[1])
52
+ except Exception:
53
+ await websocket.send_text("HTTP/1.1 400 Bad Request\r\n\r\n")
54
+ await websocket.close()
55
+ return
56
+
57
+ # ---------------------------
58
+ # 2. 建立到目标主机的 TCP 连接
59
+ # ---------------------------
60
+ try:
61
+ reader, writer = await asyncio.open_connection(dest_host, dest_port)
62
+ except Exception as e:
63
+ err_msg = f"HTTP/1.1 502 Bad Gateway\r\n\r\n无法连接 {dest_host}:{dest_port},错误:{e}"
64
+ await websocket.send_text(err_msg)
65
+ await websocket.close()
66
+ return
67
+
68
+ # ---------------------------
69
+ # 3. 向客户端返回 200 成功响应
70
+ # ---------------------------
71
+ await websocket.send_text("HTTP/1.1 200 Connection Established\r\n\r\n")
72
+
73
+ # ---------------------------
74
+ # 4. 双向数据转发
75
+ # ---------------------------
76
+ async def tcp_to_ws():
77
+ """
78
+ 从 TCP 连接中读取数据,通过 WebSocket 以二进制方式发送给客户端
79
+ """
80
+ try:
81
+ while True:
82
+ data = await reader.read(1024)
83
+ if not data:
84
+ break
85
+ await websocket.send_bytes(data)
86
+ except Exception as e:
87
+ # 读取异常或对方关闭连接时退出
88
+ print("tcp_to_ws 异常:", e)
89
+
90
+ async def ws_to_tcp():
91
+ """
92
+ 从客户端通过 WebSocket 发送的数据写入 TCP 连接
93
+ """
94
+ try:
95
+ while True:
96
+ message = await websocket.receive()
97
+ # 接收到的数据可能是文本或二进制,这里尽量以二进制方式处理
98
+ if "bytes" in message:
99
+ data = message["bytes"]
100
+ elif "text" in message:
101
+ # 若收到文本数据,则转换为 bytes(可能只在握手阶段出现)
102
+ data = message["text"].encode("utf-8")
103
+ else:
104
+ break
105
+ writer.write(data)
106
+ await writer.drain()
107
+ except Exception as e:
108
+ print("ws_to_tcp 异常:", e)
109
+
110
+ # 并发执行数据转发任务,任一方向关闭则结束隧道
111
+ await asyncio.gather(tcp_to_ws(), ws_to_tcp())
112
+ except Exception as e:
113
+ print("WebSocket 隧道处理异常:", e)
114
+ finally:
115
+ # 关闭连接
116
+ await websocket.close()
117
+
118
+ # ---------------------------
119
+ # 启动服务器:监听 0.0.0.0:7860
120
+ # ---------------------------
121
+ if __name__ == "__main__":
122
+ uvicorn.run("main:app", host="0.0.0.0", port=7860, reload=False)