mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-02 03:05:02 +03:00
5cf2ab4f69
max_idle_time and authentication_timeout are second counts multiplied into a Duration with no bound, so a stored value past the int64 range wrapped negative and the QUIC listener panicked on the first ClientHello, taking the panel down at every start until the row was fixed. Saves now refuse more than a day, and a stored row past it fails its own listener start instead.
122 lines
3.5 KiB
Go
122 lines
3.5 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
|
"github.com/mhsanaei/3x-ui/v3/internal/tuic"
|
|
)
|
|
|
|
func normalizeTuicSettings(inbound *model.Inbound) error {
|
|
if inbound == nil || inbound.Protocol != model.TUIC || inbound.Settings == "" {
|
|
return nil
|
|
}
|
|
var root map[string]json.RawMessage
|
|
if err := json.Unmarshal([]byte(inbound.Settings), &root); err != nil {
|
|
return fmt.Errorf("invalid TUIC settings: %w", err)
|
|
}
|
|
if err := normalizeTuicSettingsBlock(root); err != nil {
|
|
return err
|
|
}
|
|
if rawServer, ok := root["server"]; ok && len(rawServer) > 0 {
|
|
var server map[string]json.RawMessage
|
|
if err := json.Unmarshal(rawServer, &server); err != nil {
|
|
return fmt.Errorf("invalid TUIC server settings: %w", err)
|
|
}
|
|
if err := normalizeTuicSettingsBlock(server); err != nil {
|
|
return err
|
|
}
|
|
encoded, err := json.Marshal(server)
|
|
if err != nil {
|
|
return fmt.Errorf("encode TUIC server settings: %w", err)
|
|
}
|
|
root["server"] = encoded
|
|
}
|
|
encoded, err := json.Marshal(root)
|
|
if err != nil {
|
|
return fmt.Errorf("encode TUIC settings: %w", err)
|
|
}
|
|
inbound.Settings = string(encoded)
|
|
return nil
|
|
}
|
|
|
|
func normalizeTuicSettingsBlock(settings map[string]json.RawMessage) error {
|
|
if raw, ok := settings["congestion_control"]; ok {
|
|
var value string
|
|
if err := json.Unmarshal(raw, &value); err != nil {
|
|
return fmt.Errorf("TUIC congestion_control must be a string: %w", err)
|
|
}
|
|
normalized, err := tuic.NormalizeCongestionControl(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
encoded, _ := json.Marshal(normalized)
|
|
settings["congestion_control"] = encoded
|
|
}
|
|
if raw, ok := settings["log_level"]; ok {
|
|
var value string
|
|
if err := json.Unmarshal(raw, &value); err != nil {
|
|
return fmt.Errorf("TUIC log_level must be a string: %w", err)
|
|
}
|
|
value = strings.ToLower(strings.TrimSpace(value))
|
|
if value == "warning" {
|
|
value = "warn"
|
|
}
|
|
if value == "" {
|
|
value = "info"
|
|
}
|
|
switch value {
|
|
case "debug", "info", "warn", "error":
|
|
default:
|
|
return fmt.Errorf("TUIC log_level %q is unsupported", value)
|
|
}
|
|
encoded, _ := json.Marshal(value)
|
|
settings["log_level"] = encoded
|
|
}
|
|
if raw, ok := settings["udp_relay_mode"]; ok {
|
|
var value string
|
|
if err := json.Unmarshal(raw, &value); err != nil {
|
|
return fmt.Errorf("TUIC udp_relay_mode must be a string: %w", err)
|
|
}
|
|
value = strings.ToLower(strings.TrimSpace(value))
|
|
if value == "" {
|
|
value = "native"
|
|
}
|
|
if value != "native" && value != "quic" {
|
|
return fmt.Errorf("TUIC udp_relay_mode %q is unsupported", value)
|
|
}
|
|
encoded, _ := json.Marshal(value)
|
|
settings["udp_relay_mode"] = encoded
|
|
}
|
|
for _, key := range []string{"max_idle_time", "authentication_timeout"} {
|
|
raw, ok := settings[key]
|
|
if !ok {
|
|
continue
|
|
}
|
|
var value int64
|
|
if err := json.Unmarshal(raw, &value); err != nil {
|
|
return fmt.Errorf("TUIC %s must be an integer: %w", key, err)
|
|
}
|
|
if value > tuic.MaxTimeoutSeconds {
|
|
return fmt.Errorf("TUIC %s must not exceed %d seconds", key, tuic.MaxTimeoutSeconds)
|
|
}
|
|
}
|
|
if raw, ok := settings["max_udp_relay_packet_size"]; ok {
|
|
var value int
|
|
if err := json.Unmarshal(raw, &value); err != nil {
|
|
return fmt.Errorf("TUIC max_udp_relay_packet_size must be an integer: %w", err)
|
|
}
|
|
if value > 65507 {
|
|
return fmt.Errorf("TUIC max_udp_relay_packet_size must not exceed %d", 65245)
|
|
}
|
|
if value > 65245 {
|
|
value = 65245
|
|
}
|
|
encoded, _ := json.Marshal(value)
|
|
settings["max_udp_relay_packet_size"] = encoded
|
|
}
|
|
return nil
|
|
}
|