File size: 3,604 Bytes
3c8ff75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// server.js
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const { handleIncomingPacket, setClientIdentifier, cleanupClientConnections } = require('./services/packetHandler');
const { authenticateClient, generateSessionKey } = require('./services/authService');

// 创建 Express 应用
const app = express();
const port = process.env.PORT || 7860;

// 创建 HTTP 服务器
const server = http.createServer(app);

// 创建 WebSocket 服务器
const wss = new WebSocket.Server({ server });

// 存储客户端连接
const clients = new Set();

// WebSocket 连接处理
wss.on('connection', (ws, req) => {
  console.log('新的 WebSocket 连接');

  // 将客户端添加到集合中
  clients.add(ws);

  // 连接错误处理
  ws.on('error', (error) => {
    console.error('WebSocket 错误:', error);
  });

  // 处理认证消息
  ws.once('message', (data) => {
    try {
      const authMessage = JSON.parse(data);

      // 检查是否为认证消息
      if (authMessage.type === 'auth') {
        const { clientId, clientSecret } = authMessage.payload;

        // 验证客户端
        if (authenticateClient(clientId, clientSecret)) {
          // 生成会话密钥
          const sessionKey = generateSessionKey(clientId);

          // 设置客户端标识
          setClientIdentifier(ws, clientId);

          // 发送认证成功消息
          ws.send(JSON.stringify({
            type: 'auth_success',
            message: 'Authentication successful',
            sessionKey: sessionKey
          }));

          console.log(`客户端 ${clientId} 认证成功`);
        } else {
          // 发送认证失败消息
          ws.send(JSON.stringify({
            type: 'auth_failed',
            message: 'Authentication failed'
          }));

          console.log(`客户端 ${clientId} 认证失败`);
          ws.close();
        }
      } else {
        // 如果不是认证消息,发送错误并关闭连接
        ws.send(JSON.stringify({
          type: 'error',
          message: 'Authentication required'
        }));

        console.log('未提供认证信息,关闭连接');
        ws.close();
      }
    } catch (error) {
      console.error('处理认证消息时出错:', error.message);
      ws.close();
    }
  });

  // 接收消息处理
  ws.on('message', async (data) => {
    // 尝试解析为 JSON
    try {
      const message = JSON.parse(data);
      if (message.type === 'auth') {
        return;
      }

      if (['connect', 'data', 'close'].includes(message.type)) {
        const { handleControlMessage } = require('./services/packetHandler');
        await handleControlMessage(message, ws);
        return;
      }
    } catch (e) {
      // 如果不是 JSON 消息,则继续处理为数据包
    }

    // console.log('接收到消息,长度:', data.length);

    // 处理接收到的数据包
    await handleIncomingPacket(data, ws);
  });

  // 连接关闭处理
  ws.on('close', () => {
    console.log('WebSocket 连接已关闭');
    // 清理客户端连接
    cleanupClientConnections(ws);
    clients.delete(ws);
  });

  // 发送欢迎消息
  ws.send(JSON.stringify({ type: 'welcome', message: 'Connected to tun2websocket server. Please authenticate.' }));
});

// 健康检查端点
app.get('/health', (req, res) => {
  res.status(200).json({ status: 'ok', timestamp: new Date().toISOString() });
});

// 启动服务器
server.listen(port, () => {
  console.log(`服务器运行在端口 ${port}`);
});

module.exports = { app, server, wss };