Browse Source

undo vnext for vmess

mhsanaei 3 days ago
parent
commit
37c17357fc
5 changed files with 80 additions and 53 deletions
  1. 0 8
      database/model/model.go
  2. 52 16
      sub/subJsonService.go
  3. 7 6
      sub/subService.go
  4. 18 18
      web/assets/js/model/outbound.js
  5. 3 5
      web/html/xray.html

+ 0 - 8
database/model/model.go

@@ -119,11 +119,3 @@ type Client struct {
 	CreatedAt  int64  `json:"created_at,omitempty"`         // Creation timestamp
 	CreatedAt  int64  `json:"created_at,omitempty"`         // Creation timestamp
 	UpdatedAt  int64  `json:"updated_at,omitempty"`         // Last update timestamp
 	UpdatedAt  int64  `json:"updated_at,omitempty"`         // Last update timestamp
 }
 }
-
-// VLESSSettings contains VLESS protocol-specific configuration settings.
-type VLESSSettings struct {
-	Clients    []Client `json:"clients"`    // List of VLESS clients
-	Decryption string   `json:"decryption"` // Decryption method
-	Encryption string   `json:"encryption"` // Encryption method (usually "none" for VLESS)
-	Fallbacks  []any    `json:"fallbacks"`  // Fallback configurations
-}

+ 52 - 16
sub/subJsonService.go

@@ -174,12 +174,12 @@ func (s *SubJsonService) getConfig(inbound *model.Inbound, client model.Client,
 		case "tls":
 		case "tls":
 			if newStream["security"] != "tls" {
 			if newStream["security"] != "tls" {
 				newStream["security"] = "tls"
 				newStream["security"] = "tls"
-				newStream["tslSettings"] = map[string]any{}
+				newStream["tlsSettings"] = map[string]any{}
 			}
 			}
 		case "none":
 		case "none":
 			if newStream["security"] != "none" {
 			if newStream["security"] != "none" {
 				newStream["security"] = "none"
 				newStream["security"] = "none"
-				delete(newStream, "tslSettings")
+				delete(newStream, "tlsSettings")
 			}
 			}
 		}
 		}
 		streamSettings, _ := json.MarshalIndent(newStream, "", "  ")
 		streamSettings, _ := json.MarshalIndent(newStream, "", "  ")
@@ -188,13 +188,9 @@ func (s *SubJsonService) getConfig(inbound *model.Inbound, client model.Client,
 
 
 		switch inbound.Protocol {
 		switch inbound.Protocol {
 		case "vmess":
 		case "vmess":
-			newOutbounds = append(newOutbounds, s.genVnext(inbound, streamSettings, client, ""))
+			newOutbounds = append(newOutbounds, s.genVnext(inbound, streamSettings, client))
 		case "vless":
 		case "vless":
-			var vlessSettings model.VLESSSettings
-			_ = json.Unmarshal([]byte(inbound.Settings), &vlessSettings)
-
-			newOutbounds = append(newOutbounds,
-				s.genVnext(inbound, streamSettings, client, vlessSettings.Encryption))
+			newOutbounds = append(newOutbounds, s.genVless(inbound, streamSettings, client))
 		case "trojan", "shadowsocks":
 		case "trojan", "shadowsocks":
 			newOutbounds = append(newOutbounds, s.genServer(inbound, streamSettings, client))
 			newOutbounds = append(newOutbounds, s.genServer(inbound, streamSettings, client))
 		}
 		}
@@ -293,7 +289,35 @@ func (s *SubJsonService) realityData(rData map[string]any) map[string]any {
 	return rltyData
 	return rltyData
 }
 }
 
 
-func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_util.RawMessage, client model.Client, encryption string) json_util.RawMessage {
+func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_util.RawMessage, client model.Client) json_util.RawMessage {
+	outbound := Outbound{}
+	usersData := make([]UserVnext, 1)
+
+	usersData[0].ID = client.ID
+	usersData[0].Email = client.Email
+	usersData[0].Security = client.Security
+	vnextData := make([]VnextSetting, 1)
+	vnextData[0] = VnextSetting{
+		Address: inbound.Listen,
+		Port:    inbound.Port,
+		Users:   usersData,
+	}
+
+	outbound.Protocol = string(inbound.Protocol)
+	outbound.Tag = "proxy"
+	if s.mux != "" {
+		outbound.Mux = json_util.RawMessage(s.mux)
+	}
+	outbound.StreamSettings = streamSettings
+	outbound.Settings = map[string]any{
+		"vnext": vnextData,
+	}
+
+	result, _ := json.MarshalIndent(outbound, "", "  ")
+	return result
+}
+
+func (s *SubJsonService) genVless(inbound *model.Inbound, streamSettings json_util.RawMessage, client model.Client) json_util.RawMessage {
 	outbound := Outbound{}
 	outbound := Outbound{}
 	outbound.Protocol = string(inbound.Protocol)
 	outbound.Protocol = string(inbound.Protocol)
 	outbound.Tag = "proxy"
 	outbound.Tag = "proxy"
@@ -301,20 +325,22 @@ func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_ut
 		outbound.Mux = json_util.RawMessage(s.mux)
 		outbound.Mux = json_util.RawMessage(s.mux)
 	}
 	}
 	outbound.StreamSettings = streamSettings
 	outbound.StreamSettings = streamSettings
-	// Emit flattened settings inside Settings to match new Xray format
 	settings := make(map[string]any)
 	settings := make(map[string]any)
 	settings["address"] = inbound.Listen
 	settings["address"] = inbound.Listen
 	settings["port"] = inbound.Port
 	settings["port"] = inbound.Port
 	settings["id"] = client.ID
 	settings["id"] = client.ID
-	if inbound.Protocol == model.VLESS {
+	if client.Flow != "" {
 		settings["flow"] = client.Flow
 		settings["flow"] = client.Flow
-		settings["encryption"] = encryption
 	}
 	}
-	if inbound.Protocol == model.VMESS {
-		settings["security"] = client.Security
+
+	// Add encryption for VLESS outbound from inbound settings
+	var inboundSettings map[string]any
+	json.Unmarshal([]byte(inbound.Settings), &inboundSettings)
+	if encryption, ok := inboundSettings["encryption"].(string); ok {
+		settings["encryption"] = encryption
 	}
 	}
-	outbound.Settings = settings
 
 
+	outbound.Settings = settings
 	result, _ := json.MarshalIndent(outbound, "", "  ")
 	result, _ := json.MarshalIndent(outbound, "", "  ")
 	return result
 	return result
 }
 }
@@ -366,7 +392,17 @@ type Outbound struct {
 	Settings       map[string]any       `json:"settings,omitempty"`
 	Settings       map[string]any       `json:"settings,omitempty"`
 }
 }
 
 
-// Legacy vnext-related structs removed for flattened schema
+type VnextSetting struct {
+	Address string      `json:"address"`
+	Port    int         `json:"port"`
+	Users   []UserVnext `json:"users"`
+}
+
+type UserVnext struct {
+	ID       string `json:"id"`
+	Email    string `json:"email,omitempty"`
+	Security string `json:"security,omitempty"`
+}
 
 
 type ServerSetting struct {
 type ServerSetting struct {
 	Password string `json:"password"`
 	Password string `json:"password"`

+ 7 - 6
sub/subService.go

@@ -321,9 +321,6 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
 	if inbound.Protocol != model.VLESS {
 	if inbound.Protocol != model.VLESS {
 		return ""
 		return ""
 	}
 	}
-	var vlessSettings model.VLESSSettings
-	_ = json.Unmarshal([]byte(inbound.Settings), &vlessSettings)
-
 	var stream map[string]any
 	var stream map[string]any
 	json.Unmarshal([]byte(inbound.StreamSettings), &stream)
 	json.Unmarshal([]byte(inbound.StreamSettings), &stream)
 	clients, _ := s.inboundService.GetClients(inbound)
 	clients, _ := s.inboundService.GetClients(inbound)
@@ -338,11 +335,15 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
 	port := inbound.Port
 	port := inbound.Port
 	streamNetwork := stream["network"].(string)
 	streamNetwork := stream["network"].(string)
 	params := make(map[string]string)
 	params := make(map[string]string)
-	if vlessSettings.Encryption != "" {
-		params["encryption"] = vlessSettings.Encryption
-	}
 	params["type"] = streamNetwork
 	params["type"] = streamNetwork
 
 
+	// Add encryption parameter for VLESS from inbound settings
+	var settings map[string]any
+	json.Unmarshal([]byte(inbound.Settings), &settings)
+	if encryption, ok := settings["encryption"].(string); ok {
+		params["encryption"] = encryption
+	}
+
 	switch streamNetwork {
 	switch streamNetwork {
 	case "tcp":
 	case "tcp":
 		tcp, _ := stream["tcpSettings"].(map[string]any)
 		tcp, _ := stream["tcpSettings"].(map[string]any)

+ 18 - 18
web/assets/js/model/outbound.js

@@ -686,14 +686,7 @@ class Outbound extends CommonClass {
             if (this.stream?.sockopt)
             if (this.stream?.sockopt)
                 stream = { sockopt: this.stream.sockopt.toJson() };
                 stream = { sockopt: this.stream.sockopt.toJson() };
         }
         }
-        // For VMess/VLESS, emit settings as a flat object
         let settingsOut = this.settings instanceof CommonClass ? this.settings.toJson() : this.settings;
         let settingsOut = this.settings instanceof CommonClass ? this.settings.toJson() : this.settings;
-        // Remove undefined/null keys
-        if (settingsOut && typeof settingsOut === 'object') {
-            Object.keys(settingsOut).forEach(k => {
-                if (settingsOut[k] === undefined || settingsOut[k] === null) delete settingsOut[k];
-            });
-        }
         return {
         return {
             protocol: this.protocol,
             protocol: this.protocol,
             settings: settingsOut,
             settings: settingsOut,
@@ -1031,21 +1024,28 @@ Outbound.VmessSettings = class extends CommonClass {
     }
     }
 
 
     static fromJson(json = {}) {
     static fromJson(json = {}) {
-        if (ObjectUtil.isEmpty(json.address) || ObjectUtil.isEmpty(json.port)) return new Outbound.VmessSettings();
-        return new Outbound.VmessSettings(
-            json.address,
-            json.port,
-            json.id,
-            json.security,
-        );
+        if (!ObjectUtil.isArrEmpty(json.vnext)) {
+            const v = json.vnext[0] || {};
+            const u = ObjectUtil.isArrEmpty(v.users) ? {} : v.users[0];
+            return new Outbound.VmessSettings(
+                v.address,
+                v.port,
+                u.id,
+                u.security,
+            );
+        }
     }
     }
 
 
     toJson() {
     toJson() {
         return {
         return {
-            address: this.address,
-            port: this.port,
-            id: this.id,
-            security: this.security,
+            vnext: [{
+                address: this.address,
+                port: this.port,
+                users: [{
+                    id: this.id,
+                    security: this.security
+                }]
+            }]
         };
         };
     }
     }
 };
 };

+ 3 - 5
web/html/xray.html

@@ -534,13 +534,11 @@
         serverObj = null;
         serverObj = null;
         switch (o.protocol) {
         switch (o.protocol) {
           case Protocols.VMess:
           case Protocols.VMess:
-          case Protocols.VLESS:
-            if (o.settings && o.settings.address && o.settings.port) {
-              return [o.settings.address + ':' + o.settings.port];
-            }
+            serverObj = o.settings.vnext;
             break;
             break;
+          case Protocols.VLESS:
           case Protocols.HTTP:
           case Protocols.HTTP:
-          case Protocols.Mixed:
+          case Protocols.Socks:
           case Protocols.Shadowsocks:
           case Protocols.Shadowsocks:
           case Protocols.Trojan:
           case Protocols.Trojan:
             serverObj = o.settings.servers;
             serverObj = o.settings.servers;