This commit is contained in:
RPRX 2020-11-25 19:01:53 +08:00
parent 47d23e9972
commit c7f7c08ead
711 changed files with 82154 additions and 2 deletions

View file

@ -0,0 +1,138 @@
package tlscmd
import (
"context"
"crypto/x509"
"encoding/json"
"os"
"strings"
"time"
"github.com/xtls/xray-core/v1/common"
"github.com/xtls/xray-core/v1/common/protocol/tls/cert"
"github.com/xtls/xray-core/v1/common/task"
"github.com/xtls/xray-core/v1/main/commands/base"
)
// CmdCert is the tls cert command
var CmdCert = &base.Command{
UsageLine: "{{.Exec}} tls cert [--ca] [--domain=xray.com] [--expire=240h]",
Short: "Generate TLS certificates",
Long: `
Generate TLS certificates.
The -domain=domain_name flag sets the domain name for the
certificate.
The -org=organization flag sets the organization name for the
certificate.
The -ca flag sets whether this certificate is a CA
The -json flag sets the output of certificate to JSON
The -file flag sets the certificate path to save.
The -expire flag expire time of the certificate. Default
value 3 months.
`,
}
func init() {
CmdCert.Run = executeCert // break init loop
}
var (
certDomainNames stringList
_ = func() bool {
CmdCert.Flag.Var(&certDomainNames, "domain", "Domain name for the certificate")
return true
}()
certCommonName = CmdCert.Flag.String("name", "Xray Inc", "The common name of this certificate")
certOrganization = CmdCert.Flag.String("org", "Xray Inc", "Organization of the certificate")
certIsCA = CmdCert.Flag.Bool("ca", false, "Whether this certificate is a CA")
certJSONOutput = CmdCert.Flag.Bool("json", true, "Print certificate in JSON format")
certFileOutput = CmdCert.Flag.String("file", "", "Save certificate in file.")
certExpire = CmdCert.Flag.Duration("expire", time.Hour*24*90 /* 90 days */, "Time until the certificate expires. Default value 3 months.")
)
func executeCert(cmd *base.Command, args []string) {
var opts []cert.Option
if *certIsCA {
opts = append(opts, cert.Authority(*certIsCA))
opts = append(opts, cert.KeyUsage(x509.KeyUsageCertSign|x509.KeyUsageKeyEncipherment|x509.KeyUsageDigitalSignature))
}
opts = append(opts, cert.NotAfter(time.Now().Add(*certExpire)))
opts = append(opts, cert.CommonName(*certCommonName))
if len(certDomainNames) > 0 {
opts = append(opts, cert.DNSNames(certDomainNames...))
}
opts = append(opts, cert.Organization(*certOrganization))
cert, err := cert.Generate(nil, opts...)
if err != nil {
base.Fatalf("failed to generate TLS certificate: %s", err)
}
if *certJSONOutput {
printJSON(cert)
}
if len(*certFileOutput) > 0 {
if err := printFile(cert, *certFileOutput); err != nil {
base.Fatalf("failed to save file: %s", err)
}
}
}
func printJSON(certificate *cert.Certificate) {
certPEM, keyPEM := certificate.ToPEM()
jCert := &jsonCert{
Certificate: strings.Split(strings.TrimSpace(string(certPEM)), "\n"),
Key: strings.Split(strings.TrimSpace(string(keyPEM)), "\n"),
}
content, err := json.MarshalIndent(jCert, "", " ")
common.Must(err)
os.Stdout.Write(content)
os.Stdout.WriteString("\n")
}
func writeFile(content []byte, name string) error {
f, err := os.Create(name)
if err != nil {
return err
}
defer f.Close()
return common.Error2(f.Write(content))
}
func printFile(certificate *cert.Certificate, name string) error {
certPEM, keyPEM := certificate.ToPEM()
return task.Run(context.Background(), func() error {
return writeFile(certPEM, name+"_cert.pem")
}, func() error {
return writeFile(keyPEM, name+"_key.pem")
})
}
type stringList []string
func (l *stringList) String() string {
return "String list"
}
func (l *stringList) Set(v string) error {
if v == "" {
base.Fatalf("empty value")
}
*l = append(*l, v)
return nil
}
type jsonCert struct {
Certificate []string `json:"certificate"`
Key []string `json:"key"`
}

View file

@ -0,0 +1,111 @@
package tlscmd
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net"
"github.com/xtls/xray-core/v1/main/commands/base"
)
// CmdPing is the tls ping command
var CmdPing = &base.Command{
UsageLine: "{{.Exec}} tls ping [-ip <ip>] <domain>",
Short: "Ping the domain with TLS handshake",
Long: `
Ping the domain with TLS handshake.
The -ip flag sets the IP address of the domain.
`,
}
func init() {
CmdPing.Run = executePing // break init loop
}
var (
pingIPStr = CmdPing.Flag.String("ip", "", "")
)
func executePing(cmd *base.Command, args []string) {
if CmdPing.Flag.NArg() < 1 {
base.Fatalf("domain not specified")
}
domain := CmdPing.Flag.Arg(0)
fmt.Println("Tls ping: ", domain)
var ip net.IP
if len(*pingIPStr) > 0 {
v := net.ParseIP(*pingIPStr)
if v == nil {
base.Fatalf("invalid IP: %s", *pingIPStr)
}
ip = v
} else {
v, err := net.ResolveIPAddr("ip", domain)
if err != nil {
base.Fatalf("Failed to resolve IP: %s", err)
}
ip = v.IP
}
fmt.Println("Using IP: ", ip.String())
fmt.Println("-------------------")
fmt.Println("Pinging without SNI")
{
tcpConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: 443})
if err != nil {
base.Fatalf("Failed to dial tcp: %s", err)
}
tlsConn := tls.Client(tcpConn, &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"http/1.1"},
MaxVersion: tls.VersionTLS12,
MinVersion: tls.VersionTLS12,
})
err = tlsConn.Handshake()
if err != nil {
fmt.Println("Handshake failure: ", err)
} else {
fmt.Println("Handshake succeeded")
printCertificates(tlsConn.ConnectionState().PeerCertificates)
}
tlsConn.Close()
}
fmt.Println("-------------------")
fmt.Println("Pinging with SNI")
{
tcpConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: 443})
if err != nil {
base.Fatalf("Failed to dial tcp: %s", err)
}
tlsConn := tls.Client(tcpConn, &tls.Config{
ServerName: domain,
NextProtos: []string{"http/1.1"},
MaxVersion: tls.VersionTLS12,
MinVersion: tls.VersionTLS12,
})
err = tlsConn.Handshake()
if err != nil {
fmt.Println("handshake failure: ", err)
} else {
fmt.Println("handshake succeeded")
printCertificates(tlsConn.ConnectionState().PeerCertificates)
}
tlsConn.Close()
}
fmt.Println("Tls ping finished")
}
func printCertificates(certs []*x509.Certificate) {
for _, cert := range certs {
if len(cert.DNSNames) == 0 {
continue
}
fmt.Println("Allowed domains: ", cert.DNSNames)
}
}