| 
					
				 | 
			
			
				@@ -1,24 +1,80 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package option 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import "github.com/sagernet/sing/common/json/badoption" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"crypto/tls" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"encoding/json" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"strings" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	E "github.com/sagernet/sing/common/exceptions" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"github.com/sagernet/sing/common/json/badoption" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type InboundTLSOptions struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Enabled         bool                       `json:"enabled,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	ServerName      string                     `json:"server_name,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Insecure        bool                       `json:"insecure,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	ALPN            badoption.Listable[string] `json:"alpn,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	MinVersion      string                     `json:"min_version,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	MaxVersion      string                     `json:"max_version,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	CipherSuites    badoption.Listable[string] `json:"cipher_suites,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Certificate     badoption.Listable[string] `json:"certificate,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	CertificatePath string                     `json:"certificate_path,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Key             badoption.Listable[string] `json:"key,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	KeyPath         string                     `json:"key_path,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	KernelTx        bool                       `json:"kernel_tx,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	KernelRx        bool                       `json:"kernel_rx,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	ACME            *InboundACMEOptions        `json:"acme,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	ECH             *InboundECHOptions         `json:"ech,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Reality         *InboundRealityOptions     `json:"reality,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Enabled                          bool                                `json:"enabled,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ServerName                       string                              `json:"server_name,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Insecure                         bool                                `json:"insecure,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ALPN                             badoption.Listable[string]          `json:"alpn,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	MinVersion                       string                              `json:"min_version,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	MaxVersion                       string                              `json:"max_version,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	CipherSuites                     badoption.Listable[string]          `json:"cipher_suites,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	CurvePreferences                 badoption.Listable[CurvePreference] `json:"curve_preferences,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Certificate                      badoption.Listable[string]          `json:"certificate,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	CertificatePath                  string                              `json:"certificate_path,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ClientAuthentication             ClientAuthType                      `json:"client_authentication,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ClientCertificate                badoption.Listable[string]          `json:"client_certificate,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ClientCertificatePath            badoption.Listable[string]          `json:"client_certificate_path,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ClientCertificatePublicKeySHA256 badoption.Listable[[]byte]          `json:"client_certificate_public_key_sha256,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Key                              badoption.Listable[string]          `json:"key,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	KeyPath                          string                              `json:"key_path,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	KernelTx                         bool                                `json:"kernel_tx,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	KernelRx                         bool                                `json:"kernel_rx,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ACME                             *InboundACMEOptions                 `json:"acme,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ECH                              *InboundECHOptions                  `json:"ech,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Reality                          *InboundRealityOptions              `json:"reality,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+type ClientAuthType tls.ClientAuthType 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (t ClientAuthType) MarshalJSON() ([]byte, error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	var stringValue string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	switch t { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case ClientAuthType(tls.NoClientCert): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stringValue = "no" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case ClientAuthType(tls.RequestClientCert): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stringValue = "request" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case ClientAuthType(tls.RequireAnyClientCert): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stringValue = "require-any" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case ClientAuthType(tls.VerifyClientCertIfGiven): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stringValue = "verify-if-given" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case ClientAuthType(tls.RequireAndVerifyClientCert): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stringValue = "require-and-verify" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return nil, E.New("unknown client authentication type: ", int(t)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return json.Marshal(stringValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (t *ClientAuthType) UnmarshalJSON(data []byte) error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	var stringValue string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	err := json.Unmarshal(data, &stringValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	switch stringValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case "no": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*t = ClientAuthType(tls.NoClientCert) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case "request": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*t = ClientAuthType(tls.RequestClientCert) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case "require-any": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*t = ClientAuthType(tls.RequireAnyClientCert) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case "verify-if-given": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*t = ClientAuthType(tls.VerifyClientCertIfGiven) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case "require-and-verify": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*t = ClientAuthType(tls.RequireAndVerifyClientCert) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return E.New("unknown client authentication type: ", stringValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return nil 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type InboundTLSOptionsContainer struct { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -39,24 +95,26 @@ func (o *InboundTLSOptionsContainer) ReplaceInboundTLSOptions(options *InboundTL 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type OutboundTLSOptions struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Enabled               bool                       `json:"enabled,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	DisableSNI            bool                       `json:"disable_sni,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	ServerName            string                     `json:"server_name,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Insecure              bool                       `json:"insecure,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	ALPN                  badoption.Listable[string] `json:"alpn,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	MinVersion            string                     `json:"min_version,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	MaxVersion            string                     `json:"max_version,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	CipherSuites          badoption.Listable[string] `json:"cipher_suites,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Certificate           badoption.Listable[string] `json:"certificate,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	CertificatePath       string                     `json:"certificate_path,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Fragment              bool                       `json:"fragment,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	FragmentFallbackDelay badoption.Duration         `json:"fragment_fallback_delay,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	RecordFragment        bool                       `json:"record_fragment,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	KernelTx              bool                       `json:"kernel_tx,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	KernelRx              bool                       `json:"kernel_rx,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	ECH                   *OutboundECHOptions        `json:"ech,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	UTLS                  *OutboundUTLSOptions       `json:"utls,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Reality               *OutboundRealityOptions    `json:"reality,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Enabled                    bool                                `json:"enabled,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	DisableSNI                 bool                                `json:"disable_sni,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ServerName                 string                              `json:"server_name,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Insecure                   bool                                `json:"insecure,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ALPN                       badoption.Listable[string]          `json:"alpn,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	MinVersion                 string                              `json:"min_version,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	MaxVersion                 string                              `json:"max_version,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	CipherSuites               badoption.Listable[string]          `json:"cipher_suites,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	CurvePreferences           badoption.Listable[CurvePreference] `json:"curve_preferences,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Certificate                badoption.Listable[string]          `json:"certificate,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	CertificatePath            string                              `json:"certificate_path,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	CertificatePublicKeySHA256 badoption.Listable[[]byte]          `json:"certificate_public_key_sha256,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Fragment                   bool                                `json:"fragment,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	FragmentFallbackDelay      badoption.Duration                  `json:"fragment_fallback_delay,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	RecordFragment             bool                                `json:"record_fragment,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	KernelTx                   bool                                `json:"kernel_tx,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	KernelRx                   bool                                `json:"kernel_rx,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ECH                        *OutboundECHOptions                 `json:"ech,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	UTLS                       *OutboundUTLSOptions                `json:"utls,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Reality                    *OutboundRealityOptions             `json:"reality,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type OutboundTLSOptionsContainer struct { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -76,6 +134,58 @@ func (o *OutboundTLSOptionsContainer) ReplaceOutboundTLSOptions(options *Outboun 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	o.TLS = options 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+type CurvePreference tls.CurveID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	CurveP256      = 23 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	CurveP384      = 24 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	CurveP521      = 25 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	X25519         = 29 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	X25519MLKEM768 = 4588 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (c CurvePreference) MarshalJSON() ([]byte, error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	var stringValue string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	switch c { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case CurvePreference(CurveP256): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stringValue = "P256" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case CurvePreference(CurveP384): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stringValue = "P384" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case CurvePreference(CurveP521): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stringValue = "P521" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case CurvePreference(X25519): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stringValue = "X25519" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case CurvePreference(X25519MLKEM768): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stringValue = "X25519MLKEM768" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return nil, E.New("unknown curve id: ", int(c)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return json.Marshal(stringValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (c *CurvePreference) UnmarshalJSON(data []byte) error { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	var stringValue string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	err := json.Unmarshal(data, &stringValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	switch strings.ToUpper(stringValue) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case "P256": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*c = CurvePreference(CurveP256) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case "P384": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*c = CurvePreference(CurveP384) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case "P521": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*c = CurvePreference(CurveP521) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case "X25519": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*c = CurvePreference(X25519) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	case "X25519MLKEM768": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*c = CurvePreference(X25519MLKEM768) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return E.New("unknown curve name: ", stringValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return nil 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type InboundRealityOptions struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Enabled           bool                           `json:"enabled,omitempty"` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Handshake         InboundRealityHandshakeOptions `json:"handshake,omitempty"` 
			 |