mirror of https://github.com/v2ray/v2ray-core
automatic issuing certificates from provided CA
parent
8ba8ce7d6a
commit
318a36fe58
|
@ -7,17 +7,39 @@ import (
|
|||
"encoding/pem"
|
||||
"math/big"
|
||||
"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
|
||||
|
||||
type Certificate struct {
|
||||
// Cerificate in x509 format
|
||||
// Cerificate in ASN.1 DER format
|
||||
Certificate []byte
|
||||
// Private key in x509 format
|
||||
// Private key in ASN.1 DER format
|
||||
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)
|
||||
|
||||
func Authority(isCA bool) Option {
|
||||
|
@ -50,10 +72,31 @@ func CommonName(name string) Option {
|
|||
}
|
||||
}
|
||||
|
||||
func Generate(parent *x509.Certificate, opts ...Option) (*Certificate, error) {
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
func KeyUsage(usage x509.KeyUsage) Option {
|
||||
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 {
|
||||
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)
|
||||
|
@ -75,20 +118,22 @@ func Generate(parent *x509.Certificate, opts ...Option) (*Certificate, error) {
|
|||
opt(template)
|
||||
}
|
||||
|
||||
if parent == nil {
|
||||
parent = template
|
||||
parentCert := 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 {
|
||||
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{
|
||||
Certificate: certPEM,
|
||||
PrivateKey: keyPEM,
|
||||
Certificate: derBytes,
|
||||
PrivateKey: x509.MarshalPKCS1PrivateKey(selfKey),
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package scenarios
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -10,6 +12,7 @@ import (
|
|||
"v2ray.com/core/app/proxyman"
|
||||
"v2ray.com/core/common/net"
|
||||
"v2ray.com/core/common/protocol"
|
||||
"v2ray.com/core/common/protocol/tls/cert"
|
||||
"v2ray.com/core/common/serial"
|
||||
"v2ray.com/core/common/uuid"
|
||||
"v2ray.com/core/proxy/dokodemo"
|
||||
|
@ -19,7 +22,6 @@ import (
|
|||
"v2ray.com/core/proxy/vmess/outbound"
|
||||
"v2ray.com/core/testing/servers/tcp"
|
||||
"v2ray.com/core/testing/servers/udp"
|
||||
tlsgen "v2ray.com/core/testing/tls"
|
||||
"v2ray.com/core/transport/internet"
|
||||
"v2ray.com/core/transport/internet/http"
|
||||
"v2ray.com/core/transport/internet/tls"
|
||||
|
@ -49,7 +51,7 @@ func TestSimpleTLSConnection(t *testing.T) {
|
|||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*serial.TypedMessage{
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
assert := With(t)
|
||||
|
||||
|
@ -164,7 +297,7 @@ func TestTLSOverKCP(t *testing.T) {
|
|||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*serial.TypedMessage{
|
||||
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{}),
|
||||
SecuritySettings: []*serial.TypedMessage{
|
||||
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{}),
|
||||
SecuritySettings: []*serial.TypedMessage{
|
||||
serial.ToTypedMessage(&tls.Config{
|
||||
Certificate: []*tls.Certificate{tlsgen.GenerateCertificateForTest()},
|
||||
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
"v2ray.com/core/common"
|
||||
"v2ray.com/core/common/buf"
|
||||
"v2ray.com/core/common/net"
|
||||
"v2ray.com/core/common/protocol/tls/cert"
|
||||
"v2ray.com/core/testing/servers/tcp"
|
||||
tlsgen "v2ray.com/core/testing/tls"
|
||||
"v2ray.com/core/transport/internet"
|
||||
. "v2ray.com/core/transport/internet/http"
|
||||
"v2ray.com/core/transport/internet/tls"
|
||||
|
@ -24,7 +24,7 @@ func TestHTTPConnection(t *testing.T) {
|
|||
|
||||
lctx := context.Background()
|
||||
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{})
|
||||
|
||||
|
|
|
@ -3,8 +3,11 @@ package tls
|
|||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"time"
|
||||
|
||||
"v2ray.com/core/common/net"
|
||||
"v2ray.com/core/common/protocol/tls/cert"
|
||||
"v2ray.com/core/transport/internet"
|
||||
)
|
||||
|
||||
|
@ -12,9 +15,36 @@ var (
|
|||
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 {
|
||||
certs := make([]tls.Certificate, 0, len(c.Certificate))
|
||||
for _, entry := range c.Certificate {
|
||||
if entry.Usage != Certificate_ENCIPHERMENT {
|
||||
continue
|
||||
}
|
||||
keyPair, err := tls.X509KeyPair(entry.Certificate, entry.Key)
|
||||
if err != nil {
|
||||
newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
|
||||
|
@ -25,9 +55,29 @@ func (c *Config) BuildCertificates() []tls.Certificate {
|
|||
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 {
|
||||
config := &tls.Config{
|
||||
ClientSessionCache: globalSessionCache,
|
||||
RootCAs: c.GetCertPool(),
|
||||
}
|
||||
if c == nil {
|
||||
return config
|
||||
|
@ -40,6 +90,53 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
|
|||
config.InsecureSkipVerify = c.AllowInsecure
|
||||
config.Certificates = c.BuildCertificates()
|
||||
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 {
|
||||
config.ServerName = c.ServerName
|
||||
}
|
||||
|
|
|
@ -15,11 +15,36 @@ var _ = math.Inf
|
|||
// proto package needs to be updated.
|
||||
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 {
|
||||
// TLS certificate in x509 format.
|
||||
Certificate []byte `protobuf:"bytes,1,opt,name=Certificate,proto3" json:"Certificate,omitempty"`
|
||||
// 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{} }
|
||||
|
@ -41,6 +66,13 @@ func (m *Certificate) GetKey() []byte {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *Certificate) GetUsage() Certificate_Usage {
|
||||
if m != nil {
|
||||
return m.Usage
|
||||
}
|
||||
return Certificate_ENCIPHERMENT
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
// Whether or not to allow self-signed certificates.
|
||||
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() {
|
||||
proto.RegisterType((*Certificate)(nil), "v2ray.core.transport.internet.tls.Certificate")
|
||||
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) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 278 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0x41, 0x6a, 0xeb, 0x30,
|
||||
0x10, 0x86, 0x71, 0xfc, 0x08, 0x2f, 0x72, 0x52, 0x8a, 0x56, 0xde, 0xd5, 0x49, 0x09, 0x78, 0x25,
|
||||
0x83, 0x7b, 0x82, 0xd6, 0xab, 0x50, 0x28, 0x46, 0x84, 0x2e, 0xba, 0x31, 0xaa, 0x98, 0x14, 0x83,
|
||||
0x2c, 0x85, 0xd1, 0x34, 0xad, 0xaf, 0xd4, 0x8b, 0xf4, 0x5a, 0xc5, 0x4e, 0x1c, 0x9c, 0x55, 0x76,
|
||||
0xd2, 0xa7, 0x4f, 0xf3, 0xff, 0x0c, 0xcb, 0x0f, 0x39, 0xaa, 0x56, 0x68, 0xd7, 0x64, 0xda, 0x21,
|
||||
0x64, 0x84, 0xca, 0xfa, 0xbd, 0x43, 0xca, 0x6a, 0x4b, 0x80, 0x16, 0x28, 0x23, 0xe3, 0x33, 0xed,
|
||||
0xec, 0xae, 0xfe, 0x10, 0x7b, 0x74, 0xe4, 0xf8, 0x72, 0xf8, 0x83, 0x20, 0xce, 0xbe, 0x18, 0x7c,
|
||||
0x41, 0xc6, 0xaf, 0x1e, 0x59, 0x54, 0x00, 0x52, 0xbd, 0xab, 0xb5, 0x22, 0xe0, 0xc9, 0xc5, 0x35,
|
||||
0x0e, 0x92, 0x20, 0x9d, 0xcb, 0x0b, 0xe3, 0x96, 0x85, 0xcf, 0xd0, 0xc6, 0x93, 0xfe, 0xa5, 0x3b,
|
||||
0xae, 0x7e, 0x03, 0x36, 0x2d, 0xfa, 0x58, 0xbe, 0x66, 0x37, 0xca, 0x18, 0xf7, 0x55, 0xd5, 0xd6,
|
||||
0x83, 0xfe, 0xc4, 0xe3, 0x84, 0xff, 0x72, 0xd1, 0xd3, 0xcd, 0x09, 0xf2, 0x92, 0x45, 0x7a, 0x94,
|
||||
0x32, 0x49, 0xc2, 0x34, 0xca, 0x85, 0xb8, 0xda, 0x56, 0x8c, 0x8a, 0xc8, 0xf1, 0x08, 0x7e, 0xc7,
|
||||
0x22, 0x0f, 0x78, 0x00, 0xac, 0xac, 0x6a, 0x20, 0x0e, 0x93, 0x20, 0x9d, 0x49, 0x76, 0x44, 0x2f,
|
||||
0xaa, 0x01, 0x7e, 0xcf, 0x16, 0x16, 0xbe, 0xa9, 0xea, 0x17, 0xa3, 0x9d, 0x89, 0xff, 0x25, 0x61,
|
||||
0x3a, 0x93, 0xf3, 0x0e, 0x96, 0x27, 0xf6, 0x24, 0xd9, 0x5a, 0xbb, 0xe6, 0x7a, 0x8f, 0x32, 0x78,
|
||||
0x0b, 0xc9, 0xf8, 0x9f, 0xc9, 0xf2, 0x35, 0x97, 0xaa, 0x15, 0x45, 0xa7, 0x6e, 0xcf, 0xea, 0x66,
|
||||
0x50, 0xb7, 0xc6, 0xbf, 0x4f, 0xfb, 0xc4, 0x87, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x84,
|
||||
0xfb, 0x07, 0xc0, 0x01, 0x00, 0x00,
|
||||
// 358 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xd1, 0x6e, 0xda, 0x30,
|
||||
0x14, 0x40, 0x97, 0x64, 0xa0, 0xe1, 0x00, 0x8b, 0xbc, 0x3d, 0xe4, 0x6d, 0x81, 0x09, 0x29, 0x4f,
|
||||
0x8e, 0x94, 0xed, 0x07, 0xb6, 0x34, 0x15, 0x69, 0x55, 0x1a, 0x99, 0x80, 0x44, 0x5f, 0x22, 0xd7,
|
||||
0x32, 0x28, 0x52, 0x12, 0x23, 0xdb, 0xd0, 0xf2, 0x4b, 0xfd, 0x91, 0x7e, 0x40, 0x7f, 0xa8, 0x4a,
|
||||
0x02, 0x14, 0x9e, 0x50, 0xdf, 0x7c, 0x8f, 0xcf, 0xbd, 0xd7, 0xf7, 0x1a, 0xf8, 0x5b, 0x5f, 0x90,
|
||||
0x1d, 0xa2, 0xbc, 0xf0, 0x28, 0x17, 0xcc, 0x53, 0x82, 0x94, 0x72, 0xcd, 0x85, 0xf2, 0xb2, 0x52,
|
||||
0x31, 0x51, 0x32, 0xe5, 0xa9, 0x5c, 0x7a, 0x94, 0x97, 0xcb, 0x6c, 0x85, 0xd6, 0x82, 0x2b, 0x0e,
|
||||
0x07, 0x87, 0x1c, 0xc1, 0xd0, 0xd1, 0x47, 0x07, 0x1f, 0xa9, 0x5c, 0x0e, 0xdf, 0x34, 0x60, 0x06,
|
||||
0x4c, 0xa8, 0x6c, 0x99, 0x51, 0xa2, 0x18, 0x74, 0xce, 0x42, 0x5b, 0x73, 0x34, 0xb7, 0x8b, 0xcf,
|
||||
0x0c, 0x0b, 0x18, 0xb7, 0x6c, 0x67, 0xeb, 0xf5, 0x4d, 0x75, 0x84, 0x37, 0xa0, 0xb5, 0x91, 0x64,
|
||||
0xc5, 0x6c, 0xc3, 0xd1, 0xdc, 0xbe, 0xff, 0x17, 0x5d, 0x6c, 0x8b, 0x4e, 0x0a, 0xa2, 0x59, 0x95,
|
||||
0x8b, 0x9b, 0x12, 0xc3, 0x2b, 0xd0, 0xaa, 0x63, 0x68, 0x81, 0x6e, 0x38, 0x09, 0xa2, 0x78, 0x1c,
|
||||
0xe2, 0xbb, 0x70, 0x92, 0x58, 0x5f, 0xe0, 0x4f, 0x60, 0xfd, 0x9b, 0x25, 0xe3, 0x7b, 0x1c, 0x25,
|
||||
0x8b, 0x74, 0x1e, 0xe2, 0xe8, 0x7a, 0x61, 0x69, 0xf0, 0x07, 0xf8, 0xfe, 0x41, 0xa3, 0xe9, 0x74,
|
||||
0x16, 0x5a, 0xfa, 0xf0, 0x55, 0x03, 0xed, 0xa0, 0xde, 0x04, 0x1c, 0x81, 0x3e, 0xc9, 0x73, 0xfe,
|
||||
0x94, 0x66, 0xa5, 0x64, 0x74, 0x23, 0x9a, 0x99, 0xbe, 0xe1, 0x5e, 0x4d, 0xa3, 0x3d, 0x84, 0x31,
|
||||
0x30, 0xe9, 0xc9, 0xdc, 0xba, 0x63, 0xb8, 0xa6, 0x8f, 0x3e, 0x37, 0x09, 0x3e, 0x2d, 0x01, 0x7f,
|
||||
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,
|
||||
}
|
||||
|
|
|
@ -12,6 +12,14 @@ message Certificate {
|
|||
|
||||
// TLS key in x509 format.
|
||||
bytes Key = 2;
|
||||
|
||||
enum Usage {
|
||||
ENCIPHERMENT = 0;
|
||||
AUTHORITY_VERIFY = 1;
|
||||
AUTHORITY_ISSUE = 2;
|
||||
}
|
||||
|
||||
Usage usage = 3;
|
||||
}
|
||||
|
||||
message Config {
|
||||
|
@ -26,4 +34,4 @@ message Config {
|
|||
|
||||
// Lists of string as ALPN values.
|
||||
repeated string next_protocol = 4;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ import (
|
|||
"time"
|
||||
|
||||
"v2ray.com/core/common/net"
|
||||
tlsgen "v2ray.com/core/testing/tls"
|
||||
"v2ray.com/core/common/protocol/tls/cert"
|
||||
"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/ext/assert"
|
||||
)
|
||||
|
@ -109,9 +109,9 @@ func Test_listenWSAndDial_TLS(t *testing.T) {
|
|||
ctx := internet.ContextWithTransportSettings(context.Background(), &Config{
|
||||
Path: "wss",
|
||||
})
|
||||
ctx = internet.ContextWithSecuritySettings(ctx, &v2tls.Config{
|
||||
ctx = internet.ContextWithSecuritySettings(ctx, &tls.Config{
|
||||
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) {
|
||||
go func() {
|
||||
|
|
Loading…
Reference in New Issue