automatic issuing certificates from provided CA

pull/1028/merge
Darien Raymond 2018-04-10 12:42:02 +02:00
parent 8ba8ce7d6a
commit 318a36fe58
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
7 changed files with 366 additions and 45 deletions

View File

@ -7,17 +7,39 @@ import (
"encoding/pem" "encoding/pem"
"math/big" "math/big"
"time" "time"
"v2ray.com/core/common"
) )
//go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg cert -path Protocol,TLS,Cert //go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg cert -path Protocol,TLS,Cert
type Certificate struct { type Certificate struct {
// Cerificate in x509 format // Cerificate in ASN.1 DER format
Certificate []byte Certificate []byte
// Private key in x509 format // Private key in ASN.1 DER format
PrivateKey []byte PrivateKey []byte
} }
func ParseCertificate(certPEM []byte, keyPEM []byte) (*Certificate, error) {
certBlock, _ := pem.Decode(certPEM)
if certBlock == nil {
return nil, newError("failed to decode certificate")
}
keyBlock, _ := pem.Decode(keyPEM)
if keyBlock == nil {
return nil, newError("failed to decode key")
}
return &Certificate{
Certificate: certBlock.Bytes,
PrivateKey: keyBlock.Bytes,
}, nil
}
func (c *Certificate) ToPEM() ([]byte, []byte) {
return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: c.Certificate}),
pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: c.PrivateKey})
}
type Option func(*x509.Certificate) type Option func(*x509.Certificate)
func Authority(isCA bool) Option { func Authority(isCA bool) Option {
@ -50,10 +72,31 @@ func CommonName(name string) Option {
} }
} }
func Generate(parent *x509.Certificate, opts ...Option) (*Certificate, error) { func KeyUsage(usage x509.KeyUsage) Option {
priv, err := rsa.GenerateKey(rand.Reader, 2048) return func(c *x509.Certificate) {
c.KeyUsage = usage
}
}
func MustGenerate(parent *Certificate, opts ...Option) *Certificate {
cert, err := Generate(parent, opts...)
common.Must(err)
return cert
}
func Generate(parent *Certificate, opts ...Option) (*Certificate, error) {
selfKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil { if err != nil {
return nil, newError("failed to generate RSA private key").Base(err) return nil, newError("failed to generate self private key").Base(err)
}
parentKey := selfKey
if parent != nil {
pKey, err := x509.ParsePKCS1PrivateKey(parent.PrivateKey)
if err != nil {
return nil, newError("failed to parse parent private key").Base(err)
}
parentKey = pKey
} }
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
@ -75,20 +118,22 @@ func Generate(parent *x509.Certificate, opts ...Option) (*Certificate, error) {
opt(template) opt(template)
} }
if parent == nil { parentCert := template
parent = template if parent != nil {
pCert, err := x509.ParseCertificate(parent.Certificate)
if err != nil {
return nil, newError("failed to parse parent certificate").Base(err)
}
parentCert = pCert
} }
derBytes, err := x509.CreateCertificate(rand.Reader, template, parent, priv.Public(), priv) derBytes, err := x509.CreateCertificate(rand.Reader, template, parentCert, selfKey.Public(), parentKey)
if err != nil { if err != nil {
return nil, newError("failed to create certificate").Base(err) return nil, newError("failed to create certificate").Base(err)
} }
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
return &Certificate{ return &Certificate{
Certificate: certPEM, Certificate: derBytes,
PrivateKey: keyPEM, PrivateKey: x509.MarshalPKCS1PrivateKey(selfKey),
}, nil }, nil
} }

View File

@ -2,6 +2,8 @@ package scenarios
import ( import (
"crypto/rand" "crypto/rand"
"crypto/x509"
"runtime"
"sync" "sync"
"testing" "testing"
"time" "time"
@ -10,6 +12,7 @@ import (
"v2ray.com/core/app/proxyman" "v2ray.com/core/app/proxyman"
"v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol" "v2ray.com/core/common/protocol"
"v2ray.com/core/common/protocol/tls/cert"
"v2ray.com/core/common/serial" "v2ray.com/core/common/serial"
"v2ray.com/core/common/uuid" "v2ray.com/core/common/uuid"
"v2ray.com/core/proxy/dokodemo" "v2ray.com/core/proxy/dokodemo"
@ -19,7 +22,6 @@ import (
"v2ray.com/core/proxy/vmess/outbound" "v2ray.com/core/proxy/vmess/outbound"
"v2ray.com/core/testing/servers/tcp" "v2ray.com/core/testing/servers/tcp"
"v2ray.com/core/testing/servers/udp" "v2ray.com/core/testing/servers/udp"
tlsgen "v2ray.com/core/testing/tls"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
"v2ray.com/core/transport/internet/http" "v2ray.com/core/transport/internet/http"
"v2ray.com/core/transport/internet/tls" "v2ray.com/core/transport/internet/tls"
@ -49,7 +51,7 @@ func TestSimpleTLSConnection(t *testing.T) {
SecurityType: serial.GetMessageType(&tls.Config{}), SecurityType: serial.GetMessageType(&tls.Config{}),
SecuritySettings: []*serial.TypedMessage{ SecuritySettings: []*serial.TypedMessage{
serial.ToTypedMessage(&tls.Config{ serial.ToTypedMessage(&tls.Config{
Certificate: []*tls.Certificate{tlsgen.GenerateCertificateForTest()}, Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
}), }),
}, },
}, },
@ -141,6 +143,137 @@ func TestSimpleTLSConnection(t *testing.T) {
CloseAllServers(servers) CloseAllServers(servers)
} }
func TestAutoIssuingCertificate(t *testing.T) {
if runtime.GOOS == "windows" {
// Not supported on Windows yet.
return
}
assert := With(t)
tcpServer := tcp.Server{
MsgProcessor: xor,
}
dest, err := tcpServer.Start()
assert(err, IsNil)
defer tcpServer.Close()
caCert, err := cert.Generate(nil, cert.Authority(true), cert.KeyUsage(x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment|x509.KeyUsageCertSign))
assert(err, IsNil)
certPEM, keyPEM := caCert.ToPEM()
userID := protocol.NewID(uuid.New())
serverPort := tcp.PickPort()
serverConfig := &core.Config{
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(serverPort),
Listen: net.NewIPOrDomain(net.LocalHostIP),
StreamSettings: &internet.StreamConfig{
SecurityType: serial.GetMessageType(&tls.Config{}),
SecuritySettings: []*serial.TypedMessage{
serial.ToTypedMessage(&tls.Config{
Certificate: []*tls.Certificate{{
Certificate: certPEM,
Key: keyPEM,
Usage: tls.Certificate_AUTHORITY_ISSUE,
}},
}),
},
},
}),
ProxySettings: serial.ToTypedMessage(&inbound.Config{
User: []*protocol.User{
{
Account: serial.ToTypedMessage(&vmess.Account{
Id: userID.String(),
}),
},
},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
},
},
}
clientPort := tcp.PickPort()
clientConfig := &core.Config{
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortRange: net.SinglePortRange(clientPort),
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
Address: net.NewIPOrDomain(dest.Address),
Port: uint32(dest.Port),
NetworkList: &net.NetworkList{
Network: []net.Network{net.Network_TCP},
},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&outbound.Config{
Receiver: []*protocol.ServerEndpoint{
{
Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(serverPort),
User: []*protocol.User{
{
Account: serial.ToTypedMessage(&vmess.Account{
Id: userID.String(),
}),
},
},
},
},
}),
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
StreamSettings: &internet.StreamConfig{
SecurityType: serial.GetMessageType(&tls.Config{}),
SecuritySettings: []*serial.TypedMessage{
serial.ToTypedMessage(&tls.Config{
ServerName: "v2ray.com",
Certificate: []*tls.Certificate{{
Certificate: certPEM,
Usage: tls.Certificate_AUTHORITY_VERIFY,
}},
}),
},
},
}),
},
},
}
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
assert(err, IsNil)
conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
IP: []byte{127, 0, 0, 1},
Port: int(clientPort),
})
assert(err, IsNil)
payload := "dokodemo request."
nBytes, err := conn.Write([]byte(payload))
assert(err, IsNil)
assert(nBytes, Equals, len(payload))
response := readFrom(conn, time.Second*2, len(payload))
assert(response, Equals, xor([]byte(payload)))
assert(conn.Close(), IsNil)
CloseAllServers(servers)
}
func TestTLSOverKCP(t *testing.T) { func TestTLSOverKCP(t *testing.T) {
assert := With(t) assert := With(t)
@ -164,7 +297,7 @@ func TestTLSOverKCP(t *testing.T) {
SecurityType: serial.GetMessageType(&tls.Config{}), SecurityType: serial.GetMessageType(&tls.Config{}),
SecuritySettings: []*serial.TypedMessage{ SecuritySettings: []*serial.TypedMessage{
serial.ToTypedMessage(&tls.Config{ serial.ToTypedMessage(&tls.Config{
Certificate: []*tls.Certificate{tlsgen.GenerateCertificateForTest()}, Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
}), }),
}, },
}, },
@ -280,7 +413,7 @@ func TestTLSOverWebSocket(t *testing.T) {
SecurityType: serial.GetMessageType(&tls.Config{}), SecurityType: serial.GetMessageType(&tls.Config{}),
SecuritySettings: []*serial.TypedMessage{ SecuritySettings: []*serial.TypedMessage{
serial.ToTypedMessage(&tls.Config{ serial.ToTypedMessage(&tls.Config{
Certificate: []*tls.Certificate{tlsgen.GenerateCertificateForTest()}, Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
}), }),
}, },
}, },
@ -412,7 +545,7 @@ func TestHTTP2(t *testing.T) {
SecurityType: serial.GetMessageType(&tls.Config{}), SecurityType: serial.GetMessageType(&tls.Config{}),
SecuritySettings: []*serial.TypedMessage{ SecuritySettings: []*serial.TypedMessage{
serial.ToTypedMessage(&tls.Config{ serial.ToTypedMessage(&tls.Config{
Certificate: []*tls.Certificate{tlsgen.GenerateCertificateForTest()}, Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
}), }),
}, },
}, },

View File

@ -9,8 +9,8 @@ import (
"v2ray.com/core/common" "v2ray.com/core/common"
"v2ray.com/core/common/buf" "v2ray.com/core/common/buf"
"v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol/tls/cert"
"v2ray.com/core/testing/servers/tcp" "v2ray.com/core/testing/servers/tcp"
tlsgen "v2ray.com/core/testing/tls"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
. "v2ray.com/core/transport/internet/http" . "v2ray.com/core/transport/internet/http"
"v2ray.com/core/transport/internet/tls" "v2ray.com/core/transport/internet/tls"
@ -24,7 +24,7 @@ func TestHTTPConnection(t *testing.T) {
lctx := context.Background() lctx := context.Background()
lctx = internet.ContextWithSecuritySettings(lctx, &tls.Config{ lctx = internet.ContextWithSecuritySettings(lctx, &tls.Config{
Certificate: []*tls.Certificate{tlsgen.GenerateCertificateForTest()}, Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil, cert.CommonName("www.v2ray.com")))},
}) })
lctx = internet.ContextWithTransportSettings(lctx, &Config{}) lctx = internet.ContextWithTransportSettings(lctx, &Config{})

View File

@ -3,8 +3,11 @@ package tls
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"crypto/x509"
"time"
"v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol/tls/cert"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
) )
@ -12,9 +15,36 @@ var (
globalSessionCache = tls.NewLRUClientSessionCache(128) globalSessionCache = tls.NewLRUClientSessionCache(128)
) )
func ParseCertificate(c *cert.Certificate) *Certificate {
certPEM, keyPEM := c.ToPEM()
return &Certificate{
Certificate: certPEM,
Key: keyPEM,
}
}
func (c *Config) GetCertPool() *x509.CertPool {
pool, err := x509.SystemCertPool()
if err != nil {
newError("failed to get system cert pool.").Base(err).WriteToLog()
return nil
}
if pool != nil {
for _, cert := range c.Certificate {
if cert.Usage == Certificate_AUTHORITY_VERIFY {
pool.AppendCertsFromPEM(cert.Certificate)
}
}
}
return pool
}
func (c *Config) BuildCertificates() []tls.Certificate { func (c *Config) BuildCertificates() []tls.Certificate {
certs := make([]tls.Certificate, 0, len(c.Certificate)) certs := make([]tls.Certificate, 0, len(c.Certificate))
for _, entry := range c.Certificate { for _, entry := range c.Certificate {
if entry.Usage != Certificate_ENCIPHERMENT {
continue
}
keyPair, err := tls.X509KeyPair(entry.Certificate, entry.Key) keyPair, err := tls.X509KeyPair(entry.Certificate, entry.Key)
if err != nil { if err != nil {
newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog() newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
@ -25,9 +55,29 @@ func (c *Config) BuildCertificates() []tls.Certificate {
return certs return certs
} }
func isCertificateExpired(c *tls.Certificate) bool {
// If leaf is not there, the certificate is probably not used yet. We trust user to provide a valid certificate.
return c.Leaf != nil && c.Leaf.NotAfter.After(time.Now().Add(-time.Minute))
}
func issueCertificate(rawCA *Certificate, domain string) (*tls.Certificate, error) {
parent, err := cert.ParseCertificate(rawCA.Certificate, rawCA.Key)
if err != nil {
return nil, newError("failed to parse raw certificate").Base(err)
}
newCert, err := cert.Generate(parent, cert.CommonName(domain), cert.DNSNames(domain))
if err != nil {
return nil, newError("failed to generate new certificate for ", domain).Base(err)
}
newCertPEM, newKeyPEM := newCert.ToPEM()
cert, err := tls.X509KeyPair(newCertPEM, newKeyPEM)
return &cert, err
}
func (c *Config) GetTLSConfig(opts ...Option) *tls.Config { func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
config := &tls.Config{ config := &tls.Config{
ClientSessionCache: globalSessionCache, ClientSessionCache: globalSessionCache,
RootCAs: c.GetCertPool(),
} }
if c == nil { if c == nil {
return config return config
@ -40,6 +90,53 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
config.InsecureSkipVerify = c.AllowInsecure config.InsecureSkipVerify = c.AllowInsecure
config.Certificates = c.BuildCertificates() config.Certificates = c.BuildCertificates()
config.BuildNameToCertificate() config.BuildNameToCertificate()
config.GetCertificate = func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
domain := hello.ServerName
certExpired := false
if certificate, found := config.NameToCertificate[domain]; found {
if !isCertificateExpired(certificate) {
return certificate, nil
}
certExpired = true
}
if certExpired {
newCerts := make([]tls.Certificate, 0, len(config.Certificates))
for _, certificate := range config.Certificates {
if !isCertificateExpired(&certificate) {
newCerts = append(newCerts, certificate)
}
}
config.Certificates = newCerts
}
var issuedCertificate *tls.Certificate
// Create a new certificate from existing CA if possible
for _, rawCert := range c.Certificate {
if rawCert.Usage == Certificate_AUTHORITY_ISSUE {
newCert, err := issueCertificate(rawCert, domain)
if err != nil {
newError("failed to issue new certificate for ", domain).Base(err).WriteToLog()
continue
}
config.Certificates = append(config.Certificates, *newCert)
issuedCertificate = &config.Certificates[len(config.Certificates)-1]
break
}
}
if issuedCertificate == nil {
return nil, newError("failed to create a new certificate for ", domain)
}
config.BuildNameToCertificate()
return issuedCertificate, nil
}
if len(c.ServerName) > 0 { if len(c.ServerName) > 0 {
config.ServerName = c.ServerName config.ServerName = c.ServerName
} }

View File

@ -15,11 +15,36 @@ var _ = math.Inf
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Certificate_Usage int32
const (
Certificate_ENCIPHERMENT Certificate_Usage = 0
Certificate_AUTHORITY_VERIFY Certificate_Usage = 1
Certificate_AUTHORITY_ISSUE Certificate_Usage = 2
)
var Certificate_Usage_name = map[int32]string{
0: "ENCIPHERMENT",
1: "AUTHORITY_VERIFY",
2: "AUTHORITY_ISSUE",
}
var Certificate_Usage_value = map[string]int32{
"ENCIPHERMENT": 0,
"AUTHORITY_VERIFY": 1,
"AUTHORITY_ISSUE": 2,
}
func (x Certificate_Usage) String() string {
return proto.EnumName(Certificate_Usage_name, int32(x))
}
func (Certificate_Usage) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
type Certificate struct { type Certificate struct {
// TLS certificate in x509 format. // TLS certificate in x509 format.
Certificate []byte `protobuf:"bytes,1,opt,name=Certificate,proto3" json:"Certificate,omitempty"` Certificate []byte `protobuf:"bytes,1,opt,name=Certificate,proto3" json:"Certificate,omitempty"`
// TLS key in x509 format. // TLS key in x509 format.
Key []byte `protobuf:"bytes,2,opt,name=Key,proto3" json:"Key,omitempty"` Key []byte `protobuf:"bytes,2,opt,name=Key,proto3" json:"Key,omitempty"`
Usage Certificate_Usage `protobuf:"varint,3,opt,name=usage,enum=v2ray.core.transport.internet.tls.Certificate_Usage" json:"usage,omitempty"`
} }
func (m *Certificate) Reset() { *m = Certificate{} } func (m *Certificate) Reset() { *m = Certificate{} }
@ -41,6 +66,13 @@ func (m *Certificate) GetKey() []byte {
return nil return nil
} }
func (m *Certificate) GetUsage() Certificate_Usage {
if m != nil {
return m.Usage
}
return Certificate_ENCIPHERMENT
}
type Config struct { type Config struct {
// Whether or not to allow self-signed certificates. // Whether or not to allow self-signed certificates.
AllowInsecure bool `protobuf:"varint,1,opt,name=allow_insecure,json=allowInsecure" json:"allow_insecure,omitempty"` AllowInsecure bool `protobuf:"varint,1,opt,name=allow_insecure,json=allowInsecure" json:"allow_insecure,omitempty"`
@ -88,28 +120,34 @@ func (m *Config) GetNextProtocol() []string {
func init() { func init() {
proto.RegisterType((*Certificate)(nil), "v2ray.core.transport.internet.tls.Certificate") proto.RegisterType((*Certificate)(nil), "v2ray.core.transport.internet.tls.Certificate")
proto.RegisterType((*Config)(nil), "v2ray.core.transport.internet.tls.Config") proto.RegisterType((*Config)(nil), "v2ray.core.transport.internet.tls.Config")
proto.RegisterEnum("v2ray.core.transport.internet.tls.Certificate_Usage", Certificate_Usage_name, Certificate_Usage_value)
} }
func init() { proto.RegisterFile("v2ray.com/core/transport/internet/tls/config.proto", fileDescriptor0) } func init() { proto.RegisterFile("v2ray.com/core/transport/internet/tls/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 278 bytes of a gzipped FileDescriptorProto // 358 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0x41, 0x6a, 0xeb, 0x30, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xd1, 0x6e, 0xda, 0x30,
0x10, 0x86, 0x71, 0xfc, 0x08, 0x2f, 0x72, 0x52, 0x8a, 0x56, 0xde, 0xd5, 0x49, 0x09, 0x78, 0x25, 0x14, 0x40, 0x97, 0x64, 0xa0, 0xe1, 0x00, 0x8b, 0xbc, 0x3d, 0xe4, 0x6d, 0x81, 0x09, 0x29, 0x4f,
0x83, 0x7b, 0x82, 0xd6, 0xab, 0x50, 0x28, 0x46, 0x84, 0x2e, 0xba, 0x31, 0xaa, 0x98, 0x14, 0x83, 0x8e, 0x94, 0xed, 0x07, 0xb6, 0x34, 0x15, 0x69, 0x55, 0x1a, 0x99, 0x80, 0x44, 0x5f, 0x22, 0xd7,
0x2c, 0x85, 0xd1, 0x34, 0xad, 0xaf, 0xd4, 0x8b, 0xf4, 0x5a, 0xc5, 0x4e, 0x1c, 0x9c, 0x55, 0x76, 0x32, 0x28, 0x52, 0x12, 0x23, 0xdb, 0xd0, 0xf2, 0x4b, 0xfd, 0x91, 0x7e, 0x40, 0x7f, 0xa8, 0x4a,
0xd2, 0xa7, 0x4f, 0xf3, 0xff, 0x0c, 0xcb, 0x0f, 0x39, 0xaa, 0x56, 0x68, 0xd7, 0x64, 0xda, 0x21, 0x02, 0x14, 0x9e, 0x50, 0xdf, 0x7c, 0x8f, 0xcf, 0xbd, 0xd7, 0xf7, 0x1a, 0xf8, 0x5b, 0x5f, 0x90,
0x64, 0x84, 0xca, 0xfa, 0xbd, 0x43, 0xca, 0x6a, 0x4b, 0x80, 0x16, 0x28, 0x23, 0xe3, 0x33, 0xed, 0x1d, 0xa2, 0xbc, 0xf0, 0x28, 0x17, 0xcc, 0x53, 0x82, 0x94, 0x72, 0xcd, 0x85, 0xf2, 0xb2, 0x52,
0xec, 0xae, 0xfe, 0x10, 0x7b, 0x74, 0xe4, 0xf8, 0x72, 0xf8, 0x83, 0x20, 0xce, 0xbe, 0x18, 0x7c, 0x31, 0x51, 0x32, 0xe5, 0xa9, 0x5c, 0x7a, 0x94, 0x97, 0xcb, 0x6c, 0x85, 0xd6, 0x82, 0x2b, 0x0e,
0x41, 0xc6, 0xaf, 0x1e, 0x59, 0x54, 0x00, 0x52, 0xbd, 0xab, 0xb5, 0x22, 0xe0, 0xc9, 0xc5, 0x35, 0x07, 0x87, 0x1c, 0xc1, 0xd0, 0xd1, 0x47, 0x07, 0x1f, 0xa9, 0x5c, 0x0e, 0xdf, 0x34, 0x60, 0x06,
0x0e, 0x92, 0x20, 0x9d, 0xcb, 0x0b, 0xe3, 0x96, 0x85, 0xcf, 0xd0, 0xc6, 0x93, 0xfe, 0xa5, 0x3b, 0x4c, 0xa8, 0x6c, 0x99, 0x51, 0xa2, 0x18, 0x74, 0xce, 0x42, 0x5b, 0x73, 0x34, 0xb7, 0x8b, 0xcf,
0xae, 0x7e, 0x03, 0x36, 0x2d, 0xfa, 0x58, 0xbe, 0x66, 0x37, 0xca, 0x18, 0xf7, 0x55, 0xd5, 0xd6, 0x0c, 0x0b, 0x18, 0xb7, 0x6c, 0x67, 0xeb, 0xf5, 0x4d, 0x75, 0x84, 0x37, 0xa0, 0xb5, 0x91, 0x64,
0x83, 0xfe, 0xc4, 0xe3, 0x84, 0xff, 0x72, 0xd1, 0xd3, 0xcd, 0x09, 0xf2, 0x92, 0x45, 0x7a, 0x94, 0xc5, 0x6c, 0xc3, 0xd1, 0xdc, 0xbe, 0xff, 0x17, 0x5d, 0x6c, 0x8b, 0x4e, 0x0a, 0xa2, 0x59, 0x95,
0x32, 0x49, 0xc2, 0x34, 0xca, 0x85, 0xb8, 0xda, 0x56, 0x8c, 0x8a, 0xc8, 0xf1, 0x08, 0x7e, 0xc7, 0x8b, 0x9b, 0x12, 0xc3, 0x2b, 0xd0, 0xaa, 0x63, 0x68, 0x81, 0x6e, 0x38, 0x09, 0xa2, 0x78, 0x1c,
0x22, 0x0f, 0x78, 0x00, 0xac, 0xac, 0x6a, 0x20, 0x0e, 0x93, 0x20, 0x9d, 0x49, 0x76, 0x44, 0x2f, 0xe2, 0xbb, 0x70, 0x92, 0x58, 0x5f, 0xe0, 0x4f, 0x60, 0xfd, 0x9b, 0x25, 0xe3, 0x7b, 0x1c, 0x25,
0xaa, 0x01, 0x7e, 0xcf, 0x16, 0x16, 0xbe, 0xa9, 0xea, 0x17, 0xa3, 0x9d, 0x89, 0xff, 0x25, 0x61, 0x8b, 0x74, 0x1e, 0xe2, 0xe8, 0x7a, 0x61, 0x69, 0xf0, 0x07, 0xf8, 0xfe, 0x41, 0xa3, 0xe9, 0x74,
0x3a, 0x93, 0xf3, 0x0e, 0x96, 0x27, 0xf6, 0x24, 0xd9, 0x5a, 0xbb, 0xe6, 0x7a, 0x8f, 0x32, 0x78, 0x16, 0x5a, 0xfa, 0xf0, 0x55, 0x03, 0xed, 0xa0, 0xde, 0x04, 0x1c, 0x81, 0x3e, 0xc9, 0x73, 0xfe,
0x0b, 0xc9, 0xf8, 0x9f, 0xc9, 0xf2, 0x35, 0x97, 0xaa, 0x15, 0x45, 0xa7, 0x6e, 0xcf, 0xea, 0x66, 0x94, 0x66, 0xa5, 0x64, 0x74, 0x23, 0x9a, 0x99, 0xbe, 0xe1, 0x5e, 0x4d, 0xa3, 0x3d, 0x84, 0x31,
0x50, 0xb7, 0xc6, 0xbf, 0x4f, 0xfb, 0xc4, 0x87, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x84, 0x30, 0xe9, 0xc9, 0xdc, 0xba, 0x63, 0xb8, 0xa6, 0x8f, 0x3e, 0x37, 0x09, 0x3e, 0x2d, 0x01, 0x7f,
0xfb, 0x07, 0xc0, 0x01, 0x00, 0x00, 0x01, 0x53, 0x32, 0xb1, 0x65, 0x22, 0x2d, 0x49, 0xd1, 0xec, 0xa6, 0x83, 0x41, 0x83, 0x26, 0xa4,
0x60, 0xf0, 0x37, 0xe8, 0x95, 0xec, 0x59, 0xa5, 0xf5, 0x5f, 0x51, 0x9e, 0xdb, 0x5f, 0x1d, 0xc3,
0xed, 0xe0, 0x6e, 0x05, 0xe3, 0x3d, 0xfb, 0x8f, 0xc1, 0x88, 0xf2, 0xe2, 0xf2, 0x3b, 0x62, 0xed,
0xc1, 0x50, 0xb9, 0x7c, 0xd1, 0x07, 0x73, 0x1f, 0x93, 0x1d, 0x0a, 0x2a, 0x35, 0x39, 0xaa, 0xd1,
0x41, 0x4d, 0x72, 0xf9, 0xd8, 0xae, 0x3b, 0xfe, 0x79, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x0b, 0xcd,
0x2a, 0x68, 0x53, 0x02, 0x00, 0x00,
} }

View File

@ -12,6 +12,14 @@ message Certificate {
// TLS key in x509 format. // TLS key in x509 format.
bytes Key = 2; bytes Key = 2;
enum Usage {
ENCIPHERMENT = 0;
AUTHORITY_VERIFY = 1;
AUTHORITY_ISSUE = 2;
}
Usage usage = 3;
} }
message Config { message Config {

View File

@ -7,9 +7,9 @@ import (
"time" "time"
"v2ray.com/core/common/net" "v2ray.com/core/common/net"
tlsgen "v2ray.com/core/testing/tls" "v2ray.com/core/common/protocol/tls/cert"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
v2tls "v2ray.com/core/transport/internet/tls" "v2ray.com/core/transport/internet/tls"
. "v2ray.com/core/transport/internet/websocket" . "v2ray.com/core/transport/internet/websocket"
. "v2ray.com/ext/assert" . "v2ray.com/ext/assert"
) )
@ -109,9 +109,9 @@ func Test_listenWSAndDial_TLS(t *testing.T) {
ctx := internet.ContextWithTransportSettings(context.Background(), &Config{ ctx := internet.ContextWithTransportSettings(context.Background(), &Config{
Path: "wss", Path: "wss",
}) })
ctx = internet.ContextWithSecuritySettings(ctx, &v2tls.Config{ ctx = internet.ContextWithSecuritySettings(ctx, &tls.Config{
AllowInsecure: true, AllowInsecure: true,
Certificate: []*v2tls.Certificate{tlsgen.GenerateCertificateForTest()}, Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil, cert.CommonName("localhost")))},
}) })
listen, err := ListenWS(ctx, net.DomainAddress("localhost"), 13143, func(conn internet.Connection) { listen, err := ListenWS(ctx, net.DomainAddress("localhost"), 13143, func(conn internet.Connection) {
go func() { go func() {