mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2025-12-19 16:30:07 +08:00
chore: alignment capability for vmess inbound
This commit is contained in:
parent
0ac6c3b185
commit
a440f64080
@ -1146,6 +1146,14 @@ listeners:
|
|||||||
# 下面两项如果填写则开启 tls(需要同时填写)
|
# 下面两项如果填写则开启 tls(需要同时填写)
|
||||||
# certificate: ./server.crt
|
# certificate: ./server.crt
|
||||||
# private-key: ./server.key
|
# private-key: ./server.key
|
||||||
|
# 如果填写reality-config则开启reality(注意不可与certificate和private-key同时填写)
|
||||||
|
# reality-config:
|
||||||
|
# dest: test.com:443
|
||||||
|
# private-key: jNXHt1yRo0vDuchQlIP6Z0ZvjT3KtzVI-T4E7RoLJS0 # 可由 mihomo generate reality-keypair 命令生成
|
||||||
|
# short-id:
|
||||||
|
# - 0123456789abcdef
|
||||||
|
# server-names:
|
||||||
|
# - test.com
|
||||||
|
|
||||||
- name: tuic-in-1
|
- name: tuic-in-1
|
||||||
type: tuic
|
type: tuic
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/metacubex/mihomo/listener/sing"
|
|
||||||
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/metacubex/mihomo/listener/reality"
|
||||||
|
"github.com/metacubex/mihomo/listener/sing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VlessUser struct {
|
type VlessUser struct {
|
||||||
@ -19,7 +20,7 @@ type VlessServer struct {
|
|||||||
WsPath string
|
WsPath string
|
||||||
Certificate string
|
Certificate string
|
||||||
PrivateKey string
|
PrivateKey string
|
||||||
RealityConfig RealityConfig
|
RealityConfig reality.Config
|
||||||
MuxOption sing.MuxOption `yaml:"mux-option" json:"mux-option,omitempty"`
|
MuxOption sing.MuxOption `yaml:"mux-option" json:"mux-option,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,12 +28,3 @@ func (t VlessServer) String() string {
|
|||||||
b, _ := json.Marshal(t)
|
b, _ := json.Marshal(t)
|
||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RealityConfig struct {
|
|
||||||
Dest string
|
|
||||||
PrivateKey string
|
|
||||||
ShortID []string
|
|
||||||
ServerNames []string
|
|
||||||
MaxTimeDifference int
|
|
||||||
Proxy string
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/metacubex/mihomo/listener/sing"
|
|
||||||
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/metacubex/mihomo/listener/reality"
|
||||||
|
"github.com/metacubex/mihomo/listener/sing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VmessUser struct {
|
type VmessUser struct {
|
||||||
@ -19,6 +20,7 @@ type VmessServer struct {
|
|||||||
WsPath string
|
WsPath string
|
||||||
Certificate string
|
Certificate string
|
||||||
PrivateKey string
|
PrivateKey string
|
||||||
|
RealityConfig reality.Config
|
||||||
MuxOption sing.MuxOption `yaml:"mux-option" json:"mux-option,omitempty"`
|
MuxOption sing.MuxOption `yaml:"mux-option" json:"mux-option,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
listener/inbound/reality.go
Normal file
23
listener/inbound/reality.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package inbound
|
||||||
|
|
||||||
|
import "github.com/metacubex/mihomo/listener/reality"
|
||||||
|
|
||||||
|
type RealityConfig struct {
|
||||||
|
Dest string `inbound:"dest"`
|
||||||
|
PrivateKey string `inbound:"private-key"`
|
||||||
|
ShortID []string `inbound:"short-id"`
|
||||||
|
ServerNames []string `inbound:"server-names"`
|
||||||
|
MaxTimeDifference int `inbound:"max-time-difference,omitempty"`
|
||||||
|
Proxy string `inbound:"proxy,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c RealityConfig) Build() reality.Config {
|
||||||
|
return reality.Config{
|
||||||
|
Dest: c.Dest,
|
||||||
|
PrivateKey: c.PrivateKey,
|
||||||
|
ShortID: c.ShortID,
|
||||||
|
ServerNames: c.ServerNames,
|
||||||
|
MaxTimeDifference: c.MaxTimeDifference,
|
||||||
|
Proxy: c.Proxy,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,26 +23,6 @@ type VlessUser struct {
|
|||||||
Flow string `inbound:"flow,omitempty"`
|
Flow string `inbound:"flow,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RealityConfig struct {
|
|
||||||
Dest string `inbound:"dest"`
|
|
||||||
PrivateKey string `inbound:"private-key"`
|
|
||||||
ShortID []string `inbound:"short-id"`
|
|
||||||
ServerNames []string `inbound:"server-names"`
|
|
||||||
MaxTimeDifference int `inbound:"max-time-difference,omitempty"`
|
|
||||||
Proxy string `inbound:"proxy,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c RealityConfig) Build() LC.RealityConfig {
|
|
||||||
return LC.RealityConfig{
|
|
||||||
Dest: c.Dest,
|
|
||||||
PrivateKey: c.PrivateKey,
|
|
||||||
ShortID: c.ShortID,
|
|
||||||
ServerNames: c.ServerNames,
|
|
||||||
MaxTimeDifference: c.MaxTimeDifference,
|
|
||||||
Proxy: c.Proxy,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o VlessOption) Equal(config C.InboundConfig) bool {
|
func (o VlessOption) Equal(config C.InboundConfig) bool {
|
||||||
return optionToString(o) == optionToString(config)
|
return optionToString(o) == optionToString(config)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ type VmessOption struct {
|
|||||||
WsPath string `inbound:"ws-path,omitempty"`
|
WsPath string `inbound:"ws-path,omitempty"`
|
||||||
Certificate string `inbound:"certificate,omitempty"`
|
Certificate string `inbound:"certificate,omitempty"`
|
||||||
PrivateKey string `inbound:"private-key,omitempty"`
|
PrivateKey string `inbound:"private-key,omitempty"`
|
||||||
|
RealityConfig RealityConfig `inbound:"reality-config,omitempty"`
|
||||||
MuxOption MuxOption `inbound:"mux-option,omitempty"`
|
MuxOption MuxOption `inbound:"mux-option,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +57,7 @@ func NewVmess(options *VmessOption) (*Vmess, error) {
|
|||||||
WsPath: options.WsPath,
|
WsPath: options.WsPath,
|
||||||
Certificate: options.Certificate,
|
Certificate: options.Certificate,
|
||||||
PrivateKey: options.PrivateKey,
|
PrivateKey: options.PrivateKey,
|
||||||
|
RealityConfig: options.RealityConfig.Build(),
|
||||||
MuxOption: options.MuxOption.Build(),
|
MuxOption: options.MuxOption.Build(),
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
104
listener/reality/reality.go
Normal file
104
listener/reality/reality.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package reality
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/metacubex/mihomo/listener/inner"
|
||||||
|
"github.com/metacubex/mihomo/ntp"
|
||||||
|
|
||||||
|
"github.com/sagernet/reality"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Conn = reality.Conn
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Dest string
|
||||||
|
PrivateKey string
|
||||||
|
ShortID []string
|
||||||
|
ServerNames []string
|
||||||
|
MaxTimeDifference int
|
||||||
|
Proxy string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Config) Build() (*Builder, error) {
|
||||||
|
realityConfig := &reality.Config{}
|
||||||
|
realityConfig.SessionTicketsDisabled = true
|
||||||
|
realityConfig.Type = "tcp"
|
||||||
|
realityConfig.Dest = c.Dest
|
||||||
|
realityConfig.Time = ntp.Now
|
||||||
|
realityConfig.ServerNames = make(map[string]bool)
|
||||||
|
for _, it := range c.ServerNames {
|
||||||
|
realityConfig.ServerNames[it] = true
|
||||||
|
}
|
||||||
|
privateKey, err := base64.RawURLEncoding.DecodeString(c.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decode private key: %w", err)
|
||||||
|
}
|
||||||
|
if len(privateKey) != 32 {
|
||||||
|
return nil, errors.New("invalid private key")
|
||||||
|
}
|
||||||
|
realityConfig.PrivateKey = privateKey
|
||||||
|
|
||||||
|
realityConfig.MaxTimeDiff = time.Duration(c.MaxTimeDifference) * time.Microsecond
|
||||||
|
|
||||||
|
realityConfig.ShortIds = make(map[[8]byte]bool)
|
||||||
|
for i, shortIDString := range c.ShortID {
|
||||||
|
var shortID [8]byte
|
||||||
|
decodedLen, err := hex.Decode(shortID[:], []byte(shortIDString))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("decode short_id[%d] '%s': %w", i, shortIDString, err)
|
||||||
|
}
|
||||||
|
if decodedLen > 8 {
|
||||||
|
return nil, fmt.Errorf("invalid short_id[%d]: %s", i, shortIDString)
|
||||||
|
}
|
||||||
|
realityConfig.ShortIds[shortID] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
realityConfig.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
|
return inner.HandleTcp(address, c.Proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Builder{realityConfig}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Builder struct {
|
||||||
|
realityConfig *reality.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Builder) NewListener(l net.Listener) net.Listener {
|
||||||
|
l = reality.NewListener(l, b.realityConfig)
|
||||||
|
// Due to low implementation quality, the reality server intercepted half close and caused memory leaks.
|
||||||
|
// We fixed it by calling Close() directly.
|
||||||
|
l = realityListenerWrapper{l}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
type realityConnWrapper struct {
|
||||||
|
*reality.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c realityConnWrapper) Upstream() any {
|
||||||
|
return c.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c realityConnWrapper) CloseWrite() error {
|
||||||
|
return c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
type realityListenerWrapper struct {
|
||||||
|
net.Listener
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l realityListenerWrapper) Accept() (net.Conn, error) {
|
||||||
|
c, err := l.Listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return realityConnWrapper{c.(*reality.Conn)}, nil
|
||||||
|
}
|
||||||
@ -3,15 +3,11 @@ package sing_vless
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/base64"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/metacubex/mihomo/adapter/inbound"
|
"github.com/metacubex/mihomo/adapter/inbound"
|
||||||
@ -19,15 +15,13 @@ import (
|
|||||||
tlsC "github.com/metacubex/mihomo/component/tls"
|
tlsC "github.com/metacubex/mihomo/component/tls"
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
LC "github.com/metacubex/mihomo/listener/config"
|
LC "github.com/metacubex/mihomo/listener/config"
|
||||||
"github.com/metacubex/mihomo/listener/inner"
|
"github.com/metacubex/mihomo/listener/reality"
|
||||||
"github.com/metacubex/mihomo/listener/sing"
|
"github.com/metacubex/mihomo/listener/sing"
|
||||||
"github.com/metacubex/mihomo/log"
|
"github.com/metacubex/mihomo/log"
|
||||||
"github.com/metacubex/mihomo/ntp"
|
|
||||||
mihomoVMess "github.com/metacubex/mihomo/transport/vmess"
|
mihomoVMess "github.com/metacubex/mihomo/transport/vmess"
|
||||||
|
|
||||||
"github.com/metacubex/sing-vmess/vless"
|
"github.com/metacubex/sing-vmess/vless"
|
||||||
utls "github.com/metacubex/utls"
|
utls "github.com/metacubex/utls"
|
||||||
"github.com/sagernet/reality"
|
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/metadata"
|
"github.com/sagernet/sing/common/metadata"
|
||||||
)
|
)
|
||||||
@ -97,7 +91,7 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition)
|
|||||||
sl = &Listener{false, config, nil, service}
|
sl = &Listener{false, config, nil, service}
|
||||||
|
|
||||||
tlsConfig := &tls.Config{}
|
tlsConfig := &tls.Config{}
|
||||||
var realityConfig *reality.Config
|
var realityBuilder *reality.Builder
|
||||||
var httpMux *http.ServeMux
|
var httpMux *http.ServeMux
|
||||||
|
|
||||||
if config.Certificate != "" && config.PrivateKey != "" {
|
if config.Certificate != "" && config.PrivateKey != "" {
|
||||||
@ -107,6 +101,15 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition)
|
|||||||
}
|
}
|
||||||
tlsConfig.Certificates = []tls.Certificate{cert}
|
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||||
}
|
}
|
||||||
|
if config.RealityConfig.PrivateKey != "" {
|
||||||
|
if tlsConfig.Certificates != nil {
|
||||||
|
return nil, errors.New("certificate is unavailable in reality")
|
||||||
|
}
|
||||||
|
realityBuilder, err = config.RealityConfig.Build()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
if config.WsPath != "" {
|
if config.WsPath != "" {
|
||||||
httpMux = http.NewServeMux()
|
httpMux = http.NewServeMux()
|
||||||
httpMux.HandleFunc(config.WsPath, func(w http.ResponseWriter, r *http.Request) {
|
httpMux.HandleFunc(config.WsPath, func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -119,47 +122,6 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition)
|
|||||||
})
|
})
|
||||||
tlsConfig.NextProtos = append(tlsConfig.NextProtos, "http/1.1")
|
tlsConfig.NextProtos = append(tlsConfig.NextProtos, "http/1.1")
|
||||||
}
|
}
|
||||||
if config.RealityConfig.PrivateKey != "" {
|
|
||||||
if tlsConfig.Certificates != nil {
|
|
||||||
return nil, errors.New("certificate is unavailable in reality")
|
|
||||||
}
|
|
||||||
realityConfig = &reality.Config{}
|
|
||||||
realityConfig.SessionTicketsDisabled = true
|
|
||||||
realityConfig.Type = "tcp"
|
|
||||||
realityConfig.Dest = config.RealityConfig.Dest
|
|
||||||
realityConfig.Time = ntp.Now
|
|
||||||
realityConfig.ServerNames = make(map[string]bool)
|
|
||||||
for _, it := range config.RealityConfig.ServerNames {
|
|
||||||
realityConfig.ServerNames[it] = true
|
|
||||||
}
|
|
||||||
privateKey, err := base64.RawURLEncoding.DecodeString(config.RealityConfig.PrivateKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("decode private key: %w", err)
|
|
||||||
}
|
|
||||||
if len(privateKey) != 32 {
|
|
||||||
return nil, errors.New("invalid private key")
|
|
||||||
}
|
|
||||||
realityConfig.PrivateKey = privateKey
|
|
||||||
|
|
||||||
realityConfig.MaxTimeDiff = time.Duration(config.RealityConfig.MaxTimeDifference) * time.Microsecond
|
|
||||||
|
|
||||||
realityConfig.ShortIds = make(map[[8]byte]bool)
|
|
||||||
for i, shortIDString := range config.RealityConfig.ShortID {
|
|
||||||
var shortID [8]byte
|
|
||||||
decodedLen, err := hex.Decode(shortID[:], []byte(shortIDString))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("decode short_id[%d] '%s': %w", i, shortIDString, err)
|
|
||||||
}
|
|
||||||
if decodedLen > 8 {
|
|
||||||
return nil, fmt.Errorf("invalid short_id[%d]: %s", i, shortIDString)
|
|
||||||
}
|
|
||||||
realityConfig.ShortIds[shortID] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
realityConfig.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) {
|
|
||||||
return inner.HandleTcp(address, config.RealityConfig.Proxy)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, addr := range strings.Split(config.Listen, ",") {
|
for _, addr := range strings.Split(config.Listen, ",") {
|
||||||
addr := addr
|
addr := addr
|
||||||
@ -169,11 +131,8 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if realityConfig != nil {
|
if realityBuilder != nil {
|
||||||
l = reality.NewListener(l, realityConfig)
|
l = realityBuilder.NewListener(l)
|
||||||
// Due to low implementation quality, the reality server intercepted half close and caused memory leaks.
|
|
||||||
// We fixed it by calling Close() directly.
|
|
||||||
l = realityListenerWrapper{l}
|
|
||||||
} else if len(tlsConfig.Certificates) > 0 {
|
} else if len(tlsConfig.Certificates) > 0 {
|
||||||
l = tls.NewListener(l, tlsConfig)
|
l = tls.NewListener(l, tlsConfig)
|
||||||
} else {
|
} else {
|
||||||
@ -237,27 +196,3 @@ func (l *Listener) HandleConn(conn net.Conn, tunnel C.Tunnel, additions ...inbou
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type realityConnWrapper struct {
|
|
||||||
*reality.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c realityConnWrapper) Upstream() any {
|
|
||||||
return c.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c realityConnWrapper) CloseWrite() error {
|
|
||||||
return c.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
type realityListenerWrapper struct {
|
|
||||||
net.Listener
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l realityListenerWrapper) Accept() (net.Conn, error) {
|
|
||||||
c, err := l.Listener.Accept()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return realityConnWrapper{c.(*reality.Conn)}, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package sing_vmess
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
N "github.com/metacubex/mihomo/common/net"
|
N "github.com/metacubex/mihomo/common/net"
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
LC "github.com/metacubex/mihomo/listener/config"
|
LC "github.com/metacubex/mihomo/listener/config"
|
||||||
|
"github.com/metacubex/mihomo/listener/reality"
|
||||||
"github.com/metacubex/mihomo/listener/sing"
|
"github.com/metacubex/mihomo/listener/sing"
|
||||||
"github.com/metacubex/mihomo/ntp"
|
"github.com/metacubex/mihomo/ntp"
|
||||||
mihomoVMess "github.com/metacubex/mihomo/transport/vmess"
|
mihomoVMess "github.com/metacubex/mihomo/transport/vmess"
|
||||||
@ -73,6 +75,7 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
|
|||||||
sl = &Listener{false, config, nil, service}
|
sl = &Listener{false, config, nil, service}
|
||||||
|
|
||||||
tlsConfig := &tls.Config{}
|
tlsConfig := &tls.Config{}
|
||||||
|
var realityBuilder *reality.Builder
|
||||||
var httpMux *http.ServeMux
|
var httpMux *http.ServeMux
|
||||||
|
|
||||||
if config.Certificate != "" && config.PrivateKey != "" {
|
if config.Certificate != "" && config.PrivateKey != "" {
|
||||||
@ -82,6 +85,15 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
|
|||||||
}
|
}
|
||||||
tlsConfig.Certificates = []tls.Certificate{cert}
|
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||||
}
|
}
|
||||||
|
if config.RealityConfig.PrivateKey != "" {
|
||||||
|
if tlsConfig.Certificates != nil {
|
||||||
|
return nil, errors.New("certificate is unavailable in reality")
|
||||||
|
}
|
||||||
|
realityBuilder, err = config.RealityConfig.Build()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
if config.WsPath != "" {
|
if config.WsPath != "" {
|
||||||
httpMux = http.NewServeMux()
|
httpMux = http.NewServeMux()
|
||||||
httpMux.HandleFunc(config.WsPath, func(w http.ResponseWriter, r *http.Request) {
|
httpMux.HandleFunc(config.WsPath, func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -103,7 +115,9 @@ func New(config LC.VmessServer, tunnel C.Tunnel, additions ...inbound.Addition)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(tlsConfig.Certificates) > 0 {
|
if realityBuilder != nil {
|
||||||
|
l = realityBuilder.NewListener(l)
|
||||||
|
} else if len(tlsConfig.Certificates) > 0 {
|
||||||
l = tls.NewListener(l, tlsConfig)
|
l = tls.NewListener(l, tlsConfig)
|
||||||
}
|
}
|
||||||
sl.listeners = append(sl.listeners, l)
|
sl.listeners = append(sl.listeners, l)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user