Compare commits

..

9 Commits

Author SHA1 Message Date
RPRX
523c416bb5 v1.2.4 2021-01-31 11:56:39 +00:00
eMeab
c13b8ec9bb Fix OCSP Stapling (#172)
Co-authored-by: RPRX <63339210+rprx@users.noreply.github.com>
2021-01-30 23:17:07 +00:00
Jim Han
4cd343f2d5 Fix tests (#201)
Co-authored-by: RPRX <63339210+rprx@users.noreply.github.com>
2021-01-30 13:01:20 +00:00
RPRX
d032a8deb7 Fix acceptProxyProtocol
https://github.com/XTLS/Xray-core/pull/182#issuecomment-768336178
2021-01-28 12:08:57 +00:00
RPRX
303fd6e261 Standardize Socks Outbound Authentication Behavior 2021-01-28 03:11:17 +00:00
RPRX
c880b916ee Avoid panic in BytesTo func 2021-01-27 01:09:58 +00:00
RPRX
ceff4185dc Improve the request for UDP Associate in Socks5 2021-01-26 23:53:01 +00:00
RPRX
59c7c4897c Add luci-app-xray (openwrt-xray) 2021-01-26 22:50:28 +00:00
RPRX
8ffc430351 Fix VLESS & Trojan fallbacks xver 2021-01-23 21:06:15 +00:00
17 changed files with 153 additions and 83 deletions

View File

@@ -34,6 +34,7 @@
- [PassWall](https://github.com/xiaorouji/openwrt-passwall)
- [Hello World](https://github.com/jerrykuku/luci-app-vssr)
- [ShadowSocksR Plus+](https://github.com/fw876/helloworld)
- [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray))
- Windows
- [v2rayN](https://github.com/2dust/v2rayN)
- [Qv2ray](https://github.com/Qv2ray/Qv2ray)

View File

@@ -18,10 +18,10 @@ func init() {
common.Must(err)
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "release", "config", "geoip.dat")))
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
}
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "release", "config", "geosite.dat")))
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "resources", "geosite.dat")))
}
}

View File

@@ -110,6 +110,9 @@ func (b *Buffer) BytesTo(to int32) []byte {
if to < 0 {
to += b.Len()
}
if to < 0 {
to = 0
}
return b.v[b.start : b.start+to]
}

View File

@@ -55,7 +55,7 @@ func TestAddressReading(t *testing.T) {
},
{
Options: []AddressOption{AddressFamilyByte(0x03, net.AddressFamilyDomain)},
Input: []byte{3, 9, 118, 50, 114, 97, 121, 46, 99, 111, 109, 0, 80},
Input: []byte{3, 11, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 0, 80},
Address: net.DomainAddress("example.com"),
Port: net.Port(80),
},
@@ -84,8 +84,9 @@ func TestAddressReading(t *testing.T) {
}
for _, tc := range data {
b := buf.New()
parser := NewAddressParser(tc.Options...)
b := buf.New()
addr, port, err := parser.ReadAddressPort(b, bytes.NewReader(tc.Input))
b.Release()
if tc.Error {

View File

@@ -18,7 +18,7 @@ import (
)
var (
version = "1.2.3"
version = "1.2.4"
build = "Custom"
codename = "Xray, Penetrates Everything."
intro = "A unified platform for anti-censorship."

View File

@@ -195,11 +195,13 @@ func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
}
if l >= 17 && s[11:17] == "trojan" || l >= 22 && s[11:22] == "shadowsocks" {
t = true
var m proxyman.SenderConfig
proto.Unmarshal(outbound.SenderSettings.Value, &m)
if m.MultiplexSettings != nil && m.MultiplexSettings.Enabled {
cone = false
break
if outbound.SenderSettings != nil {
var m proxyman.SenderConfig
proto.Unmarshal(outbound.SenderSettings.Value, &m)
if m.MultiplexSettings != nil && m.MultiplexSettings.Enabled {
cone = false
break
}
}
}
}

8
go.mod
View File

@@ -9,17 +9,17 @@ require (
github.com/google/go-cmp v0.5.4
github.com/gorilla/websocket v1.4.2
github.com/lucas-clemente/quic-go v0.19.3
github.com/miekg/dns v1.1.35
github.com/miekg/dns v1.1.37
github.com/pelletier/go-toml v1.8.1
github.com/pires/go-proxyproto v0.4.1
github.com/pires/go-proxyproto v0.4.2
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c
github.com/stretchr/testify v1.7.0
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499
go.starlark.net v0.0.0-20210121225809-cea917ab6e0f
go.starlark.net v0.0.0-20210126161401-bc864be25151
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
golang.org/x/net v0.0.0-20210119194325-5f4716e94777
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
google.golang.org/grpc v1.35.0
google.golang.org/protobuf v1.25.0
h12.io/socks v1.0.2

16
go.sum
View File

@@ -107,8 +107,8 @@ github.com/marten-seemann/qtls-go1-15 v0.1.1 h1:LIH6K34bPVttyXnUWixk0bzH6/N07Vxb
github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.37 h1:+kky2ArpBqk0S/74RkwFjmKM9jja7AB1RN7VUuVq0iM=
github.com/miekg/dns v1.1.37/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
@@ -127,8 +127,8 @@ github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNC
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pires/go-proxyproto v0.4.1 h1:30QkyOjKU3FcTLiu1359sSQ7ml56wpM4i/uViqODSsI=
github.com/pires/go-proxyproto v0.4.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pires/go-proxyproto v0.4.2 h1:VRAvsUCTrmiahoU5fqQqkbY0GWcJ1Q0F7b7CkFaipSU=
github.com/pires/go-proxyproto v0.4.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -180,8 +180,8 @@ github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 h1:QHESTXtfgc1ABV+ArlbPVqU
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499/go.mod h1:5TB2+k58gx4A4g2Nf5miSHNDF6CuAzHKpWBooLAshTs=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.starlark.net v0.0.0-20210121225809-cea917ab6e0f h1:MfDkeyR3bphbh1zJ3Z7cTsZ8Ydd4mXQiBEhcZRltwaM=
go.starlark.net v0.0.0-20210121225809-cea917ab6e0f/go.mod h1:vxxlMsgCAPH7BR2LtxjJC4WhhZhCGd/b01+CIpj8H4k=
go.starlark.net v0.0.0-20210126161401-bc864be25151 h1:BkNycm5DBve8zINASgjl15CPNQq/xuZ0ViAlir4sUcw=
go.starlark.net v0.0.0-20210126161401-bc864be25151/go.mod h1:vxxlMsgCAPH7BR2LtxjJC4WhhZhCGd/b01+CIpj8H4k=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -244,8 +244,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@@ -21,7 +21,7 @@ func init() {
common.Must(err)
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "release", "config", "geoip.dat")))
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
}
geositeFilePath := filepath.Join(wd, "geosite.dat")
@@ -112,6 +112,11 @@ func TestDNSConfigParsing(t *testing.T) {
Domain: "example.com",
ProxiedDomain: "google.com",
},
{
Type: dns.DomainMatchingType_Full,
Domain: "example.com",
Ip: [][]byte{{127, 0, 0, 1}},
},
{
Type: dns.DomainMatchingType_Full,
Domain: "example.com",
@@ -127,11 +132,6 @@ func TestDNSConfigParsing(t *testing.T) {
Domain: ".*\\.com",
Ip: [][]byte{{8, 8, 4, 4}},
},
{
Type: dns.DomainMatchingType_Full,
Domain: "example.com",
Ip: [][]byte{{127, 0, 0, 1}},
},
},
ClientIp: []byte{10, 0, 0, 1},
},

View File

@@ -45,7 +45,7 @@ func TestUDPEncoding(t *testing.T) {
t.Error("data: ", r)
}
if r := cmp.Diff(decodedRequest, request); r != "" {
if r := cmp.Diff(decodedRequest, request, cmp.Comparer(func(a1, a2 protocol.Account) bool { return a1.Equals(a2) })); r != "" {
t.Error("request: ", r)
}
}
@@ -119,7 +119,7 @@ func TestTCPRequest(t *testing.T) {
decodedRequest, reader, err := ReadTCPSession([]*protocol.MemoryUser{request.User}, cache)
common.Must(err)
if r := cmp.Diff(decodedRequest, request); r != "" {
if r := cmp.Diff(decodedRequest, request, cmp.Comparer(func(a1, a2 protocol.Account) bool { return a1.Equals(a2) })); r != "" {
t.Error("request: ", r)
}

View File

@@ -422,16 +422,6 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
defer b.Release()
common.Must2(b.Write([]byte{socks5Version, 0x01, authByte}))
if authByte == authPassword {
account := request.User.Account.(*Account)
common.Must(b.WriteByte(0x01))
common.Must(b.WriteByte(byte(len(account.Username))))
common.Must2(b.WriteString(account.Username))
common.Must(b.WriteByte(byte(len(account.Password))))
common.Must2(b.WriteString(account.Password))
}
if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {
return nil, err
}
@@ -449,6 +439,17 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
}
if authByte == authPassword {
b.Clear()
account := request.User.Account.(*Account)
common.Must(b.WriteByte(0x01))
common.Must(b.WriteByte(byte(len(account.Username))))
common.Must2(b.WriteString(account.Username))
common.Must(b.WriteByte(byte(len(account.Password))))
common.Must2(b.WriteString(account.Password))
if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {
return nil, err
}
b.Clear()
if _, err := b.ReadFullFrom(reader, 2); err != nil {
return nil, err
@@ -465,8 +466,12 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
command = byte(cmdUDPAssociate)
}
common.Must2(b.Write([]byte{socks5Version, command, 0x00 /* reserved */}))
if err := addrParser.WriteAddressPort(b, request.Address, request.Port); err != nil {
return nil, err
if request.Command == protocol.RequestCommandUDP {
common.Must2(b.Write([]byte{1, 0, 0, 0, 0, 0, 0 /* RFC 1928 */}))
} else {
if err := addrParser.WriteAddressPort(b, request.Address, request.Port); err != nil {
return nil, err
}
}
if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {

View File

@@ -500,19 +500,16 @@ func (s *Server) fallback(ctx context.Context, sid errors.ExportOption, err erro
postRequest := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
if fb.Xver != 0 {
var remoteAddr, remotePort, localAddr, localPort string
ipType, network := 0, connection.RemoteAddr().Network()
if len(network) >= 3 && network[:3] == "tcp" {
var err error
remoteAddr, remotePort, err = net.SplitHostPort(connection.RemoteAddr().String())
if err != nil {
return err
}
localAddr, localPort, err = net.SplitHostPort(connection.LocalAddr().String())
if err != nil {
return err
}
ipType = 4
ipType := 4
remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String())
if err != nil {
ipType = 0
}
localAddr, localPort, err := net.SplitHostPort(connection.LocalAddr().String())
if err != nil {
ipType = 0
}
if ipType == 4 {
for i := 0; i < len(remoteAddr); i++ {
if remoteAddr[i] == ':' {
ipType = 6

View File

@@ -335,19 +335,16 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
postRequest := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
if fb.Xver != 0 {
var remoteAddr, remotePort, localAddr, localPort string
ipType, network := 0, connection.RemoteAddr().Network()
if len(network) >= 3 && network[:3] == "tcp" {
var err error
remoteAddr, remotePort, err = net.SplitHostPort(connection.RemoteAddr().String())
if err != nil {
return err
}
localAddr, localPort, err = net.SplitHostPort(connection.LocalAddr().String())
if err != nil {
return err
}
ipType = 4
ipType := 4
remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String())
if err != nil {
ipType = 0
}
localAddr, localPort, err := net.SplitHostPort(connection.LocalAddr().String())
if err != nil {
ipType = 0
}
if ipType == 4 {
for i := 0; i < len(remoteAddr); i++ {
if remoteAddr[i] == ':' {
ipType = 6

View File

@@ -118,7 +118,7 @@ func genTestBinaryPath() {
}
func GetSourcePath() string {
return filepath.Join("example.com", "core", "main")
return filepath.Join("github.com", "xtls", "xray-core", "main")
}
func CloseAllServers(servers []*exec.Cmd) {

View File

@@ -17,6 +17,8 @@ func BuildXray() error {
fmt.Printf("Building Xray into path (%s)\n", testBinaryPath)
cmd := exec.Command("go", "build", "-o="+testBinaryPath, GetSourcePath())
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}

View File

@@ -42,8 +42,8 @@ func (c *Config) loadSelfCertPool() (*x509.CertPool, error) {
}
// BuildCertificates builds a list of TLS certificates from proto definition.
func (c *Config) BuildCertificates() []tls.Certificate {
certs := make([]tls.Certificate, 0, len(c.Certificate))
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
@@ -53,7 +53,12 @@ func (c *Config) BuildCertificates() []tls.Certificate {
newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
continue
}
certs = append(certs, keyPair)
keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
if err != nil {
newError("ignoring invalid certificate").Base(err).AtWarning().WriteToLog()
continue
}
certs = append(certs, &keyPair)
if entry.OcspStapling != 0 {
go func(cert *tls.Certificate) {
t := time.NewTicker(time.Duration(entry.OcspStapling) * time.Second)
@@ -65,7 +70,7 @@ func (c *Config) BuildCertificates() []tls.Certificate {
}
<-t.C
}
}(&certs[len(certs)-1])
}(certs[len(certs)-1])
}
}
return certs
@@ -169,6 +174,33 @@ func getGetCertificateFunc(c *tls.Config, ca []*Certificate) func(hello *tls.Cli
}
}
func getNewGetCertficateFunc(certs []*tls.Certificate) func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
return func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
if len(certs) == 0 {
return nil, newError("empty certs")
}
sni := strings.ToLower(hello.ServerName)
if len(certs) == 1 || sni == "" {
return certs[0], nil
}
gsni := "*"
if index := strings.IndexByte(sni, '.'); index != -1 {
gsni += sni[index:]
}
for _, keyPair := range certs {
if keyPair.Leaf.Subject.CommonName == sni || keyPair.Leaf.Subject.CommonName == gsni {
return keyPair, nil
}
for _, name := range keyPair.Leaf.DNSNames {
if name == sni || name == gsni {
return keyPair, nil
}
}
}
return certs[0], nil
}
}
func (c *Config) IsExperiment8357() bool {
return strings.HasPrefix(c.ServerName, exp8357)
}
@@ -210,12 +242,11 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
opt(config)
}
config.Certificates = c.BuildCertificates()
config.BuildNameToCertificate()
caCerts := c.getCustomCA()
if len(caCerts) > 0 {
config.GetCertificate = getGetCertificateFunc(config, caCerts)
} else {
config.GetCertificate = getNewGetCertficateFunc(c.BuildCertificates())
}
if sn := c.parseServerName(); len(sn) > 0 {

View File

@@ -41,8 +41,8 @@ func (c *Config) loadSelfCertPool() (*x509.CertPool, error) {
}
// BuildCertificates builds a list of TLS certificates from proto definition.
func (c *Config) BuildCertificates() []xtls.Certificate {
certs := make([]xtls.Certificate, 0, len(c.Certificate))
func (c *Config) BuildCertificates() []*xtls.Certificate {
certs := make([]*xtls.Certificate, 0, len(c.Certificate))
for _, entry := range c.Certificate {
if entry.Usage != Certificate_ENCIPHERMENT {
continue
@@ -52,7 +52,12 @@ func (c *Config) BuildCertificates() []xtls.Certificate {
newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
continue
}
certs = append(certs, keyPair)
keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
if err != nil {
newError("ignoring invalid certificate").Base(err).AtWarning().WriteToLog()
continue
}
certs = append(certs, &keyPair)
if entry.OcspStapling != 0 {
go func(cert *xtls.Certificate) {
t := time.NewTicker(time.Duration(entry.OcspStapling) * time.Second)
@@ -64,7 +69,7 @@ func (c *Config) BuildCertificates() []xtls.Certificate {
}
<-t.C
}
}(&certs[len(certs)-1])
}(certs[len(certs)-1])
}
}
return certs
@@ -168,6 +173,33 @@ func getGetCertificateFunc(c *xtls.Config, ca []*Certificate) func(hello *xtls.C
}
}
func getNewGetCertficateFunc(certs []*xtls.Certificate) func(hello *xtls.ClientHelloInfo) (*xtls.Certificate, error) {
return func(hello *xtls.ClientHelloInfo) (*xtls.Certificate, error) {
if len(certs) == 0 {
return nil, newError("empty certs")
}
sni := strings.ToLower(hello.ServerName)
if len(certs) == 1 || sni == "" {
return certs[0], nil
}
gsni := "*"
if index := strings.IndexByte(sni, '.'); index != -1 {
gsni += sni[index:]
}
for _, keyPair := range certs {
if keyPair.Leaf.Subject.CommonName == sni || keyPair.Leaf.Subject.CommonName == gsni {
return keyPair, nil
}
for _, name := range keyPair.Leaf.DNSNames {
if name == sni || name == gsni {
return keyPair, nil
}
}
}
return certs[0], nil
}
}
func (c *Config) parseServerName() string {
return c.ServerName
}
@@ -201,12 +233,11 @@ func (c *Config) GetXTLSConfig(opts ...Option) *xtls.Config {
opt(config)
}
config.Certificates = c.BuildCertificates()
config.BuildNameToCertificate()
caCerts := c.getCustomCA()
if len(caCerts) > 0 {
config.GetCertificate = getGetCertificateFunc(config, caCerts)
} else {
config.GetCertificate = getNewGetCertficateFunc(c.BuildCertificates())
}
if sn := c.parseServerName(); len(sn) > 0 {