去除代理头支持, 增加节点面板通信加密 增加导出sql

This commit is contained in:
qaq
2025-07-11 16:24:12 +08:00
parent b690e68951
commit e313a1953c
21 changed files with 960 additions and 143 deletions
+124
View File
@@ -0,0 +1,124 @@
package crypto
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"fmt"
)
// AESCrypto AES 加密器结构
type AESCrypto struct {
key []byte
}
// NewAESCrypto 创建新的 AES 加密器
// secret: 用于生成密钥的密码字符串
func NewAESCrypto(secret string) (*AESCrypto, error) {
if secret == "" {
return nil, fmt.Errorf("密钥不能为空")
}
// 使用 SHA256 将密码转换为 32 字节密钥
hash := sha256.Sum256([]byte(secret))
return &AESCrypto{
key: hash[:],
}, nil
}
// Encrypt 加密数据
// data: 要加密的原始数据
// 返回: base64编码的加密数据
func (a *AESCrypto) Encrypt(data []byte) (string, error) {
if len(data) == 0 {
return "", fmt.Errorf("待加密数据不能为空")
}
// 创建 AES cipher
block, err := aes.NewCipher(a.key)
if err != nil {
return "", fmt.Errorf("创建 AES cipher 失败: %v", err)
}
// 使用 GCM 模式
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", fmt.Errorf("创建 GCM 失败: %v", err)
}
// 生成随机 nonce
nonce := make([]byte, gcm.NonceSize())
if _, err := rand.Read(nonce); err != nil {
return "", fmt.Errorf("生成 nonce 失败: %v", err)
}
// 加密数据
ciphertext := gcm.Seal(nil, nonce, data, nil)
// 组合 nonce + ciphertext
encrypted := append(nonce, ciphertext...)
// 返回 base64 编码结果
return base64.StdEncoding.EncodeToString(encrypted), nil
}
// Decrypt 解密数据
// encryptedData: base64编码的加密数据
// 返回: 解密后的原始数据
func (a *AESCrypto) Decrypt(encryptedData string) ([]byte, error) {
if encryptedData == "" {
return nil, fmt.Errorf("加密数据不能为空")
}
// base64 解码
encrypted, err := base64.StdEncoding.DecodeString(encryptedData)
if err != nil {
return nil, fmt.Errorf("base64 解码失败: %v", err)
}
// 创建 AES cipher
block, err := aes.NewCipher(a.key)
if err != nil {
return nil, fmt.Errorf("创建 AES cipher 失败: %v", err)
}
// 使用 GCM 模式
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, fmt.Errorf("创建 GCM 失败: %v", err)
}
nonceSize := gcm.NonceSize()
if len(encrypted) < nonceSize {
return nil, fmt.Errorf("加密数据长度不足")
}
// 分离 nonce 和 ciphertext
nonce := encrypted[:nonceSize]
ciphertext := encrypted[nonceSize:]
// 解密数据
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return nil, fmt.Errorf("解密失败: %v", err)
}
return plaintext, nil
}
// EncryptString 加密字符串并返回加密后的字符串
func (a *AESCrypto) EncryptString(data string) (string, error) {
return a.Encrypt([]byte(data))
}
// DecryptString 解密字符串并返回解密后的字符串
func (a *AESCrypto) DecryptString(encryptedData string) (string, error) {
plaintext, err := a.Decrypt(encryptedData)
if err != nil {
return "", err
}
return string(plaintext), nil
}
+65 -3
View File
@@ -11,11 +11,13 @@ import (
"github.com/go-gost/core/observer/stats"
"github.com/go-gost/x/config"
"github.com/go-gost/x/internal/util/crypto"
"github.com/go-gost/x/registry"
)
var httpReportURL string
var configReportURL string
var httpAESCrypto *crypto.AESCrypto // 新增:HTTP上报加密器
// TrafficReportItem 流量报告项(压缩格式)
type TrafficReportItem struct {
@@ -28,6 +30,16 @@ type TrafficReportItem struct {
func SetHTTPReportURL(addr string, secret string) {
httpReportURL = "http://" + addr + "/flow/upload?secret=" + secret
configReportURL = "http://" + addr + "/flow/config?secret=" + secret
// 创建 AES 加密器
var err error
httpAESCrypto, err = crypto.NewAESCrypto(secret)
if err != nil {
fmt.Printf("❌ 创建 HTTP AES 加密器失败: %v\n", err)
httpAESCrypto = nil
} else {
fmt.Printf("🔐 HTTP AES 加密器创建成功\n")
}
}
// sendTrafficReport 发送流量报告到HTTP接口
@@ -37,7 +49,32 @@ func sendTrafficReport(ctx context.Context, reportItems []TrafficReportItem) (bo
return false, fmt.Errorf("序列化报告数据失败: %v", err)
}
req, err := http.NewRequestWithContext(ctx, "POST", httpReportURL, bytes.NewBuffer(jsonData))
var requestBody []byte
// 如果有加密器,则加密数据
if httpAESCrypto != nil {
encryptedData, err := httpAESCrypto.Encrypt(jsonData)
if err != nil {
fmt.Printf("⚠️ 加密流量报告失败,发送原始数据: %v\n", err)
requestBody = jsonData
} else {
// 创建加密消息包装器
encryptedMessage := map[string]interface{}{
"encrypted": true,
"data": encryptedData,
"timestamp": time.Now().Unix(),
}
requestBody, err = json.Marshal(encryptedMessage)
if err != nil {
fmt.Printf("⚠️ 序列化加密流量报告失败,发送原始数据: %v\n", err)
requestBody = jsonData
}
}
} else {
requestBody = jsonData
}
req, err := http.NewRequestWithContext(ctx, "POST", httpReportURL, bytes.NewBuffer(requestBody))
if err != nil {
return false, fmt.Errorf("创建HTTP请求失败: %v", err)
}
@@ -88,13 +125,38 @@ func sendConfigReport(ctx context.Context) (bool, error) {
return false, fmt.Errorf("获取配置数据失败: %v", err)
}
req, err := http.NewRequestWithContext(ctx, "POST", configReportURL, bytes.NewBuffer(configData))
var requestBody []byte
// 如果有加密器,则加密数据
if httpAESCrypto != nil {
encryptedData, err := httpAESCrypto.Encrypt(configData)
if err != nil {
fmt.Printf("⚠️ 加密配置报告失败,发送原始数据: %v\n", err)
requestBody = configData
} else {
// 创建加密消息包装器
encryptedMessage := map[string]interface{}{
"encrypted": true,
"data": encryptedData,
"timestamp": time.Now().Unix(),
}
requestBody, err = json.Marshal(encryptedMessage)
if err != nil {
fmt.Printf("⚠️ 序列化加密配置报告失败,发送原始数据: %v\n", err)
requestBody = configData
}
}
} else {
requestBody = configData
}
req, err := http.NewRequestWithContext(ctx, "POST", configReportURL, bytes.NewBuffer(requestBody))
if err != nil {
return false, fmt.Errorf("创建HTTP请求失败: %v", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "GOST-Config-Reporter/1.0")
req.Header.Set("User-Agent", "Config-Reporter/1.0")
client := &http.Client{
Timeout: 10 * time.Second, // 配置上报可以稍长一些
+103 -16
View File
@@ -16,6 +16,7 @@ import (
"time"
"github.com/go-gost/x/config"
"github.com/go-gost/x/internal/util/crypto"
"github.com/gorilla/websocket"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/host"
@@ -90,13 +91,24 @@ type WebSocketReporter struct {
ctx context.Context
cancel context.CancelFunc
connected bool
connecting bool // 新增:正在连接状态
connMutex sync.Mutex // 新增:连接状态锁
connecting bool // 新增:正在连接状态
connMutex sync.Mutex // 新增:连接状态锁
aesCrypto *crypto.AESCrypto // 新增:AES加密器
}
// NewWebSocketReporter 创建一个新的WebSocket报告器
func NewWebSocketReporter(serverURL string) *WebSocketReporter {
func NewWebSocketReporter(serverURL string, secret string) *WebSocketReporter {
ctx, cancel := context.WithCancel(context.Background())
// 创建 AES 加密器
aesCrypto, err := crypto.NewAESCrypto(secret)
if err != nil {
fmt.Printf("❌ 创建 AES 加密器失败: %v\n", err)
aesCrypto = nil
} else {
fmt.Printf("🔐 AES 加密器创建成功\n")
}
return &WebSocketReporter{
url: serverURL,
reconnectTime: 5 * time.Second, // 重连间隔
@@ -106,6 +118,7 @@ func NewWebSocketReporter(serverURL string) *WebSocketReporter {
cancel: cancel,
connected: false,
connecting: false,
aesCrypto: aesCrypto,
}
}
@@ -134,7 +147,7 @@ func (w *WebSocketReporter) run() {
w.connMutex.Lock()
needConnect := !w.connected && !w.connecting
w.connMutex.Unlock()
if needConnect {
if err := w.connect(); err != nil {
fmt.Printf("❌ WebSocket连接失败: %v,%v后重试\n", err, w.reconnectTime)
@@ -167,12 +180,12 @@ func (w *WebSocketReporter) run() {
func (w *WebSocketReporter) connect() error {
w.connMutex.Lock()
defer w.connMutex.Unlock()
// 如果已经在连接中或已连接,直接返回
if w.connecting || w.connected {
return nil
}
// 设置连接中状态
w.connecting = true
defer func() {
@@ -242,7 +255,7 @@ func (w *WebSocketReporter) handleConnection() {
w.connMutex.Lock()
isConnected := w.connected
w.connMutex.Unlock()
if !isConnected {
return
}
@@ -276,7 +289,7 @@ func (w *WebSocketReporter) collectSystemInfo() SystemInfo {
func (w *WebSocketReporter) sendSystemInfo(sysInfo SystemInfo) error {
w.connMutex.Lock()
defer w.connMutex.Unlock()
if w.conn == nil || !w.connected {
return fmt.Errorf("连接未建立")
}
@@ -287,10 +300,35 @@ func (w *WebSocketReporter) sendSystemInfo(sysInfo SystemInfo) error {
return fmt.Errorf("序列化系统信息失败: %v", err)
}
var messageData []byte
// 如果有加密器,则加密数据
if w.aesCrypto != nil {
encryptedData, err := w.aesCrypto.Encrypt(jsonData)
if err != nil {
fmt.Printf("⚠️ 加密失败,发送原始数据: %v\n", err)
messageData = jsonData
} else {
// 创建加密消息包装器
encryptedMessage := map[string]interface{}{
"encrypted": true,
"data": encryptedData,
"timestamp": time.Now().Unix(),
}
messageData, err = json.Marshal(encryptedMessage)
if err != nil {
fmt.Printf("⚠️ 序列化加密消息失败,发送原始数据: %v\n", err)
messageData = jsonData
}
}
} else {
messageData = jsonData
}
// 设置写入超时
w.conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
if err := w.conn.WriteMessage(websocket.TextMessage, jsonData); err != nil {
if err := w.conn.WriteMessage(websocket.TextMessage, messageData); err != nil {
w.connected = false // 标记连接已断开
return fmt.Errorf("写入消息失败: %v", err)
}
@@ -309,7 +347,7 @@ func (w *WebSocketReporter) receiveMessages() {
conn := w.conn
connected := w.connected
w.connMutex.Unlock()
if conn == nil || !connected {
return
}
@@ -338,6 +376,30 @@ func (w *WebSocketReporter) receiveMessages() {
func (w *WebSocketReporter) handleReceivedMessage(messageType int, message []byte) {
switch messageType {
case websocket.TextMessage:
// 先检查是否是加密消息
var encryptedWrapper struct {
Encrypted bool `json:"encrypted"`
Data string `json:"data"`
Timestamp int64 `json:"timestamp"`
}
// 尝试解析为加密消息格式
if err := json.Unmarshal(message, &encryptedWrapper); err == nil && encryptedWrapper.Encrypted {
if w.aesCrypto != nil {
// 解密数据
decryptedData, err := w.aesCrypto.Decrypt(encryptedWrapper.Data)
if err != nil {
fmt.Printf("❌ 解密失败: %v\n", err)
w.sendErrorResponse("DecryptError", fmt.Sprintf("解密失败: %v", err))
return
}
message = decryptedData
} else {
fmt.Printf("❌ 收到加密消息但没有加密器\n")
w.sendErrorResponse("NoDecryptor", "没有可用的解密器")
return
}
}
// 先尝试解析是否是压缩消息
var compressedMsg struct {
Type string `json:"type"`
@@ -744,7 +806,7 @@ func (w *WebSocketReporter) handleCall(data interface{}) error {
func (w *WebSocketReporter) sendResponse(response CommandResponse) {
w.connMutex.Lock()
defer w.connMutex.Unlock()
if w.conn == nil || !w.connected {
fmt.Printf("❌ 无法发送响应:连接未建立\n")
return
@@ -756,19 +818,44 @@ func (w *WebSocketReporter) sendResponse(response CommandResponse) {
return
}
var messageData []byte
// 如果有加密器,则加密数据
if w.aesCrypto != nil {
encryptedData, err := w.aesCrypto.Encrypt(jsonData)
if err != nil {
fmt.Printf("⚠️ 加密响应失败,发送原始数据: %v\n", err)
messageData = jsonData
} else {
// 创建加密消息包装器
encryptedMessage := map[string]interface{}{
"encrypted": true,
"data": encryptedData,
"timestamp": time.Now().Unix(),
}
messageData, err = json.Marshal(encryptedMessage)
if err != nil {
fmt.Printf("⚠️ 序列化加密响应失败,发送原始数据: %v\n", err)
messageData = jsonData
}
}
} else {
messageData = jsonData
}
// 检查消息大小,如果超过10MB则记录警告
if len(jsonData) > 10*1024*1024 {
fmt.Printf("⚠️ 响应消息过大 (%.2f MB),可能会被拒绝\n", float64(len(jsonData))/(1024*1024))
if len(messageData) > 10*1024*1024 {
fmt.Printf("⚠️ 响应消息过大 (%.2f MB),可能会被拒绝\n", float64(len(messageData))/(1024*1024))
}
// 设置较长的写入超时,以应对大消息
timeout := 5 * time.Second
if len(jsonData) > 1024*1024 {
if len(messageData) > 1024*1024 {
timeout = 30 * time.Second
}
w.conn.SetWriteDeadline(time.Now().Add(timeout))
if err := w.conn.WriteMessage(websocket.TextMessage, jsonData); err != nil {
if err := w.conn.WriteMessage(websocket.TextMessage, messageData); err != nil {
fmt.Printf("❌ 发送响应失败: %v\n", err)
w.connected = false
}
@@ -852,7 +939,7 @@ func StartWebSocketReporterWithConfig(Addr string, Secret string, Version string
fmt.Printf("🔗 WebSocket连接URL: %s\n", fullURL)
reporter := NewWebSocketReporter(fullURL)
reporter := NewWebSocketReporter(fullURL, Secret) // Pass Secret here
reporter.Start()
return reporter
}