Преглед изворни кода

Add TLS self sign generate command

世界 пре 2 година
родитељ
комит
97286eea1e

+ 1 - 48
cmd/sing-box/cmd_generate.go

@@ -11,7 +11,6 @@ import (
 
 	"github.com/gofrs/uuid/v5"
 	"github.com/spf13/cobra"
-	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
 
 var commandGenerate = &cobra.Command{
@@ -22,8 +21,7 @@ var commandGenerate = &cobra.Command{
 func init() {
 	commandGenerate.AddCommand(commandGenerateUUID)
 	commandGenerate.AddCommand(commandGenerateRandom)
-	commandGenerate.AddCommand(commandGenerateWireGuardKeyPair)
-	commandGenerate.AddCommand(commandGenerateRealityKeyPair)
+
 	mainCommand.AddCommand(commandGenerate)
 }
 
@@ -92,48 +90,3 @@ func generateUUID() error {
 	_, err = os.Stdout.WriteString(newUUID.String() + "\n")
 	return err
 }
-
-var commandGenerateWireGuardKeyPair = &cobra.Command{
-	Use:   "wg-keypair",
-	Short: "Generate WireGuard key pair",
-	Args:  cobra.NoArgs,
-	Run: func(cmd *cobra.Command, args []string) {
-		err := generateWireGuardKey()
-		if err != nil {
-			log.Fatal(err)
-		}
-	},
-}
-
-func generateWireGuardKey() error {
-	privateKey, err := wgtypes.GeneratePrivateKey()
-	if err != nil {
-		return err
-	}
-	os.Stdout.WriteString("PrivateKey: " + privateKey.String() + "\n")
-	os.Stdout.WriteString("PublicKey: " + privateKey.PublicKey().String() + "\n")
-	return nil
-}
-
-var commandGenerateRealityKeyPair = &cobra.Command{
-	Use:   "reality-keypair",
-	Short: "Generate reality key pair",
-	Args:  cobra.NoArgs,
-	Run: func(cmd *cobra.Command, args []string) {
-		err := generateRealityKey()
-		if err != nil {
-			log.Fatal(err)
-		}
-	},
-}
-
-func generateRealityKey() error {
-	privateKey, err := wgtypes.GeneratePrivateKey()
-	if err != nil {
-		return err
-	}
-	publicKey := privateKey.PublicKey()
-	os.Stdout.WriteString("PrivateKey: " + base64.RawURLEncoding.EncodeToString(privateKey[:]) + "\n")
-	os.Stdout.WriteString("PublicKey: " + base64.RawURLEncoding.EncodeToString(publicKey[:]) + "\n")
-	return nil
-}

+ 40 - 0
cmd/sing-box/cmd_generate_tls.go

@@ -0,0 +1,40 @@
+package main
+
+import (
+	"os"
+	"time"
+
+	"github.com/sagernet/sing-box/common/tls"
+	"github.com/sagernet/sing-box/log"
+
+	"github.com/spf13/cobra"
+)
+
+var flagGenerateTLSKeyPairMonths int
+
+var commandGenerateTLSKeyPair = &cobra.Command{
+	Use:   "tls-keypair <server_name>",
+	Short: "Generate TLS self sign key pair",
+	Args:  cobra.ExactArgs(1),
+	Run: func(cmd *cobra.Command, args []string) {
+		err := generateTLSKeyPair(args[0])
+		if err != nil {
+			log.Fatal(err)
+		}
+	},
+}
+
+func init() {
+	commandGenerateTLSKeyPair.Flags().IntVarP(&flagGenerateTLSKeyPairMonths, "months", "m", 1, "Valid months")
+	commandGenerate.AddCommand(commandGenerateTLSKeyPair)
+}
+
+func generateTLSKeyPair(serverName string) error {
+	privateKeyPem, publicKeyPem, err := tls.GenerateKeyPair(time.Now, serverName, time.Now().AddDate(0, flagGenerateTLSKeyPairMonths, 0))
+	if err != nil {
+		return err
+	}
+	os.Stdout.WriteString(string(privateKeyPem) + "\n")
+	os.Stdout.WriteString(string(publicKeyPem) + "\n")
+	return nil
+}

+ 40 - 0
cmd/sing-box/cmd_generate_vapid.go

@@ -0,0 +1,40 @@
+//go:build go1.20
+
+package main
+
+import (
+	"crypto/ecdh"
+	"crypto/rand"
+	"encoding/base64"
+	"os"
+
+	"github.com/sagernet/sing-box/log"
+
+	"github.com/spf13/cobra"
+)
+
+var commandGenerateVAPIDKeyPair = &cobra.Command{
+	Use:   "vapid-keypair",
+	Short: "Generate VAPID key pair",
+	Run: func(cmd *cobra.Command, args []string) {
+		err := generateVAPIDKeyPair()
+		if err != nil {
+			log.Fatal(err)
+		}
+	},
+}
+
+func init() {
+	commandGenerate.AddCommand(commandGenerateVAPIDKeyPair)
+}
+
+func generateVAPIDKeyPair() error {
+	privateKey, err := ecdh.P256().GenerateKey(rand.Reader)
+	if err != nil {
+		return err
+	}
+	publicKey := privateKey.PublicKey()
+	os.Stdout.WriteString("PrivateKey: " + base64.RawURLEncoding.EncodeToString(privateKey.Bytes()) + "\n")
+	os.Stdout.WriteString("PublicKey: " + base64.RawURLEncoding.EncodeToString(publicKey.Bytes()) + "\n")
+	return nil
+}

+ 61 - 0
cmd/sing-box/cmd_generate_wireguard.go

@@ -0,0 +1,61 @@
+package main
+
+import (
+	"encoding/base64"
+	"os"
+
+	"github.com/sagernet/sing-box/log"
+
+	"github.com/spf13/cobra"
+	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
+)
+
+func init() {
+	commandGenerate.AddCommand(commandGenerateWireGuardKeyPair)
+	commandGenerate.AddCommand(commandGenerateRealityKeyPair)
+}
+
+var commandGenerateWireGuardKeyPair = &cobra.Command{
+	Use:   "wg-keypair",
+	Short: "Generate WireGuard key pair",
+	Args:  cobra.NoArgs,
+	Run: func(cmd *cobra.Command, args []string) {
+		err := generateWireGuardKey()
+		if err != nil {
+			log.Fatal(err)
+		}
+	},
+}
+
+func generateWireGuardKey() error {
+	privateKey, err := wgtypes.GeneratePrivateKey()
+	if err != nil {
+		return err
+	}
+	os.Stdout.WriteString("PrivateKey: " + privateKey.String() + "\n")
+	os.Stdout.WriteString("PublicKey: " + privateKey.PublicKey().String() + "\n")
+	return nil
+}
+
+var commandGenerateRealityKeyPair = &cobra.Command{
+	Use:   "reality-keypair",
+	Short: "Generate reality key pair",
+	Args:  cobra.NoArgs,
+	Run: func(cmd *cobra.Command, args []string) {
+		err := generateRealityKey()
+		if err != nil {
+			log.Fatal(err)
+		}
+	},
+}
+
+func generateRealityKey() error {
+	privateKey, err := wgtypes.GeneratePrivateKey()
+	if err != nil {
+		return err
+	}
+	publicKey := privateKey.PublicKey()
+	os.Stdout.WriteString("PrivateKey: " + base64.RawURLEncoding.EncodeToString(privateKey[:]) + "\n")
+	os.Stdout.WriteString("PublicKey: " + base64.RawURLEncoding.EncodeToString(publicKey[:]) + "\n")
+	return nil
+}

+ 21 - 13
common/tls/mkcert.go

@@ -11,22 +11,34 @@ import (
 	"time"
 )
 
-func GenerateKeyPair(timeFunc func() time.Time, serverName string) (*tls.Certificate, error) {
+func GenerateCertificate(timeFunc func() time.Time, serverName string) (*tls.Certificate, error) {
+	privateKeyPem, publicKeyPem, err := GenerateKeyPair(timeFunc, serverName, timeFunc().Add(time.Hour))
+	if err != nil {
+		return nil, err
+	}
+	certificate, err := tls.X509KeyPair(publicKeyPem, privateKeyPem)
+	if err != nil {
+		return nil, err
+	}
+	return &certificate, err
+}
+
+func GenerateKeyPair(timeFunc func() time.Time, serverName string, expire time.Time) (privateKeyPem []byte, publicKeyPem []byte, err error) {
 	if timeFunc == nil {
 		timeFunc = time.Now
 	}
 	key, err := rsa.GenerateKey(rand.Reader, 2048)
 	if err != nil {
-		return nil, err
+		return
 	}
 	serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
 	if err != nil {
-		return nil, err
+		return
 	}
 	template := &x509.Certificate{
 		SerialNumber:          serialNumber,
 		NotBefore:             timeFunc().Add(time.Hour * -1),
-		NotAfter:              timeFunc().Add(time.Hour),
+		NotAfter:              expire,
 		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
 		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 		BasicConstraintsValid: true,
@@ -37,17 +49,13 @@ func GenerateKeyPair(timeFunc func() time.Time, serverName string) (*tls.Certifi
 	}
 	publicDer, err := x509.CreateCertificate(rand.Reader, template, template, key.Public(), key)
 	if err != nil {
-		return nil, err
+		return
 	}
 	privateDer, err := x509.MarshalPKCS8PrivateKey(key)
 	if err != nil {
-		return nil, err
-	}
-	publicPem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: publicDer})
-	privPem := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privateDer})
-	keyPair, err := tls.X509KeyPair(publicPem, privPem)
-	if err != nil {
-		return nil, err
+		return
 	}
-	return &keyPair, err
+	publicKeyPem = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: publicDer})
+	privateKeyPem = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privateDer})
+	return
 }

+ 1 - 1
common/tls/std_server.go

@@ -233,7 +233,7 @@ func NewSTDServer(ctx context.Context, logger log.Logger, options option.Inbound
 		}
 		if certificate == nil && key == nil && options.Insecure {
 			tlsConfig.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
-				return GenerateKeyPair(ntp.TimeFuncFromContext(ctx), info.ServerName)
+				return GenerateCertificate(ntp.TimeFuncFromContext(ctx), info.ServerName)
 			}
 		} else {
 			if certificate == nil {