Compare commits

..

63 Commits

Author SHA1 Message Date
RPRX
7da97635b2 v1.2.3 2021-01-22 04:00:03 +00:00
Arthur Morgan
ba41513967 Changes from v2fly-core (#173) 2021-01-22 03:35:56 +00:00
Bohan Yang
5bc1bf30ae Fix fallbacks xver when original address is not TCP address (#182)
Co-authored-by: RPRX <63339210+rprx@users.noreply.github.com>
2021-01-22 03:26:57 +00:00
Arthur Morgan
5aa053a65f Convert domain names to lowercase before matching (#195)
Co-authored-by: RPRX <63339210+rprx@users.noreply.github.com>
2021-01-21 23:37:55 +00:00
秋のかえで
0b4858d016 Feature: Exclude some domains in sniffing destOverride (#151)
Co-authored-by: RPRX <63339210+rprx@users.noreply.github.com>
2021-01-21 20:50:09 +00:00
Jim Han
7f5e34c857 Regenerate .pb.go files (#187)
Co-authored-by: RPRX <63339210+rprx@users.noreply.github.com>
2021-01-21 18:58:19 +00:00
RPRX
b60cf02603 Optimize TPROXY Inbound UDP write back
Enhanced stability.
2021-01-20 23:58:59 +00:00
RPRX
ae98dc75cf Set unix.SO_REUSEPORT=1 for TPROXY Inbound FakeUDP
Solved some issues.
2021-01-19 14:50:21 +00:00
RPRX
8ff43519fd Fix Shadowsocks tests; AEAD drop small UDP packets
https://t.me/projectXray/172063
2021-01-19 10:35:30 +00:00
RPRX
33755d6e90 Refactor: Shadowsocks AEAD Single-port Multi-user (Needs Optimizations)
https://t.me/projectXray/170851
2021-01-18 22:52:35 +00:00
RPRX
99863aa2ac Add SNI shunt support for Trojan fallbacks 2021-01-18 07:41:00 +00:00
RPRX
8eed8a0824 v1.2.2 2021-01-15 13:18:37 +00:00
RPRX
88f6537540 Make necessary maps in non-empty names before copy 2021-01-15 11:36:31 +00:00
RPRX
f0efc0cfde As substring to match in VLESS fallbacks SNI shunt 2021-01-15 09:43:39 +00:00
RPRX
f13ac3cb55 Fix VLESS fallbacks SNI shunt 2021-01-14 21:55:52 +00:00
eMeab
638e8384b6 Optimized log (#167) 2021-01-14 14:45:23 +00:00
eMeab
d85162ea44 Add SNI shunt support for VLESS (#141) 2021-01-13 15:13:51 +00:00
Arthur Morgan
11a851f957 Fix non-local DoH requests & Apply routing (#147) 2021-01-13 07:53:08 +00:00
RPRX
822afb0cc8 Improve UUID generator
https://github.com/XTLS/Xray-core/issues/158
2021-01-12 18:23:54 +00:00
RPRX
157918859f Add pre-checking conversion for VLESS & VMess UUID
https://github.com/XTLS/Xray-core/issues/158
2021-01-12 11:31:02 +00:00
RPRX
40271c09a0 Support for VLESS & VMess UUID v5 mapping standard
https://github.com/XTLS/Xray-core/issues/158
2021-01-11 17:56:33 +00:00
maskedeken
96adf3fbca Trojan: Do not panic when UDP dispatcher failed to write response (#153) 2021-01-11 09:30:57 +00:00
RPRX
e254424c43 v1.2.1 2021-01-10 07:58:53 +00:00
RPRX
ee15cc253f Improve configuration detector (cone or symmetric) 2021-01-10 07:50:21 +00:00
RPRX
43eb5d1b25 16 -> 60, 8 -> 300
https://github.com/XTLS/Xray-core/issues/129#issuecomment-757355137

十分感谢 @GleenJi 等协助测试
2021-01-10 04:50:26 +00:00
RPRX
700966508f Improve the response to UDP Associate in Socks5 2021-01-09 16:36:20 +00:00
RPRX
7427a55ef1 Adjust Trojan Outbound postRequest 2021-01-08 12:00:46 +00:00
RPRX
fb0e517158 Adjust Trojan & Socks handleUDPPayload 2021-01-08 06:00:51 +00:00
maskedeken
d5aeb6c545 Refine Trojan packet reader & writer (#142) 2021-01-08 03:55:25 +00:00
RPRX
161e18299c Fix TPROXY UDP/IPv6
https://github.com/XTLS/Xray-core/issues/137#issuecomment-756064627

十分感谢 @Ninedyz @changyp6
2021-01-07 12:21:27 +00:00
eMeab
be9421fedf Optimized log (#121) 2021-01-04 05:05:38 +00:00
RPRX
8fc2d3b61f v1.2.0 2021-01-01 12:30:16 +00:00
秋のかえで
9d4038427d Enable loading TOML & YAML by confdir (#120) 2021-01-01 12:16:22 +00:00
秋のかえで
38ec9208d8 Change TOML package to github.com/pelletier/go-toml (#119) 2021-01-01 11:37:38 +00:00
RPRX
7df135a5c4 Disable session resumption by default
https://github.com/v2fly/v2ray-core/issues/557#issuecomment-751962569
2021-01-01 11:33:09 +00:00
RPRX
c41a1a56fe Refactor: TPROXY inbound UDP write back
https://t.me/projectXray/119670

虽然不一定是最终的版本,但值得记录,感谢协助测试的各位朋友,特别感谢 @yichya @huyz
2020-12-31 15:57:15 +00:00
RPRX
310a938511 VLESS & VMess are not ready to accept FullCone yet 2020-12-30 08:10:26 +00:00
RPRX
2da07e0f8a Refactor: FullCone TPROXY Inbound & Socks Outbound
https://t.me/projectXray/116037
2020-12-29 11:50:17 +00:00
RPRX
13ad3fddf6 Refactor: *net.UDPAddr -> *net.Destination
https://t.me/projectXray/111998
2020-12-28 09:40:28 +00:00
RPRX
6bcac6cb10 Move common/net/connection.go into cnc folder 2020-12-28 03:20:39 +08:00
RPRX
0203190a98 v1.1.5 2020-12-25 15:25:10 +00:00
RPRX
a78db47571 Adjust OCSP Stapling 2020-12-25 15:10:12 +00:00
RPRX
ffd8fd1d8a Adjust JSON & TOML & YAML 2020-12-25 18:53:17 +08:00
eMeab
3d7e86efba Add OCSP Stapling for TLS & XTLS (#92) 2020-12-25 08:01:20 +00:00
Arthur Morgan
6f25191822 Changes from v2ray-core (#93) 2020-12-24 19:45:35 +00:00
Monsoon
85619b5a29 Add YAML Support (#86) 2020-12-24 19:30:26 +00:00
秋のかえで
f073456ac0 Add TOML Support (#98) 2020-12-24 19:11:32 +00:00
RPRX
09f9d03fb6 Add Homebrew 2020-12-24 12:43:19 +00:00
RPRX
8f8f7dd66f Refactor: Shadowsocks & Trojan UDP FullCone NAT
https://t.me/projectXray/95704
2020-12-23 13:06:21 +00:00
RPRX
4140ed7ab0 v1.1.4 2020-12-18 13:12:41 +00:00
RPRX
f390047b37 Disable VMess drain when not pure connection 2020-12-18 12:45:47 +00:00
RPRX
ff9bb2d8df Optimize cipherSuites setting loader 2020-12-17 09:25:30 +00:00
RPRX
38faac5ffc Adjust config loader of TLS & XTLS 2020-12-16 15:59:04 +00:00
eMeab
88dfed931b Add cipherSuites setting for TLS & XTLS (#78) 2020-12-16 12:53:55 +00:00
Jim Han
19ce0e99a5 Config loader returns error instead of directly panic (#80) 2020-12-16 12:35:27 +00:00
Jim Han
fe445f8e1a Fix: HTTP dialer uses ctx instead of context.Background() (#79) 2020-12-16 11:52:45 +00:00
RPRX
6a5618bc54 Outbound Splice supports Inbound XTLS 2020-12-16 10:35:28 +00:00
RPRX
ed0e9b12dc Adjust ProtoBuf of TLS & XTLS 2020-12-16 08:50:18 +00:00
eMeab
dab978749c Add minVersion setting for TLS & XTLS (#77) 2020-12-16 05:20:24 +00:00
RPRX
45f44c401a Refactor: Optimize Memory Usage At Startup
https://github.com/XTLS/Xray-core/issues/68#issuecomment-745231528
2020-12-15 20:27:18 +08:00
RPRX
2e942e0303 Fix Trojan XTLS 2020-12-14 17:05:15 +08:00
RPRX
decb012f9d Add Qv2ray and Kitsunebi 2020-12-13 06:21:50 +00:00
RPRX
574446f942 Add Hello World and ShadowSocksR Plus+ 2020-12-13 05:55:38 +00:00
101 changed files with 2571 additions and 1015 deletions

View File

@@ -20,6 +20,9 @@
- Magisk
- [Xray4Magisk](https://github.com/CerteKim/Xray4Magisk)
- [Xray_For_Magisk](https://github.com/E7KMbb/Xray_For_Magisk)
- Homebrew
- [Repository 0](https://github.com/N4FA/homebrew-xray)
- [Repository 1](https://github.com/xiruizhao/homebrew-xray)
## Usage
@@ -29,10 +32,14 @@
- OpenWrt
- [PassWall](https://github.com/xiaorouji/openwrt-passwall)
- [Hello World](https://github.com/jerrykuku/luci-app-vssr)
- [ShadowSocksR Plus+](https://github.com/fw876/helloworld)
- Windows
- [v2rayN](https://github.com/2dust/v2rayN)
- [Qv2ray](https://github.com/Qv2ray/Qv2ray)
- Android
- [v2rayNG](https://github.com/2dust/v2rayNG)
- [Kitsunebi](https://github.com/rurirei/Kitsunebi/tree/release_xtls)
- iOS / Mac
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)

View File

@@ -6,6 +6,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/signal/done"
"github.com/xtls/xray-core/transport"
)
@@ -79,7 +80,7 @@ func (co *Outbound) Dispatch(ctx context.Context, link *transport.Link) {
}
closeSignal := done.New()
c := net.NewConnection(net.ConnectionInputMulti(link.Writer), net.ConnectionOutputMulti(link.Reader), net.ConnectionOnClose(closeSignal))
c := cnc.NewConnection(cnc.ConnectionInputMulti(link.Writer), cnc.ConnectionOutputMulti(link.Reader), cnc.ConnectionOnClose(closeSignal))
co.listener.add(c)
co.access.RUnlock()
<-closeSignal.Wait()

View File

@@ -175,12 +175,21 @@ func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *tran
return inboundLink, outboundLink
}
func shouldOverride(result SniffResult, domainOverride []string) bool {
for _, p := range domainOverride {
if strings.HasPrefix(result.Protocol(), p) {
func shouldOverride(result SniffResult, request session.SniffingRequest) bool {
domain := result.Domain()
for _, d := range request.ExcludeForDomain {
if domain == d {
return false
}
}
protocol := result.Protocol()
for _, p := range request.OverrideDestinationForProtocol {
if strings.HasPrefix(protocol, p) {
return true
}
}
return false
}
@@ -213,7 +222,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
if err == nil {
content.Protocol = result.Protocol()
}
if err == nil && shouldOverride(result, sniffingRequest.OverrideDestinationForProtocol) {
if err == nil && shouldOverride(result, sniffingRequest) {
domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
destination.Address = net.ParseAddress(domain)
@@ -263,14 +272,18 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
skipRoutePick = content.SkipRoutePick
}
routingLink := routing_session.AsRoutingContext(ctx)
inTag := routingLink.GetInboundTag()
isPickRoute := false
if d.router != nil && !skipRoutePick {
if route, err := d.router.PickRoute(routing_session.AsRoutingContext(ctx)); err == nil {
tag := route.GetOutboundTag()
if h := d.ohm.GetHandler(tag); h != nil {
newError("taking detour [", tag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
if route, err := d.router.PickRoute(routingLink); err == nil {
outTag := route.GetOutboundTag()
isPickRoute = true
if h := d.ohm.GetHandler(outTag); h != nil {
newError("taking detour [", outTag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
handler = h
} else {
newError("non existing tag: ", tag).AtWarning().WriteToLog(session.ExportIDToError(ctx))
newError("non existing outTag: ", outTag).AtWarning().WriteToLog(session.ExportIDToError(ctx))
}
} else {
newError("default route for ", destination).WriteToLog(session.ExportIDToError(ctx))
@@ -290,7 +303,19 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
if accessMessage := log.AccessMessageFromContext(ctx); accessMessage != nil {
if tag := handler.Tag(); tag != "" {
accessMessage.Detour = tag
if isPickRoute {
if inTag != "" {
accessMessage.Detour = inTag + " -> " + tag
} else {
accessMessage.Detour = tag
}
} else {
if inTag != "" {
accessMessage.Detour = inTag + " >> " + tag
} else {
accessMessage.Detour = tag
}
}
}
log.Record(accessMessage)
}

View File

@@ -14,6 +14,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/protocol/dns"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal/pubsub"
@@ -28,6 +29,7 @@ import (
// which is compatible with traditional dns over udp(RFC1035),
// thus most of the DOH implementation is copied from udpns.go
type DoHNameServer struct {
dispatcher routing.Dispatcher
sync.RWMutex
ips map[string]record
pub *pubsub.Service
@@ -44,40 +46,8 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, clientIP net.
newError("DNS: created Remote DOH client for ", url.String()).AtInfo().WriteToLog()
s := baseDOHNameServer(url, "DOH", clientIP)
// Dispatched connection will be closed (interrupted) after each request
// This makes DOH inefficient without a keep-alived connection
// See: core/app/proxyman/outbound/handler.go:113
// Using mux (https request wrapped in a stream layer) improves the situation.
// Recommend to use NewDoHLocalNameServer (DOHL:) if xray instance is running on
// a normal network eg. the server side of xray
tr := &http.Transport{
MaxIdleConns: 30,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 30 * time.Second,
ForceAttemptHTTP2: true,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}
s.dispatcher = dispatcher
link, err := dispatcher.Dispatch(ctx, dest)
if err != nil {
return nil, err
}
return net.NewConnection(
net.ConnectionInputMulti(link.Writer),
net.ConnectionOutputMulti(link.Reader),
), nil
},
}
dispatchedClient := &http.Client{
Transport: tr,
Timeout: 60 * time.Second,
}
s.httpClient = dispatchedClient
return s, nil
}
@@ -210,6 +180,11 @@ func (s *DoHNameServer) newReqID() uint16 {
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, option IPOption) {
newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx))
if s.name+"." == "DOH//"+domain {
newError(s.name, " tries to resolve itself! Use IP or set \"hosts\" instead.").AtError().WriteToLog(session.ExportIDToError(ctx))
return
}
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP))
var deadline time.Time
@@ -231,12 +206,12 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, option IPO
}
dnsCtx = session.ContextWithContent(dnsCtx, &session.Content{
Protocol: "https",
SkipRoutePick: true,
Protocol: "https",
//SkipRoutePick: true,
})
// forced to use mux for DOH
dnsCtx = session.ContextWithMuxPrefered(dnsCtx, true)
// dnsCtx = session.ContextWithMuxPrefered(dnsCtx, true)
var cancel context.CancelFunc
dnsCtx, cancel = context.WithDeadline(dnsCtx, deadline)
@@ -244,17 +219,17 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, option IPO
b, err := dns.PackMessage(r.msg)
if err != nil {
newError("failed to pack dns query").Base(err).AtError().WriteToLog()
newError("failed to pack dns query for ", domain).Base(err).AtError().WriteToLog()
return
}
resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes())
if err != nil {
newError("failed to retrieve response").Base(err).AtError().WriteToLog()
newError("failed to retrieve response for ", domain).Base(err).AtError().WriteToLog()
return
}
rec, err := parseResponse(resp)
if err != nil {
newError("failed to handle DOH response").Base(err).AtError().WriteToLog()
newError("failed to handle DOH response for ", domain).Base(err).AtError().WriteToLog()
return
}
s.updateIP(r, rec)
@@ -272,7 +247,44 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
req.Header.Add("Accept", "application/dns-message")
req.Header.Add("Content-Type", "application/dns-message")
resp, err := s.httpClient.Do(req.WithContext(ctx))
hc := s.httpClient
// Dispatched connection will be closed (interrupted) after each request
// This makes DOH inefficient without a keep-alived connection
// See: core/app/proxyman/outbound/handler.go:113
// Using mux (https request wrapped in a stream layer) improves the situation.
// Recommend to use NewDoHLocalNameServer (DOHL:) if xray instance is running on
// a normal network eg. the server side of xray
if s.dispatcher != nil {
tr := &http.Transport{
MaxIdleConns: 30,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 30 * time.Second,
ForceAttemptHTTP2: true,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}
link, err := s.dispatcher.Dispatch(ctx, dest)
if err != nil {
return nil, err
}
return cnc.NewConnection(
cnc.ConnectionInputMulti(link.Writer),
cnc.ConnectionOutputMulti(link.Reader),
), nil
},
}
hc = &http.Client{
Timeout: time.Second * 180,
Transport: tr,
}
}
resp, err := hc.Do(req.WithContext(ctx))
if err != nil {
return nil, err
}

View File

@@ -364,6 +364,7 @@ func (s *Server) lookupIPInternal(domain string, option IPOption) ([]net.IP, err
if domain == "" {
return nil, newError("empty domain name")
}
domain = strings.ToLower(domain)
// normalize the FQDN form query
if domain[len(domain)-1] == '.' {

View File

@@ -44,7 +44,7 @@ func (s *service) Register(server *grpc.Server) {
RegisterLoggerServiceServer(server, ls)
// For compatibility purposes
vCoreDesc := _LoggerService_serviceDesc
vCoreDesc := LoggerService_ServiceDesc
vCoreDesc.ServiceName = "v2ray.core.app.log.command.LoggerService"
server.RegisterService(&vCoreDesc, ls)
}

View File

@@ -11,6 +11,7 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// LoggerServiceClient is the client API for LoggerService service.
@@ -62,7 +63,7 @@ type UnsafeLoggerServiceServer interface {
}
func RegisterLoggerServiceServer(s grpc.ServiceRegistrar, srv LoggerServiceServer) {
s.RegisterService(&_LoggerService_serviceDesc, srv)
s.RegisterService(&LoggerService_ServiceDesc, srv)
}
func _LoggerService_RestartLogger_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
@@ -83,7 +84,10 @@ func _LoggerService_RestartLogger_Handler(srv interface{}, ctx context.Context,
return interceptor(ctx, in, info, handler)
}
var _LoggerService_serviceDesc = grpc.ServiceDesc{
// LoggerService_ServiceDesc is the grpc.ServiceDesc for LoggerService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var LoggerService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "xray.app.log.command.LoggerService",
HandlerType: (*LoggerServiceServer)(nil),
Methods: []grpc.MethodDesc{

View File

@@ -140,7 +140,7 @@ func (s *service) Register(server *grpc.Server) {
RegisterHandlerServiceServer(server, hs)
// For compatibility purposes
vCoreDesc := _HandlerService_serviceDesc
vCoreDesc := HandlerService_ServiceDesc
vCoreDesc.ServiceName = "v2ray.core.app.proxyman.command.HandlerService"
server.RegisterService(&vCoreDesc, hs)
}

View File

@@ -11,6 +11,7 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// HandlerServiceClient is the client API for HandlerService service.
@@ -132,7 +133,7 @@ type UnsafeHandlerServiceServer interface {
}
func RegisterHandlerServiceServer(s grpc.ServiceRegistrar, srv HandlerServiceServer) {
s.RegisterService(&_HandlerService_serviceDesc, srv)
s.RegisterService(&HandlerService_ServiceDesc, srv)
}
func _HandlerService_AddInbound_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
@@ -243,7 +244,10 @@ func _HandlerService_AlterOutbound_Handler(srv interface{}, ctx context.Context,
return interceptor(ctx, in, info, handler)
}
var _HandlerService_serviceDesc = grpc.ServiceDesc{
// HandlerService_ServiceDesc is the grpc.ServiceDesc for HandlerService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var HandlerService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "xray.app.proxyman.command.HandlerService",
HandlerType: (*HandlerServiceServer)(nil),
Methods: []grpc.MethodDesc{

View File

@@ -241,6 +241,7 @@ type SniffingConfig struct {
// Override target destination if sniff'ed protocol is in the given list.
// Supported values are "http", "tls".
DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
DomainsExcluded []string `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"`
}
func (x *SniffingConfig) Reset() {
@@ -289,6 +290,13 @@ func (x *SniffingConfig) GetDestinationOverride() []string {
return nil
}
func (x *SniffingConfig) GetDomainsExcluded() []string {
if x != nil {
return x.DomainsExcluded
}
return nil
}
type ReceiverConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -756,92 +764,95 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12,
0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52,
0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x78, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0x5d, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e,
0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72,
0x72, 0x69, 0x64, 0x65, 0x22, 0x90, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f,
0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f,
0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e,
0x67, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52,
0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c,
0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12,
0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e,
0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 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, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69,
0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72,
0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72,
0x72, 0x69, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b,
0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18,
0x01, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
0x65, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65,
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e,
0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f,
0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74,
0x61, 0x67, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73,
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69,
0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52,
0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0x88, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69,
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62,
0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65,
0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73,
0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64,
0x22, 0x90, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x67,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61,
0x6e, 0x67, 0x65, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x33,
0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74,
0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69, 0x73,
0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53,
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4e, 0x0a, 0x0f, 0x73,
0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 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, 0x53,
0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72,
0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x72,
0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f,
0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28,
0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a,
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0e, 0x64,
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x4e, 0x0a,
0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e,
0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e, 0x69,
0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e, 0x69,
0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04, 0x08,
0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48,
0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03,
0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x4d,
0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54,
0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f,
0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75,
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02, 0x0a,
0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a,
0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f,
0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f,
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 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,
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74,
0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e,
0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 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, 0x50,
0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78,
0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c,
0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70,
0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75,
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22,
0x50, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12,
0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
0x79, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a,
0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50,
0x01, 0x5a, 0x26, 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, 0x61, 0x70, 0x70,
0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79,
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x72, 0x65, 0x63,
0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a,
0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65,
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75,
0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02, 0x0a, 0x0c, 0x53, 0x65, 0x6e,
0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69, 0x61,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d,
0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65,
0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x25, 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, 0x53, 0x74, 0x72, 0x65,
0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78,
0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x24, 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, 0x50, 0x72, 0x6f, 0x78, 0x79,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x74,
0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c,
0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f,
0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69,
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x50, 0x0a, 0x12, 0x4d,
0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63,
0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2a, 0x23, 0x0a,
0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12,
0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x4c, 0x53,
0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26, 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, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f,
0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70,
0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (

View File

@@ -56,6 +56,7 @@ message SniffingConfig {
// Override target destination if sniff'ed protocol is in the given list.
// Supported values are "http", "tls".
repeated string destination_override = 2;
repeated string domains_excluded = 3;
}
message ReceiverConfig {

View File

@@ -136,6 +136,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
uplinkCounter: uplinkCounter,
downlinkCounter: downlinkCounter,
stream: mss,
ctx: ctx,
}
h.workers = append(h.workers, worker)
}

View File

@@ -156,6 +156,7 @@ func (h *DynamicInboundHandler) refresh() error {
uplinkCounter: uplinkCounter,
downlinkCounter: downlinkCounter,
stream: h.streamSettings,
ctx: h.ctx,
}
if err := worker.Start(); err != nil {
newError("failed to create UDP worker").Base(err).AtWarning().WriteToLog()

View File

@@ -97,6 +97,7 @@ func (w *tcpWorker) callback(conn internet.Connection) {
if w.sniffingConfig != nil {
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
}
ctx = session.ContextWithContent(ctx, content)
@@ -239,6 +240,9 @@ type udpWorker struct {
checker *task.Periodic
activeConn map[connID]*udpConn
ctx context.Context
cone bool
}
func (w *udpWorker) getConnection(id connID) (*udpConn, bool) {
@@ -279,7 +283,10 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
src: source,
}
if originalDest.IsValid() {
id.dest = originalDest
if !w.cone {
id.dest = originalDest
}
b.UDP = &originalDest
}
conn, existing := w.getConnection(id)
@@ -336,7 +343,7 @@ func (w *udpWorker) clean() error {
}
for addr, conn := range w.activeConn {
if nowSec-atomic.LoadInt64(&conn.lastActivityTime) > 8 { // TODO Timeout too small
if nowSec-atomic.LoadInt64(&conn.lastActivityTime) > 300 {
delete(w.activeConn, addr)
conn.Close()
}
@@ -357,8 +364,10 @@ func (w *udpWorker) Start() error {
return err
}
w.cone = w.ctx.Value("cone").(bool)
w.checker = &task.Periodic{
Interval: time.Second * 16,
Interval: time.Minute,
Execute: w.clean,
}
@@ -441,6 +450,7 @@ func (w *dsWorker) callback(conn internet.Connection) {
if w.sniffingConfig != nil {
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
}
ctx = session.ContextWithContent(ctx, content)

View File

@@ -7,6 +7,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/mux"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/outbound"
@@ -173,7 +174,7 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn
downlinkReader, downlinkWriter := pipe.New(opts...)
go handler.Dispatch(ctx, &transport.Link{Reader: uplinkReader, Writer: downlinkWriter})
conn := net.NewConnection(net.ConnectionInputMulti(uplinkWriter), net.ConnectionOutputMulti(downlinkReader))
conn := cnc.NewConnection(cnc.ConnectionInputMulti(uplinkWriter), cnc.ConnectionOutputMulti(downlinkReader))
if config := tls.ConfigFromStreamSettings(h.streamSettings); config != nil {
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))

View File

@@ -85,7 +85,7 @@ func (s *service) Register(server *grpc.Server) {
RegisterRoutingServiceServer(server, rs)
// For compatibility purposes
vCoreDesc := _RoutingService_serviceDesc
vCoreDesc := RoutingService_ServiceDesc
vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService"
server.RegisterService(&vCoreDesc, rs)
}))

View File

@@ -11,6 +11,7 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// RoutingServiceClient is the client API for RoutingService service.
@@ -30,7 +31,7 @@ func NewRoutingServiceClient(cc grpc.ClientConnInterface) RoutingServiceClient {
}
func (c *routingServiceClient) SubscribeRoutingStats(ctx context.Context, in *SubscribeRoutingStatsRequest, opts ...grpc.CallOption) (RoutingService_SubscribeRoutingStatsClient, error) {
stream, err := c.cc.NewStream(ctx, &_RoutingService_serviceDesc.Streams[0], "/xray.app.router.command.RoutingService/SubscribeRoutingStats", opts...)
stream, err := c.cc.NewStream(ctx, &RoutingService_ServiceDesc.Streams[0], "/xray.app.router.command.RoutingService/SubscribeRoutingStats", opts...)
if err != nil {
return nil, err
}
@@ -99,7 +100,7 @@ type UnsafeRoutingServiceServer interface {
}
func RegisterRoutingServiceServer(s grpc.ServiceRegistrar, srv RoutingServiceServer) {
s.RegisterService(&_RoutingService_serviceDesc, srv)
s.RegisterService(&RoutingService_ServiceDesc, srv)
}
func _RoutingService_SubscribeRoutingStats_Handler(srv interface{}, stream grpc.ServerStream) error {
@@ -141,7 +142,10 @@ func _RoutingService_TestRoute_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
var _RoutingService_serviceDesc = grpc.ServiceDesc{
// RoutingService_ServiceDesc is the grpc.ServiceDesc for RoutingService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var RoutingService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "xray.app.router.command.RoutingService",
HandlerType: (*RoutingServiceServer)(nil),
Methods: []grpc.MethodDesc{

View File

@@ -91,7 +91,7 @@ func (m *DomainMatcher) Apply(ctx routing.Context) bool {
if len(domain) == 0 {
return false
}
return m.ApplyDomain(domain)
return m.ApplyDomain(strings.ToLower(domain))
}
type MultiGeoIPMatcher struct {

View File

@@ -113,7 +113,7 @@ func (s *service) Register(server *grpc.Server) {
RegisterStatsServiceServer(server, ss)
// For compatibility purposes
vCoreDesc := _StatsService_serviceDesc
vCoreDesc := StatsService_ServiceDesc
vCoreDesc.ServiceName = "v2ray.core.app.stats.command.StatsService"
server.RegisterService(&vCoreDesc, ss)
}

View File

@@ -11,6 +11,7 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// StatsServiceClient is the client API for StatsService service.
@@ -90,7 +91,7 @@ type UnsafeStatsServiceServer interface {
}
func RegisterStatsServiceServer(s grpc.ServiceRegistrar, srv StatsServiceServer) {
s.RegisterService(&_StatsService_serviceDesc, srv)
s.RegisterService(&StatsService_ServiceDesc, srv)
}
func _StatsService_GetStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
@@ -147,7 +148,10 @@ func _StatsService_GetSysStats_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
var _StatsService_serviceDesc = grpc.ServiceDesc{
// StatsService_ServiceDesc is the grpc.ServiceDesc for StatsService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var StatsService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "xray.app.stats.command.StatsService",
HandlerType: (*StatsServiceServer)(nil),
Methods: []grpc.MethodDesc{

View File

@@ -4,6 +4,7 @@ import (
"io"
"github.com/xtls/xray-core/common/bytespool"
"github.com/xtls/xray-core/common/net"
)
const (
@@ -20,6 +21,7 @@ type Buffer struct {
v []byte
start int32
end int32
UDP *net.Destination
}
// New creates a Buffer with 0 length and 2K capacity.
@@ -47,6 +49,7 @@ func (b *Buffer) Release() {
b.v = nil
b.Clear()
pool.Put(p)
b.UDP = nil
}
// Clear clears the content of the buffer, results an empty buffer with

View File

@@ -36,19 +36,23 @@ func (m *AccessMessage) String() string {
builder.WriteString(string(m.Status))
builder.WriteByte(' ')
builder.WriteString(serial.ToString(m.To))
builder.WriteByte(' ')
if len(m.Detour) > 0 {
builder.WriteByte('[')
builder.WriteString(" [")
builder.WriteString(m.Detour)
builder.WriteString("] ")
builder.WriteByte(']')
}
if reason := serial.ToString(m.Reason); len(reason) > 0 {
builder.WriteString(" ")
builder.WriteString(reason)
}
builder.WriteString(serial.ToString(m.Reason))
if len(m.Email) > 0 {
builder.WriteString("email:")
builder.WriteString(" email: ")
builder.WriteString(m.Email)
builder.WriteByte(' ')
}
return builder.String()
}

View File

@@ -1,12 +1,12 @@
package net
package cnc
import (
"io"
"net"
"time"
"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/signal/done"
)
@@ -88,8 +88,8 @@ type connection struct {
writer buf.Writer
done *done.Instance
onClose io.Closer
local Addr
remote Addr
local net.Addr
remote net.Addr
}
func (c *connection) Read(b []byte) (int, error) {

View File

@@ -1,4 +1,4 @@
package jsonem
package ocsp
import "github.com/xtls/xray-core/common/errors"

136
common/ocsp/ocsp.go Normal file
View File

@@ -0,0 +1,136 @@
package ocsp
import (
"bytes"
"crypto/x509"
"encoding/pem"
"io/ioutil"
"net/http"
"os"
"golang.org/x/crypto/ocsp"
"github.com/xtls/xray-core/common/platform/filesystem"
)
func GetOCSPForFile(path string) ([]byte, error) {
return filesystem.ReadFile(path)
}
func CheckOCSPFileIsNotExist(path string) bool {
_, err := os.Stat(path)
if err != nil {
return os.IsNotExist(err)
}
return false
}
func GetOCSPStapling(cert [][]byte, path string) ([]byte, error) {
ocspData, err := GetOCSPForFile(path)
if err != nil {
ocspData, err = GetOCSPForCert(cert)
if !CheckOCSPFileIsNotExist(path) {
err = os.Remove(path)
if err != nil {
return nil, err
}
}
newFile, err := os.Create(path)
if err != nil {
return nil, err
}
newFile.Write(ocspData)
defer newFile.Close()
}
return ocspData, nil
}
func GetOCSPForCert(cert [][]byte) ([]byte, error) {
bundle := new(bytes.Buffer)
for _, derBytes := range cert {
err := pem.Encode(bundle, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
if err != nil {
return nil, err
}
}
pemBundle := bundle.Bytes()
certificates, err := parsePEMBundle(pemBundle)
if err != nil {
return nil, err
}
issuedCert := certificates[0]
if len(issuedCert.OCSPServer) == 0 {
return nil, newError("no OCSP server specified in cert")
}
if len(certificates) == 1 {
if len(issuedCert.IssuingCertificateURL) == 0 {
return nil, newError("no issuing certificate URL")
}
resp, errC := http.Get(issuedCert.IssuingCertificateURL[0])
if errC != nil {
return nil, newError("no issuing certificate URL")
}
defer resp.Body.Close()
issuerBytes, errC := ioutil.ReadAll(resp.Body)
if errC != nil {
return nil, newError(errC)
}
issuerCert, errC := x509.ParseCertificate(issuerBytes)
if errC != nil {
return nil, newError(errC)
}
certificates = append(certificates, issuerCert)
}
issuerCert := certificates[1]
ocspReq, err := ocsp.CreateRequest(issuedCert, issuerCert, nil)
if err != nil {
return nil, err
}
reader := bytes.NewReader(ocspReq)
req, err := http.Post(issuedCert.OCSPServer[0], "application/ocsp-request", reader)
if err != nil {
return nil, newError(err)
}
defer req.Body.Close()
ocspResBytes, err := ioutil.ReadAll(req.Body)
if err != nil {
return nil, newError(err)
}
return ocspResBytes, nil
}
// parsePEMBundle parses a certificate bundle from top to bottom and returns
// a slice of x509 certificates. This function will error if no certificates are found.
func parsePEMBundle(bundle []byte) ([]*x509.Certificate, error) {
var certificates []*x509.Certificate
var certDERBlock *pem.Block
for {
certDERBlock, bundle = pem.Decode(bundle)
if certDERBlock == nil {
break
}
if certDERBlock.Type == "CERTIFICATE" {
cert, err := x509.ParseCertificate(certDERBlock.Bytes)
if err != nil {
return nil, err
}
certificates = append(certificates, cert)
}
}
if len(certificates) == 0 {
return nil, newError("no certificates were found while parsing the bundle")
}
return certificates, nil
}

View File

@@ -102,7 +102,7 @@ func ReadClientHello(data []byte, h *SniffHeader) error {
return errNotClientHello
}
if nameType == 0 {
serverName := string(d[:nameLen])
serverName := strings.ToLower(string(d[:nameLen]))
// An SNI value may not include a
// trailing dot. See
// https://tools.ietf.org/html/rfc6066#section-3.

View File

@@ -8,7 +8,7 @@ import (
// ToString serialize an arbitrary value into string.
func ToString(v interface{}) string {
if v == nil {
return " "
return ""
}
switch value := v.(type) {

View File

@@ -60,6 +60,7 @@ type Outbound struct {
// SniffingRequest controls the behavior of content sniffing.
type SniffingRequest struct {
ExcludeForDomain []string
OverrideDestinationForProtocol []string
Enabled bool
}

View File

@@ -3,6 +3,7 @@ package uuid // import "github.com/xtls/xray-core/common/uuid"
import (
"bytes"
"crypto/rand"
"crypto/sha1"
"encoding/hex"
"github.com/xtls/xray-core/common"
@@ -49,6 +50,8 @@ func (u *UUID) Equals(another *UUID) bool {
func New() UUID {
var uuid UUID
common.Must2(rand.Read(uuid.Bytes()))
uuid[6] = (uuid[6] & 0x0f) | (4 << 4)
uuid[8] = (uuid[8]&(0xff>>2) | (0x02 << 6))
return uuid
}
@@ -67,8 +70,18 @@ func ParseString(str string) (UUID, error) {
var uuid UUID
text := []byte(str)
if len(text) < 32 {
return uuid, errors.New("invalid UUID: ", str)
if l := len(text); l < 32 || l > 36 {
if l == 0 || l > 30 {
return uuid, errors.New("invalid UUID: ", str)
}
h := sha1.New()
h.Write(uuid[:])
h.Write(text)
u := h.Sum(nil)[:16]
u[6] = (u[6] & 0x0f) | (5 << 4)
u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
copy(uuid[:], u)
return uuid, nil
}
b := uuid.Bytes()

View File

@@ -35,9 +35,10 @@ func TestParseString(t *testing.T) {
t.Fatal(r)
}
_, err = ParseString("2418d087")
if err == nil {
t.Fatal("Expect error but nil")
u0, _ := ParseString("example")
u5, _ := ParseString("feb54431-301b-52bb-a6dd-e1e93e81bb9e")
if r := cmp.Diff(u0, u5); r != "" {
t.Fatal(r)
}
_, err = ParseString("2418d087-648k-4990-86e8-19dca1d006d3")

View File

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

View File

@@ -6,6 +6,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/udp"
)
@@ -53,13 +54,13 @@ func Dial(ctx context.Context, v *Instance, dest net.Destination) (net.Conn, err
if err != nil {
return nil, err
}
var readerOpt net.ConnectionOption
var readerOpt cnc.ConnectionOption
if dest.Network == net.Network_TCP {
readerOpt = net.ConnectionOutputMulti(r.Reader)
readerOpt = cnc.ConnectionOutputMulti(r.Reader)
} else {
readerOpt = net.ConnectionOutputMultiUDP(r.Reader)
readerOpt = cnc.ConnectionOutputMultiUDP(r.Reader)
}
return net.NewConnection(net.ConnectionInputMulti(r.Writer), readerOpt), nil
return cnc.NewConnection(cnc.ConnectionInputMulti(r.Writer), readerOpt), nil
}
// DialUDP provides a way to exchange UDP packets through Xray instance to remote servers.

View File

@@ -3,8 +3,13 @@ package core
import (
"context"
"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"
@@ -179,6 +184,31 @@ 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
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()
if config.Transport != nil {
features.PrintDeprecatedFeatureWarning("global transport settings")
}

21
go.mod
View File

@@ -3,23 +3,24 @@ module github.com/xtls/xray-core
go 1.15
require (
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 // indirect
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
github.com/golang/mock v1.4.4
github.com/golang/protobuf v1.4.3
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/pires/go-proxyproto v0.3.3
github.com/seiflotfy/cuckoofilter v0.0.0-20201009151232-afb285a456ab
github.com/stretchr/testify v1.6.1
github.com/pelletier/go-toml v1.8.1
github.com/pires/go-proxyproto v0.4.1
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-20201210151846-e81fc95f7bd5
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11
go.starlark.net v0.0.0-20210121225809-cea917ab6e0f
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-20201211002650-1f0c578a6b29
google.golang.org/grpc v1.34.0
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4
google.golang.org/grpc v1.35.0
google.golang.org/protobuf v1.25.0
h12.io/socks v1.0.1
h12.io/socks v1.0.2
)

45
go.sum
View File

@@ -19,7 +19,7 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -29,7 +29,7 @@ github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fp
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
@@ -37,6 +37,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -121,10 +123,12 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
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.3.3 h1:jOXGrsAfSQVFiD1hWg1aiHpLYsd6SJw/8cLN594sB7Q=
github.com/pires/go-proxyproto v0.3.3/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
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/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=
@@ -134,8 +138,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/seiflotfy/cuckoofilter v0.0.0-20201009151232-afb285a456ab h1:O43uBnD2Y6fo1oFsXY+Vqp1n3RFfxg1u3XATDGvUXgI=
github.com/seiflotfy/cuckoofilter v0.0.0-20201009151232-afb285a456ab/go.mod h1:ET5mVvNjwaGXRgZxO9UZr7X+8eAf87AfIYNwRSp9s4Y=
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c h1:pqy40B3MQWYrza7YZXOXgl0Nf0QGFqrOC0BKae1UNAA=
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
@@ -167,6 +171,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
@@ -174,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-20201210151846-e81fc95f7bd5 h1:F1LaLz0cvAJWMa5r3bogEYXD7/5fgA9a9jOX4DAobN8=
go.starlark.net v0.0.0-20201210151846-e81fc95f7bd5/go.mod h1:vxxlMsgCAPH7BR2LtxjJC4WhhZhCGd/b01+CIpj8H4k=
go.starlark.net v0.0.0-20210121225809-cea917ab6e0f h1:MfDkeyR3bphbh1zJ3Z7cTsZ8Ydd4mXQiBEhcZRltwaM=
go.starlark.net v0.0.0-20210121225809-cea917ab6e0f/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=
@@ -184,8 +190,8 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 h1:sYNJzB4J8toYPQTM6pAkcmBRgw9SnQKP9oXCHfgy604=
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -206,8 +212,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 h1:lwlPPsmjDKK0J6eG6xDWd5XPehI0R024zxjDnw3esPA=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -238,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-20201211002650-1f0c578a6b29 h1:hAYi5mzhvBeCfkgaIHGZ8R+Q04WjSW5ZvQO3BZ94dHY=
golang.org/x/sys v0.0.0-20201211002650-1f0c578a6b29/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/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=
@@ -286,8 +292,8 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.34.0 h1:raiipEjMOIC/TO2AvyTxP25XFdLxNIBwzDh3FM3XztI=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -310,11 +316,12 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
h12.io/socks v1.0.1 h1:bXESSI/+hbdrp+22vcc7/JiXjmLH4UWktKdYgGr3ShA=
h12.io/socks v1.0.1/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
h12.io/socks v1.0.2 h1:cZhhbV8+DE0Y1kotwhr1a3RC3kFO7AtuZ4GLr3qKSc8=
h12.io/socks v1.0.2/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -84,7 +84,7 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
geoipList, err := toCidrList(c.ExpectIPs)
if err != nil {
return nil, newError("invalid ip rule: ", c.ExpectIPs).Base(err)
return nil, newError("invalid IP rule: ", c.ExpectIPs).Base(err)
}
return &dns.NameServer{
@@ -142,7 +142,7 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
for _, server := range c.Servers {
ns, err := server.Build()
if err != nil {
return nil, newError("failed to build name server").Base(err)
return nil, newError("failed to build nameserver").Base(err)
}
config.NameServer = append(config.NameServer, ns)
}
@@ -159,15 +159,23 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
var mappings []*dns.Config_HostMapping
switch {
case strings.HasPrefix(domain, "domain:"):
domainName := domain[7:]
if len(domainName) == 0 {
return nil, newError("empty domain type of rule: ", domain)
}
mapping := getHostMapping(addr)
mapping.Type = dns.DomainMatchingType_Subdomain
mapping.Domain = domain[7:]
mapping.Domain = domainName
mappings = append(mappings, mapping)
case strings.HasPrefix(domain, "geosite:"):
domains, err := loadGeositeWithAttr("geosite.dat", strings.ToUpper(domain[8:]))
listName := domain[8:]
if len(listName) == 0 {
return nil, newError("empty geosite rule: ", domain)
}
domains, err := loadGeositeWithAttr("geosite.dat", listName)
if err != nil {
return nil, newError("invalid geosite settings: ", domain).Base(err)
return nil, newError("failed to load geosite: ", listName).Base(err)
}
for _, d := range domains {
mapping := getHostMapping(addr)
@@ -177,21 +185,33 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
}
case strings.HasPrefix(domain, "regexp:"):
regexpVal := domain[7:]
if len(regexpVal) == 0 {
return nil, newError("empty regexp type of rule: ", domain)
}
mapping := getHostMapping(addr)
mapping.Type = dns.DomainMatchingType_Regex
mapping.Domain = domain[7:]
mapping.Domain = regexpVal
mappings = append(mappings, mapping)
case strings.HasPrefix(domain, "keyword:"):
keywordVal := domain[8:]
if len(keywordVal) == 0 {
return nil, newError("empty keyword type of rule: ", domain)
}
mapping := getHostMapping(addr)
mapping.Type = dns.DomainMatchingType_Keyword
mapping.Domain = domain[8:]
mapping.Domain = keywordVal
mappings = append(mappings, mapping)
case strings.HasPrefix(domain, "full:"):
fullVal := domain[5:]
if len(fullVal) == 0 {
return nil, newError("empty full domain type of rule: ", domain)
}
mapping := getHostMapping(addr)
mapping.Type = dns.DomainMatchingType_Full
mapping.Domain = domain[5:]
mapping.Domain = fullVal
mappings = append(mappings, mapping)
case strings.HasPrefix(domain, "dotless:"):
@@ -213,10 +233,10 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
return nil, newError("invalid external resource: ", domain)
}
filename := kv[0]
country := kv[1]
domains, err := loadGeositeWithAttr(filename, country)
list := kv[1]
domains, err := loadGeositeWithAttr(filename, list)
if err != nil {
return nil, newError("failed to load domains: ", country, " from ", filename).Base(err)
return nil, newError("failed to load domain list: ", list, " from ", filename).Base(err)
}
for _, d := range domains {
mapping := getHostMapping(addr)

View File

@@ -2,6 +2,7 @@ package conf
import (
"encoding/json"
"runtime"
"strconv"
"strings"
@@ -147,46 +148,109 @@ func ParseIP(s string) (*router.CIDR, error) {
}
}
func loadGeoIP(country string) ([]*router.CIDR, error) {
return loadIP("geoip.dat", country)
func loadGeoIP(code string) ([]*router.CIDR, error) {
return loadIP("geoip.dat", code)
}
func loadIP(filename, country string) ([]*router.CIDR, error) {
geoipBytes, err := filesystem.ReadAsset(filename)
if err != nil {
return nil, newError("failed to open file: ", filename).Base(err)
}
var geoipList router.GeoIPList
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
return nil, err
}
var (
FileCache = make(map[string][]byte)
IPCache = make(map[string]*router.GeoIP)
SiteCache = make(map[string]*router.GeoSite)
)
for _, geoip := range geoipList.Entry {
if geoip.CountryCode == country {
return geoip.Cidr, nil
func loadFile(file string) ([]byte, error) {
if FileCache[file] == nil {
bs, err := filesystem.ReadAsset(file)
if err != nil {
return nil, newError("failed to open file: ", file).Base(err)
}
if len(bs) == 0 {
return nil, newError("empty file: ", file)
}
// Do not cache file, may save RAM when there
// are many files, but consume CPU each time.
return bs, nil
FileCache[file] = bs
}
return nil, newError("country not found in ", filename, ": ", country)
return FileCache[file], nil
}
func loadSite(filename, country string) ([]*router.Domain, error) {
geositeBytes, err := filesystem.ReadAsset(filename)
if err != nil {
return nil, newError("failed to open file: ", filename).Base(err)
}
var geositeList router.GeoSiteList
if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
return nil, err
}
for _, site := range geositeList.Entry {
if site.CountryCode == country {
return site.Domain, nil
func loadIP(file, code string) ([]*router.CIDR, error) {
index := file + ":" + code
if IPCache[index] == nil {
bs, err := loadFile(file)
if err != nil {
return nil, newError("failed to load file: ", file).Base(err)
}
bs = find(bs, []byte(code))
if bs == nil {
return nil, newError("code not found in ", file, ": ", code)
}
var geoip router.GeoIP
if err := proto.Unmarshal(bs, &geoip); err != nil {
return nil, newError("error unmarshal IP in ", file, ": ", code).Base(err)
}
defer runtime.GC() // or debug.FreeOSMemory()
return geoip.Cidr, nil // do not cache geoip
IPCache[index] = &geoip
}
return IPCache[index].Cidr, nil
}
return nil, newError("list not found in ", filename, ": ", country)
func loadSite(file, code string) ([]*router.Domain, error) {
index := file + ":" + code
if SiteCache[index] == nil {
bs, err := loadFile(file)
if err != nil {
return nil, newError("failed to load file: ", file).Base(err)
}
bs = find(bs, []byte(code))
if bs == nil {
return nil, newError("list not found in ", file, ": ", code)
}
var geosite router.GeoSite
if err := proto.Unmarshal(bs, &geosite); err != nil {
return nil, newError("error unmarshal Site in ", file, ": ", code).Base(err)
}
defer runtime.GC() // or debug.FreeOSMemory()
return geosite.Domain, nil // do not cache geosite
SiteCache[index] = &geosite
}
return SiteCache[index].Domain, nil
}
func find(data, code []byte) []byte {
codeL := len(code)
if codeL == 0 {
return nil
}
for {
dataL := len(data)
if dataL < 2 {
return nil
}
x, y := proto.DecodeVarint(data[1:])
if x == 0 && y == 0 {
return nil
}
headL, bodyL := 1+y, int(x)
dataL -= headL
if dataL < bodyL {
return nil
}
data = data[headL:]
if int(data[1]) == codeL {
for i := 0; i < codeL && data[2+i] == code[i]; i++ {
if i+1 == codeL {
return data[:bodyL]
}
}
}
if dataL == bodyL {
return nil
}
data = data[bodyL:]
}
}
type AttributeMatcher interface {
@@ -396,6 +460,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
type RawFieldRule struct {
RouterRule
Domain *StringList `json:"domain"`
Domains *StringList `json:"domains"`
IP *StringList `json:"ip"`
Port *PortList `json:"port"`
Network *NetworkList `json:"network"`
@@ -436,6 +501,16 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
}
}
if rawFieldRule.Domains != nil {
for _, domain := range *rawFieldRule.Domains {
rules, err := parseDomainRule(domain)
if err != nil {
return nil, newError("failed to parse domain rule: ", domain).Base(err)
}
rule.Domain = append(rule.Domain, rules...)
}
}
if rawFieldRule.IP != nil {
geoipList, err := toCidrList(*rawFieldRule.IP)
if err != nil {

View File

@@ -4,6 +4,10 @@ import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"github.com/ghodss/yaml"
"github.com/pelletier/go-toml"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core"
@@ -80,3 +84,68 @@ func LoadJSONConfig(reader io.Reader) (*core.Config, error) {
return pbConfig, nil
}
// DecodeTOMLConfig reads from reader and decode the config into *conf.Config
// using github.com/pelletier/go-toml and map to convert toml to json.
func DecodeTOMLConfig(reader io.Reader) (*conf.Config, error) {
tomlFile, err := ioutil.ReadAll(reader)
if err != nil {
return nil, newError("failed to read config file").Base(err)
}
configMap := make(map[string]interface{})
if err := toml.Unmarshal(tomlFile, &configMap); err != nil {
return nil, newError("failed to convert toml to map").Base(err)
}
jsonFile, err := json.Marshal(&configMap)
if err != nil {
return nil, newError("failed to convert map to json").Base(err)
}
return DecodeJSONConfig(bytes.NewReader(jsonFile))
}
func LoadTOMLConfig(reader io.Reader) (*core.Config, error) {
tomlConfig, err := DecodeTOMLConfig(reader)
if err != nil {
return nil, err
}
pbConfig, err := tomlConfig.Build()
if err != nil {
return nil, newError("failed to parse toml config").Base(err)
}
return pbConfig, nil
}
// DecodeYAMLConfig reads from reader and decode the config into *conf.Config
// using github.com/ghodss/yaml to convert yaml to json.
func DecodeYAMLConfig(reader io.Reader) (*conf.Config, error) {
yamlFile, err := ioutil.ReadAll(reader)
if err != nil {
return nil, newError("failed to read config file").Base(err)
}
jsonFile, err := yaml.YAMLToJSON(yamlFile)
if err != nil {
return nil, newError("failed to convert yaml to json").Base(err)
}
return DecodeJSONConfig(bytes.NewReader(jsonFile))
}
func LoadYAMLConfig(reader io.Reader) (*core.Config, error) {
yamlConfig, err := DecodeYAMLConfig(reader)
if err != nil {
return nil, err
}
pbConfig, err := yamlConfig.Build()
if err != nil {
return nil, newError("failed to parse yaml config").Base(err)
}
return pbConfig, nil
}

View File

@@ -33,35 +33,60 @@ func cipherFromString(c string) shadowsocks.CipherType {
}
}
type ShadowsocksUserConfig struct {
Cipher string `json:"method"`
Password string `json:"password"`
Level byte `json:"level"`
Email string `json:"email"`
}
type ShadowsocksServerConfig struct {
Cipher string `json:"method"`
Password string `json:"password"`
UDP bool `json:"udp"`
Level byte `json:"level"`
Email string `json:"email"`
NetworkList *NetworkList `json:"network"`
Cipher string `json:"method"`
Password string `json:"password"`
Level byte `json:"level"`
Email string `json:"email"`
Users []*ShadowsocksUserConfig `json:"clients"`
NetworkList *NetworkList `json:"network"`
}
func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
config := new(shadowsocks.ServerConfig)
config.UdpEnabled = v.UDP
config.Network = v.NetworkList.Build()
if v.Password == "" {
return nil, newError("Shadowsocks password is not specified.")
}
account := &shadowsocks.Account{
Password: v.Password,
}
account.CipherType = cipherFromString(v.Cipher)
if account.CipherType == shadowsocks.CipherType_UNKNOWN {
return nil, newError("unknown cipher method: ", v.Cipher)
}
config.User = &protocol.User{
Email: v.Email,
Level: uint32(v.Level),
Account: serial.ToTypedMessage(account),
if v.Users != nil {
for _, user := range v.Users {
account := &shadowsocks.Account{
Password: user.Password,
CipherType: cipherFromString(user.Cipher),
}
if account.Password == "" {
return nil, newError("Shadowsocks password is not specified.")
}
if account.CipherType < 5 || account.CipherType > 7 {
return nil, newError("unsupported cipher method: ", user.Cipher)
}
config.Users = append(config.Users, &protocol.User{
Email: user.Email,
Level: uint32(user.Level),
Account: serial.ToTypedMessage(account),
})
}
} else {
account := &shadowsocks.Account{
Password: v.Password,
CipherType: cipherFromString(v.Cipher),
}
if account.Password == "" {
return nil, newError("Shadowsocks password is not specified.")
}
if account.CipherType == shadowsocks.CipherType_UNKNOWN {
return nil, newError("unknown cipher method: ", v.Cipher)
}
config.Users = append(config.Users, &protocol.User{
Email: v.Email,
Level: uint32(v.Level),
Account: serial.ToTypedMessage(account),
})
}
return config, nil
@@ -73,7 +98,6 @@ type ShadowsocksServerTarget struct {
Cipher string `json:"method"`
Password string `json:"password"`
Email string `json:"email"`
Ota bool `json:"ota"`
Level byte `json:"level"`
}

View File

@@ -18,17 +18,17 @@ func TestShadowsocksServerConfigParsing(t *testing.T) {
runMultiTestCase(t, []TestCase{
{
Input: `{
"method": "aes-128-cfb",
"method": "aes-128-gcm",
"password": "xray-password"
}`,
Parser: loadJSON(creator),
Output: &shadowsocks.ServerConfig{
User: &protocol.User{
Users: []*protocol.User{{
Account: serial.ToTypedMessage(&shadowsocks.Account{
CipherType: shadowsocks.CipherType_AES_128_CFB,
CipherType: shadowsocks.CipherType_AES_128_GCM,
Password: "xray-password",
}),
},
}},
Network: []net.Network{net.Network_TCP},
},
},

View File

@@ -247,11 +247,12 @@ func readFileOrString(f string, s []string) ([]byte, error) {
}
type TLSCertConfig struct {
CertFile string `json:"certificateFile"`
CertStr []string `json:"certificate"`
KeyFile string `json:"keyFile"`
KeyStr []string `json:"key"`
Usage string `json:"usage"`
CertFile string `json:"certificateFile"`
CertStr []string `json:"certificate"`
KeyFile string `json:"keyFile"`
KeyStr []string `json:"key"`
Usage string `json:"usage"`
OcspStapling int64 `json:"ocspStapling"`
}
// Build implements Buildable.
@@ -283,17 +284,22 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
certificate.Usage = tls.Certificate_ENCIPHERMENT
}
certificate.OcspStapling = c.OcspStapling
return certificate, nil
}
type TLSConfig struct {
Insecure bool `json:"allowInsecure"`
InsecureCiphers bool `json:"allowInsecureCiphers"`
Certs []*TLSCertConfig `json:"certificates"`
ServerName string `json:"serverName"`
ALPN *StringList `json:"alpn"`
DisableSessionResumption bool `json:"disableSessionResumption"`
EnableSessionResumption bool `json:"enableSessionResumption"`
DisableSystemRoot bool `json:"disableSystemRoot"`
MinVersion string `json:"minVersion"`
MaxVersion string `json:"maxVersion"`
CipherSuites string `json:"cipherSuites"`
PreferServerCipherSuites bool `json:"preferServerCipherSuites"`
}
// Build implements Buildable.
@@ -309,24 +315,28 @@ func (c *TLSConfig) Build() (proto.Message, error) {
}
serverName := c.ServerName
config.AllowInsecure = c.Insecure
config.AllowInsecureCiphers = c.InsecureCiphers
if len(c.ServerName) > 0 {
config.ServerName = serverName
}
if c.ALPN != nil && len(*c.ALPN) > 0 {
config.NextProtocol = []string(*c.ALPN)
}
config.DisableSessionResumption = c.DisableSessionResumption
config.EnableSessionResumption = c.EnableSessionResumption
config.DisableSystemRoot = c.DisableSystemRoot
config.MinVersion = c.MinVersion
config.MaxVersion = c.MaxVersion
config.CipherSuites = c.CipherSuites
config.PreferServerCipherSuites = c.PreferServerCipherSuites
return config, nil
}
type XTLSCertConfig struct {
CertFile string `json:"certificateFile"`
CertStr []string `json:"certificate"`
KeyFile string `json:"keyFile"`
KeyStr []string `json:"key"`
Usage string `json:"usage"`
CertFile string `json:"certificateFile"`
CertStr []string `json:"certificate"`
KeyFile string `json:"keyFile"`
KeyStr []string `json:"key"`
Usage string `json:"usage"`
OcspStapling int64 `json:"ocspStapling"`
}
// Build implements Buildable.
@@ -358,17 +368,22 @@ func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) {
certificate.Usage = xtls.Certificate_ENCIPHERMENT
}
certificate.OcspStapling = c.OcspStapling
return certificate, nil
}
type XTLSConfig struct {
Insecure bool `json:"allowInsecure"`
InsecureCiphers bool `json:"allowInsecureCiphers"`
Certs []*XTLSCertConfig `json:"certificates"`
ServerName string `json:"serverName"`
ALPN *StringList `json:"alpn"`
DisableSessionResumption bool `json:"disableSessionResumption"`
EnableSessionResumption bool `json:"enableSessionResumption"`
DisableSystemRoot bool `json:"disableSystemRoot"`
MinVersion string `json:"minVersion"`
MaxVersion string `json:"maxVersion"`
CipherSuites string `json:"cipherSuites"`
PreferServerCipherSuites bool `json:"preferServerCipherSuites"`
}
// Build implements Buildable.
@@ -384,15 +399,18 @@ func (c *XTLSConfig) Build() (proto.Message, error) {
}
serverName := c.ServerName
config.AllowInsecure = c.Insecure
config.AllowInsecureCiphers = c.InsecureCiphers
if len(c.ServerName) > 0 {
config.ServerName = serverName
}
if c.ALPN != nil && len(*c.ALPN) > 0 {
config.NextProtocol = []string(*c.ALPN)
}
config.DisableSessionResumption = c.DisableSessionResumption
config.EnableSessionResumption = c.EnableSessionResumption
config.DisableSystemRoot = c.DisableSystemRoot
config.MinVersion = c.MinVersion
config.MaxVersion = c.MaxVersion
config.CipherSuites = c.CipherSuites
config.PreferServerCipherSuites = c.PreferServerCipherSuites
return config, nil
}

View File

@@ -52,6 +52,17 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
Password: rec.Password,
Flow: rec.Flow,
}
switch account.Flow {
case "", "xtls-rprx-origin", "xtls-rprx-origin-udp443", "xtls-rprx-direct", "xtls-rprx-direct-udp443":
case "xtls-rprx-splice", "xtls-rprx-splice-udp443":
if runtime.GOOS != "linux" && runtime.GOOS != "android" {
return nil, newError(`Trojan servers: "` + account.Flow + `" only support linux in this version`)
}
default:
return nil, newError(`Trojan servers: "flow" doesn't support "` + account.Flow + `" in this version`)
}
trojan := &protocol.ServerEndpoint{
Address: rec.Address.Build(),
Port: uint32(rec.Port),
@@ -74,6 +85,7 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
// TrojanInboundFallback is fallback configuration
type TrojanInboundFallback struct {
Name string `json:"name"`
Alpn string `json:"alpn"`
Path string `json:"path"`
Type string `json:"type"`
@@ -107,6 +119,14 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
Flow: rawUser.Flow,
}
switch account.Flow {
case "", "xtls-rprx-origin", "xtls-rprx-direct":
case "xtls-rprx-splice":
return nil, newError(`Trojan clients: inbound doesn't support "xtls-rprx-splice" in this version, please use "xtls-rprx-direct" instead`)
default:
return nil, newError(`Trojan clients: "flow" doesn't support "` + account.Flow + `" in this version`)
}
user.Email = rawUser.Email
user.Level = uint32(rawUser.Level)
user.Account = serial.ToTypedMessage(account)
@@ -125,6 +145,7 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
_ = json.Unmarshal(fb.Dest, &s)
}
config.Fallbacks = append(config.Fallbacks, &trojan.Fallback{
Name: fb.Name,
Alpn: fb.Alpn,
Path: fb.Path,
Type: fb.Type,
@@ -148,7 +169,7 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
switch fb.Dest[0] {
case '@', '/':
fb.Type = "unix"
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && runtime.GOOS == "linux" {
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy
copy(fullAddr, fb.Dest[1:])
fb.Dest = string(fullAddr)

View File

@@ -11,12 +11,14 @@ import (
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/uuid"
"github.com/xtls/xray-core/proxy/vless"
"github.com/xtls/xray-core/proxy/vless/inbound"
"github.com/xtls/xray-core/proxy/vless/outbound"
)
type VLessInboundFallback struct {
Name string `json:"name"`
Alpn string `json:"alpn"`
Path string `json:"path"`
Type string `json:"type"`
@@ -45,6 +47,12 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
return nil, newError(`VLESS clients: invalid user`).Base(err)
}
u, err := uuid.ParseString(account.Id)
if err != nil {
return nil, err
}
account.Id = u.String()
switch account.Flow {
case "", "xtls-rprx-origin", "xtls-rprx-direct":
case "xtls-rprx-splice":
@@ -78,6 +86,7 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
_ = json.Unmarshal(fb.Dest, &s)
}
config.Fallbacks = append(config.Fallbacks, &inbound.Fallback{
Name: fb.Name,
Alpn: fb.Alpn,
Path: fb.Path,
Type: fb.Type,
@@ -101,7 +110,7 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
switch fb.Dest[0] {
case '@', '/':
fb.Type = "unix"
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && runtime.GOOS == "linux" {
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy
copy(fullAddr, fb.Dest[1:])
fb.Dest = string(fullAddr)
@@ -167,6 +176,12 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
return nil, newError(`VLESS users: invalid user`).Base(err)
}
u, err := uuid.ParseString(account.Id)
if err != nil {
return nil, err
}
account.Id = u.String()
switch account.Flow {
case "", "xtls-rprx-origin", "xtls-rprx-origin-udp443", "xtls-rprx-direct", "xtls-rprx-direct-udp443":
case "xtls-rprx-splice", "xtls-rprx-splice-udp443":

View File

@@ -8,6 +8,7 @@ import (
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/uuid"
"github.com/xtls/xray-core/proxy/vmess"
"github.com/xtls/xray-core/proxy/vmess/inbound"
"github.com/xtls/xray-core/proxy/vmess/outbound"
@@ -105,6 +106,13 @@ func (c *VMessInboundConfig) Build() (proto.Message, error) {
if err := json.Unmarshal(rawData, account); err != nil {
return nil, newError("invalid VMess user").Base(err)
}
u, err := uuid.ParseString(account.ID)
if err != nil {
return nil, err
}
account.ID = u.String()
user.Account = serial.ToTypedMessage(account.Build())
config.User[idx] = user
}
@@ -149,6 +157,13 @@ func (c *VMessOutboundConfig) Build() (proto.Message, error) {
if err := json.Unmarshal(rawUser, account); err != nil {
return nil, newError("invalid VMess user").Base(err)
}
u, err := uuid.ParseString(account.ID)
if err != nil {
return nil, err
}
account.ID = u.String()
user.Account = serial.ToTypedMessage(account.Build())
spec.User = append(spec.User, user)
}

View File

@@ -58,29 +58,38 @@ func toProtocolList(s []string) ([]proxyman.KnownProtocols, error) {
}
type SniffingConfig struct {
Enabled bool `json:"enabled"`
DestOverride *StringList `json:"destOverride"`
Enabled bool `json:"enabled"`
DestOverride *StringList `json:"destOverride"`
DomainsExcluded *StringList `json:"domainsExcluded"`
}
// Build implements Buildable.
func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
var p []string
if c.DestOverride != nil {
for _, domainOverride := range *c.DestOverride {
switch strings.ToLower(domainOverride) {
for _, protocol := range *c.DestOverride {
switch strings.ToLower(protocol) {
case "http":
p = append(p, "http")
case "tls", "https", "ssl":
p = append(p, "tls")
default:
return nil, newError("unknown protocol: ", domainOverride)
return nil, newError("unknown protocol: ", protocol)
}
}
}
var d []string
if c.DomainsExcluded != nil {
for _, domain := range *c.DomainsExcluded {
d = append(d, strings.ToLower(domain))
}
}
return &proxyman.SniffingConfig{
Enabled: c.Enabled,
DestinationOverride: p,
DomainsExcluded: d,
}, nil
}

View File

@@ -8,15 +8,33 @@ import (
)
var cmdUUID = &base.Command{
UsageLine: "{{.Exec}} uuid",
Short: "Generate new UUIDs",
UsageLine: `{{.Exec}} uuid [-i "example"]`,
Short: `Generate UUIDv4 or UUIDv5`,
Long: `
Generate new UUIDs.
`,
Run: executeUUID,
Generate UUIDv4 or UUIDv5.
UUIDv4 (random): {{.Exec}} uuid
UUIDv5 (from input): {{.Exec}} uuid -i "example"
`,
}
func executeUUID(cmd *base.Command, args []string) {
u := uuid.New()
fmt.Println(u.String())
func init() {
cmdUUID.Run = executeUUID // break init loop
}
var input = cmdUUID.Flag.String("i", "", "")
func executeUUID(cmd *base.Command, args []string) {
var output string
if l := len(*input); l == 0 {
u := uuid.New()
output = u.String()
} else if l <= 30 {
u, _ := uuid.ParseString(*input)
output = u.String()
} else {
output = "Input must be within 30 bytes."
}
fmt.Println(output)
}

View File

@@ -57,15 +57,14 @@ import (
_ "github.com/xtls/xray-core/transport/internet/headers/wechat"
_ "github.com/xtls/xray-core/transport/internet/headers/wireguard"
// JSON config support. Choose only one from the two below.
// The following line loads JSON from xctl
// _ "github.com/xtls/xray-core/main/json"
// The following line loads JSON internally
_ "github.com/xtls/xray-core/main/jsonem"
// JSON & TOML & YAML
_ "github.com/xtls/xray-core/main/json"
_ "github.com/xtls/xray-core/main/toml"
_ "github.com/xtls/xray-core/main/yaml"
// Load config from file or http(s)
_ "github.com/xtls/xray-core/main/confloader/external"
// commands
// Commands
_ "github.com/xtls/xray-core/main/commands/all"
)

View File

@@ -1,38 +0,0 @@
package json
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import (
"io"
"os"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/cmdarg"
core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/main/confloader"
)
func init() {
common.Must(core.RegisterConfigLoader(&core.ConfigFormat{
Name: "JSON",
Extension: []string{"json"},
Loader: func(input interface{}) (*core.Config, error) {
switch v := input.(type) {
case cmdarg.Arg:
r, err := confloader.LoadExtConfig(v, os.Stdin)
if err != nil {
return nil, newError("failed to execute xctl to convert config file.").Base(err).AtWarning()
}
return core.LoadConfig("protobuf", "", r)
case io.Reader:
r, err := confloader.LoadExtConfig([]string{"stdin:"}, os.Stdin)
if err != nil {
return nil, newError("failed to execute xctl to convert config file.").Base(err).AtWarning()
}
return core.LoadConfig("protobuf", "", r)
default:
return nil, newError("unknown type")
}
},
}))
}

View File

@@ -1,4 +1,4 @@
package jsonem
package json
import (
"io"
@@ -22,9 +22,13 @@ func init() {
for i, arg := range v {
newError("Reading config: ", arg).AtInfo().WriteToLog()
r, err := confloader.LoadConfig(arg)
common.Must(err)
if err != nil {
return nil, newError("failed to read config: ", arg).Base(err)
}
c, err := serial.DecodeJSONConfig(r)
common.Must(err)
if err != nil {
return nil, newError("failed to decode config: ", arg).Base(err)
}
if i == 0 {
// This ensure even if the muti-json parser do not support a setting,
// It is still respected automatically for the first configure file

View File

@@ -8,13 +8,16 @@ import (
"os/signal"
"path"
"path/filepath"
"regexp"
"runtime"
"runtime/debug"
"strings"
"syscall"
"github.com/xtls/xray-core/common/cmdarg"
"github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/infra/conf"
"github.com/xtls/xray-core/main/commands/base"
)
@@ -64,22 +67,29 @@ func executeRun(cmd *base.Command, args []string) {
printVersion()
server, err := startXray()
if err != nil {
base.Fatalf("Failed to start: %s", err)
fmt.Println("Failed to start:", err)
// Configuration error. Exit with a special value to prevent systemd from restarting.
os.Exit(23)
}
if *test {
fmt.Println("Configuration OK.")
base.SetExitStatus(0)
base.Exit()
os.Exit(0)
}
if err := server.Start(); err != nil {
base.Fatalf("Failed to start: %s", err)
fmt.Println("Failed to start:", err)
os.Exit(-1)
}
defer server.Close()
conf.FileCache = nil
conf.IPCache = nil
conf.SiteCache = nil
// Explicitly triggering GC to remove garbage from config loading.
runtime.GC()
debug.FreeOSMemory()
{
osSignals := make(chan os.Signal, 1)
@@ -107,7 +117,11 @@ func readConfDir(dirPath string) {
log.Fatalln(err)
}
for _, f := range confs {
if strings.HasSuffix(f.Name(), ".json") {
matched, err := regexp.MatchString(`^.+\.(json|toml|yaml|yml)$`, f.Name())
if err != nil {
log.Fatalln(err)
}
if matched {
configFiles.Set(path.Join(dirPath, f.Name()))
}
}
@@ -147,6 +161,10 @@ func getConfigFormat() string {
switch strings.ToLower(*format) {
case "pb", "protobuf":
return "protobuf"
case "yaml", "yml":
return "yaml"
case "toml":
return "toml"
default:
return "json"
}
@@ -156,8 +174,11 @@ func startXray() (core.Server, error) {
configFiles := getConfigFilePath()
config, err := core.LoadConfig(getConfigFormat(), configFiles[0], configFiles)
//config, err := core.LoadConfigs(getConfigFormat(), configFiles)
if err != nil {
return nil, newError("failed to read config files: [", configFiles.String(), "]").Base(err)
return nil, newError("failed to load config files: [", configFiles.String(), "]").Base(err)
}
server, err := core.New(config)

View File

@@ -0,0 +1,9 @@
package toml
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

48
main/toml/toml.go Normal file
View File

@@ -0,0 +1,48 @@
package toml
import (
"io"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/cmdarg"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/infra/conf"
"github.com/xtls/xray-core/infra/conf/serial"
"github.com/xtls/xray-core/main/confloader"
)
func init() {
common.Must(core.RegisterConfigLoader(&core.ConfigFormat{
Name: "TOML",
Extension: []string{"toml"},
Loader: func(input interface{}) (*core.Config, error) {
switch v := input.(type) {
case cmdarg.Arg:
cf := &conf.Config{}
for i, arg := range v {
newError("Reading config: ", arg).AtInfo().WriteToLog()
r, err := confloader.LoadConfig(arg)
if err != nil {
return nil, newError("failed to read config: ", arg).Base(err)
}
c, err := serial.DecodeTOMLConfig(r)
if err != nil {
return nil, newError("failed to decode config: ", arg).Base(err)
}
if i == 0 {
// This ensure even if the muti-json parser do not support a setting,
// It is still respected automatically for the first configure file
*cf = *c
continue
}
cf.Override(c, arg)
}
return cf.Build()
case io.Reader:
return serial.LoadTOMLConfig(v)
default:
return nil, newError("unknow type")
}
},
}))
}

View File

@@ -0,0 +1,9 @@
package yaml
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

48
main/yaml/yaml.go Normal file
View File

@@ -0,0 +1,48 @@
package yaml
import (
"io"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/cmdarg"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/infra/conf"
"github.com/xtls/xray-core/infra/conf/serial"
"github.com/xtls/xray-core/main/confloader"
)
func init() {
common.Must(core.RegisterConfigLoader(&core.ConfigFormat{
Name: "YAML",
Extension: []string{"yaml", "yml"},
Loader: func(input interface{}) (*core.Config, error) {
switch v := input.(type) {
case cmdarg.Arg:
cf := &conf.Config{}
for i, arg := range v {
newError("Reading config: ", arg).AtInfo().WriteToLog()
r, err := confloader.LoadConfig(arg)
if err != nil {
return nil, newError("failed to read config: ", arg).Base(err)
}
c, err := serial.DecodeYAMLConfig(r)
if err != nil {
return nil, newError("failed to decode config: ", arg).Base(err)
}
if i == 0 {
// This ensure even if the muti-json parser do not support a setting,
// It is still respected automatically for the first configure file
*cf = *c
continue
}
cf.Override(c, arg)
}
return cf.Build()
case io.Reader:
return serial.LoadYAMLConfig(v)
default:
return nil, newError("unknow type")
}
},
}))
}

View File

@@ -163,36 +163,60 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in
if !destinationOverridden {
writer = &buf.SequentialWriter{Writer: conn}
} else {
sockopt := &internet.SocketConfig{
Tproxy: internet.SocketConfig_TProxy,
back := conn.RemoteAddr().(*net.UDPAddr)
if !dest.Address.Family().IsIP() {
if len(back.IP) == 4 {
dest.Address = net.AnyIP
} else {
dest.Address = net.AnyIPv6
}
}
if dest.Address.Family().IsIP() {
sockopt.BindAddress = dest.Address.IP()
sockopt.BindPort = uint32(dest.Port)
addr := &net.UDPAddr{
IP: dest.Address.IP(),
Port: int(dest.Port),
}
var mark int
if d.sockopt != nil {
sockopt.Mark = d.sockopt.Mark
mark = int(d.sockopt.Mark)
}
tConn, err := internet.DialSystem(ctx, net.DestinationFromAddr(conn.RemoteAddr()), sockopt)
pConn, err := FakeUDP(addr, mark)
if err != nil {
return err
}
defer tConn.Close()
writer = &buf.SequentialWriter{Writer: tConn}
tReader := buf.NewPacketReader(tConn)
requestCount++
tproxyRequest = func() error {
defer func() {
if atomic.AddInt32(&requestCount, -1) == 0 {
timer.SetTimeout(plcy.Timeouts.DownlinkOnly)
}
}()
if err := buf.Copy(tReader, link.Writer, buf.UpdateActivity(timer)); err != nil {
return newError("failed to transport request (TPROXY conn)").Base(err)
writer = NewPacketWriter(pConn, &dest, mark, back)
defer writer.(*PacketWriter).Close()
/*
sockopt := &internet.SocketConfig{
Tproxy: internet.SocketConfig_TProxy,
}
return nil
}
if dest.Address.Family().IsIP() {
sockopt.BindAddress = dest.Address.IP()
sockopt.BindPort = uint32(dest.Port)
}
if d.sockopt != nil {
sockopt.Mark = d.sockopt.Mark
}
tConn, err := internet.DialSystem(ctx, net.DestinationFromAddr(conn.RemoteAddr()), sockopt)
if err != nil {
return err
}
defer tConn.Close()
writer = &buf.SequentialWriter{Writer: tConn}
tReader := buf.NewPacketReader(tConn)
requestCount++
tproxyRequest = func() error {
defer func() {
if atomic.AddInt32(&requestCount, -1) == 0 {
timer.SetTimeout(plcy.Timeouts.DownlinkOnly)
}
}()
if err := buf.Copy(tReader, link.Writer, buf.UpdateActivity(timer)); err != nil {
return newError("failed to transport request (TPROXY conn)").Base(err)
}
return nil
}
*/
}
}
@@ -215,3 +239,74 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in
return nil
}
func NewPacketWriter(conn net.PacketConn, d *net.Destination, mark int, back *net.UDPAddr) buf.Writer {
writer := &PacketWriter{
conn: conn,
conns: make(map[net.Destination]net.PacketConn),
mark: mark,
back: back,
}
writer.conns[*d] = conn
return writer
}
type PacketWriter struct {
conn net.PacketConn
conns map[net.Destination]net.PacketConn
mark int
back *net.UDPAddr
}
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
for {
mb2, b := buf.SplitFirst(mb)
mb = mb2
if b == nil {
break
}
var err error
if b.UDP != nil && b.UDP.Address.Family().IsIP() {
conn := w.conns[*b.UDP]
if conn == nil {
conn, err = FakeUDP(
&net.UDPAddr{
IP: b.UDP.Address.IP(),
Port: int(b.UDP.Port),
},
w.mark,
)
if err != nil {
newError(err).WriteToLog()
b.Release()
continue
}
w.conns[*b.UDP] = conn
}
_, err = conn.WriteTo(b.Bytes(), w.back)
if err != nil {
newError(err).WriteToLog()
w.conns[*b.UDP] = nil
conn.Close()
}
b.Release()
} else {
_, err = w.conn.WriteTo(b.Bytes(), w.back)
b.Release()
if err != nil {
buf.ReleaseMulti(mb)
return err
}
}
}
return nil
}
func (w *PacketWriter) Close() error {
for _, conn := range w.conns {
if conn != nil {
conn.Close()
}
}
return nil
}

View File

@@ -0,0 +1,66 @@
// +build linux
package dokodemo
import (
"fmt"
"net"
"os"
"syscall"
"golang.org/x/sys/unix"
)
func FakeUDP(addr *net.UDPAddr, mark int) (net.PacketConn, error) {
var af int
var sockaddr syscall.Sockaddr
if len(addr.IP) == 4 {
af = syscall.AF_INET
sockaddr = &syscall.SockaddrInet4{Port: addr.Port}
copy(sockaddr.(*syscall.SockaddrInet4).Addr[:], addr.IP)
} else {
af = syscall.AF_INET6
sockaddr = &syscall.SockaddrInet6{Port: addr.Port}
copy(sockaddr.(*syscall.SockaddrInet6).Addr[:], addr.IP)
}
var fd int
var err error
if fd, err = syscall.Socket(af, syscall.SOCK_DGRAM, 0); err != nil {
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("socket open: %s", err)}
}
if mark != 0 {
if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, mark); err != nil {
syscall.Close(fd)
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("set socket option: SO_MARK: %s", err)}
}
}
if err = syscall.SetsockoptInt(fd, syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil {
syscall.Close(fd)
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("set socket option: IP_TRANSPARENT: %s", err)}
}
syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1)
if err = syscall.Bind(fd, sockaddr); err != nil {
syscall.Close(fd)
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("socket bind: %s", err)}
}
fdFile := os.NewFile(uintptr(fd), fmt.Sprintf("net-udp-fake-%s", addr.String()))
defer fdFile.Close()
packetConn, err := net.FilePacketConn(fdFile)
if err != nil {
syscall.Close(fd)
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("convert file descriptor to connection: %s", err)}
}
return packetConn, nil
}

View File

@@ -0,0 +1,12 @@
// +build !linux
package dokodemo
import (
"fmt"
"net"
)
func FakeUDP(addr *net.UDPAddr, mark int) (net.PacketConn, error) {
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("!linux")}
}

View File

@@ -17,6 +17,7 @@ import (
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet"
)
@@ -148,7 +149,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
if destination.Network == net.Network_TCP {
writer = buf.NewWriter(conn)
} else {
writer = &buf.SequentialWriter{Writer: conn}
writer = NewPacketWriter(conn, h, ctx)
}
if err := buf.Copy(input, writer, buf.UpdateActivity(timer)); err != nil {
@@ -165,7 +166,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
if destination.Network == net.Network_TCP {
reader = buf.NewReader(conn)
} else {
reader = buf.NewPacketReader(conn)
reader = NewPacketReader(conn)
}
if err := buf.Copy(reader, output, buf.UpdateActivity(timer)); err != nil {
return newError("failed to process response").Base(err)
@@ -180,3 +181,112 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
return nil
}
func NewPacketReader(conn net.Conn) buf.Reader {
iConn := conn
statConn, ok := iConn.(*internet.StatCouterConnection)
if ok {
iConn = statConn.Connection
}
var counter stats.Counter
if statConn != nil {
counter = statConn.ReadCounter
}
if c, ok := iConn.(*internet.PacketConnWrapper); ok {
return &PacketReader{
PacketConnWrapper: c,
Counter: counter,
}
}
return &buf.PacketReader{Reader: conn}
}
type PacketReader struct {
*internet.PacketConnWrapper
stats.Counter
}
func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
b := buf.New()
b.Resize(0, buf.Size)
n, d, err := r.PacketConnWrapper.ReadFrom(b.Bytes())
if err != nil {
b.Release()
return nil, err
}
b.Resize(0, int32(n))
b.UDP = &net.Destination{
Address: net.IPAddress(d.(*net.UDPAddr).IP),
Port: net.Port(d.(*net.UDPAddr).Port),
Network: net.Network_UDP,
}
if r.Counter != nil {
r.Counter.Add(int64(n))
}
return buf.MultiBuffer{b}, nil
}
func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context) buf.Writer {
iConn := conn
statConn, ok := iConn.(*internet.StatCouterConnection)
if ok {
iConn = statConn.Connection
}
var counter stats.Counter
if statConn != nil {
counter = statConn.WriteCounter
}
if c, ok := iConn.(*internet.PacketConnWrapper); ok {
return &PacketWriter{
PacketConnWrapper: c,
Counter: counter,
Handler: h,
Context: ctx,
}
}
return &buf.SequentialWriter{Writer: conn}
}
type PacketWriter struct {
*internet.PacketConnWrapper
stats.Counter
*Handler
context.Context
}
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
for {
mb2, b := buf.SplitFirst(mb)
mb = mb2
if b == nil {
break
}
var n int
var err error
if b.UDP != nil {
if w.Handler.config.useIP() && b.UDP.Address.Family().IsDomain() {
ip := w.Handler.resolveIP(w.Context, b.UDP.Address.Domain(), nil)
if ip != nil {
b.UDP.Address = ip
}
}
destAddr, _ := net.ResolveUDPAddr("udp", b.UDP.NetAddr())
if destAddr == nil {
b.Release()
continue
}
n, err = w.PacketConnWrapper.WriteTo(b.Bytes(), destAddr)
} else {
n, err = w.PacketConnWrapper.Write(b.Bytes())
}
b.Release()
if err != nil {
buf.ReleaseMulti(mb)
return err
}
if w.Counter != nil {
w.Counter.Add(int64(n))
}
}
return nil
}

View File

@@ -168,6 +168,7 @@ func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, u
rawConn.Close()
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
rawConn.Close()

View File

@@ -293,6 +293,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
response.Close = true
result = nil
}
defer response.Body.Close()
} else {
newError("failed to read response from ", request.Host).Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
response = &http.Response{

View File

@@ -134,14 +134,15 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
}
if request.Command == protocol.RequestCommandUDP {
writer := &buf.SequentialWriter{Writer: &UDPWriter{
Writer: conn,
Request: request,
}}
requestDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
writer := &UDPWriter{
Writer: conn,
Request: request,
}
if err := buf.Copy(link.Reader, writer, buf.UpdateActivity(timer)); err != nil {
return newError("failed to transport all UDP request").Base(err)
}

View File

@@ -154,13 +154,8 @@ type ServerConfig struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// UdpEnabled specified whether or not to enable UDP for Shadowsocks.
// Deprecated. Use 'network' field.
//
// Deprecated: Do not use.
UdpEnabled bool `protobuf:"varint,1,opt,name=udp_enabled,json=udpEnabled,proto3" json:"udp_enabled,omitempty"`
User *protocol.User `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"`
Network []net.Network `protobuf:"varint,3,rep,packed,name=network,proto3,enum=xray.common.net.Network" json:"network,omitempty"`
Users []*protocol.User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
Network []net.Network `protobuf:"varint,2,rep,packed,name=network,proto3,enum=xray.common.net.Network" json:"network,omitempty"`
}
func (x *ServerConfig) Reset() {
@@ -195,17 +190,9 @@ func (*ServerConfig) Descriptor() ([]byte, []int) {
return file_proxy_shadowsocks_config_proto_rawDescGZIP(), []int{1}
}
// Deprecated: Do not use.
func (x *ServerConfig) GetUdpEnabled() bool {
func (x *ServerConfig) GetUsers() []*protocol.User {
if x != nil {
return x.UdpEnabled
}
return false
}
func (x *ServerConfig) GetUser() *protocol.User {
if x != nil {
return x.User
return x.Users
}
return nil
}
@@ -282,39 +269,37 @@ var file_proxy_shadowsocks_config_proto_rawDesc = []byte{
0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f,
0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x54, 0x79, 0x70,
0x65, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x22, 0x97, 0x01,
0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23,
0x0a, 0x0b, 0x75, 0x64, 0x70, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x75, 0x64, 0x70, 0x45, 0x6e, 0x61, 0x62,
0x6c, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75,
0x73, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x03,
0x20, 0x03, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07,
0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53,
0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x2a, 0x9f, 0x01, 0x0a, 0x0a, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72,
0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x43, 0x46, 0x42,
0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x43, 0x46,
0x42, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x10,
0x03, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x49, 0x45,
0x54, 0x46, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f,
0x47, 0x43, 0x4d, 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36,
0x5f, 0x47, 0x43, 0x4d, 0x10, 0x06, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41,
0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x10, 0x07, 0x12, 0x08, 0x0a,
0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x08, 0x42, 0x64, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77,
0x73, 0x6f, 0x63, 0x6b, 0x73, 0x50, 0x01, 0x5a, 0x2b, 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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73,
0x6f, 0x63, 0x6b, 0x73, 0xaa, 0x02, 0x16, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78,
0x79, 0x2e, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
0x65, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x22, 0x74, 0x0a,
0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a,
0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12,
0x32, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e,
0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e,
0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77,
0x6f, 0x72, 0x6b, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65,
0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65,
0x72, 0x2a, 0x9f, 0x01, 0x0a, 0x0a, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65,
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a,
0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x43, 0x46, 0x42, 0x10, 0x01, 0x12, 0x0f,
0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x43, 0x46, 0x42, 0x10, 0x02, 0x12,
0x0c, 0x0a, 0x08, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x10, 0x03, 0x12, 0x11, 0x0a,
0x0d, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x49, 0x45, 0x54, 0x46, 0x10, 0x04,
0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x10,
0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, 0x4d,
0x10, 0x06, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50,
0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x10, 0x07, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e,
0x45, 0x10, 0x08, 0x42, 0x64, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b,
0x73, 0x50, 0x01, 0x5a, 0x2b, 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, 0x70,
0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73,
0xaa, 0x02, 0x16, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x53, 0x68,
0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (
@@ -342,7 +327,7 @@ var file_proxy_shadowsocks_config_proto_goTypes = []interface{}{
}
var file_proxy_shadowsocks_config_proto_depIdxs = []int32{
0, // 0: xray.proxy.shadowsocks.Account.cipher_type:type_name -> xray.proxy.shadowsocks.CipherType
4, // 1: xray.proxy.shadowsocks.ServerConfig.user:type_name -> xray.common.protocol.User
4, // 1: xray.proxy.shadowsocks.ServerConfig.users:type_name -> xray.common.protocol.User
5, // 2: xray.proxy.shadowsocks.ServerConfig.network:type_name -> xray.common.net.Network
6, // 3: xray.proxy.shadowsocks.ClientConfig.server:type_name -> xray.common.protocol.ServerEndpoint
4, // [4:4] is the sub-list for method output_type

View File

@@ -28,11 +28,8 @@ enum CipherType {
}
message ServerConfig {
// UdpEnabled specified whether or not to enable UDP for Shadowsocks.
// Deprecated. Use 'network' field.
bool udp_enabled = 1 [deprecated = true];
xray.common.protocol.User user = 2;
repeated xray.common.net.Network network = 3;
repeated xray.common.protocol.User users = 1;
repeated xray.common.net.Network network = 2;
}
message ClientConfig {

View File

@@ -1,6 +1,7 @@
package shadowsocks
import (
"crypto/cipher"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
@@ -10,6 +11,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
@@ -28,8 +30,32 @@ var addrParser = protocol.NewAddressParser(
}),
)
type FullReader struct {
reader io.Reader
buffer []byte
}
func (r *FullReader) Read(p []byte) (n int, err error) {
if r.buffer != nil {
n := copy(p, r.buffer)
if n == len(r.buffer) {
r.buffer = nil
} else {
r.buffer = r.buffer[n:]
}
if n == len(p) {
return n, nil
} else {
m, err := r.reader.Read(p[n:])
return n + m, err
}
}
return r.reader.Read(p)
}
// ReadTCPSession reads a Shadowsocks TCP session from the given reader, returns its header and remaining parts.
func ReadTCPSession(user *protocol.MemoryUser, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
func ReadTCPSession(users []*protocol.MemoryUser, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
user := users[0]
account := user.Account.(*MemoryAccount)
hashkdf := hmac.New(sha256.New, []byte("SSBSKDF"))
@@ -44,28 +70,78 @@ func ReadTCPSession(user *protocol.MemoryUser, reader io.Reader) (*protocol.Requ
DrainSize := BaseDrainSize + 16 + 38 + RandDrainRolled
readSizeRemain := DrainSize
var r2 buf.Reader
if len(users) > 1 {
buffer := buf.New()
defer buffer.Release()
if _, err := buffer.ReadFullFrom(reader, 50); err != nil {
readSizeRemain -= int(buffer.Len())
DrainConnN(reader, readSizeRemain)
return nil, nil, newError("failed to read 50 bytes").Base(err)
}
bs := buffer.Bytes()
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 err != nil {
readSizeRemain -= int(buffer.Len())
DrainConnN(reader, readSizeRemain)
return nil, nil, newError("failed to match an user").Base(err)
}
}
buffer := buf.New()
defer buffer.Release()
ivLen := account.Cipher.IVSize()
var iv []byte
if ivLen > 0 {
if _, err := buffer.ReadFullFrom(reader, ivLen); err != nil {
readSizeRemain -= int(buffer.Len())
DrainConnN(reader, readSizeRemain)
return nil, nil, newError("failed to read IV").Base(err)
if r2 == nil {
ivLen := account.Cipher.IVSize()
var iv []byte
if ivLen > 0 {
if _, err := buffer.ReadFullFrom(reader, ivLen); err != nil {
readSizeRemain -= int(buffer.Len())
DrainConnN(reader, readSizeRemain)
return nil, nil, newError("failed to read IV").Base(err)
}
iv = append([]byte(nil), buffer.BytesTo(ivLen)...)
}
iv = append([]byte(nil), buffer.BytesTo(ivLen)...)
r, err := account.Cipher.NewDecryptionReader(account.Key, iv, reader)
if err != nil {
readSizeRemain -= int(buffer.Len())
DrainConnN(reader, readSizeRemain)
return nil, nil, newError("failed to initialize decoding stream").Base(err).AtError()
}
r2 = r
}
r, err := account.Cipher.NewDecryptionReader(account.Key, iv, reader)
if err != nil {
readSizeRemain -= int(buffer.Len())
DrainConnN(reader, readSizeRemain)
return nil, nil, newError("failed to initialize decoding stream").Base(err).AtError()
}
br := &buf.BufferedReader{Reader: r}
br := &buf.BufferedReader{Reader: r2}
request := &protocol.RequestHeader{
Version: Version,
@@ -185,17 +261,52 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buff
return buffer, nil
}
func DecodeUDPPacket(user *protocol.MemoryUser, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
account := user.Account.(*MemoryAccount)
func DecodeUDPPacket(users []*protocol.MemoryUser, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
var user *protocol.MemoryUser
var account *MemoryAccount
var err error
var iv []byte
if !account.Cipher.IsAEAD() && account.Cipher.IVSize() > 0 {
// Keep track of IV as it gets removed from payload in DecodePacket.
iv = make([]byte, account.Cipher.IVSize())
copy(iv, payload.BytesTo(account.Cipher.IVSize()))
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
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
}
}
} else {
user = users[0]
account = user.Account.(*MemoryAccount)
var iv []byte
if !account.Cipher.IsAEAD() && account.Cipher.IVSize() > 0 {
// Keep track of IV as it gets removed from payload in DecodePacket.
iv = make([]byte, account.Cipher.IVSize())
copy(iv, payload.BytesTo(account.Cipher.IVSize()))
}
err = account.Cipher.DecodePacket(account.Key, payload)
}
if err := account.Cipher.DecodePacket(account.Key, payload); err != nil {
if err != nil {
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
}
@@ -230,11 +341,13 @@ func (v *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
buffer.Release()
return nil, err
}
_, payload, err := DecodeUDPPacket(v.User, buffer)
u, payload, err := DecodeUDPPacket([]*protocol.MemoryUser{v.User}, buffer)
if err != nil {
buffer.Release()
return nil, err
}
dest := u.Destination()
payload.UDP = &dest
return buf.MultiBuffer{payload}, nil
}
@@ -243,13 +356,33 @@ type UDPWriter struct {
Request *protocol.RequestHeader
}
// Write implements io.Writer.
func (w *UDPWriter) Write(payload []byte) (int, error) {
packet, err := EncodeUDPPacket(w.Request, payload)
if err != nil {
return 0, err
func (w *UDPWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
for {
mb2, b := buf.SplitFirst(mb)
mb = mb2
if b == nil {
break
}
request := w.Request
if b.UDP != nil {
request = &protocol.RequestHeader{
User: w.Request.User,
Address: b.UDP.Address,
Port: b.UDP.Port,
}
}
packet, err := EncodeUDPPacket(request, b.Bytes())
b.Release()
if err != nil {
buf.ReleaseMulti(mb)
return err
}
_, err = w.Writer.Write(packet.Bytes())
packet.Release()
if err != nil {
buf.ReleaseMulti(mb)
return err
}
}
_, err = w.Writer.Write(packet.Bytes())
packet.Release()
return len(payload), err
return nil
}

View File

@@ -28,7 +28,7 @@ func TestUDPEncoding(t *testing.T) {
Email: "love@example.com",
Account: toAccount(&Account{
Password: "shadowsocks-password",
CipherType: CipherType_AES_128_CFB,
CipherType: CipherType_AES_128_GCM,
}),
},
}
@@ -38,7 +38,7 @@ func TestUDPEncoding(t *testing.T) {
encodedData, err := EncodeUDPPacket(request, data.Bytes())
common.Must(err)
decodedRequest, decodedData, err := DecodeUDPPacket(request.User, encodedData)
decodedRequest, decodedData, err := DecodeUDPPacket([]*protocol.MemoryUser{request.User}, encodedData)
common.Must(err)
if r := cmp.Diff(decodedData.Bytes(), data.Bytes()); r != "" {
@@ -65,7 +65,7 @@ func TestTCPRequest(t *testing.T) {
Email: "love@example.com",
Account: toAccount(&Account{
Password: "tcp-password",
CipherType: CipherType_CHACHA20,
CipherType: CipherType_CHACHA20_POLY1305,
}),
},
},
@@ -81,7 +81,7 @@ func TestTCPRequest(t *testing.T) {
Email: "love@example.com",
Account: toAccount(&Account{
Password: "password",
CipherType: CipherType_AES_256_CFB,
CipherType: CipherType_AES_256_GCM,
}),
},
},
@@ -97,7 +97,7 @@ func TestTCPRequest(t *testing.T) {
Email: "love@example.com",
Account: toAccount(&Account{
Password: "password",
CipherType: CipherType_CHACHA20_IETF,
CipherType: CipherType_AES_128_GCM,
}),
},
},
@@ -117,7 +117,7 @@ func TestTCPRequest(t *testing.T) {
common.Must(writer.WriteMultiBuffer(buf.MultiBuffer{data}))
decodedRequest, reader, err := ReadTCPSession(request.User, cache)
decodedRequest, reader, err := ReadTCPSession([]*protocol.MemoryUser{request.User}, cache)
common.Must(err)
if r := cmp.Diff(decodedRequest, request); r != "" {
t.Error("request: ", r)
@@ -139,13 +139,13 @@ func TestUDPReaderWriter(t *testing.T) {
user := &protocol.MemoryUser{
Account: toAccount(&Account{
Password: "test-password",
CipherType: CipherType_CHACHA20_IETF,
CipherType: CipherType_CHACHA20_POLY1305,
}),
}
cache := buf.New()
defer cache.Release()
writer := &buf.SequentialWriter{Writer: &UDPWriter{
writer := &UDPWriter{
Writer: cache,
Request: &protocol.RequestHeader{
Version: Version,
@@ -153,7 +153,7 @@ func TestUDPReaderWriter(t *testing.T) {
Port: 123,
User: user,
},
}}
}
reader := &UDPReader{
Reader: cache,

View File

@@ -22,26 +22,30 @@ import (
type Server struct {
config *ServerConfig
user *protocol.MemoryUser
users []*protocol.MemoryUser
policyManager policy.Manager
cone bool
}
// NewServer create a new Shadowsocks server.
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
if config.GetUser() == nil {
return nil, newError("user is not specified")
}
mUser, err := config.User.ToMemoryUser()
if err != nil {
return nil, newError("failed to parse user account").Base(err)
if config.Users == nil {
return nil, newError("empty users")
}
v := core.MustFromContext(ctx)
s := &Server{
config: config,
user: mUser,
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
@@ -52,9 +56,6 @@ func (s *Server) Network() []net.Network {
if len(list) == 0 {
list = append(list, net.Network_TCP)
}
if s.config.UdpEnabled {
list = append(list, net.Network_UDP)
}
return list
}
@@ -77,6 +78,15 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
}
payload := packet.Payload
if payload.UDP != nil {
request = &protocol.RequestHeader{
User: request.User,
Address: payload.UDP.Address,
Port: payload.UDP.Port,
}
}
data, err := EncodeUDPPacket(request, payload.Bytes())
payload.Release()
if err != nil {
@@ -92,7 +102,11 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
if inbound == nil {
panic("no inbound metadata")
}
inbound.User = s.user
if len(s.users) == 1 {
inbound.User = s.users[0]
}
var dest *net.Destination
reader := buf.NewPacketReader(conn)
for {
@@ -102,9 +116,21 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
}
for _, payload := range mpayload {
request, data, err := DecodeUDPPacket(s.user, payload)
var request *protocol.RequestHeader
var data *buf.Buffer
var err error
if inbound.User != nil {
request, data, err = DecodeUDPPacket([]*protocol.MemoryUser{inbound.User}, payload)
} else {
request, data, err = DecodeUDPPacket(s.users, payload)
if err == nil {
inbound.User = request.User
}
}
if err != nil {
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
if inbound.Source.IsValid() {
newError("dropping invalid UDP packet from: ", inbound.Source).Base(err).WriteToLog(session.ExportIDToError(ctx))
log.Record(&log.AccessMessage{
From: inbound.Source,
@@ -117,21 +143,28 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
continue
}
destination := request.Destination()
currentPacketCtx := ctx
dest := request.Destination()
if inbound.Source.IsValid() {
currentPacketCtx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: inbound.Source,
To: dest,
To: destination,
Status: log.AccessAccepted,
Reason: "",
Email: request.User.Email,
})
}
newError("tunnelling request to ", dest).WriteToLog(session.ExportIDToError(currentPacketCtx))
newError("tunnelling request to ", destination).WriteToLog(session.ExportIDToError(currentPacketCtx))
data.UDP = &destination
if !s.cone || dest == nil {
dest = &destination
}
currentPacketCtx = protocol.ContextWithRequestHeader(currentPacketCtx, request)
udpServer.Dispatch(currentPacketCtx, dest, data)
udpServer.Dispatch(currentPacketCtx, *dest, data)
}
}
@@ -139,11 +172,13 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
}
func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, dispatcher routing.Dispatcher) error {
sessionPolicy := s.policyManager.ForLevel(s.user.Level)
conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake))
sessionPolicy := s.policyManager.ForLevel(0)
if err := conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
return newError("unable to set read deadline").Base(err).AtWarning()
}
bufferedReader := buf.BufferedReader{Reader: buf.NewReader(conn)}
request, bodyReader, err := ReadTCPSession(s.user, &bufferedReader)
request, bodyReader, err := ReadTCPSession(s.users, &bufferedReader)
if err != nil {
log.Record(&log.AccessMessage{
From: conn.RemoteAddr(),
@@ -159,7 +194,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
if inbound == nil {
panic("no inbound metadata")
}
inbound.User = s.user
inbound.User = request.User
dest := request.Destination()
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
@@ -171,6 +206,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
})
newError("tunnelling request to ", dest).WriteToLog(session.ExportIDToError(ctx))
sessionPolicy = s.policyManager.ForLevel(request.User.Level)
ctx, cancel := context.WithCancel(ctx)
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)

View File

@@ -51,14 +51,19 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
if outbound == nil || !outbound.Target.IsValid() {
return newError("target not specified.")
}
// Destination of the inner request.
destination := outbound.Target
// Outbound server.
var server *protocol.ServerSpec
// Outbound server's destination.
var dest net.Destination
// Connection to the outbound server.
var conn internet.Connection
if err := retry.ExponentialBackoff(5, 100).On(func() error {
server = c.serverPicker.PickServer()
dest := server.Destination()
dest = server.Destination()
rawConn, err := dialer.Dial(ctx, dest)
if err != nil {
return err
@@ -101,6 +106,11 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
if err != nil {
return newError("failed to establish connection to server").AtWarning().Base(err)
}
if udpRequest != nil {
if udpRequest.Address == net.AnyIP || udpRequest.Address == net.AnyIPv6 {
udpRequest.Address = dest.Address
}
}
if err := conn.SetDeadline(time.Time{}); err != nil {
newError("failed to clear deadline after handshake").Base(err).WriteToLog(session.ExportIDToError(ctx))
@@ -128,11 +138,12 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
defer udpConn.Close()
requestFunc = func() error {
defer timer.SetTimeout(p.Timeouts.DownlinkOnly)
return buf.Copy(link.Reader, &buf.SequentialWriter{Writer: NewUDPWriter(request, udpConn)}, buf.UpdateActivity(timer))
writer := &UDPWriter{Writer: udpConn, Request: request}
return buf.Copy(link.Reader, writer, buf.UpdateActivity(timer))
}
responseFunc = func() error {
defer timer.SetTimeout(p.Timeouts.UplinkOnly)
reader := &UDPReader{reader: udpConn}
reader := &UDPReader{Reader: udpConn}
return buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))
}
}

View File

@@ -16,7 +16,7 @@ const (
cmdTCPConnect = 0x01
cmdTCPBind = 0x02
cmdUDPPort = 0x03
cmdUDPAssociate = 0x03
cmdTorResolve = 0xF0
cmdTorResolvePTR = 0xF1
@@ -39,8 +39,10 @@ var addrParser = protocol.NewAddressParser(
)
type ServerSession struct {
config *ServerConfig
port net.Port
config *ServerConfig
address net.Address
port net.Port
localAddress net.Address
}
func (s *ServerSession) handshake4(cmd byte, reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) {
@@ -162,7 +164,7 @@ func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer io.Wri
case cmdTCPConnect, cmdTorResolve, cmdTorResolvePTR:
// We don't have a solution for Tor case now. Simply treat it as connect command.
request.Command = protocol.RequestCommandTCP
case cmdUDPPort:
case cmdUDPAssociate:
if !s.config.UdpEnabled {
writeSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0))
return nil, newError("UDP is not enabled.")
@@ -185,15 +187,17 @@ func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer io.Wri
request.Address = addr
request.Port = port
responseAddress := net.AnyIP
responsePort := net.Port(1717)
responseAddress := s.address
responsePort := s.port
//nolint:gocritic // Use if else chain for clarity
if request.Command == protocol.RequestCommandUDP {
addr := s.config.Address.AsAddress()
if addr == nil {
addr = net.LocalHostIP
if s.config.Address != nil {
// Use configured IP as remote address in the response to UDP Associate
responseAddress = s.config.Address.AsAddress()
} else {
// Use conn.LocalAddr() IP as remote address in the response by default
responseAddress = s.localAddress
}
responseAddress = addr
responsePort = s.port
}
if err := writeSocks5Response(writer, statusSuccess, responseAddress, responsePort); err != nil {
return nil, err
@@ -353,47 +357,59 @@ func EncodeUDPPacket(request *protocol.RequestHeader, data []byte) (*buf.Buffer,
}
type UDPReader struct {
reader io.Reader
}
func NewUDPReader(reader io.Reader) *UDPReader {
return &UDPReader{reader: reader}
Reader io.Reader
}
func (r *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
b := buf.New()
if _, err := b.ReadFrom(r.reader); err != nil {
buffer := buf.New()
_, err := buffer.ReadFrom(r.Reader)
if err != nil {
buffer.Release()
return nil, err
}
if _, err := DecodeUDPPacket(b); err != nil {
u, err := DecodeUDPPacket(buffer)
if err != nil {
buffer.Release()
return nil, err
}
return buf.MultiBuffer{b}, nil
dest := u.Destination()
buffer.UDP = &dest
return buf.MultiBuffer{buffer}, nil
}
type UDPWriter struct {
request *protocol.RequestHeader
writer io.Writer
Writer io.Writer
Request *protocol.RequestHeader
}
func NewUDPWriter(request *protocol.RequestHeader, writer io.Writer) *UDPWriter {
return &UDPWriter{
request: request,
writer: writer,
func (w *UDPWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
for {
mb2, b := buf.SplitFirst(mb)
mb = mb2
if b == nil {
break
}
request := w.Request
if b.UDP != nil {
request = &protocol.RequestHeader{
Address: b.UDP.Address,
Port: b.UDP.Port,
}
}
packet, err := EncodeUDPPacket(request, b.Bytes())
b.Release()
if err != nil {
buf.ReleaseMulti(mb)
return err
}
_, err = w.Writer.Write(packet.Bytes())
packet.Release()
if err != nil {
buf.ReleaseMulti(mb)
return err
}
}
}
// Write implements io.Writer.
func (w *UDPWriter) Write(b []byte) (int, error) {
eb, err := EncodeUDPPacket(w.request, b)
if err != nil {
return 0, err
}
defer eb.Release()
if _, err := w.writer.Write(eb.Bytes()); err != nil {
return 0, err
}
return len(b), nil
return nil
}
func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) {
@@ -446,7 +462,7 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
command := byte(cmdTCPConnect)
if request.Command == protocol.RequestCommandUDP {
command = byte(cmdUDPPort)
command = byte(cmdUDPAssociate)
}
common.Must2(b.Write([]byte{socks5Version, command, 0x00 /* reserved */}))
if err := addrParser.WriteAddressPort(b, request.Address, request.Port); err != nil {

View File

@@ -20,14 +20,14 @@ func TestUDPEncoding(t *testing.T) {
Address: net.IPAddress([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}),
Port: 1024,
}
writer := &buf.SequentialWriter{Writer: NewUDPWriter(request, b)}
writer := &UDPWriter{Writer: b, Request: request}
content := []byte{'a'}
payload := buf.New()
payload.Write(content)
common.Must(writer.WriteMultiBuffer(buf.MultiBuffer{payload}))
reader := NewUDPReader(b)
reader := &UDPReader{Reader: b}
decodedPayload, err := reader.ReadMultiBuffer()
common.Must(err)

View File

@@ -26,6 +26,7 @@ import (
type Server struct {
config *ServerConfig
policyManager policy.Manager
cone bool
}
// NewServer creates a new Server object.
@@ -34,6 +35,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
s := &Server{
config: config,
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
cone: ctx.Value("cone").(bool),
}
return s, nil
}
@@ -89,8 +91,10 @@ func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispa
}
svrSession := &ServerSession{
config: s.config,
port: inbound.Gateway.Port,
config: s.config,
address: inbound.Gateway.Address,
port: inbound.Gateway.Port,
localAddress: net.IPAddress(conn.LocalAddr().(*net.TCPAddr).IP),
}
reader := &buf.BufferedReader{Reader: buf.NewReader(conn)}
@@ -196,6 +200,15 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
if request == nil {
return
}
if payload.UDP != nil {
request = &protocol.RequestHeader{
User: request.User,
Address: payload.UDP.Address,
Port: payload.UDP.Port,
}
}
udpMessage, err := EncodeUDPPacket(request, payload.Bytes())
payload.Release()
@@ -207,10 +220,13 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
conn.Write(udpMessage.Bytes())
})
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
inbound := session.InboundFromContext(ctx)
if inbound != nil && inbound.Source.IsValid() {
newError("client UDP connection from ", inbound.Source).WriteToLog(session.ExportIDToError(ctx))
}
var dest *net.Destination
reader := buf.NewPacketReader(conn)
for {
mpayload, err := reader.ReadMultiBuffer()
@@ -231,19 +247,28 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
payload.Release()
continue
}
destination := request.Destination()
currentPacketCtx := ctx
newError("send packet to ", request.Destination(), " with ", payload.Len(), " bytes").AtDebug().WriteToLog(session.ExportIDToError(ctx))
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
newError("send packet to ", destination, " with ", payload.Len(), " bytes").AtDebug().WriteToLog(session.ExportIDToError(ctx))
if inbound != nil && inbound.Source.IsValid() {
currentPacketCtx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: inbound.Source,
To: request.Destination(),
To: destination,
Status: log.AccessAccepted,
Reason: "",
})
}
payload.UDP = &destination
if !s.cone || dest == nil {
dest = &destination
}
currentPacketCtx = protocol.ContextWithRequestHeader(currentPacketCtx, request)
udpServer.Dispatch(currentPacketCtx, request.Destination(), payload)
udpServer.Dispatch(currentPacketCtx, *dest, payload)
}
}
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/protocol"
@@ -79,62 +80,63 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
defer conn.Close()
user := server.PickUser()
account, ok := user.Account.(*MemoryAccount)
if !ok {
return newError("user account is not valid")
}
iConn := conn
statConn, ok := iConn.(*internet.StatCouterConnection)
if ok {
iConn = statConn.Connection
}
user := server.PickUser()
account, ok := user.Account.(*MemoryAccount)
if !ok {
return newError("user account is not valid")
}
connWriter := &ConnWriter{
Flow: account.Flow,
}
var rawConn syscall.RawConn
var sctx context.Context
connWriter := &ConnWriter{}
allowUDP443 := false
switch account.Flow {
switch connWriter.Flow {
case XRO + "-udp443", XRD + "-udp443", XRS + "-udp443":
allowUDP443 = true
account.Flow = account.Flow[:16]
connWriter.Flow = connWriter.Flow[:16]
fallthrough
case XRO, XRD, XRS:
if destination.Address.Family().IsDomain() && destination.Address.Domain() == muxCoolAddress {
return newError(account.Flow + " doesn't support Mux").AtWarning()
return newError(connWriter.Flow + " doesn't support Mux").AtWarning()
}
if destination.Network == net.Network_UDP {
if !allowUDP443 && destination.Port == 443 {
return newError(account.Flow + " stopped UDP/443").AtInfo()
return newError(connWriter.Flow + " stopped UDP/443").AtInfo()
}
connWriter.Flow = ""
} else { // enable XTLS only if making TCP request
if xtlsConn, ok := iConn.(*xtls.Conn); ok {
xtlsConn.RPRX = true
xtlsConn.SHOW = trojanXTLSShow
xtlsConn.SHOW = xtls_show
xtlsConn.MARK = "XTLS"
if account.Flow == XRS {
if connWriter.Flow == XRS {
sctx = ctx
account.Flow = XRD
connWriter.Flow = XRD
}
if account.Flow == XRD {
if connWriter.Flow == XRD {
xtlsConn.DirectMode = true
if sc, ok := xtlsConn.Connection.(syscall.Conn); ok {
rawConn, _ = sc.SyscallConn()
}
}
connWriter.Flow = account.Flow
} else {
return newError(`failed to use ` + account.Flow + `, maybe "security" is not "xtls"`).AtWarning()
return newError(`failed to use ` + connWriter.Flow + `, maybe "security" is not "xtls"`).AtWarning()
}
}
case "":
default:
if _, ok := iConn.(*xtls.Conn); ok {
panic(`To avoid misunderstanding, you must fill in Trojan "flow" when using XTLS.`)
}
default:
return newError("unsupported flow " + account.Flow).AtWarning()
}
sessionPolicy := c.policyManager.ForLevel(user.Level)
@@ -144,12 +146,13 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
postRequest := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
var bodyWriter buf.Writer
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
connWriter.Writer = bufferWriter
connWriter.Target = destination
connWriter.Account = account
var bodyWriter buf.Writer
if destination.Network == net.Network_UDP {
bodyWriter = &PacketWriter{Writer: connWriter, Target: destination}
} else {
@@ -166,6 +169,11 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
return newError("failed to flush payload").Base(err).AtWarning()
}
// Send header if not sent yet
if _, err = connWriter.Write([]byte{}); err != nil {
return err.(*errors.Error).AtWarning()
}
if err = buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer)); err != nil {
return newError("failed to transfer request payload").Base(err).AtInfo()
}
@@ -211,6 +219,6 @@ func init() {
xtlsShow := platform.NewEnvFlag("xray.trojan.xtls.show").GetValue(func() string { return defaultFlagValue })
if xtlsShow == "true" {
trojanXTLSShow = true
xtls_show = true
}
}

View File

@@ -86,11 +86,12 @@ type Fallback struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Alpn string `protobuf:"bytes,1,opt,name=alpn,proto3" json:"alpn,omitempty"`
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
Dest string `protobuf:"bytes,4,opt,name=dest,proto3" json:"dest,omitempty"`
Xver uint64 `protobuf:"varint,5,opt,name=xver,proto3" json:"xver,omitempty"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Alpn string `protobuf:"bytes,2,opt,name=alpn,proto3" json:"alpn,omitempty"`
Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"`
Dest string `protobuf:"bytes,5,opt,name=dest,proto3" json:"dest,omitempty"`
Xver uint64 `protobuf:"varint,6,opt,name=xver,proto3" json:"xver,omitempty"`
}
func (x *Fallback) Reset() {
@@ -125,6 +126,13 @@ func (*Fallback) Descriptor() ([]byte, []int) {
return file_proxy_trojan_config_proto_rawDescGZIP(), []int{1}
}
func (x *Fallback) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Fallback) GetAlpn() string {
if x != nil {
return x.Alpn
@@ -275,33 +283,34 @@ var file_proxy_trojan_config_proto_rawDesc = []byte{
0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0x6e, 0x0a, 0x08, 0x46, 0x61, 0x6c, 0x6c,
0x62, 0x61, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04,
0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01,
0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65,
0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e,
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65,
0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x09, 0x66, 0x61, 0x6c, 0x6c,
0x62, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x2e,
0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61,
0x63, 0x6b, 0x73, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26,
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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f,
0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72,
0x6f, 0x78, 0x79, 0x2e, 0x54, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
0x28, 0x09, 0x52, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0x82, 0x01, 0x0a, 0x08, 0x46, 0x61, 0x6c,
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x6c, 0x70,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x12, 0x12, 0x0a,
0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74,
0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65,
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a,
0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a,
0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x0c, 0x53,
0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x05, 0x75,
0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a,
0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72,
0x6f, 0x6a, 0x61, 0x6e, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x09, 0x66,
0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, 0x61,
0x6e, 0x50, 0x01, 0x5a, 0x26, 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, 0x70,
0x72, 0x6f, 0x78, 0x79, 0x2f, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72,
0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x54, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@@ -15,11 +15,12 @@ message Account {
}
message Fallback {
string alpn = 1;
string path = 2;
string type = 3;
string dest = 4;
uint64 xver = 5;
string name = 1;
string alpn = 2;
string path = 3;
string type = 4;
string dest = 5;
uint64 xver = 6;
}
message ClientConfig {

View File

@@ -28,7 +28,7 @@ var (
protocol.AddressFamilyByte(0x03, net.AddressFamilyDomain),
)
trojanXTLSShow = false
xtls_show = false
)
const (
@@ -90,10 +90,10 @@ func (c *ConnWriter) writeHeader() error {
command := commandTCP
if c.Target.Network == net.Network_UDP {
command = commandUDP
} else if c.Flow == XRO {
command = commandXRO
} else if c.Flow == XRD {
command = commandXRD
} else if c.Flow == XRO {
command = commandXRO
}
if _, err := buffer.Write(c.Account.Key); err != nil {
@@ -128,31 +128,21 @@ type PacketWriter struct {
// WriteMultiBuffer implements buf.Writer
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
b := make([]byte, maxLength)
for !mb.IsEmpty() {
var length int
mb, length = buf.SplitBytes(mb, b)
if _, err := w.writePacket(b[:length], w.Target); err != nil {
for {
mb2, b := buf.SplitFirst(mb)
mb = mb2
if b == nil {
break
}
target := &w.Target
if b.UDP != nil {
target = b.UDP
}
if _, err := w.writePacket(b.Bytes(), *target); err != nil {
buf.ReleaseMulti(mb)
return err
}
}
return nil
}
// WriteMultiBufferWithMetadata writes udp packet with destination specified
func (w *PacketWriter) WriteMultiBufferWithMetadata(mb buf.MultiBuffer, dest net.Destination) error {
b := make([]byte, maxLength)
for !mb.IsEmpty() {
var length int
mb, length = buf.SplitBytes(mb, b)
if _, err := w.writePacket(b[:length], dest); err != nil {
buf.ReleaseMulti(mb)
return err
}
}
return nil
}
@@ -211,10 +201,10 @@ func (c *ConnReader) ParseHeader() error {
network := net.Network_TCP
if command[0] == commandUDP {
network = net.Network_UDP
} else if command[0] == commandXRO {
c.Flow = XRO
} else if command[0] == commandXRD {
c.Flow = XRD
} else if command[0] == commandXRO {
c.Flow = XRO
}
addr, port, err := addrParser.ReadAddressPort(nil, c.Reader)
@@ -249,12 +239,6 @@ func (c *ConnReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
return buf.MultiBuffer{b}, err
}
// PacketPayload combines udp payload and destination
type PacketPayload struct {
Target net.Destination
Buffer buf.MultiBuffer
}
// PacketReader is UDP Connection Reader Wrapper for trojan protocol
type PacketReader struct {
io.Reader
@@ -262,15 +246,6 @@ type PacketReader struct {
// ReadMultiBuffer implements buf.Reader
func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
p, err := r.ReadMultiBufferWithMetadata()
if p != nil {
return p.Buffer, err
}
return nil, err
}
// ReadMultiBufferWithMetadata reads udp packet with destination
func (r *PacketReader) ReadMultiBufferWithMetadata() (*PacketPayload, error) {
addr, port, err := addrParser.ReadAddressPort(nil, r)
if err != nil {
return nil, newError("failed to read address and port").Base(err)
@@ -300,6 +275,7 @@ func (r *PacketReader) ReadMultiBufferWithMetadata() (*PacketPayload, error) {
}
b := buf.New()
b.UDP = &dest
mb = append(mb, b)
n, err := b.ReadFullFrom(r, int32(length))
if err != nil {
@@ -310,7 +286,7 @@ func (r *PacketReader) ReadMultiBufferWithMetadata() (*PacketPayload, error) {
remain -= int(n)
}
return &PacketPayload{Target: dest, Buffer: mb}, nil
return mb, nil
}
func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn *xtls.Conn, rawConn syscall.RawConn, counter stats.Counter, sctx context.Context) error {
@@ -326,6 +302,9 @@ func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, c
if ok {
iConn = statConn.Connection
}
if xc, ok := iConn.(*xtls.Conn); ok {
iConn = xc.Connection
}
if tc, ok := iConn.(*net.TCPConn); ok {
if conn.SHOW {
fmt.Println(conn.MARK, "Splice")

View File

@@ -71,21 +71,22 @@ func TestUDPRequest(t *testing.T) {
common.Must(connReader.ParseHeader())
packetReader := &PacketReader{Reader: connReader}
p, err := packetReader.ReadMultiBufferWithMetadata()
mb, err := packetReader.ReadMultiBuffer()
common.Must(err)
if p.Buffer.IsEmpty() {
if mb.IsEmpty() {
t.Error("no request data")
}
if r := cmp.Diff(p.Target, destination); r != "" {
mb2, b := buf.SplitFirst(mb)
defer buf.ReleaseMulti(mb2)
dest := *b.UDP
if r := cmp.Diff(dest, destination); r != "" {
t.Error("destination: ", r)
}
mb, decoded := buf.SplitFirst(p.Buffer)
buf.ReleaseMulti(mb)
if r := cmp.Diff(decoded.Bytes(), payload); r != "" {
if r := cmp.Diff(b.Bytes(), payload); r != "" {
t.Error("data: ", r)
}
}

View File

@@ -5,6 +5,7 @@ import (
"crypto/tls"
"io"
"strconv"
"strings"
"syscall"
"time"
@@ -38,7 +39,7 @@ func init() {
xtlsShow := platform.NewEnvFlag("xray.trojan.xtls.show").GetValue(func() string { return defaultFlagValue })
if xtlsShow == "true" {
trojanXTLSShow = true
xtls_show = true
}
}
@@ -46,7 +47,8 @@ func init() {
type Server struct {
policyManager policy.Manager
validator *Validator
fallbacks map[string]map[string]*Fallback // or nil
fallbacks map[string]map[string]map[string]*Fallback // or nil
cone bool
}
// NewServer creates a new trojan inbound handler.
@@ -67,22 +69,52 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
server := &Server{
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
validator: validator,
cone: ctx.Value("cone").(bool),
}
if config.Fallbacks != nil {
server.fallbacks = make(map[string]map[string]*Fallback)
server.fallbacks = make(map[string]map[string]map[string]*Fallback)
for _, fb := range config.Fallbacks {
if server.fallbacks[fb.Alpn] == nil {
server.fallbacks[fb.Alpn] = make(map[string]*Fallback)
if server.fallbacks[fb.Name] == nil {
server.fallbacks[fb.Name] = make(map[string]map[string]*Fallback)
}
server.fallbacks[fb.Alpn][fb.Path] = fb
if server.fallbacks[fb.Name][fb.Alpn] == nil {
server.fallbacks[fb.Name][fb.Alpn] = make(map[string]*Fallback)
}
server.fallbacks[fb.Name][fb.Alpn][fb.Path] = fb
}
if server.fallbacks[""] != nil {
for alpn, pfb := range server.fallbacks {
if alpn != "" { // && alpn != "h2" {
for path, fb := range server.fallbacks[""] {
if pfb[path] == nil {
pfb[path] = fb
for name, apfb := range server.fallbacks {
if name != "" {
for alpn := range server.fallbacks[""] {
if apfb[alpn] == nil {
apfb[alpn] = make(map[string]*Fallback)
}
}
}
}
}
for _, apfb := range server.fallbacks {
if apfb[""] != nil {
for alpn, pfb := range apfb {
if alpn != "" { // && alpn != "h2" {
for path, fb := range apfb[""] {
if pfb[path] == nil {
pfb[path] = fb
}
}
}
}
}
}
if server.fallbacks[""] != nil {
for name, apfb := range server.fallbacks {
if name != "" {
for alpn, pfb := range server.fallbacks[""] {
for path, fb := range pfb {
if apfb[alpn][path] == nil {
apfb[alpn][path] = fb
}
}
}
}
@@ -139,8 +171,8 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
var user *protocol.MemoryUser
apfb := s.fallbacks
isfb := apfb != nil
napfb := s.fallbacks
isfb := napfb != nil
shouldFallback := false
if firstLen < 58 || first.Byte(56) != '\r' {
@@ -171,7 +203,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
}
if isfb && shouldFallback {
return s.fallback(ctx, sid, err, sessionPolicy, conn, iConn, apfb, first, firstLen, bufferedReader)
return s.fallback(ctx, sid, err, sessionPolicy, conn, iConn, napfb, first, firstLen, bufferedReader)
} else if shouldFallback {
return newError("invalid protocol or invalid user")
}
@@ -219,7 +251,8 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
}
if xtlsConn, ok := iConn.(*xtls.Conn); ok {
xtlsConn.RPRX = true
xtlsConn.SHOW = trojanXTLSShow
xtlsConn.SHOW = xtls_show
xtlsConn.MARK = "XTLS"
if clientReader.Flow == XRD {
xtlsConn.DirectMode = true
if sc, ok := xtlsConn.Connection.(syscall.Conn); ok {
@@ -230,11 +263,9 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
return newError(`failed to use ` + clientReader.Flow + `, maybe "security" is not "xtls"`).AtWarning()
}
} else {
return newError("unable to use ", clientReader.Flow).AtWarning()
return newError(account.Password + " is not able to use " + clientReader.Flow).AtWarning()
}
case "":
default:
return newError("unsupported flow " + account.Flow).AtWarning()
}
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
@@ -251,18 +282,27 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error {
udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
common.Must(clientWriter.WriteMultiBufferWithMetadata(buf.MultiBuffer{packet.Payload}, packet.Source))
udpPayload := packet.Payload
if udpPayload.UDP == nil {
udpPayload.UDP = &packet.Source
}
if err := clientWriter.WriteMultiBuffer(buf.MultiBuffer{udpPayload}); err != nil {
newError("failed to write response").Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
}
})
inbound := session.InboundFromContext(ctx)
user := inbound.User
var dest *net.Destination
for {
select {
case <-ctx.Done():
return nil
default:
p, err := clientReader.ReadMultiBufferWithMetadata()
mb, err := clientReader.ReadMultiBuffer()
if err != nil {
if errors.Cause(err) != io.EOF {
return newError("unexpected EOF").Base(err)
@@ -270,17 +310,31 @@ func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReade
return nil
}
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: inbound.Source,
To: p.Target,
Status: log.AccessAccepted,
Reason: "",
Email: user.Email,
})
newError("tunnelling request to ", p.Target).WriteToLog(session.ExportIDToError(ctx))
mb2, b := buf.SplitFirst(mb)
if b == nil {
continue
}
destination := *b.UDP
for _, b := range p.Buffer {
udpServer.Dispatch(ctx, p.Target, b)
currentPacketCtx := ctx
if inbound.Source.IsValid() {
currentPacketCtx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: inbound.Source,
To: destination,
Status: log.AccessAccepted,
Reason: "",
Email: user.Email,
})
}
newError("tunnelling request to ", destination).WriteToLog(session.ExportIDToError(ctx))
if !s.cone || dest == nil {
dest = &destination
}
udpServer.Dispatch(currentPacketCtx, *dest, b) // first packet
for _, payload := range mb2 {
udpServer.Dispatch(currentPacketCtx, *dest, payload)
}
}
}
@@ -337,25 +391,53 @@ func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Sess
return nil
}
func (s *Server) fallback(ctx context.Context, sid errors.ExportOption, err error, sessionPolicy policy.Session, connection internet.Connection, iConn internet.Connection, apfb map[string]map[string]*Fallback, first *buf.Buffer, firstLen int64, reader buf.Reader) error {
func (s *Server) fallback(ctx context.Context, sid errors.ExportOption, err error, sessionPolicy policy.Session, connection internet.Connection, iConn internet.Connection, napfb map[string]map[string]map[string]*Fallback, first *buf.Buffer, firstLen int64, reader buf.Reader) error {
if err := connection.SetReadDeadline(time.Time{}); err != nil {
newError("unable to set back read deadline").Base(err).AtWarning().WriteToLog(sid)
}
newError("fallback starts").Base(err).AtInfo().WriteToLog(sid)
name := ""
alpn := ""
if len(apfb) > 1 || apfb[""] == nil {
if tlsConn, ok := iConn.(*tls.Conn); ok {
alpn = tlsConn.ConnectionState().NegotiatedProtocol
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
alpn = xtlsConn.ConnectionState().NegotiatedProtocol
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
}
if apfb[alpn] == nil {
alpn = ""
if tlsConn, ok := iConn.(*tls.Conn); ok {
cs := tlsConn.ConnectionState()
name = cs.ServerName
alpn = cs.NegotiatedProtocol
newError("realName = " + name).AtInfo().WriteToLog(sid)
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
cs := xtlsConn.ConnectionState()
name = cs.ServerName
alpn = cs.NegotiatedProtocol
newError("realName = " + name).AtInfo().WriteToLog(sid)
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
}
name = strings.ToLower(name)
alpn = strings.ToLower(alpn)
if len(napfb) > 1 || napfb[""] == nil {
if name != "" && napfb[name] == nil {
match := ""
for n := range napfb {
if n != "" && strings.Contains(name, n) && len(n) > len(match) {
match = n
}
}
name = match
}
}
if napfb[name] == nil {
name = ""
}
apfb := napfb[name]
if apfb == nil {
return newError(`failed to find the default "name" config`).AtWarning()
}
if apfb[alpn] == nil {
alpn = ""
}
pfb := apfb[alpn]
if pfb == nil {
return newError(`failed to find the default "alpn" config`).AtWarning()
@@ -418,38 +500,51 @@ 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 {
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
}
ipv4 := true
for i := 0; i < len(remoteAddr); i++ {
if remoteAddr[i] == ':' {
ipv4 = false
break
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
for i := 0; i < len(remoteAddr); i++ {
if remoteAddr[i] == ':' {
ipType = 6
break
}
}
}
pro := buf.New()
defer pro.Release()
switch fb.Xver {
case 1:
if ipv4 {
if ipType == 0 {
common.Must2(pro.Write([]byte("PROXY UNKNOWN\r\n")))
break
}
if ipType == 4 {
common.Must2(pro.Write([]byte("PROXY TCP4 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n")))
} else {
common.Must2(pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n")))
}
case 2:
common.Must2(pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21"))) // signature + v2 + PROXY
if ipv4 {
common.Must2(pro.Write([]byte("\x11\x00\x0C"))) // AF_INET + STREAM + 12 bytes
common.Must2(pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"))) // signature
if ipType == 0 {
common.Must2(pro.Write([]byte("\x20\x00\x00\x00"))) // v2 + LOCAL + UNSPEC + UNSPEC + 0 bytes
break
}
if ipType == 4 {
common.Must2(pro.Write([]byte("\x21\x11\x00\x0C"))) // v2 + PROXY + AF_INET + STREAM + 12 bytes
common.Must2(pro.Write(net.ParseIP(remoteAddr).To4()))
common.Must2(pro.Write(net.ParseIP(localAddr).To4()))
} else {
common.Must2(pro.Write([]byte("\x21\x00\x24"))) // AF_INET6 + STREAM + 36 bytes
common.Must2(pro.Write([]byte("\x21\x21\x00\x24"))) // v2 + PROXY + AF_INET6 + STREAM + 36 bytes
common.Must2(pro.Write(net.ParseIP(remoteAddr).To16()))
common.Must2(pro.Write(net.ParseIP(localAddr).To16()))
}

View File

@@ -278,10 +278,7 @@ func (m *Addons) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthAddons
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthAddons
}
if (iNdEx + skippy) > l {

View File

@@ -189,6 +189,9 @@ func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, c
if ok {
iConn = statConn.Connection
}
if xc, ok := iConn.(*xtls.Conn); ok {
iConn = xc.Connection
}
if tc, ok := iConn.(*net.TCPConn); ok {
if conn.SHOW {
fmt.Println(conn.MARK, "Splice")

View File

@@ -31,11 +31,12 @@ type Fallback struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Alpn string `protobuf:"bytes,1,opt,name=alpn,proto3" json:"alpn,omitempty"`
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
Dest string `protobuf:"bytes,4,opt,name=dest,proto3" json:"dest,omitempty"`
Xver uint64 `protobuf:"varint,5,opt,name=xver,proto3" json:"xver,omitempty"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Alpn string `protobuf:"bytes,2,opt,name=alpn,proto3" json:"alpn,omitempty"`
Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"`
Dest string `protobuf:"bytes,5,opt,name=dest,proto3" json:"dest,omitempty"`
Xver uint64 `protobuf:"varint,6,opt,name=xver,proto3" json:"xver,omitempty"`
}
func (x *Fallback) Reset() {
@@ -70,6 +71,13 @@ func (*Fallback) Descriptor() ([]byte, []int) {
return file_proxy_vless_inbound_config_proto_rawDescGZIP(), []int{0}
}
func (x *Fallback) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Fallback) GetAlpn() string {
if x != nil {
return x.Alpn
@@ -178,31 +186,33 @@ var file_proxy_vless_inbound_config_proto_rawDesc = []byte{
0x74, 0x6f, 0x12, 0x18, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76,
0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x1a, 0x1a, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x75, 0x73,
0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6e, 0x0a, 0x08, 0x46, 0x61, 0x6c, 0x6c,
0x62, 0x61, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04,
0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01,
0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0xa0, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72,
0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x63,
0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64,
0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x09, 0x66, 0x61, 0x6c,
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e,
0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
0x52, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x42, 0x6a, 0x0a, 0x1c, 0x63,
0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c,
0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2d, 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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76,
0x6c, 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x18, 0x58,
0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x2e,
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x01, 0x0a, 0x08, 0x46, 0x61, 0x6c,
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x6c, 0x70,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x12, 0x12, 0x0a,
0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74,
0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65,
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0xa0, 0x01,
0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65,
0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1e,
0x0a, 0x0a, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x40,
0x0a, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76,
0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x46, 0x61, 0x6c,
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73,
0x42, 0x6a, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f,
0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
0x50, 0x01, 0x5a, 0x2d, 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, 0x70, 0x72,
0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
0x64, 0xaa, 0x02, 0x18, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56,
0x6c, 0x65, 0x73, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@@ -9,11 +9,12 @@ option java_multiple_files = true;
import "common/protocol/user.proto";
message Fallback {
string alpn = 1;
string path = 2;
string type = 3;
string dest = 4;
uint64 xver = 5;
string name = 1;
string alpn = 2;
string path = 3;
string type = 4;
string dest = 5;
uint64 xver = 6;
}
message Config {

View File

@@ -6,6 +6,7 @@ import (
"context"
"io"
"strconv"
"strings"
"syscall"
"time"
@@ -63,7 +64,7 @@ type Handler struct {
policyManager policy.Manager
validator *vless.Validator
dns dns.Client
fallbacks map[string]map[string]*Fallback // or nil
fallbacks map[string]map[string]map[string]*Fallback // or nil
// regexps map[string]*regexp.Regexp // or nil
}
@@ -88,13 +89,16 @@ func New(ctx context.Context, config *Config, dc dns.Client) (*Handler, error) {
}
if config.Fallbacks != nil {
handler.fallbacks = make(map[string]map[string]*Fallback)
handler.fallbacks = make(map[string]map[string]map[string]*Fallback)
// handler.regexps = make(map[string]*regexp.Regexp)
for _, fb := range config.Fallbacks {
if handler.fallbacks[fb.Alpn] == nil {
handler.fallbacks[fb.Alpn] = make(map[string]*Fallback)
if handler.fallbacks[fb.Name] == nil {
handler.fallbacks[fb.Name] = make(map[string]map[string]*Fallback)
}
handler.fallbacks[fb.Alpn][fb.Path] = fb
if handler.fallbacks[fb.Name][fb.Alpn] == nil {
handler.fallbacks[fb.Name][fb.Alpn] = make(map[string]*Fallback)
}
handler.fallbacks[fb.Name][fb.Alpn][fb.Path] = fb
/*
if fb.Path != "" {
if r, err := regexp.Compile(fb.Path); err != nil {
@@ -106,11 +110,37 @@ func New(ctx context.Context, config *Config, dc dns.Client) (*Handler, error) {
*/
}
if handler.fallbacks[""] != nil {
for alpn, pfb := range handler.fallbacks {
if alpn != "" { // && alpn != "h2" {
for path, fb := range handler.fallbacks[""] {
if pfb[path] == nil {
pfb[path] = fb
for name, apfb := range handler.fallbacks {
if name != "" {
for alpn := range handler.fallbacks[""] {
if apfb[alpn] == nil {
apfb[alpn] = make(map[string]*Fallback)
}
}
}
}
}
for _, apfb := range handler.fallbacks {
if apfb[""] != nil {
for alpn, pfb := range apfb {
if alpn != "" { // && alpn != "h2" {
for path, fb := range apfb[""] {
if pfb[path] == nil {
pfb[path] = fb
}
}
}
}
}
}
if handler.fallbacks[""] != nil {
for name, apfb := range handler.fallbacks {
if name != "" {
for alpn, pfb := range handler.fallbacks[""] {
for path, fb := range pfb {
if apfb[alpn][path] == nil {
apfb[alpn][path] = fb
}
}
}
}
@@ -171,8 +201,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
var requestAddons *encoding.Addons
var err error
apfb := h.fallbacks
isfb := apfb != nil
napfb := h.fallbacks
isfb := napfb != nil
if isfb && firstLen < 18 {
err = newError("fallback directly")
@@ -187,19 +217,47 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
}
newError("fallback starts").Base(err).AtInfo().WriteToLog(sid)
name := ""
alpn := ""
if len(apfb) > 1 || apfb[""] == nil {
if tlsConn, ok := iConn.(*tls.Conn); ok {
alpn = tlsConn.ConnectionState().NegotiatedProtocol
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
alpn = xtlsConn.ConnectionState().NegotiatedProtocol
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
}
if apfb[alpn] == nil {
alpn = ""
if tlsConn, ok := iConn.(*tls.Conn); ok {
cs := tlsConn.ConnectionState()
name = cs.ServerName
alpn = cs.NegotiatedProtocol
newError("realName = " + name).AtInfo().WriteToLog(sid)
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
cs := xtlsConn.ConnectionState()
name = cs.ServerName
alpn = cs.NegotiatedProtocol
newError("realName = " + name).AtInfo().WriteToLog(sid)
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
}
name = strings.ToLower(name)
alpn = strings.ToLower(alpn)
if len(napfb) > 1 || napfb[""] == nil {
if name != "" && napfb[name] == nil {
match := ""
for n := range napfb {
if n != "" && strings.Contains(name, n) && len(n) > len(match) {
match = n
}
}
name = match
}
}
if napfb[name] == nil {
name = ""
}
apfb := napfb[name]
if apfb == nil {
return newError(`failed to find the default "name" config`).AtWarning()
}
if apfb[alpn] == nil {
alpn = ""
}
pfb := apfb[alpn]
if pfb == nil {
return newError(`failed to find the default "alpn" config`).AtWarning()
@@ -277,39 +335,51 @@ 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 {
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
}
ipv4 := true
for i := 0; i < len(remoteAddr); i++ {
if remoteAddr[i] == ':' {
ipv4 = false
break
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
for i := 0; i < len(remoteAddr); i++ {
if remoteAddr[i] == ':' {
ipType = 6
break
}
}
}
pro := buf.New()
defer pro.Release()
switch fb.Xver {
case 1:
if ipv4 {
if ipType == 0 {
pro.Write([]byte("PROXY UNKNOWN\r\n"))
break
}
if ipType == 4 {
pro.Write([]byte("PROXY TCP4 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n"))
} else {
pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n"))
}
case 2:
pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21")) // signature + v2 + PROXY
if ipv4 {
pro.Write([]byte("\x11\x00\x0C")) // AF_INET + STREAM + 12 bytes
pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A")) // signature
if ipType == 0 {
pro.Write([]byte("\x20\x00\x00\x00")) // v2 + LOCAL + UNSPEC + UNSPEC + 0 bytes
break
}
if ipType == 4 {
pro.Write([]byte("\x21\x11\x00\x0C")) // v2 + PROXY + AF_INET + STREAM + 12 bytes
pro.Write(net.ParseIP(remoteAddr).To4())
pro.Write(net.ParseIP(localAddr).To4())
} else {
pro.Write([]byte("\x21\x00\x24")) // AF_INET6 + STREAM + 36 bytes
pro.Write([]byte("\x21\x21\x00\x24")) // v2 + PROXY + AF_INET6 + STREAM + 36 bytes
pro.Write(net.ParseIP(remoteAddr).To16())
pro.Write(net.ParseIP(localAddr).To16())
}

View File

@@ -57,14 +57,14 @@ func TestRequestSerialization(t *testing.T) {
defer common.Close(userValidator)
server := NewServerSession(userValidator, sessionHistory)
actualRequest, err := server.DecodeRequestHeader(buffer)
actualRequest, err := server.DecodeRequestHeader(buffer, false)
common.Must(err)
if r := cmp.Diff(actualRequest, expectedRequest, cmp.AllowUnexported(protocol.ID{})); r != "" {
t.Error(r)
}
_, err = server.DecodeRequestHeader(buffer2)
_, err = server.DecodeRequestHeader(buffer2, false)
// anti replay attack
if err == nil {
t.Error("nil error")
@@ -107,7 +107,7 @@ func TestInvalidRequest(t *testing.T) {
defer common.Close(userValidator)
server := NewServerSession(userValidator, sessionHistory)
_, err := server.DecodeRequestHeader(buffer)
_, err := server.DecodeRequestHeader(buffer, false)
if err == nil {
t.Error("nil error")
}
@@ -148,7 +148,7 @@ func TestMuxRequest(t *testing.T) {
defer common.Close(userValidator)
server := NewServerSession(userValidator, sessionHistory)
actualRequest, err := server.DecodeRequestHeader(buffer)
actualRequest, err := server.DecodeRequestHeader(buffer, false)
common.Must(err)
if r := cmp.Diff(actualRequest, expectedRequest, cmp.AllowUnexported(protocol.ID{})); r != "" {

View File

@@ -131,7 +131,7 @@ func parseSecurityType(b byte) protocol.SecurityType {
}
// DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.RequestHeader, error) {
func (s *ServerSession) DecodeRequestHeader(reader io.Reader, isDrain bool) (*protocol.RequestHeader, error) {
buffer := buf.New()
behaviorRand := dice.NewDeterministicDice(int64(s.userValidator.GetBehaviorSeed()))
BaseDrainSize := behaviorRand.Roll(3266)
@@ -143,7 +143,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
drainConnection := func(e error) error {
// We read a deterministic generated length of data before closing the connection to offset padding read pattern
readSizeRemain -= int(buffer.Len())
if readSizeRemain > 0 {
if readSizeRemain > 0 && isDrain {
err := s.DrainConnN(reader, readSizeRemain)
if err != nil {
return newError("failed to drain connection DrainSize = ", BaseDrainSize, " ", RandDrainMax, " ", RandDrainRolled).Base(err).Base(e)

View File

@@ -220,9 +220,18 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
return newError("unable to set read deadline").Base(err).AtWarning()
}
iConn := connection
if statConn, ok := iConn.(*internet.StatCouterConnection); ok {
iConn = statConn.Connection
}
_, isDrain := iConn.(*net.TCPConn)
if !isDrain {
_, isDrain = iConn.(*net.UnixConn)
}
reader := &buf.BufferedReader{Reader: buf.NewReader(connection)}
svrSession := encoding.NewServerSession(h.clients, h.sessionHistory)
request, err := svrSession.DecodeRequestHeader(reader)
request, err := svrSession.DecodeRequestHeader(reader, isDrain)
if err != nil {
if errors.Cause(err) != io.EOF {
log.Record(&log.AccessMessage{

View File

@@ -52,10 +52,10 @@ func TestShadowsocksAES256TCP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Users: []*protocol.User{{
Account: account,
Level: 1,
},
}},
Network: []net.Network{net.Network_TCP},
}),
},
@@ -150,10 +150,10 @@ func TestShadowsocksAES128UDP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Users: []*protocol.User{{
Account: account,
Level: 1,
},
}},
Network: []net.Network{net.Network_UDP},
}),
},
@@ -276,10 +276,10 @@ func TestShadowsocksChacha20TCP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Users: []*protocol.User{{
Account: account,
Level: 1,
},
}},
Network: []net.Network{net.Network_TCP},
}),
},
@@ -369,10 +369,10 @@ func TestShadowsocksChacha20Poly1305TCP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Users: []*protocol.User{{
Account: account,
Level: 1,
},
}},
Network: []net.Network{net.Network_TCP},
}),
},
@@ -461,10 +461,10 @@ func TestShadowsocksAES256GCMTCP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Users: []*protocol.User{{
Account: account,
Level: 1,
},
}},
Network: []net.Network{net.Network_TCP},
}),
},
@@ -560,10 +560,10 @@ func TestShadowsocksAES128GCMUDP(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Users: []*protocol.User{{
Account: account,
Level: 1,
},
}},
Network: []net.Network{net.Network_UDP},
}),
},
@@ -658,10 +658,10 @@ func TestShadowsocksAES128GCMUDPMux(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Users: []*protocol.User{{
Account: account,
Level: 1,
},
}},
Network: []net.Network{net.Network_TCP},
}),
},
@@ -757,10 +757,10 @@ func TestShadowsocksNone(t *testing.T) {
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
User: &protocol.User{
Users: []*protocol.User{{
Account: account,
Level: 1,
},
}},
Network: []net.Network{net.Network_TCP},
}),
},

View File

@@ -136,8 +136,8 @@ func TestHTTPConnectionHeader(t *testing.T) {
}
func TestDomainSocket(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("Not supported on windows")
if runtime.GOOS == "windows" || runtime.GOOS == "android" {
t.Skip("Not supported on windows or android")
return
}
tcpServer := tcp.Server{

View File

@@ -1,4 +1,5 @@
// +build !windows
// +build !android
package domainsocket_test

View File

@@ -10,6 +10,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/net/cnc"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/tls"
"github.com/xtls/xray-core/transport/pipe"
@@ -21,7 +22,7 @@ var (
globalDialerAccess sync.Mutex
)
func getHTTPClient(_ context.Context, dest net.Destination, tlsSettings *tls.Config) (*http.Client, error) {
func getHTTPClient(ctx context.Context, dest net.Destination, tlsSettings *tls.Config) (*http.Client, error) {
globalDialerAccess.Lock()
defer globalDialerAccess.Unlock()
@@ -48,7 +49,7 @@ func getHTTPClient(_ context.Context, dest net.Destination, tlsSettings *tls.Con
}
address := net.ParseAddress(rawHost)
pconn, err := internet.DialSystem(context.Background(), net.TCPDestination(address, port), nil)
pconn, err := internet.DialSystem(ctx, net.TCPDestination(address, port), nil)
if err != nil {
return nil, err
}
@@ -124,10 +125,10 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
bwriter := buf.NewBufferedWriter(pwriter)
common.Must(bwriter.SetBuffered(false))
return net.NewConnection(
net.ConnectionOutput(response.Body),
net.ConnectionInput(bwriter),
net.ConnectionOnClose(common.ChainedClosable{breader, bwriter, response.Body}),
return cnc.NewConnection(
cnc.ConnectionOutput(response.Body),
cnc.ConnectionInput(bwriter),
cnc.ConnectionOnClose(common.ChainedClosable{breader, bwriter, response.Body}),
), nil
}

View File

@@ -2,10 +2,8 @@ package http
import (
"context"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
@@ -14,6 +12,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
http_proto "github.com/xtls/xray-core/common/protocol/http"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/session"
@@ -36,7 +35,6 @@ func (l *Listener) Addr() net.Addr {
func (l *Listener) Close() error {
if l.locker != nil {
fmt.Fprintln(os.Stderr, "RELEASE LOCK")
l.locker.Release()
}
return l.server.Close()
@@ -88,21 +86,21 @@ func (l *Listener) ServeHTTP(writer http.ResponseWriter, request *http.Request)
}
}
forwardedAddrs := http_proto.ParseXForwardedFor(request.Header)
if len(forwardedAddrs) > 0 && forwardedAddrs[0].Family().IsIP() {
forwardedAddress := http_proto.ParseXForwardedFor(request.Header)
if len(forwardedAddress) > 0 && forwardedAddress[0].Family().IsIP() {
remoteAddr = &net.TCPAddr{
IP: forwardedAddrs[0].IP(),
Port: int(0),
IP: forwardedAddress[0].IP(),
Port: 0,
}
}
done := done.New()
conn := net.NewConnection(
net.ConnectionOutput(request.Body),
net.ConnectionInput(flushWriter{w: writer, d: done}),
net.ConnectionOnClose(common.ChainedClosable{done, request.Body}),
net.ConnectionLocalAddr(l.Addr()),
net.ConnectionRemoteAddr(remoteAddr),
conn := cnc.NewConnection(
cnc.ConnectionOutput(request.Body),
cnc.ConnectionInput(flushWriter{w: writer, d: done}),
cnc.ConnectionOnClose(common.ChainedClosable{done, request.Body}),
cnc.ConnectionLocalAddr(l.Addr()),
cnc.ConnectionRemoteAddr(remoteAddr),
)
l.handler(conn)
<-done.Wait()
@@ -164,7 +162,7 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
Net: "unix",
}, streamSettings.SocketSettings)
if err != nil {
newError("failed to listen on ", address).Base(err).WriteToLog(session.ExportIDToError(ctx))
newError("failed to listen on ", address).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx))
return
}
locker := ctx.Value(address.Domain())
@@ -177,7 +175,7 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
Port: int(port),
}, streamSettings.SocketSettings)
if err != nil {
newError("failed to listen on ", address, ":", port).Base(err).WriteToLog(session.ExportIDToError(ctx))
newError("failed to listen on ", address, ":", port).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx))
return
}
}
@@ -185,12 +183,12 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
if config == nil {
err = server.Serve(streamListener)
if err != nil {
newError("stoping serving H2C").Base(err).WriteToLog(session.ExportIDToError(ctx))
newError("stopping serving H2C").Base(err).WriteToLog(session.ExportIDToError(ctx))
}
} else {
err = server.ServeTLS(streamListener, "", "")
if err != nil {
newError("stoping serving TLS").Base(err).WriteToLog(session.ExportIDToError(ctx))
newError("stopping serving TLS").Base(err).WriteToLog(session.ExportIDToError(ctx))
}
}
}()

View File

@@ -60,7 +60,7 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne
if err != nil {
return nil, err
}
return &packetConnWrapper{
return &PacketConnWrapper{
conn: packetConn,
dest: destAddr,
}, nil
@@ -98,41 +98,49 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne
return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr())
}
type packetConnWrapper struct {
type PacketConnWrapper struct {
conn net.PacketConn
dest net.Addr
}
func (c *packetConnWrapper) Close() error {
func (c *PacketConnWrapper) Close() error {
return c.conn.Close()
}
func (c *packetConnWrapper) LocalAddr() net.Addr {
func (c *PacketConnWrapper) LocalAddr() net.Addr {
return c.conn.LocalAddr()
}
func (c *packetConnWrapper) RemoteAddr() net.Addr {
func (c *PacketConnWrapper) RemoteAddr() net.Addr {
return c.dest
}
func (c *packetConnWrapper) Write(p []byte) (int, error) {
func (c *PacketConnWrapper) Write(p []byte) (int, error) {
return c.conn.WriteTo(p, c.dest)
}
func (c *packetConnWrapper) Read(p []byte) (int, error) {
func (c *PacketConnWrapper) Read(p []byte) (int, error) {
n, _, err := c.conn.ReadFrom(p)
return n, err
}
func (c *packetConnWrapper) SetDeadline(t time.Time) error {
func (c *PacketConnWrapper) WriteTo(p []byte, d net.Addr) (int, error) {
return c.conn.WriteTo(p, d)
}
func (c *PacketConnWrapper) ReadFrom(p []byte) (int, net.Addr, error) {
return c.conn.ReadFrom(p)
}
func (c *PacketConnWrapper) SetDeadline(t time.Time) error {
return c.conn.SetDeadline(t)
}
func (c *packetConnWrapper) SetReadDeadline(t time.Time) error {
func (c *PacketConnWrapper) SetReadDeadline(t time.Time) error {
return c.conn.SetReadDeadline(t)
}
func (c *packetConnWrapper) SetWriteDeadline(t time.Time) error {
func (c *PacketConnWrapper) SetWriteDeadline(t time.Time) error {
return c.conn.SetWriteDeadline(t)
}

View File

@@ -54,7 +54,7 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S
lc.Control = nil
network = addr.Network()
address = addr.Name
if runtime.GOOS == "linux" && address[0] == '@' {
if (runtime.GOOS == "linux" || runtime.GOOS == "android") && address[0] == '@' {
// linux abstract unix domain socket is lockfree
if len(address) > 1 && address[1] == '@' {
// but may need padding to work with haproxy

View File

@@ -48,7 +48,7 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSe
Net: "unix",
}, streamSettings.SocketSettings)
if err != nil {
return nil, newError("failed to listen Unix Doman Socket on ", address).Base(err)
return nil, newError("failed to listen Unix Domain Socket on ", address).Base(err)
}
newError("listening Unix Domain Socket on ", address).WriteToLog(session.ExportIDToError(ctx))
locker := ctx.Value(address.Domain())

View File

@@ -8,6 +8,7 @@ import (
"time"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/ocsp"
"github.com/xtls/xray-core/common/protocol/tls/cert"
"github.com/xtls/xray-core/transport/internet"
)
@@ -53,6 +54,19 @@ func (c *Config) BuildCertificates() []tls.Certificate {
continue
}
certs = append(certs, keyPair)
if entry.OcspStapling != 0 {
go func(cert *tls.Certificate) {
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
}
<-t.C
}
}(&certs[len(certs)-1])
}
}
return certs
}
@@ -180,7 +194,7 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
RootCAs: root,
InsecureSkipVerify: false,
NextProtos: nil,
SessionTicketsDisabled: false,
SessionTicketsDisabled: true,
}
}
@@ -189,7 +203,7 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
RootCAs: root,
InsecureSkipVerify: c.AllowInsecure,
NextProtos: c.NextProtocol,
SessionTicketsDisabled: c.DisableSessionResumption,
SessionTicketsDisabled: !c.EnableSessionResumption,
}
for _, opt := range opts {
@@ -212,6 +226,42 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
config.NextProtos = []string{"h2", "http/1.1"}
}
switch c.MinVersion {
case "1.0":
config.MinVersion = tls.VersionTLS10
case "1.1":
config.MinVersion = tls.VersionTLS11
case "1.2":
config.MinVersion = tls.VersionTLS12
case "1.3":
config.MinVersion = tls.VersionTLS13
}
switch c.MaxVersion {
case "1.0":
config.MaxVersion = tls.VersionTLS10
case "1.1":
config.MaxVersion = tls.VersionTLS11
case "1.2":
config.MaxVersion = tls.VersionTLS12
case "1.3":
config.MaxVersion = tls.VersionTLS13
}
if len(c.CipherSuites) > 0 {
id := make(map[string]uint16)
for _, s := range tls.CipherSuites() {
id[s.Name] = s.ID
}
for _, n := range strings.Split(c.CipherSuites, ":") {
if id[n] != 0 {
config.CipherSuites = append(config.CipherSuites, id[n])
}
}
}
config.PreferServerCipherSuites = c.PreferServerCipherSuites
return config
}

View File

@@ -80,10 +80,11 @@ type Certificate struct {
unknownFields protoimpl.UnknownFields
// TLS certificate in x509 format.
Certificate []byte `protobuf:"bytes,1,opt,name=Certificate,proto3" json:"Certificate,omitempty"`
Certificate []byte `protobuf:"bytes,1,opt,name=certificate,proto3" json:"certificate,omitempty"`
// TLS key in x509 format.
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"`
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"`
}
func (x *Certificate) Reset() {
@@ -139,6 +140,13 @@ func (x *Certificate) GetUsage() Certificate_Usage {
return Certificate_ENCIPHERMENT
}
func (x *Certificate) GetOcspStapling() int64 {
if x != nil {
return x.OcspStapling
}
return 0
}
type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -146,19 +154,25 @@ type Config struct {
// Whether or not to allow self-signed certificates.
AllowInsecure bool `protobuf:"varint,1,opt,name=allow_insecure,json=allowInsecure,proto3" json:"allow_insecure,omitempty"`
// Whether or not to allow insecure cipher suites.
AllowInsecureCiphers bool `protobuf:"varint,5,opt,name=allow_insecure_ciphers,json=allowInsecureCiphers,proto3" json:"allow_insecure_ciphers,omitempty"`
// List of certificates to be served on server.
Certificate []*Certificate `protobuf:"bytes,2,rep,name=certificate,proto3" json:"certificate,omitempty"`
// Override server name.
ServerName string `protobuf:"bytes,3,opt,name=server_name,json=serverName,proto3" json:"server_name,omitempty"`
// Lists of string as ALPN values.
NextProtocol []string `protobuf:"bytes,4,rep,name=next_protocol,json=nextProtocol,proto3" json:"next_protocol,omitempty"`
// Whether or not to disable session (ticket) resumption.
DisableSessionResumption bool `protobuf:"varint,6,opt,name=disable_session_resumption,json=disableSessionResumption,proto3" json:"disable_session_resumption,omitempty"`
// Whether or not to enable session (ticket) resumption.
EnableSessionResumption bool `protobuf:"varint,5,opt,name=enable_session_resumption,json=enableSessionResumption,proto3" json:"enable_session_resumption,omitempty"`
// If true, root certificates on the system will not be loaded for
// verification.
DisableSystemRoot bool `protobuf:"varint,7,opt,name=disable_system_root,json=disableSystemRoot,proto3" json:"disable_system_root,omitempty"`
DisableSystemRoot bool `protobuf:"varint,6,opt,name=disable_system_root,json=disableSystemRoot,proto3" json:"disable_system_root,omitempty"`
// The minimum TLS version.
MinVersion string `protobuf:"bytes,7,opt,name=min_version,json=minVersion,proto3" json:"min_version,omitempty"`
// The maximum TLS version.
MaxVersion string `protobuf:"bytes,8,opt,name=max_version,json=maxVersion,proto3" json:"max_version,omitempty"`
// Specify cipher suites, except for TLS 1.3.
CipherSuites string `protobuf:"bytes,9,opt,name=cipher_suites,json=cipherSuites,proto3" json:"cipher_suites,omitempty"`
// Whether the server selects its most preferred ciphersuite.
PreferServerCipherSuites bool `protobuf:"varint,10,opt,name=prefer_server_cipher_suites,json=preferServerCipherSuites,proto3" json:"prefer_server_cipher_suites,omitempty"`
}
func (x *Config) Reset() {
@@ -200,13 +214,6 @@ func (x *Config) GetAllowInsecure() bool {
return false
}
func (x *Config) GetAllowInsecureCiphers() bool {
if x != nil {
return x.AllowInsecureCiphers
}
return false
}
func (x *Config) GetCertificate() []*Certificate {
if x != nil {
return x.Certificate
@@ -228,9 +235,9 @@ func (x *Config) GetNextProtocol() []string {
return nil
}
func (x *Config) GetDisableSessionResumption() bool {
func (x *Config) GetEnableSessionResumption() bool {
if x != nil {
return x.DisableSessionResumption
return x.EnableSessionResumption
}
return false
}
@@ -242,6 +249,34 @@ func (x *Config) GetDisableSystemRoot() bool {
return false
}
func (x *Config) GetMinVersion() string {
if x != nil {
return x.MinVersion
}
return ""
}
func (x *Config) GetMaxVersion() string {
if x != nil {
return x.MaxVersion
}
return ""
}
func (x *Config) GetCipherSuites() string {
if x != nil {
return x.CipherSuites
}
return ""
}
func (x *Config) GetPreferServerCipherSuites() bool {
if x != nil {
return x.PreferServerCipherSuites
}
return false
}
var File_transport_internet_tls_config_proto protoreflect.FileDescriptor
var file_transport_internet_tls_config_proto_rawDesc = []byte{
@@ -249,50 +284,59 @@ 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, 0xcd, 0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18,
0x6c, 0x73, 0x22, 0xf2, 0x01, 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,
0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 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, 0x2e,
0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 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, 0xe5, 0x02, 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, 0x34, 0x0a, 0x16, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e,
0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 0x18, 0x05,
0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63,
0x75, 0x72, 0x65, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 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, 0x3c, 0x0a, 0x1a,
0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
0x52, 0x18, 0x64, 0x69, 0x73, 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, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f, 0x74, 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,
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,
}
var (

View File

@@ -8,10 +8,10 @@ option java_multiple_files = true;
message Certificate {
// TLS certificate in x509 format.
bytes Certificate = 1;
bytes certificate = 1;
// TLS key in x509 format.
bytes Key = 2;
bytes key = 2;
enum Usage {
ENCIPHERMENT = 0;
@@ -20,15 +20,14 @@ message Certificate {
}
Usage usage = 3;
int64 ocsp_stapling = 4;
}
message Config {
// Whether or not to allow self-signed certificates.
bool allow_insecure = 1;
// Whether or not to allow insecure cipher suites.
bool allow_insecure_ciphers = 5;
// List of certificates to be served on server.
repeated Certificate certificate = 2;
@@ -38,10 +37,22 @@ message Config {
// Lists of string as ALPN values.
repeated string next_protocol = 4;
// Whether or not to disable session (ticket) resumption.
bool disable_session_resumption = 6;
// Whether or not to enable session (ticket) resumption.
bool enable_session_resumption = 5;
// If true, root certificates on the system will not be loaded for
// verification.
bool disable_system_root = 7;
bool disable_system_root = 6;
// The minimum TLS version.
string min_version = 7;
// The maximum TLS version.
string max_version = 8;
// Specify cipher suites, except for TLS 1.3.
string cipher_suites = 9;
// Whether the server selects its most preferred ciphersuite.
bool prefer_server_cipher_suites = 10;
}

View File

@@ -64,9 +64,7 @@ func TestExpiredCertificate(t *testing.T) {
}
func TestInsecureCertificates(t *testing.T) {
c := &Config{
AllowInsecureCiphers: true,
}
c := &Config{}
tlsConfig := c.GetTLSConfig()
if len(tlsConfig.CipherSuites) > 0 {

View File

@@ -66,7 +66,7 @@ func (v *Dispatcher) getInboundRay(ctx context.Context, dest net.Destination) *c
cancel()
v.RemoveRay(dest)
}
timer := signal.CancelAfterInactivity(ctx, removeRay, time.Second*4)
timer := signal.CancelAfterInactivity(ctx, removeRay, time.Minute)
link, _ := v.dispatcher.Dispatch(ctx, dest)
entry := &connEntry{
link: link,

View File

@@ -2,12 +2,14 @@ package xtls
import (
"crypto/x509"
"strings"
"sync"
"time"
xtls "github.com/xtls/go"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/ocsp"
"github.com/xtls/xray-core/common/protocol/tls/cert"
"github.com/xtls/xray-core/transport/internet"
)
@@ -51,6 +53,19 @@ func (c *Config) BuildCertificates() []xtls.Certificate {
continue
}
certs = append(certs, keyPair)
if entry.OcspStapling != 0 {
go func(cert *xtls.Certificate) {
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
}
<-t.C
}
}(&certs[len(certs)-1])
}
}
return certs
}
@@ -170,7 +185,7 @@ func (c *Config) GetXTLSConfig(opts ...Option) *xtls.Config {
RootCAs: root,
InsecureSkipVerify: false,
NextProtos: nil,
SessionTicketsDisabled: false,
SessionTicketsDisabled: true,
}
}
@@ -179,7 +194,7 @@ func (c *Config) GetXTLSConfig(opts ...Option) *xtls.Config {
RootCAs: root,
InsecureSkipVerify: c.AllowInsecure,
NextProtos: c.NextProtocol,
SessionTicketsDisabled: c.DisableSessionResumption,
SessionTicketsDisabled: !c.EnableSessionResumption,
}
for _, opt := range opts {
@@ -202,6 +217,42 @@ func (c *Config) GetXTLSConfig(opts ...Option) *xtls.Config {
config.NextProtos = []string{"h2", "http/1.1"}
}
switch c.MinVersion {
case "1.0":
config.MinVersion = xtls.VersionTLS10
case "1.1":
config.MinVersion = xtls.VersionTLS11
case "1.2":
config.MinVersion = xtls.VersionTLS12
case "1.3":
config.MinVersion = xtls.VersionTLS13
}
switch c.MaxVersion {
case "1.0":
config.MaxVersion = xtls.VersionTLS10
case "1.1":
config.MaxVersion = xtls.VersionTLS11
case "1.2":
config.MaxVersion = xtls.VersionTLS12
case "1.3":
config.MaxVersion = xtls.VersionTLS13
}
if len(c.CipherSuites) > 0 {
id := make(map[string]uint16)
for _, s := range xtls.CipherSuites() {
id[s.Name] = s.ID
}
for _, n := range strings.Split(c.CipherSuites, ":") {
if id[n] != 0 {
config.CipherSuites = append(config.CipherSuites, id[n])
}
}
}
config.PreferServerCipherSuites = c.PreferServerCipherSuites
return config
}

View File

@@ -79,11 +79,12 @@ type Certificate struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// XTLS certificate in x509 format.
Certificate []byte `protobuf:"bytes,1,opt,name=Certificate,proto3" json:"Certificate,omitempty"`
// XTLS key in x509 format.
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"`
// TLS certificate in x509 format.
Certificate []byte `protobuf:"bytes,1,opt,name=certificate,proto3" json:"certificate,omitempty"`
// TLS key in x509 format.
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
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"`
}
func (x *Certificate) Reset() {
@@ -139,6 +140,13 @@ func (x *Certificate) GetUsage() Certificate_Usage {
return Certificate_ENCIPHERMENT
}
func (x *Certificate) GetOcspStapling() int64 {
if x != nil {
return x.OcspStapling
}
return 0
}
type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -146,19 +154,25 @@ type Config struct {
// Whether or not to allow self-signed certificates.
AllowInsecure bool `protobuf:"varint,1,opt,name=allow_insecure,json=allowInsecure,proto3" json:"allow_insecure,omitempty"`
// Whether or not to allow insecure cipher suites.
AllowInsecureCiphers bool `protobuf:"varint,5,opt,name=allow_insecure_ciphers,json=allowInsecureCiphers,proto3" json:"allow_insecure_ciphers,omitempty"`
// List of certificates to be served on server.
Certificate []*Certificate `protobuf:"bytes,2,rep,name=certificate,proto3" json:"certificate,omitempty"`
// Override server name.
ServerName string `protobuf:"bytes,3,opt,name=server_name,json=serverName,proto3" json:"server_name,omitempty"`
// Lists of string as ALPN values.
NextProtocol []string `protobuf:"bytes,4,rep,name=next_protocol,json=nextProtocol,proto3" json:"next_protocol,omitempty"`
// Whether or not to disable session (ticket) resumption.
DisableSessionResumption bool `protobuf:"varint,6,opt,name=disable_session_resumption,json=disableSessionResumption,proto3" json:"disable_session_resumption,omitempty"`
// Whether or not to enable session (ticket) resumption.
EnableSessionResumption bool `protobuf:"varint,5,opt,name=enable_session_resumption,json=enableSessionResumption,proto3" json:"enable_session_resumption,omitempty"`
// If true, root certificates on the system will not be loaded for
// verification.
DisableSystemRoot bool `protobuf:"varint,7,opt,name=disable_system_root,json=disableSystemRoot,proto3" json:"disable_system_root,omitempty"`
DisableSystemRoot bool `protobuf:"varint,6,opt,name=disable_system_root,json=disableSystemRoot,proto3" json:"disable_system_root,omitempty"`
// The minimum TLS version.
MinVersion string `protobuf:"bytes,7,opt,name=min_version,json=minVersion,proto3" json:"min_version,omitempty"`
// The maximum TLS version.
MaxVersion string `protobuf:"bytes,8,opt,name=max_version,json=maxVersion,proto3" json:"max_version,omitempty"`
// Specify cipher suites, except for TLS 1.3.
CipherSuites string `protobuf:"bytes,9,opt,name=cipher_suites,json=cipherSuites,proto3" json:"cipher_suites,omitempty"`
// Whether the server selects its most preferred ciphersuite.
PreferServerCipherSuites bool `protobuf:"varint,10,opt,name=prefer_server_cipher_suites,json=preferServerCipherSuites,proto3" json:"prefer_server_cipher_suites,omitempty"`
}
func (x *Config) Reset() {
@@ -200,13 +214,6 @@ func (x *Config) GetAllowInsecure() bool {
return false
}
func (x *Config) GetAllowInsecureCiphers() bool {
if x != nil {
return x.AllowInsecureCiphers
}
return false
}
func (x *Config) GetCertificate() []*Certificate {
if x != nil {
return x.Certificate
@@ -228,9 +235,9 @@ func (x *Config) GetNextProtocol() []string {
return nil
}
func (x *Config) GetDisableSessionResumption() bool {
func (x *Config) GetEnableSessionResumption() bool {
if x != nil {
return x.DisableSessionResumption
return x.EnableSessionResumption
}
return false
}
@@ -242,6 +249,34 @@ func (x *Config) GetDisableSystemRoot() bool {
return false
}
func (x *Config) GetMinVersion() string {
if x != nil {
return x.MinVersion
}
return ""
}
func (x *Config) GetMaxVersion() string {
if x != nil {
return x.MaxVersion
}
return ""
}
func (x *Config) GetCipherSuites() string {
if x != nil {
return x.CipherSuites
}
return ""
}
func (x *Config) GetPreferServerCipherSuites() bool {
if x != nil {
return x.PreferServerCipherSuites
}
return false
}
var File_transport_internet_xtls_config_proto protoreflect.FileDescriptor
var file_transport_internet_xtls_config_proto_rawDesc = []byte{
@@ -249,50 +284,60 @@ 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, 0xce, 0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x45, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67,
0x78, 0x74, 0x6c, 0x73, 0x22, 0xf3, 0x01, 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, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x45, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67,
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 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, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 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, 0xe6, 0x02, 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, 0x34, 0x0a, 0x16, 0x61, 0x6c, 0x6c, 0x6f, 0x77,
0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72,
0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e,
0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x73, 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, 0x3c, 0x0a, 0x1a, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73,
0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06,
0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x64, 0x69, 0x73, 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, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73,
0x61, 0x62, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f, 0x74, 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,
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,
}
var (

View File

@@ -7,11 +7,11 @@ option java_package = "com.xray.transport.internet.xtls";
option java_multiple_files = true;
message Certificate {
// XTLS certificate in x509 format.
bytes Certificate = 1;
// TLS certificate in x509 format.
bytes certificate = 1;
// XTLS key in x509 format.
bytes Key = 2;
// TLS key in x509 format.
bytes key = 2;
enum Usage {
ENCIPHERMENT = 0;
@@ -20,15 +20,14 @@ message Certificate {
}
Usage usage = 3;
int64 ocsp_stapling = 4;
}
message Config {
// Whether or not to allow self-signed certificates.
bool allow_insecure = 1;
// Whether or not to allow insecure cipher suites.
bool allow_insecure_ciphers = 5;
// List of certificates to be served on server.
repeated Certificate certificate = 2;
@@ -38,10 +37,22 @@ message Config {
// Lists of string as ALPN values.
repeated string next_protocol = 4;
// Whether or not to disable session (ticket) resumption.
bool disable_session_resumption = 6;
// Whether or not to enable session (ticket) resumption.
bool enable_session_resumption = 5;
// If true, root certificates on the system will not be loaded for
// verification.
bool disable_system_root = 7;
bool disable_system_root = 6;
// The minimum TLS version.
string min_version = 7;
// The maximum TLS version.
string max_version = 8;
// Specify cipher suites, except for TLS 1.3.
string cipher_suites = 9;
// Whether the server selects its most preferred ciphersuite.
bool prefer_server_cipher_suites = 10;
}

Some files were not shown because too many files have changed in this diff Show More