mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-23 18:16:50 +08:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
573b7807c0 | ||
![]() |
81d993158f | ||
![]() |
df39991bb3 | ||
![]() |
1b87264c53 | ||
![]() |
96d7156eba | ||
![]() |
d170416219 | ||
![]() |
8ca8a7126b | ||
![]() |
1174ff3090 |
@@ -330,7 +330,7 @@ func (m *ClientWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.Buffere
|
||||
return buf.Copy(NewStreamReader(reader), buf.Discard)
|
||||
}
|
||||
|
||||
rr := s.NewReader(reader)
|
||||
rr := s.NewReader(reader, &meta.Target)
|
||||
err := buf.Copy(rr, s.output)
|
||||
if err != nil && buf.IsWriteError(err) {
|
||||
newError("failed to write to downstream. closing session ", s.ID).Base(err).WriteToLog()
|
||||
|
@@ -81,6 +81,9 @@ func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
||||
if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if b.UDP != nil {
|
||||
b.WriteByte(byte(TargetNetworkUDP))
|
||||
addrParser.WriteAddressPort(b, b.UDP.Address, b.UDP.Port)
|
||||
}
|
||||
|
||||
len1 := b.Len()
|
||||
@@ -119,7 +122,7 @@ func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
|
||||
f.Option = bitmask.Byte(b.Byte(3))
|
||||
f.Target.Network = net.Network_Unknown
|
||||
|
||||
if f.SessionStatus == SessionStatusNew {
|
||||
if f.SessionStatus == SessionStatusNew || (f.SessionStatus == SessionStatusKeep && b.Len() != 4) {
|
||||
if b.Len() < 8 {
|
||||
return newError("insufficient buffer: ", b.Len())
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/crypto"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
)
|
||||
|
||||
@@ -12,13 +13,15 @@ import (
|
||||
type PacketReader struct {
|
||||
reader io.Reader
|
||||
eof bool
|
||||
dest *net.Destination
|
||||
}
|
||||
|
||||
// NewPacketReader creates a new PacketReader.
|
||||
func NewPacketReader(reader io.Reader) *PacketReader {
|
||||
func NewPacketReader(reader io.Reader, dest *net.Destination) *PacketReader {
|
||||
return &PacketReader{
|
||||
reader: reader,
|
||||
eof: false,
|
||||
dest: dest,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +46,9 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
return nil, err
|
||||
}
|
||||
r.eof = true
|
||||
if r.dest != nil && r.dest.Network == net.Network_UDP {
|
||||
b.UDP = r.dest
|
||||
}
|
||||
return buf.MultiBuffer{b}, nil
|
||||
}
|
||||
|
||||
|
@@ -145,7 +145,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
|
||||
return nil
|
||||
}
|
||||
|
||||
rr := s.NewReader(reader)
|
||||
rr := s.NewReader(reader, &meta.Target)
|
||||
if err := buf.Copy(rr, s.output); err != nil {
|
||||
buf.Copy(rr, buf.Discard)
|
||||
common.Interrupt(s.input)
|
||||
@@ -168,7 +168,7 @@ func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.Buffere
|
||||
return buf.Copy(NewStreamReader(reader), buf.Discard)
|
||||
}
|
||||
|
||||
rr := s.NewReader(reader)
|
||||
rr := s.NewReader(reader, &meta.Target)
|
||||
err := buf.Copy(rr, s.output)
|
||||
|
||||
if err != nil && buf.IsWriteError(err) {
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
)
|
||||
|
||||
@@ -152,9 +153,9 @@ func (s *Session) Close() error {
|
||||
}
|
||||
|
||||
// NewReader creates a buf.Reader based on the transfer type of this Session.
|
||||
func (s *Session) NewReader(reader *buf.BufferedReader) buf.Reader {
|
||||
func (s *Session) NewReader(reader *buf.BufferedReader, dest *net.Destination) buf.Reader {
|
||||
if s.transferType == protocol.TransferTypeStream {
|
||||
return NewStreamReader(reader)
|
||||
}
|
||||
return NewPacketReader(reader)
|
||||
return NewPacketReader(reader, dest)
|
||||
}
|
||||
|
@@ -63,6 +63,9 @@ func (w *Writer) writeMetaOnly() error {
|
||||
|
||||
func writeMetaWithFrame(writer buf.Writer, meta FrameMetadata, data buf.MultiBuffer) error {
|
||||
frame := buf.New()
|
||||
if len(data) == 1 {
|
||||
frame.UDP = data[0].UDP
|
||||
}
|
||||
if err := meta.WriteTo(frame); err != nil {
|
||||
return err
|
||||
}
|
||||
|
137
common/xudp/xudp.go
Normal file
137
common/xudp/xudp.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package xudp
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
)
|
||||
|
||||
var addrParser = protocol.NewAddressParser(
|
||||
protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv4), net.AddressFamilyIPv4),
|
||||
protocol.AddressFamilyByte(byte(protocol.AddressTypeDomain), net.AddressFamilyDomain),
|
||||
protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv6), net.AddressFamilyIPv6),
|
||||
protocol.PortThenAddress(),
|
||||
)
|
||||
|
||||
func NewPacketWriter(writer buf.Writer, dest net.Destination) *PacketWriter {
|
||||
return &PacketWriter{
|
||||
Writer: writer,
|
||||
Dest: dest,
|
||||
}
|
||||
}
|
||||
|
||||
type PacketWriter struct {
|
||||
Writer buf.Writer
|
||||
Dest net.Destination
|
||||
}
|
||||
|
||||
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
defer buf.ReleaseMulti(mb)
|
||||
mb2Write := make(buf.MultiBuffer, 0, len(mb))
|
||||
for _, b := range mb {
|
||||
length := b.Len()
|
||||
if length == 0 || length+666 > buf.Size {
|
||||
continue
|
||||
}
|
||||
|
||||
eb := buf.New()
|
||||
eb.Write([]byte{0, 0, 0, 0})
|
||||
if w.Dest.Network == net.Network_UDP {
|
||||
eb.WriteByte(1) // New
|
||||
eb.WriteByte(1) // Opt
|
||||
eb.WriteByte(2) // UDP
|
||||
addrParser.WriteAddressPort(eb, w.Dest.Address, w.Dest.Port)
|
||||
w.Dest.Network = net.Network_Unknown
|
||||
} else {
|
||||
eb.WriteByte(2) // Keep
|
||||
eb.WriteByte(1)
|
||||
if b.UDP != nil {
|
||||
eb.WriteByte(2)
|
||||
addrParser.WriteAddressPort(eb, b.UDP.Address, b.UDP.Port)
|
||||
}
|
||||
}
|
||||
l := eb.Len() - 2
|
||||
eb.SetByte(0, byte(l>>8))
|
||||
eb.SetByte(1, byte(l))
|
||||
eb.WriteByte(byte(length >> 8))
|
||||
eb.WriteByte(byte(length))
|
||||
eb.Write(b.Bytes())
|
||||
|
||||
mb2Write = append(mb2Write, eb)
|
||||
}
|
||||
if mb2Write.IsEmpty() {
|
||||
return nil
|
||||
}
|
||||
return w.Writer.WriteMultiBuffer(mb2Write)
|
||||
}
|
||||
|
||||
func NewPacketReader(reader io.Reader) *PacketReader {
|
||||
return &PacketReader{
|
||||
Reader: reader,
|
||||
cache: make([]byte, 2),
|
||||
}
|
||||
}
|
||||
|
||||
type PacketReader struct {
|
||||
Reader io.Reader
|
||||
cache []byte
|
||||
}
|
||||
|
||||
func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
for {
|
||||
if _, err := io.ReadFull(r.Reader, r.cache); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := int32(r.cache[0])<<8 | int32(r.cache[1])
|
||||
if l < 4 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
b := buf.New()
|
||||
if _, err := b.ReadFullFrom(r.Reader, l); err != nil {
|
||||
b.Release()
|
||||
return nil, err
|
||||
}
|
||||
discard := false
|
||||
switch b.Byte(2) {
|
||||
case 2:
|
||||
if l != 4 {
|
||||
b.Advance(5)
|
||||
addr, port, err := addrParser.ReadAddressPort(nil, b)
|
||||
if err != nil {
|
||||
b.Release()
|
||||
return nil, err
|
||||
}
|
||||
b.UDP = &net.Destination{
|
||||
Network: net.Network_UDP,
|
||||
Address: addr,
|
||||
Port: port,
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
discard = true
|
||||
default:
|
||||
b.Release()
|
||||
return nil, io.EOF
|
||||
}
|
||||
if b.Byte(3) == 1 {
|
||||
if _, err := io.ReadFull(r.Reader, r.cache); err != nil {
|
||||
b.Release()
|
||||
return nil, err
|
||||
}
|
||||
length := int32(r.cache[0])<<8 | int32(r.cache[1])
|
||||
if length > 0 {
|
||||
b.Clear()
|
||||
if _, err := b.ReadFullFrom(r.Reader, length); err != nil {
|
||||
b.Release()
|
||||
return nil, err
|
||||
}
|
||||
if !discard {
|
||||
return buf.MultiBuffer{b}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
b.Release()
|
||||
}
|
||||
}
|
@@ -22,9 +22,13 @@ type ConfigFormat struct {
|
||||
// ConfigLoader is a utility to load Xray config from external source.
|
||||
type ConfigLoader func(input interface{}) (*Config, error)
|
||||
|
||||
// ConfigBuilder is a builder to build core.Config from filenames and formats
|
||||
type ConfigBuilder func(files []string, formats []string) (*Config, error)
|
||||
|
||||
var (
|
||||
configLoaderByName = make(map[string]*ConfigFormat)
|
||||
configLoaderByExt = make(map[string]*ConfigFormat)
|
||||
configLoaderByName = make(map[string]*ConfigFormat)
|
||||
configLoaderByExt = make(map[string]*ConfigFormat)
|
||||
ConfigBuilderForFiles ConfigBuilder
|
||||
)
|
||||
|
||||
// RegisterConfigLoader add a new ConfigLoader.
|
||||
@@ -46,6 +50,21 @@ func RegisterConfigLoader(format *ConfigFormat) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetFormatByExtension(ext string) string {
|
||||
switch strings.ToLower(ext) {
|
||||
case "pb", "protobuf":
|
||||
return "protobuf"
|
||||
case "yaml", "yml":
|
||||
return "yaml"
|
||||
case "toml":
|
||||
return "toml"
|
||||
case "json":
|
||||
return "json"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func getExtension(filename string) string {
|
||||
idx := strings.LastIndexByte(filename, '.')
|
||||
if idx == -1 {
|
||||
@@ -54,23 +73,48 @@ func getExtension(filename string) string {
|
||||
return filename[idx+1:]
|
||||
}
|
||||
|
||||
// LoadConfig loads config with given format from given source.
|
||||
// input accepts 2 different types:
|
||||
// * []string slice of multiple filename/url(s) to open to read
|
||||
// * io.Reader that reads a config content (the original way)
|
||||
func LoadConfig(formatName string, filename string, input interface{}) (*Config, error) {
|
||||
ext := getExtension(filename)
|
||||
if len(ext) > 0 {
|
||||
if f, found := configLoaderByExt[ext]; found {
|
||||
return f.Loader(input)
|
||||
func getFormat(filename string) string {
|
||||
return GetFormatByExtension(getExtension(filename))
|
||||
}
|
||||
|
||||
func LoadConfig(formatName string, input interface{}) (*Config, error) {
|
||||
switch v := input.(type) {
|
||||
case cmdarg.Arg:
|
||||
|
||||
formats := make([]string, len(v))
|
||||
hasProtobuf := false
|
||||
for i, file := range v {
|
||||
f := getFormat(file)
|
||||
if f == "" {
|
||||
f = formatName
|
||||
}
|
||||
if f == "protobuf" {
|
||||
hasProtobuf = true
|
||||
}
|
||||
formats[i] = f
|
||||
}
|
||||
|
||||
// only one protobuf config file is allowed
|
||||
if hasProtobuf {
|
||||
if len(v) == 1 {
|
||||
return configLoaderByName["protobuf"].Loader(v)
|
||||
} else {
|
||||
return nil, newError("Only one protobuf config file is allowed").AtWarning()
|
||||
}
|
||||
}
|
||||
|
||||
// to avoid import cycle
|
||||
return ConfigBuilderForFiles(v, formats)
|
||||
|
||||
case io.Reader:
|
||||
if f, found := configLoaderByName[formatName]; found {
|
||||
return f.Loader(v)
|
||||
} else {
|
||||
return nil, newError("Unable to load config in", formatName).AtWarning()
|
||||
}
|
||||
}
|
||||
|
||||
if f, found := configLoaderByName[formatName]; found {
|
||||
return f.Loader(input)
|
||||
}
|
||||
|
||||
return nil, newError("Unable to load config in ", formatName).AtWarning()
|
||||
return nil, newError("Unable to load config").AtWarning()
|
||||
}
|
||||
|
||||
func loadProtobufConfig(data []byte) (*Config, error) {
|
||||
|
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
version = "1.2.4"
|
||||
version = "1.3.0"
|
||||
build = "Custom"
|
||||
codename = "Xray, Penetrates Everything."
|
||||
intro = "A unified platform for anti-censorship."
|
||||
|
@@ -25,7 +25,7 @@ func CreateObject(v *Instance, config interface{}) (interface{}, error) {
|
||||
//
|
||||
// xray:api:stable
|
||||
func StartInstance(configFormat string, configBytes []byte) (*Instance, error) {
|
||||
config, err := LoadConfig(configFormat, "", bytes.NewReader(configBytes))
|
||||
config, err := LoadConfig(configFormat, bytes.NewReader(configBytes))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
33
core/xray.go
33
core/xray.go
@@ -2,14 +2,10 @@ package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
"github.com/xtls/xray-core/app/proxyman"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
"github.com/xtls/xray-core/features"
|
||||
@@ -184,32 +180,7 @@ func NewWithContext(ctx context.Context, config *Config) (*Instance, error) {
|
||||
}
|
||||
|
||||
func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
|
||||
cone := true
|
||||
v, t := false, false
|
||||
for _, outbound := range config.Outbound {
|
||||
s := strings.ToLower(outbound.ProxySettings.Type)
|
||||
l := len(s)
|
||||
if l >= 16 && s[11:16] == "vless" || l >= 16 && s[11:16] == "vmess" {
|
||||
v = true
|
||||
continue
|
||||
}
|
||||
if l >= 17 && s[11:17] == "trojan" || l >= 22 && s[11:22] == "shadowsocks" {
|
||||
t = true
|
||||
if outbound.SenderSettings != nil {
|
||||
var m proxyman.SenderConfig
|
||||
proto.Unmarshal(outbound.SenderSettings.Value, &m)
|
||||
if m.MultiplexSettings != nil && m.MultiplexSettings.Enabled {
|
||||
cone = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if v && !t {
|
||||
cone = false
|
||||
}
|
||||
server.ctx = context.WithValue(server.ctx, "cone", cone)
|
||||
defer debug.FreeOSMemory()
|
||||
server.ctx = context.WithValue(server.ctx, "cone", os.Getenv("XRAY_CONE_DISABLED") != "true")
|
||||
|
||||
if config.Transport != nil {
|
||||
features.PrintDeprecatedFeatureWarning("global transport settings")
|
||||
|
44
infra/conf/serial/builder.go
Normal file
44
infra/conf/serial/builder.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package serial
|
||||
|
||||
import (
|
||||
"github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/infra/conf"
|
||||
"github.com/xtls/xray-core/main/confloader"
|
||||
"io"
|
||||
)
|
||||
|
||||
func BuildConfig(files []string, formats []string) (*core.Config, error) {
|
||||
|
||||
cf := &conf.Config{}
|
||||
for i, file := range files {
|
||||
newError("Reading config: ", file).AtInfo().WriteToLog()
|
||||
r, err := confloader.LoadConfig(file)
|
||||
if err != nil {
|
||||
return nil, newError("failed to read config: ", file).Base(err)
|
||||
}
|
||||
c, err := ReaderDecoderByFormat[formats[i]](r)
|
||||
if err != nil {
|
||||
return nil, newError("failed to decode config: ", file).Base(err)
|
||||
}
|
||||
if i == 0 {
|
||||
*cf = *c
|
||||
continue
|
||||
}
|
||||
cf.Override(c, file)
|
||||
}
|
||||
return cf.Build()
|
||||
}
|
||||
|
||||
type readerDecoder func(io.Reader) (*conf.Config, error)
|
||||
|
||||
var (
|
||||
ReaderDecoderByFormat = make(map[string]readerDecoder)
|
||||
)
|
||||
|
||||
func init() {
|
||||
ReaderDecoderByFormat["json"] = DecodeJSONConfig
|
||||
ReaderDecoderByFormat["yaml"] = DecodeYAMLConfig
|
||||
ReaderDecoderByFormat["toml"] = DecodeTOMLConfig
|
||||
|
||||
core.ConfigBuilderForFiles = BuildConfig
|
||||
}
|
@@ -264,6 +264,7 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
|
||||
return nil, newError("failed to parse certificate").Base(err)
|
||||
}
|
||||
certificate.Certificate = cert
|
||||
certificate.CertificatePath = c.CertFile
|
||||
|
||||
if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
|
||||
key, err := readFileOrString(c.KeyFile, c.KeyStr)
|
||||
@@ -271,6 +272,7 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
|
||||
return nil, newError("failed to parse key").Base(err)
|
||||
}
|
||||
certificate.Key = key
|
||||
certificate.KeyPath = c.KeyFile
|
||||
}
|
||||
|
||||
switch strings.ToLower(c.Usage) {
|
||||
@@ -348,6 +350,7 @@ func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) {
|
||||
return nil, newError("failed to parse certificate").Base(err)
|
||||
}
|
||||
certificate.Certificate = cert
|
||||
certificate.CertificatePath = c.CertFile
|
||||
|
||||
if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
|
||||
key, err := readFileOrString(c.KeyFile, c.KeyStr)
|
||||
@@ -355,6 +358,7 @@ func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) {
|
||||
return nil, newError("failed to parse key").Base(err)
|
||||
}
|
||||
certificate.Key = key
|
||||
certificate.KeyPath = c.KeyFile
|
||||
}
|
||||
|
||||
switch strings.ToLower(c.Usage) {
|
||||
|
20
main/run.go
20
main/run.go
@@ -11,7 +11,6 @@ import (
|
||||
"regexp"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/xtls/xray-core/common/cmdarg"
|
||||
@@ -158,30 +157,25 @@ func getConfigFilePath() cmdarg.Arg {
|
||||
}
|
||||
|
||||
func getConfigFormat() string {
|
||||
switch strings.ToLower(*format) {
|
||||
case "pb", "protobuf":
|
||||
return "protobuf"
|
||||
case "yaml", "yml":
|
||||
return "yaml"
|
||||
case "toml":
|
||||
return "toml"
|
||||
default:
|
||||
return "json"
|
||||
f := core.GetFormatByExtension(*format)
|
||||
if f == "" {
|
||||
f = "json"
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func startXray() (core.Server, error) {
|
||||
configFiles := getConfigFilePath()
|
||||
|
||||
config, err := core.LoadConfig(getConfigFormat(), configFiles[0], configFiles)
|
||||
//config, err := core.LoadConfig(getConfigFormat(), configFiles[0], configFiles)
|
||||
|
||||
//config, err := core.LoadConfigs(getConfigFormat(), configFiles)
|
||||
c, err := core.LoadConfig(getConfigFormat(), configFiles)
|
||||
|
||||
if err != nil {
|
||||
return nil, newError("failed to load config files: [", configFiles.String(), "]").Base(err)
|
||||
}
|
||||
|
||||
server, err := core.New(config)
|
||||
server, err := core.New(c)
|
||||
if err != nil {
|
||||
return nil, newError("failed to create server").Base(err)
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@ import (
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
@@ -31,6 +33,31 @@ func (a *MemoryAccount) Equals(another protocol.Account) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *MemoryAccount) GetCipherName() string {
|
||||
switch a.Cipher.(type) {
|
||||
case *AesCfb:
|
||||
keyBytes := a.Cipher.(*AesCfb).KeyBytes
|
||||
return "AES_" + strconv.FormatInt(int64(keyBytes*8), 10) + "_CFB"
|
||||
case *ChaCha20:
|
||||
if a.Cipher.(*ChaCha20).IVBytes == 8 {
|
||||
return "CHACHA20"
|
||||
}
|
||||
return "CHACHA20_IETF"
|
||||
case *AEADCipher:
|
||||
switch reflect.ValueOf(a.Cipher.(*AEADCipher).AEADAuthCreator).Pointer() {
|
||||
case reflect.ValueOf(createAesGcm).Pointer():
|
||||
keyBytes := a.Cipher.(*AEADCipher).KeyBytes
|
||||
return "AES_" + strconv.FormatInt(int64(keyBytes*8), 10) + "_GCM"
|
||||
case reflect.ValueOf(createChacha20Poly1305).Pointer():
|
||||
return "CHACHA20_POLY1305"
|
||||
}
|
||||
case *NoneCipher:
|
||||
return "NONE"
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func createAesGcm(key []byte) cipher.AEAD {
|
||||
block, err := aes.NewCipher(key)
|
||||
common.Must(err)
|
||||
|
@@ -54,12 +54,9 @@ func (r *FullReader) Read(p []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
// ReadTCPSession reads a Shadowsocks TCP session from the given reader, returns its header and remaining parts.
|
||||
func ReadTCPSession(users []*protocol.MemoryUser, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
|
||||
user := users[0]
|
||||
account := user.Account.(*MemoryAccount)
|
||||
func ReadTCPSession(validator *Validator, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
|
||||
|
||||
hashkdf := hmac.New(sha256.New, []byte("SSBSKDF"))
|
||||
hashkdf.Write(account.Key)
|
||||
|
||||
behaviorSeed := crc32.ChecksumIEEE(hashkdf.Sum(nil))
|
||||
|
||||
@@ -71,10 +68,20 @@ func ReadTCPSession(users []*protocol.MemoryUser, reader io.Reader) (*protocol.R
|
||||
readSizeRemain := DrainSize
|
||||
|
||||
var r2 buf.Reader
|
||||
buffer := buf.New()
|
||||
defer buffer.Release()
|
||||
|
||||
if len(users) > 1 {
|
||||
buffer := buf.New()
|
||||
defer buffer.Release()
|
||||
var user *protocol.MemoryUser
|
||||
var ivLen int32
|
||||
var err error
|
||||
|
||||
count := validator.Count()
|
||||
if count == 0 {
|
||||
readSizeRemain -= int(buffer.Len())
|
||||
DrainConnN(reader, readSizeRemain)
|
||||
return nil, nil, newError("invalid user")
|
||||
} else if count > 1 {
|
||||
var aead cipher.AEAD
|
||||
|
||||
if _, err := buffer.ReadFullFrom(reader, 50); err != nil {
|
||||
readSizeRemain -= int(buffer.Len())
|
||||
@@ -83,45 +90,26 @@ func ReadTCPSession(users []*protocol.MemoryUser, reader io.Reader) (*protocol.R
|
||||
}
|
||||
|
||||
bs := buffer.Bytes()
|
||||
user, aead, _, ivLen, err = validator.Get(bs, protocol.RequestCommandTCP)
|
||||
|
||||
var aeadCipher *AEADCipher
|
||||
var ivLen int32
|
||||
subkey := make([]byte, 32)
|
||||
length := make([]byte, 16)
|
||||
var aead cipher.AEAD
|
||||
var err error
|
||||
for _, user = range users {
|
||||
account = user.Account.(*MemoryAccount)
|
||||
aeadCipher = account.Cipher.(*AEADCipher)
|
||||
ivLen = aeadCipher.IVSize()
|
||||
subkey = subkey[:aeadCipher.KeyBytes]
|
||||
hkdfSHA1(account.Key, bs[:ivLen], subkey)
|
||||
aead = aeadCipher.AEADAuthCreator(subkey)
|
||||
_, err = aead.Open(length[:0], length[4:16], bs[ivLen:ivLen+18], nil)
|
||||
if err == nil {
|
||||
reader = &FullReader{reader, bs[ivLen:]}
|
||||
auth := &crypto.AEADAuthenticator{
|
||||
AEAD: aead,
|
||||
NonceGenerator: crypto.GenerateInitialAEADNonce(),
|
||||
}
|
||||
r2 = crypto.NewAuthenticationReader(auth, &crypto.AEADChunkSizeParser{
|
||||
Auth: auth,
|
||||
}, reader, protocol.TransferTypeStream, nil)
|
||||
break
|
||||
if user != nil {
|
||||
reader = &FullReader{reader, bs[ivLen:]}
|
||||
auth := &crypto.AEADAuthenticator{
|
||||
AEAD: aead,
|
||||
NonceGenerator: crypto.GenerateInitialAEADNonce(),
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
r2 = crypto.NewAuthenticationReader(auth, &crypto.AEADChunkSizeParser{
|
||||
Auth: auth,
|
||||
}, reader, protocol.TransferTypeStream, nil)
|
||||
} else {
|
||||
readSizeRemain -= int(buffer.Len())
|
||||
DrainConnN(reader, readSizeRemain)
|
||||
return nil, nil, newError("failed to match an user").Base(err)
|
||||
}
|
||||
}
|
||||
|
||||
buffer := buf.New()
|
||||
defer buffer.Release()
|
||||
|
||||
if r2 == nil {
|
||||
ivLen := account.Cipher.IVSize()
|
||||
} else {
|
||||
user, ivLen = validator.GetOnlyUser()
|
||||
account := user.Account.(*MemoryAccount)
|
||||
hashkdf.Write(account.Key)
|
||||
var iv []byte
|
||||
if ivLen > 0 {
|
||||
if _, err := buffer.ReadFullFrom(reader, ivLen); err != nil {
|
||||
@@ -261,40 +249,31 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buff
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
func DecodeUDPPacket(users []*protocol.MemoryUser, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
|
||||
func DecodeUDPPacket(validator *Validator, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
|
||||
bs := payload.Bytes()
|
||||
if len(bs) <= 32 {
|
||||
return nil, nil, newError("len(bs) <= 32")
|
||||
}
|
||||
|
||||
var user *protocol.MemoryUser
|
||||
var account *MemoryAccount
|
||||
var err error
|
||||
|
||||
if len(users) > 1 {
|
||||
bs := payload.Bytes()
|
||||
if len(bs) <= 32 {
|
||||
return nil, nil, newError("len(bs) <= 32")
|
||||
}
|
||||
|
||||
var aeadCipher *AEADCipher
|
||||
var ivLen int32
|
||||
subkey := make([]byte, 32)
|
||||
data := make([]byte, 8192)
|
||||
var aead cipher.AEAD
|
||||
count := validator.Count()
|
||||
if count == 0 {
|
||||
return nil, nil, newError("invalid user")
|
||||
} else if count > 1 {
|
||||
var d []byte
|
||||
for _, user = range users {
|
||||
account = user.Account.(*MemoryAccount)
|
||||
aeadCipher = account.Cipher.(*AEADCipher)
|
||||
ivLen = aeadCipher.IVSize()
|
||||
subkey = subkey[:aeadCipher.KeyBytes]
|
||||
hkdfSHA1(account.Key, bs[:ivLen], subkey)
|
||||
aead = aeadCipher.AEADAuthCreator(subkey)
|
||||
d, err = aead.Open(data[:0], data[8180:8192], bs[ivLen:], nil)
|
||||
if err == nil {
|
||||
payload.Clear()
|
||||
payload.Write(d)
|
||||
break
|
||||
}
|
||||
user, _, d, _, err = validator.Get(bs, protocol.RequestCommandUDP)
|
||||
|
||||
if user != nil {
|
||||
payload.Clear()
|
||||
payload.Write(d)
|
||||
} else {
|
||||
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
|
||||
}
|
||||
} else {
|
||||
user = users[0]
|
||||
account = user.Account.(*MemoryAccount)
|
||||
user, _ = validator.GetOnlyUser()
|
||||
account := user.Account.(*MemoryAccount)
|
||||
|
||||
var iv []byte
|
||||
if !account.Cipher.IsAEAD() && account.Cipher.IVSize() > 0 {
|
||||
@@ -302,12 +281,9 @@ func DecodeUDPPacket(users []*protocol.MemoryUser, payload *buf.Buffer) (*protoc
|
||||
iv = make([]byte, account.Cipher.IVSize())
|
||||
copy(iv, payload.BytesTo(account.Cipher.IVSize()))
|
||||
}
|
||||
|
||||
err = account.Cipher.DecodePacket(account.Key, payload)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
|
||||
if err = account.Cipher.DecodePacket(account.Key, payload); err != nil {
|
||||
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
|
||||
}
|
||||
}
|
||||
|
||||
request := &protocol.RequestHeader{
|
||||
@@ -341,7 +317,10 @@ func (v *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
buffer.Release()
|
||||
return nil, err
|
||||
}
|
||||
u, payload, err := DecodeUDPPacket([]*protocol.MemoryUser{v.User}, buffer)
|
||||
validator := new(Validator)
|
||||
validator.Add(v.User)
|
||||
|
||||
u, payload, err := DecodeUDPPacket(validator, buffer)
|
||||
if err != nil {
|
||||
buffer.Release()
|
||||
return nil, err
|
||||
|
@@ -38,7 +38,9 @@ func TestUDPEncoding(t *testing.T) {
|
||||
encodedData, err := EncodeUDPPacket(request, data.Bytes())
|
||||
common.Must(err)
|
||||
|
||||
decodedRequest, decodedData, err := DecodeUDPPacket([]*protocol.MemoryUser{request.User}, encodedData)
|
||||
validator := new(Validator)
|
||||
validator.Add(request.User)
|
||||
decodedRequest, decodedData, err := DecodeUDPPacket(validator, encodedData)
|
||||
common.Must(err)
|
||||
|
||||
if r := cmp.Diff(decodedData.Bytes(), data.Bytes()); r != "" {
|
||||
@@ -117,7 +119,9 @@ func TestTCPRequest(t *testing.T) {
|
||||
|
||||
common.Must(writer.WriteMultiBuffer(buf.MultiBuffer{data}))
|
||||
|
||||
decodedRequest, reader, err := ReadTCPSession([]*protocol.MemoryUser{request.User}, cache)
|
||||
validator := new(Validator)
|
||||
validator.Add(request.User)
|
||||
decodedRequest, reader, err := ReadTCPSession(validator, cache)
|
||||
common.Must(err)
|
||||
if r := cmp.Diff(decodedRequest, request, cmp.Comparer(func(a1, a2 protocol.Account) bool { return a1.Equals(a2) })); r != "" {
|
||||
t.Error("request: ", r)
|
||||
|
@@ -22,35 +22,46 @@ import (
|
||||
|
||||
type Server struct {
|
||||
config *ServerConfig
|
||||
users []*protocol.MemoryUser
|
||||
validator *Validator
|
||||
policyManager policy.Manager
|
||||
cone bool
|
||||
}
|
||||
|
||||
// NewServer create a new Shadowsocks server.
|
||||
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||
if config.Users == nil {
|
||||
return nil, newError("empty users")
|
||||
validator := new(Validator)
|
||||
for _, user := range config.Users {
|
||||
u, err := user.ToMemoryUser()
|
||||
if err != nil {
|
||||
return nil, newError("failed to get shadowsocks user").Base(err).AtError()
|
||||
}
|
||||
|
||||
if err := validator.Add(u); err != nil {
|
||||
return nil, newError("failed to add user").Base(err).AtError()
|
||||
}
|
||||
}
|
||||
|
||||
v := core.MustFromContext(ctx)
|
||||
s := &Server{
|
||||
config: config,
|
||||
validator: validator,
|
||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||
cone: ctx.Value("cone").(bool),
|
||||
}
|
||||
|
||||
for _, user := range config.Users {
|
||||
u, err := user.ToMemoryUser()
|
||||
if err != nil {
|
||||
return nil, newError("failed to parse user account").Base(err)
|
||||
}
|
||||
s.users = append(s.users, u)
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// AddUser implements proxy.UserManager.AddUser().
|
||||
func (s *Server) AddUser(ctx context.Context, u *protocol.MemoryUser) error {
|
||||
return s.validator.Add(u)
|
||||
}
|
||||
|
||||
// RemoveUser implements proxy.UserManager.RemoveUser().
|
||||
func (s *Server) RemoveUser(ctx context.Context, e string) error {
|
||||
return s.validator.Del(e)
|
||||
}
|
||||
|
||||
func (s *Server) Network() []net.Network {
|
||||
list := s.config.Network
|
||||
if len(list) == 0 {
|
||||
@@ -64,13 +75,13 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
|
||||
case net.Network_TCP:
|
||||
return s.handleConnection(ctx, conn, dispatcher)
|
||||
case net.Network_UDP:
|
||||
return s.handlerUDPPayload(ctx, conn, dispatcher)
|
||||
return s.handleUDPPayload(ctx, conn, dispatcher)
|
||||
default:
|
||||
return newError("unknown network: ", network)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection, dispatcher routing.Dispatcher) error {
|
||||
func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection, dispatcher routing.Dispatcher) error {
|
||||
udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
|
||||
request := protocol.RequestHeaderFromContext(ctx)
|
||||
if request == nil {
|
||||
@@ -102,8 +113,9 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
|
||||
if inbound == nil {
|
||||
panic("no inbound metadata")
|
||||
}
|
||||
if len(s.users) == 1 {
|
||||
inbound.User = s.users[0]
|
||||
|
||||
if s.validator.Count() == 1 {
|
||||
inbound.User, _ = s.validator.GetOnlyUser()
|
||||
}
|
||||
|
||||
var dest *net.Destination
|
||||
@@ -121,9 +133,11 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
|
||||
var err error
|
||||
|
||||
if inbound.User != nil {
|
||||
request, data, err = DecodeUDPPacket([]*protocol.MemoryUser{inbound.User}, payload)
|
||||
validator := new(Validator)
|
||||
validator.Add(inbound.User)
|
||||
request, data, err = DecodeUDPPacket(validator, payload)
|
||||
} else {
|
||||
request, data, err = DecodeUDPPacket(s.users, payload)
|
||||
request, data, err = DecodeUDPPacket(s.validator, payload)
|
||||
if err == nil {
|
||||
inbound.User = request.User
|
||||
}
|
||||
@@ -178,7 +192,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
|
||||
}
|
||||
|
||||
bufferedReader := buf.BufferedReader{Reader: buf.NewReader(conn)}
|
||||
request, bodyReader, err := ReadTCPSession(s.users, &bufferedReader)
|
||||
request, bodyReader, err := ReadTCPSession(s.validator, &bufferedReader)
|
||||
if err != nil {
|
||||
log.Record(&log.AccessMessage{
|
||||
From: conn.RemoteAddr(),
|
||||
|
113
proxy/shadowsocks/validator.go
Normal file
113
proxy/shadowsocks/validator.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package shadowsocks
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
)
|
||||
|
||||
// Validator stores valid Shadowsocks users.
|
||||
type Validator struct {
|
||||
// Considering email's usage here, map + sync.Mutex/RWMutex may have better performance.
|
||||
email sync.Map
|
||||
users sync.Map
|
||||
}
|
||||
|
||||
// Add a Shadowsocks user, Email must be empty or unique.
|
||||
func (v *Validator) Add(u *protocol.MemoryUser) error {
|
||||
account := u.Account.(*MemoryAccount)
|
||||
|
||||
if !account.Cipher.IsAEAD() && v.Count() > 0 {
|
||||
return newError("The cipher do not support Single-port Multi-user")
|
||||
}
|
||||
|
||||
if u.Email != "" {
|
||||
_, loaded := v.email.LoadOrStore(strings.ToLower(u.Email), u)
|
||||
if loaded {
|
||||
return newError("User ", u.Email, " already exists.")
|
||||
}
|
||||
}
|
||||
|
||||
v.users.Store(string(account.Key)+"&"+account.GetCipherName(), u)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Del a Shadowsocks user with a non-empty Email.
|
||||
func (v *Validator) Del(e string) error {
|
||||
if e == "" {
|
||||
return newError("Email must not be empty.")
|
||||
}
|
||||
le := strings.ToLower(e)
|
||||
u, _ := v.email.Load(le)
|
||||
if u == nil {
|
||||
return newError("User ", e, " not found.")
|
||||
}
|
||||
account := u.(*protocol.MemoryUser).Account.(*MemoryAccount)
|
||||
v.email.Delete(le)
|
||||
v.users.Delete(string(account.Key) + "&" + account.GetCipherName())
|
||||
return nil
|
||||
}
|
||||
|
||||
// Count the number of Shadowsocks users
|
||||
func (v *Validator) Count() int {
|
||||
length := 0
|
||||
v.users.Range(func(_, _ interface{}) bool {
|
||||
length++
|
||||
|
||||
return true
|
||||
})
|
||||
return length
|
||||
}
|
||||
|
||||
// Get a Shadowsocks user and the user's cipher.
|
||||
func (v *Validator) Get(bs []byte, command protocol.RequestCommand) (u *protocol.MemoryUser, aead cipher.AEAD, ret []byte, ivLen int32, err error) {
|
||||
var dataSize int
|
||||
|
||||
switch command {
|
||||
case protocol.RequestCommandTCP:
|
||||
dataSize = 16
|
||||
case protocol.RequestCommandUDP:
|
||||
dataSize = 8192
|
||||
}
|
||||
|
||||
var aeadCipher *AEADCipher
|
||||
subkey := make([]byte, 32)
|
||||
data := make([]byte, dataSize)
|
||||
|
||||
v.users.Range(func(key, user interface{}) bool {
|
||||
account := user.(*protocol.MemoryUser).Account.(*MemoryAccount)
|
||||
aeadCipher = account.Cipher.(*AEADCipher)
|
||||
ivLen = aeadCipher.IVSize()
|
||||
subkey = subkey[:aeadCipher.KeyBytes]
|
||||
hkdfSHA1(account.Key, bs[:ivLen], subkey)
|
||||
aead = aeadCipher.AEADAuthCreator(subkey)
|
||||
|
||||
switch command {
|
||||
case protocol.RequestCommandTCP:
|
||||
ret, err = aead.Open(data[:0], data[4:16], bs[ivLen:ivLen+18], nil)
|
||||
case protocol.RequestCommandUDP:
|
||||
ret, err = aead.Open(data[:0], data[8180:8192], bs[ivLen:], nil)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
u = user.(*protocol.MemoryUser)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Get the only user without authentication
|
||||
func (v *Validator) GetOnlyUser() (u *protocol.MemoryUser, ivLen int32) {
|
||||
v.users.Range(func(_, user interface{}) bool {
|
||||
u = user.(*protocol.MemoryUser)
|
||||
return false
|
||||
})
|
||||
ivLen = u.Account.(*MemoryAccount).Cipher.IVSize()
|
||||
|
||||
return
|
||||
}
|
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
"github.com/xtls/xray-core/common/signal"
|
||||
"github.com/xtls/xray-core/common/task"
|
||||
"github.com/xtls/xray-core/common/xudp"
|
||||
core "github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/features/policy"
|
||||
"github.com/xtls/xray-core/features/stats"
|
||||
@@ -48,6 +49,7 @@ type Handler struct {
|
||||
serverList *protocol.ServerList
|
||||
serverPicker protocol.ServerPicker
|
||||
policyManager policy.Manager
|
||||
cone bool
|
||||
}
|
||||
|
||||
// New creates a new VLess outbound handler.
|
||||
@@ -66,6 +68,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||
serverList: serverList,
|
||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||
cone: ctx.Value("cone").(bool),
|
||||
}
|
||||
|
||||
return handler, nil
|
||||
@@ -175,6 +178,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
clientReader := link.Reader // .(*pipe.Reader)
|
||||
clientWriter := link.Writer // .(*pipe.Writer)
|
||||
|
||||
if request.Command == protocol.RequestCommandUDP && h.cone {
|
||||
request.Command = protocol.RequestCommandMux
|
||||
request.Address = net.DomainAddress("v1.mux.cool")
|
||||
request.Port = net.Port(666)
|
||||
}
|
||||
|
||||
postRequest := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||
|
||||
@@ -185,6 +194,9 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
|
||||
// default: serverWriter := bufferWriter
|
||||
serverWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons)
|
||||
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||
serverWriter = xudp.NewPacketWriter(serverWriter, target)
|
||||
}
|
||||
if err := buf.CopyOnceTimeout(clientReader, serverWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
|
||||
return err // ...
|
||||
}
|
||||
@@ -216,6 +228,9 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
|
||||
// default: serverReader := buf.NewReader(conn)
|
||||
serverReader := encoding.DecodeBodyAddons(conn, request, responseAddons)
|
||||
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||
serverReader = xudp.NewPacketReader(conn)
|
||||
}
|
||||
|
||||
if rawConn != nil {
|
||||
var counter stats.Counter
|
||||
|
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
"github.com/xtls/xray-core/common/signal"
|
||||
"github.com/xtls/xray-core/common/task"
|
||||
"github.com/xtls/xray-core/common/xudp"
|
||||
core "github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/features/policy"
|
||||
"github.com/xtls/xray-core/proxy/vmess"
|
||||
@@ -28,6 +29,7 @@ type Handler struct {
|
||||
serverList *protocol.ServerList
|
||||
serverPicker protocol.ServerPicker
|
||||
policyManager policy.Manager
|
||||
cone bool
|
||||
}
|
||||
|
||||
// New creates a new VMess outbound handler.
|
||||
@@ -46,6 +48,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||
serverList: serverList,
|
||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||
cone: ctx.Value("cone").(bool),
|
||||
}
|
||||
|
||||
return handler, nil
|
||||
@@ -122,6 +125,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||
|
||||
if request.Command == protocol.RequestCommandUDP && h.cone {
|
||||
request.Command = protocol.RequestCommandMux
|
||||
request.Address = net.DomainAddress("v1.mux.cool")
|
||||
request.Port = net.Port(666)
|
||||
}
|
||||
|
||||
requestDone := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||
|
||||
@@ -131,6 +140,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
}
|
||||
|
||||
bodyWriter := session.EncodeRequestBody(request, writer)
|
||||
bodyWriter2 := bodyWriter
|
||||
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||
bodyWriter = xudp.NewPacketWriter(bodyWriter, target)
|
||||
}
|
||||
if err := buf.CopyOnceTimeout(input, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
|
||||
return newError("failed to write first payload").Base(err)
|
||||
}
|
||||
@@ -144,7 +157,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
}
|
||||
|
||||
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||
if err := bodyWriter.WriteMultiBuffer(buf.MultiBuffer{}); err != nil {
|
||||
if err := bodyWriter2.WriteMultiBuffer(buf.MultiBuffer{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -163,6 +176,9 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
h.handleCommand(rec.Destination(), header.Command)
|
||||
|
||||
bodyReader := session.DecodeResponseBody(request, reader)
|
||||
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||
bodyReader = xudp.NewPacketReader(&buf.BufferedReader{Reader: bodyReader})
|
||||
}
|
||||
|
||||
return buf.Copy(bodyReader, output, buf.UpdateActivity(timer))
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/ocsp"
|
||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
@@ -60,17 +61,47 @@ func (c *Config) BuildCertificates() []*tls.Certificate {
|
||||
}
|
||||
certs = append(certs, &keyPair)
|
||||
if entry.OcspStapling != 0 {
|
||||
go func(cert *tls.Certificate) {
|
||||
index := len(certs) - 1
|
||||
go func(cert *tls.Certificate, index int) {
|
||||
t := time.NewTicker(time.Duration(entry.OcspStapling) * time.Second)
|
||||
for {
|
||||
if newData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
|
||||
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
|
||||
} else if string(newData) != string(cert.OCSPStaple) {
|
||||
cert.OCSPStaple = newData
|
||||
if entry.CertificatePath != "" && entry.KeyPath != "" {
|
||||
newCert, err := filesystem.ReadFile(entry.CertificatePath)
|
||||
if err != nil {
|
||||
newError("failed to parse certificate").Base(err).AtError().WriteToLog()
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
newKey, err := filesystem.ReadFile(entry.KeyPath)
|
||||
if err != nil {
|
||||
newError("failed to parse key").Base(err).AtError().WriteToLog()
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
if string(newCert) != string(entry.Certificate) && string(newKey) != string(entry.Key) {
|
||||
newKeyPair, err := tls.X509KeyPair(newCert, newKey)
|
||||
if err != nil {
|
||||
newError("ignoring invalid X509 key pair").Base(err).AtError().WriteToLog()
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
if newKeyPair.Leaf, err = x509.ParseCertificate(newKeyPair.Certificate[0]); err != nil {
|
||||
newError("ignoring invalid certificate").Base(err).AtError().WriteToLog()
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
cert = &newKeyPair
|
||||
}
|
||||
}
|
||||
if newOCSPData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
|
||||
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
|
||||
} else if string(newOCSPData) != string(cert.OCSPStaple) {
|
||||
cert.OCSPStaple = newOCSPData
|
||||
}
|
||||
certs[index] = cert
|
||||
<-t.C
|
||||
}
|
||||
}(certs[len(certs)-1])
|
||||
}(certs[len(certs)-1], index)
|
||||
}
|
||||
}
|
||||
return certs
|
||||
|
@@ -85,6 +85,10 @@ type Certificate struct {
|
||||
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Usage Certificate_Usage `protobuf:"varint,3,opt,name=usage,proto3,enum=xray.transport.internet.tls.Certificate_Usage" json:"usage,omitempty"`
|
||||
OcspStapling int64 `protobuf:"varint,4,opt,name=ocsp_stapling,json=ocspStapling,proto3" json:"ocsp_stapling,omitempty"`
|
||||
// TLS certificate path
|
||||
CertificatePath string `protobuf:"bytes,5,opt,name=certificate_path,json=certificatePath,proto3" json:"certificate_path,omitempty"`
|
||||
// TLS Key path
|
||||
KeyPath string `protobuf:"bytes,6,opt,name=key_path,json=keyPath,proto3" json:"key_path,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Certificate) Reset() {
|
||||
@@ -147,6 +151,20 @@ func (x *Certificate) GetOcspStapling() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Certificate) GetCertificatePath() string {
|
||||
if x != nil {
|
||||
return x.CertificatePath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Certificate) GetKeyPath() string {
|
||||
if x != nil {
|
||||
return x.KeyPath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -284,7 +302,7 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x74, 0x6c, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74,
|
||||
0x6c, 0x73, 0x22, 0xf2, 0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
||||
0x6c, 0x73, 0x22, 0xb8, 0x02, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
|
||||
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
|
||||
0x63, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
@@ -295,48 +313,52 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
||||
0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d,
|
||||
0x6f, 0x63, 0x73, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x63, 0x73, 0x70, 0x53, 0x74, 0x61, 0x70, 0x6c, 0x69, 0x6e,
|
||||
0x67, 0x22, 0x44, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x4e,
|
||||
0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10,
|
||||
0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59,
|
||||
0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f,
|
||||
0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xd3, 0x03, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x73, 0x65,
|
||||
0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f,
|
||||
0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x63, 0x65, 0x72,
|
||||
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28,
|
||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x2e, 0x43, 0x65, 0x72,
|
||||
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
|
||||
0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6e,
|
||||
0x65, 0x78, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x3a, 0x0a, 0x19, 0x65,
|
||||
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65,
|
||||
0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17,
|
||||
0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73,
|
||||
0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62,
|
||||
0x6c, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x79, 0x73,
|
||||
0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x69,
|
||||
0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f,
|
||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d,
|
||||
0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x69, 0x70,
|
||||
0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x3d,
|
||||
0x0a, 0x1b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
|
||||
0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x18, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x42, 0x73, 0x0a,
|
||||
0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
||||
0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73,
|
||||
0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
|
||||
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||
0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54,
|
||||
0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x67, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
|
||||
0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x65, 0x72,
|
||||
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08,
|
||||
0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||
0x6b, 0x65, 0x79, 0x50, 0x61, 0x74, 0x68, 0x22, 0x44, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65,
|
||||
0x12, 0x10, 0x0a, 0x0c, 0x45, 0x4e, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54,
|
||||
0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f,
|
||||
0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48,
|
||||
0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xd3, 0x03,
|
||||
0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f,
|
||||
0x77, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12,
|
||||
0x4a, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74,
|
||||
0x6c, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b,
|
||||
0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d,
|
||||
0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20,
|
||||
0x03, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||
0x6c, 0x12, 0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x73, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a,
|
||||
0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f,
|
||||
0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61,
|
||||
0x62, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1f, 0x0a,
|
||||
0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f,
|
||||
0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
|
||||
0x23, 0x0a, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73,
|
||||
0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75,
|
||||
0x69, 0x74, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69,
|
||||
0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x70, 0x72, 0x65, 0x66, 0x65,
|
||||
0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69,
|
||||
0x74, 0x65, 0x73, 0x42, 0x73, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b, 0x58, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -22,6 +22,12 @@ message Certificate {
|
||||
Usage usage = 3;
|
||||
|
||||
int64 ocsp_stapling = 4;
|
||||
|
||||
// TLS certificate path
|
||||
string certificate_path = 5;
|
||||
|
||||
// TLS Key path
|
||||
string key_path = 6;
|
||||
}
|
||||
|
||||
message Config {
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/ocsp"
|
||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
@@ -59,17 +60,47 @@ func (c *Config) BuildCertificates() []*xtls.Certificate {
|
||||
}
|
||||
certs = append(certs, &keyPair)
|
||||
if entry.OcspStapling != 0 {
|
||||
go func(cert *xtls.Certificate) {
|
||||
index := len(certs) - 1
|
||||
go func(cert *xtls.Certificate, index int) {
|
||||
t := time.NewTicker(time.Duration(entry.OcspStapling) * time.Second)
|
||||
for {
|
||||
if newData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
|
||||
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
|
||||
} else if string(newData) != string(cert.OCSPStaple) {
|
||||
cert.OCSPStaple = newData
|
||||
if entry.CertificatePath != "" && entry.KeyPath != "" {
|
||||
newCert, err := filesystem.ReadFile(entry.CertificatePath)
|
||||
if err != nil {
|
||||
newError("failed to parse certificate").Base(err).AtError().WriteToLog()
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
newKey, err := filesystem.ReadFile(entry.KeyPath)
|
||||
if err != nil {
|
||||
newError("failed to parse key").Base(err).AtError().WriteToLog()
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
if string(newCert) != string(entry.Certificate) && string(newKey) != string(entry.Key) {
|
||||
newKeyPair, err := xtls.X509KeyPair(newCert, newKey)
|
||||
if err != nil {
|
||||
newError("ignoring invalid X509 key pair").Base(err).AtError().WriteToLog()
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
if newKeyPair.Leaf, err = x509.ParseCertificate(newKeyPair.Certificate[0]); err != nil {
|
||||
newError("ignoring invalid certificate").Base(err).AtError().WriteToLog()
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
cert = &newKeyPair
|
||||
}
|
||||
}
|
||||
if newOCSPData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
|
||||
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
|
||||
} else if string(newOCSPData) != string(cert.OCSPStaple) {
|
||||
cert.OCSPStaple = newOCSPData
|
||||
}
|
||||
certs[index] = cert
|
||||
<-t.C
|
||||
}
|
||||
}(certs[len(certs)-1])
|
||||
}(certs[len(certs)-1], index)
|
||||
}
|
||||
}
|
||||
return certs
|
||||
|
@@ -85,6 +85,10 @@ type Certificate struct {
|
||||
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Usage Certificate_Usage `protobuf:"varint,3,opt,name=usage,proto3,enum=xray.transport.internet.xtls.Certificate_Usage" json:"usage,omitempty"`
|
||||
OcspStapling int64 `protobuf:"varint,4,opt,name=ocsp_stapling,json=ocspStapling,proto3" json:"ocsp_stapling,omitempty"`
|
||||
// TLS certificate path
|
||||
CertificatePath string `protobuf:"bytes,5,opt,name=certificate_path,json=certificatePath,proto3" json:"certificate_path,omitempty"`
|
||||
// TLS Key path
|
||||
KeyPath string `protobuf:"bytes,6,opt,name=key_path,json=keyPath,proto3" json:"key_path,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Certificate) Reset() {
|
||||
@@ -147,6 +151,20 @@ func (x *Certificate) GetOcspStapling() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Certificate) GetCertificatePath() string {
|
||||
if x != nil {
|
||||
return x.CertificatePath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Certificate) GetKeyPath() string {
|
||||
if x != nil {
|
||||
return x.KeyPath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -284,7 +302,7 @@ var file_transport_internet_xtls_config_proto_rawDesc = []byte{
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
||||
0x78, 0x74, 0x6c, 0x73, 0x22, 0xf3, 0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
|
||||
0x78, 0x74, 0x6c, 0x73, 0x22, 0xb9, 0x02, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
|
||||
0x63, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
||||
0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69,
|
||||
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20,
|
||||
@@ -295,49 +313,53 @@ var file_transport_internet_xtls_config_proto_rawDesc = []byte{
|
||||
0x74, 0x65, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12,
|
||||
0x23, 0x0a, 0x0d, 0x6f, 0x63, 0x73, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x70, 0x6c, 0x69, 0x6e, 0x67,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x63, 0x73, 0x70, 0x53, 0x74, 0x61, 0x70,
|
||||
0x6c, 0x69, 0x6e, 0x67, 0x22, 0x44, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a,
|
||||
0x0c, 0x45, 0x4e, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12,
|
||||
0x14, 0x0a, 0x10, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x56, 0x45, 0x52,
|
||||
0x49, 0x46, 0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49,
|
||||
0x54, 0x59, 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xd4, 0x03, 0x0a, 0x06, 0x43,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69,
|
||||
0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61,
|
||||
0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x4b, 0x0a, 0x0b,
|
||||
0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x78, 0x74, 0x6c, 0x73,
|
||||
0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x65,
|
||||
0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72,
|
||||
0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
|
||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x65,
|
||||
0x78, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28,
|
||||
0x09, 0x52, 0x0c, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12,
|
||||
0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x64,
|
||||
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x72, 0x6f,
|
||||
0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
|
||||
0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d,
|
||||
0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b,
|
||||
0x6d, 0x61, 0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a,
|
||||
0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x09,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74,
|
||||
0x65, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72,
|
||||
0x76, 0x65, 0x72, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65,
|
||||
0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x53,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65,
|
||||
0x73, 0x42, 0x76, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||
0x2e, 0x78, 0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
|
||||
0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1c, 0x58, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2e, 0x58, 0x74, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x33,
|
||||
0x6c, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
||||
0x61, 0x74, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
|
||||
0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12,
|
||||
0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x50, 0x61, 0x74, 0x68, 0x22, 0x44, 0x0a, 0x05, 0x55, 0x73,
|
||||
0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x4e, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d,
|
||||
0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49,
|
||||
0x54, 0x59, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41,
|
||||
0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02,
|
||||
0x22, 0xd4, 0x03, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61,
|
||||
0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75,
|
||||
0x72, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
|
||||
0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74,
|
||||
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
||||
0x74, 0x2e, 0x78, 0x74, 0x6c, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12,
|
||||
0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||
0x6c, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f,
|
||||
0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x79, 0x73,
|
||||
0x74, 0x65, 0x6d, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11,
|
||||
0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f,
|
||||
0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75,
|
||||
0x69, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68,
|
||||
0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x70, 0x72, 0x65, 0x66,
|
||||
0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72,
|
||||
0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x70,
|
||||
0x72, 0x65, 0x66, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65,
|
||||
0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x42, 0x76, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x78, 0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x31, 0x67,
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x78, 0x74, 0x6c, 0x73,
|
||||
0xaa, 0x02, 0x1c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x58, 0x74, 0x6c, 0x73, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -22,6 +22,12 @@ message Certificate {
|
||||
Usage usage = 3;
|
||||
|
||||
int64 ocsp_stapling = 4;
|
||||
|
||||
// TLS certificate path
|
||||
string certificate_path = 5;
|
||||
|
||||
// TLS Key path
|
||||
string key_path = 6;
|
||||
}
|
||||
|
||||
message Config {
|
||||
|
Reference in New Issue
Block a user