mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-22 17:46:48 +08:00
Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
573b7807c0 | ||
![]() |
81d993158f | ||
![]() |
df39991bb3 | ||
![]() |
1b87264c53 | ||
![]() |
96d7156eba | ||
![]() |
d170416219 | ||
![]() |
8ca8a7126b | ||
![]() |
1174ff3090 | ||
![]() |
523c416bb5 | ||
![]() |
c13b8ec9bb | ||
![]() |
4cd343f2d5 | ||
![]() |
d032a8deb7 | ||
![]() |
303fd6e261 | ||
![]() |
c880b916ee | ||
![]() |
ceff4185dc | ||
![]() |
59c7c4897c | ||
![]() |
8ffc430351 | ||
![]() |
7da97635b2 | ||
![]() |
ba41513967 | ||
![]() |
5bc1bf30ae | ||
![]() |
5aa053a65f | ||
![]() |
0b4858d016 | ||
![]() |
7f5e34c857 | ||
![]() |
b60cf02603 | ||
![]() |
ae98dc75cf | ||
![]() |
8ff43519fd | ||
![]() |
33755d6e90 | ||
![]() |
99863aa2ac |
@@ -34,6 +34,7 @@
|
|||||||
- [PassWall](https://github.com/xiaorouji/openwrt-passwall)
|
- [PassWall](https://github.com/xiaorouji/openwrt-passwall)
|
||||||
- [Hello World](https://github.com/jerrykuku/luci-app-vssr)
|
- [Hello World](https://github.com/jerrykuku/luci-app-vssr)
|
||||||
- [ShadowSocksR Plus+](https://github.com/fw876/helloworld)
|
- [ShadowSocksR Plus+](https://github.com/fw876/helloworld)
|
||||||
|
- [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray))
|
||||||
- Windows
|
- Windows
|
||||||
- [v2rayN](https://github.com/2dust/v2rayN)
|
- [v2rayN](https://github.com/2dust/v2rayN)
|
||||||
- [Qv2ray](https://github.com/Qv2ray/Qv2ray)
|
- [Qv2ray](https://github.com/Qv2ray/Qv2ray)
|
||||||
|
@@ -175,12 +175,21 @@ func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *tran
|
|||||||
return inboundLink, outboundLink
|
return inboundLink, outboundLink
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldOverride(result SniffResult, domainOverride []string) bool {
|
func shouldOverride(result SniffResult, request session.SniffingRequest) bool {
|
||||||
for _, p := range domainOverride {
|
domain := result.Domain()
|
||||||
if strings.HasPrefix(result.Protocol(), p) {
|
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 true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +222,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
content.Protocol = result.Protocol()
|
content.Protocol = result.Protocol()
|
||||||
}
|
}
|
||||||
if err == nil && shouldOverride(result, sniffingRequest.OverrideDestinationForProtocol) {
|
if err == nil && shouldOverride(result, sniffingRequest) {
|
||||||
domain := result.Domain()
|
domain := result.Domain()
|
||||||
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
|
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
|
||||||
destination.Address = net.ParseAddress(domain)
|
destination.Address = net.ParseAddress(domain)
|
||||||
|
@@ -364,6 +364,7 @@ func (s *Server) lookupIPInternal(domain string, option IPOption) ([]net.IP, err
|
|||||||
if domain == "" {
|
if domain == "" {
|
||||||
return nil, newError("empty domain name")
|
return nil, newError("empty domain name")
|
||||||
}
|
}
|
||||||
|
domain = strings.ToLower(domain)
|
||||||
|
|
||||||
// normalize the FQDN form query
|
// normalize the FQDN form query
|
||||||
if domain[len(domain)-1] == '.' {
|
if domain[len(domain)-1] == '.' {
|
||||||
|
@@ -44,7 +44,7 @@ func (s *service) Register(server *grpc.Server) {
|
|||||||
RegisterLoggerServiceServer(server, ls)
|
RegisterLoggerServiceServer(server, ls)
|
||||||
|
|
||||||
// For compatibility purposes
|
// For compatibility purposes
|
||||||
vCoreDesc := _LoggerService_serviceDesc
|
vCoreDesc := LoggerService_ServiceDesc
|
||||||
vCoreDesc.ServiceName = "v2ray.core.app.log.command.LoggerService"
|
vCoreDesc.ServiceName = "v2ray.core.app.log.command.LoggerService"
|
||||||
server.RegisterService(&vCoreDesc, ls)
|
server.RegisterService(&vCoreDesc, ls)
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
// LoggerServiceClient is the client API for LoggerService service.
|
// LoggerServiceClient is the client API for LoggerService service.
|
||||||
@@ -62,7 +63,7 @@ type UnsafeLoggerServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterLoggerServiceServer(s grpc.ServiceRegistrar, srv LoggerServiceServer) {
|
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) {
|
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)
|
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",
|
ServiceName: "xray.app.log.command.LoggerService",
|
||||||
HandlerType: (*LoggerServiceServer)(nil),
|
HandlerType: (*LoggerServiceServer)(nil),
|
||||||
Methods: []grpc.MethodDesc{
|
Methods: []grpc.MethodDesc{
|
||||||
|
@@ -140,7 +140,7 @@ func (s *service) Register(server *grpc.Server) {
|
|||||||
RegisterHandlerServiceServer(server, hs)
|
RegisterHandlerServiceServer(server, hs)
|
||||||
|
|
||||||
// For compatibility purposes
|
// For compatibility purposes
|
||||||
vCoreDesc := _HandlerService_serviceDesc
|
vCoreDesc := HandlerService_ServiceDesc
|
||||||
vCoreDesc.ServiceName = "v2ray.core.app.proxyman.command.HandlerService"
|
vCoreDesc.ServiceName = "v2ray.core.app.proxyman.command.HandlerService"
|
||||||
server.RegisterService(&vCoreDesc, hs)
|
server.RegisterService(&vCoreDesc, hs)
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
// HandlerServiceClient is the client API for HandlerService service.
|
// HandlerServiceClient is the client API for HandlerService service.
|
||||||
@@ -132,7 +133,7 @@ type UnsafeHandlerServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterHandlerServiceServer(s grpc.ServiceRegistrar, srv HandlerServiceServer) {
|
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) {
|
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)
|
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",
|
ServiceName: "xray.app.proxyman.command.HandlerService",
|
||||||
HandlerType: (*HandlerServiceServer)(nil),
|
HandlerType: (*HandlerServiceServer)(nil),
|
||||||
Methods: []grpc.MethodDesc{
|
Methods: []grpc.MethodDesc{
|
||||||
|
@@ -241,6 +241,7 @@ type SniffingConfig struct {
|
|||||||
// Override target destination if sniff'ed protocol is in the given list.
|
// Override target destination if sniff'ed protocol is in the given list.
|
||||||
// Supported values are "http", "tls".
|
// Supported values are "http", "tls".
|
||||||
DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
|
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() {
|
func (x *SniffingConfig) Reset() {
|
||||||
@@ -289,6 +290,13 @@ func (x *SniffingConfig) GetDestinationOverride() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *SniffingConfig) GetDomainsExcluded() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.DomainsExcluded
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type ReceiverConfig struct {
|
type ReceiverConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
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,
|
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,
|
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,
|
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,
|
0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0x88, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69,
|
||||||
0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62,
|
||||||
0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
||||||
0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
|
||||||
0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
|
0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
|
||||||
0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72,
|
0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65,
|
||||||
0x72, 0x69, 0x64, 0x65, 0x22, 0x90, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
|
0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73,
|
||||||
0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f,
|
0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72,
|
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64,
|
||||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f,
|
0x22, 0x90, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e,
|
||||||
0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e,
|
0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x67,
|
||||||
0x67, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01,
|
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||||
0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61,
|
||||||
0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52,
|
0x6e, 0x67, 0x65, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x33,
|
||||||
0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
|
0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69, 0x73,
|
||||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
|
0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
||||||
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c,
|
0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12,
|
0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||||
0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53,
|
||||||
0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
|
||||||
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4e, 0x0a, 0x0f, 0x73,
|
||||||
0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
|
0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04,
|
||||||
0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
||||||
0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69,
|
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53,
|
||||||
0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
|
0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72,
|
||||||
0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72,
|
0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x72,
|
||||||
0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
|
0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f,
|
||||||
0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72,
|
0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||||
0x72, 0x69, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61,
|
0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b,
|
0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a,
|
||||||
0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18,
|
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
|
||||||
0x01, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x65, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65,
|
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e,
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78,
|
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0e, 0x64,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e,
|
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x4e, 0x0a,
|
||||||
0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
|
0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||||
0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
|
0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f,
|
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e, 0x69,
|
||||||
0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e, 0x69,
|
||||||
0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74,
|
0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04, 0x08,
|
||||||
0x61, 0x67, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73,
|
0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48,
|
||||||
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
|
0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69,
|
0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x4d,
|
||||||
0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52,
|
0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
|
0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
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,
|
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,
|
0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x72, 0x65, 0x63,
|
||||||
0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75,
|
0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a,
|
||||||
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02, 0x0a,
|
0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
||||||
0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a,
|
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
||||||
0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
|
0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64,
|
||||||
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f,
|
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65,
|
||||||
0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f,
|
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75,
|
||||||
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02, 0x0a, 0x0c, 0x53, 0x65, 0x6e,
|
||||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69, 0x61,
|
||||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
|
||||||
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74,
|
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d,
|
||||||
0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e,
|
0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65,
|
||||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03,
|
0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
||||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x50,
|
0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65,
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78,
|
0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
|
||||||
0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c,
|
0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78,
|
||||||
0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70,
|
0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79,
|
||||||
0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75,
|
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x74,
|
||||||
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22,
|
0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c,
|
||||||
0x50, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43,
|
0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
|
0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12,
|
0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69,
|
||||||
0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02,
|
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
|
||||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
|
0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x50, 0x0a, 0x12, 0x4d,
|
||||||
0x79, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a,
|
0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
|
0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50,
|
0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
|
||||||
0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74,
|
0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2a, 0x23, 0x0a,
|
||||||
0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70,
|
0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12,
|
||||||
0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79,
|
0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x4c, 0x53,
|
||||||
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70,
|
0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
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 (
|
var (
|
||||||
|
@@ -56,6 +56,7 @@ message SniffingConfig {
|
|||||||
// Override target destination if sniff'ed protocol is in the given list.
|
// Override target destination if sniff'ed protocol is in the given list.
|
||||||
// Supported values are "http", "tls".
|
// Supported values are "http", "tls".
|
||||||
repeated string destination_override = 2;
|
repeated string destination_override = 2;
|
||||||
|
repeated string domains_excluded = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ReceiverConfig {
|
message ReceiverConfig {
|
||||||
|
@@ -97,6 +97,7 @@ func (w *tcpWorker) callback(conn internet.Connection) {
|
|||||||
if w.sniffingConfig != nil {
|
if w.sniffingConfig != nil {
|
||||||
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
||||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
||||||
|
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
||||||
}
|
}
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
|
|
||||||
@@ -449,6 +450,7 @@ func (w *dsWorker) callback(conn internet.Connection) {
|
|||||||
if w.sniffingConfig != nil {
|
if w.sniffingConfig != nil {
|
||||||
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
||||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
||||||
|
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
||||||
}
|
}
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
|
|
||||||
|
@@ -85,7 +85,7 @@ func (s *service) Register(server *grpc.Server) {
|
|||||||
RegisterRoutingServiceServer(server, rs)
|
RegisterRoutingServiceServer(server, rs)
|
||||||
|
|
||||||
// For compatibility purposes
|
// For compatibility purposes
|
||||||
vCoreDesc := _RoutingService_serviceDesc
|
vCoreDesc := RoutingService_ServiceDesc
|
||||||
vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService"
|
vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService"
|
||||||
server.RegisterService(&vCoreDesc, rs)
|
server.RegisterService(&vCoreDesc, rs)
|
||||||
}))
|
}))
|
||||||
|
@@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
// RoutingServiceClient is the client API for RoutingService service.
|
// 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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -99,7 +100,7 @@ type UnsafeRoutingServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterRoutingServiceServer(s grpc.ServiceRegistrar, srv RoutingServiceServer) {
|
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 {
|
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)
|
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",
|
ServiceName: "xray.app.router.command.RoutingService",
|
||||||
HandlerType: (*RoutingServiceServer)(nil),
|
HandlerType: (*RoutingServiceServer)(nil),
|
||||||
Methods: []grpc.MethodDesc{
|
Methods: []grpc.MethodDesc{
|
||||||
|
@@ -91,7 +91,7 @@ func (m *DomainMatcher) Apply(ctx routing.Context) bool {
|
|||||||
if len(domain) == 0 {
|
if len(domain) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return m.ApplyDomain(domain)
|
return m.ApplyDomain(strings.ToLower(domain))
|
||||||
}
|
}
|
||||||
|
|
||||||
type MultiGeoIPMatcher struct {
|
type MultiGeoIPMatcher struct {
|
||||||
|
@@ -18,10 +18,10 @@ func init() {
|
|||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
|
||||||
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "release", "config", "geoip.dat")))
|
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
|
||||||
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "release", "config", "geosite.dat")))
|
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "resources", "geosite.dat")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -113,7 +113,7 @@ func (s *service) Register(server *grpc.Server) {
|
|||||||
RegisterStatsServiceServer(server, ss)
|
RegisterStatsServiceServer(server, ss)
|
||||||
|
|
||||||
// For compatibility purposes
|
// For compatibility purposes
|
||||||
vCoreDesc := _StatsService_serviceDesc
|
vCoreDesc := StatsService_ServiceDesc
|
||||||
vCoreDesc.ServiceName = "v2ray.core.app.stats.command.StatsService"
|
vCoreDesc.ServiceName = "v2ray.core.app.stats.command.StatsService"
|
||||||
server.RegisterService(&vCoreDesc, ss)
|
server.RegisterService(&vCoreDesc, ss)
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
// StatsServiceClient is the client API for StatsService service.
|
// StatsServiceClient is the client API for StatsService service.
|
||||||
@@ -90,7 +91,7 @@ type UnsafeStatsServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterStatsServiceServer(s grpc.ServiceRegistrar, srv StatsServiceServer) {
|
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) {
|
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)
|
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",
|
ServiceName: "xray.app.stats.command.StatsService",
|
||||||
HandlerType: (*StatsServiceServer)(nil),
|
HandlerType: (*StatsServiceServer)(nil),
|
||||||
Methods: []grpc.MethodDesc{
|
Methods: []grpc.MethodDesc{
|
||||||
|
@@ -110,6 +110,9 @@ func (b *Buffer) BytesTo(to int32) []byte {
|
|||||||
if to < 0 {
|
if to < 0 {
|
||||||
to += b.Len()
|
to += b.Len()
|
||||||
}
|
}
|
||||||
|
if to < 0 {
|
||||||
|
to = 0
|
||||||
|
}
|
||||||
return b.v[b.start : b.start+to]
|
return b.v[b.start : b.start+to]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -330,7 +330,7 @@ func (m *ClientWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.Buffere
|
|||||||
return buf.Copy(NewStreamReader(reader), buf.Discard)
|
return buf.Copy(NewStreamReader(reader), buf.Discard)
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := s.NewReader(reader)
|
rr := s.NewReader(reader, &meta.Target)
|
||||||
err := buf.Copy(rr, s.output)
|
err := buf.Copy(rr, s.output)
|
||||||
if err != nil && buf.IsWriteError(err) {
|
if err != nil && buf.IsWriteError(err) {
|
||||||
newError("failed to write to downstream. closing session ", s.ID).Base(err).WriteToLog()
|
newError("failed to write to downstream. closing session ", s.ID).Base(err).WriteToLog()
|
||||||
|
@@ -81,6 +81,9 @@ func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
|||||||
if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil {
|
if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else if b.UDP != nil {
|
||||||
|
b.WriteByte(byte(TargetNetworkUDP))
|
||||||
|
addrParser.WriteAddressPort(b, b.UDP.Address, b.UDP.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
len1 := b.Len()
|
len1 := b.Len()
|
||||||
@@ -119,7 +122,7 @@ func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
|
|||||||
f.Option = bitmask.Byte(b.Byte(3))
|
f.Option = bitmask.Byte(b.Byte(3))
|
||||||
f.Target.Network = net.Network_Unknown
|
f.Target.Network = net.Network_Unknown
|
||||||
|
|
||||||
if f.SessionStatus == SessionStatusNew {
|
if f.SessionStatus == SessionStatusNew || (f.SessionStatus == SessionStatusKeep && b.Len() != 4) {
|
||||||
if b.Len() < 8 {
|
if b.Len() < 8 {
|
||||||
return newError("insufficient buffer: ", b.Len())
|
return newError("insufficient buffer: ", b.Len())
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/crypto"
|
"github.com/xtls/xray-core/common/crypto"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,13 +13,15 @@ import (
|
|||||||
type PacketReader struct {
|
type PacketReader struct {
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
eof bool
|
eof bool
|
||||||
|
dest *net.Destination
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPacketReader creates a new PacketReader.
|
// NewPacketReader creates a new PacketReader.
|
||||||
func NewPacketReader(reader io.Reader) *PacketReader {
|
func NewPacketReader(reader io.Reader, dest *net.Destination) *PacketReader {
|
||||||
return &PacketReader{
|
return &PacketReader{
|
||||||
reader: reader,
|
reader: reader,
|
||||||
eof: false,
|
eof: false,
|
||||||
|
dest: dest,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +46,9 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.eof = true
|
r.eof = true
|
||||||
|
if r.dest != nil && r.dest.Network == net.Network_UDP {
|
||||||
|
b.UDP = r.dest
|
||||||
|
}
|
||||||
return buf.MultiBuffer{b}, nil
|
return buf.MultiBuffer{b}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -145,7 +145,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := s.NewReader(reader)
|
rr := s.NewReader(reader, &meta.Target)
|
||||||
if err := buf.Copy(rr, s.output); err != nil {
|
if err := buf.Copy(rr, s.output); err != nil {
|
||||||
buf.Copy(rr, buf.Discard)
|
buf.Copy(rr, buf.Discard)
|
||||||
common.Interrupt(s.input)
|
common.Interrupt(s.input)
|
||||||
@@ -168,7 +168,7 @@ func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.Buffere
|
|||||||
return buf.Copy(NewStreamReader(reader), buf.Discard)
|
return buf.Copy(NewStreamReader(reader), buf.Discard)
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := s.NewReader(reader)
|
rr := s.NewReader(reader, &meta.Target)
|
||||||
err := buf.Copy(rr, s.output)
|
err := buf.Copy(rr, s.output)
|
||||||
|
|
||||||
if err != nil && buf.IsWriteError(err) {
|
if err != nil && buf.IsWriteError(err) {
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -152,9 +153,9 @@ func (s *Session) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewReader creates a buf.Reader based on the transfer type of this Session.
|
// NewReader creates a buf.Reader based on the transfer type of this Session.
|
||||||
func (s *Session) NewReader(reader *buf.BufferedReader) buf.Reader {
|
func (s *Session) NewReader(reader *buf.BufferedReader, dest *net.Destination) buf.Reader {
|
||||||
if s.transferType == protocol.TransferTypeStream {
|
if s.transferType == protocol.TransferTypeStream {
|
||||||
return NewStreamReader(reader)
|
return NewStreamReader(reader)
|
||||||
}
|
}
|
||||||
return NewPacketReader(reader)
|
return NewPacketReader(reader, dest)
|
||||||
}
|
}
|
||||||
|
@@ -63,6 +63,9 @@ func (w *Writer) writeMetaOnly() error {
|
|||||||
|
|
||||||
func writeMetaWithFrame(writer buf.Writer, meta FrameMetadata, data buf.MultiBuffer) error {
|
func writeMetaWithFrame(writer buf.Writer, meta FrameMetadata, data buf.MultiBuffer) error {
|
||||||
frame := buf.New()
|
frame := buf.New()
|
||||||
|
if len(data) == 1 {
|
||||||
|
frame.UDP = data[0].UDP
|
||||||
|
}
|
||||||
if err := meta.WriteTo(frame); err != nil {
|
if err := meta.WriteTo(frame); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -55,7 +55,7 @@ func TestAddressReading(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Options: []AddressOption{AddressFamilyByte(0x03, net.AddressFamilyDomain)},
|
Options: []AddressOption{AddressFamilyByte(0x03, net.AddressFamilyDomain)},
|
||||||
Input: []byte{3, 9, 118, 50, 114, 97, 121, 46, 99, 111, 109, 0, 80},
|
Input: []byte{3, 11, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 0, 80},
|
||||||
Address: net.DomainAddress("example.com"),
|
Address: net.DomainAddress("example.com"),
|
||||||
Port: net.Port(80),
|
Port: net.Port(80),
|
||||||
},
|
},
|
||||||
@@ -84,8 +84,9 @@ func TestAddressReading(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range data {
|
for _, tc := range data {
|
||||||
b := buf.New()
|
|
||||||
parser := NewAddressParser(tc.Options...)
|
parser := NewAddressParser(tc.Options...)
|
||||||
|
|
||||||
|
b := buf.New()
|
||||||
addr, port, err := parser.ReadAddressPort(b, bytes.NewReader(tc.Input))
|
addr, port, err := parser.ReadAddressPort(b, bytes.NewReader(tc.Input))
|
||||||
b.Release()
|
b.Release()
|
||||||
if tc.Error {
|
if tc.Error {
|
||||||
|
@@ -102,7 +102,7 @@ func ReadClientHello(data []byte, h *SniffHeader) error {
|
|||||||
return errNotClientHello
|
return errNotClientHello
|
||||||
}
|
}
|
||||||
if nameType == 0 {
|
if nameType == 0 {
|
||||||
serverName := string(d[:nameLen])
|
serverName := strings.ToLower(string(d[:nameLen]))
|
||||||
// An SNI value may not include a
|
// An SNI value may not include a
|
||||||
// trailing dot. See
|
// trailing dot. See
|
||||||
// https://tools.ietf.org/html/rfc6066#section-3.
|
// https://tools.ietf.org/html/rfc6066#section-3.
|
||||||
|
@@ -60,6 +60,7 @@ type Outbound struct {
|
|||||||
|
|
||||||
// SniffingRequest controls the behavior of content sniffing.
|
// SniffingRequest controls the behavior of content sniffing.
|
||||||
type SniffingRequest struct {
|
type SniffingRequest struct {
|
||||||
|
ExcludeForDomain []string
|
||||||
OverrideDestinationForProtocol []string
|
OverrideDestinationForProtocol []string
|
||||||
Enabled bool
|
Enabled bool
|
||||||
}
|
}
|
||||||
|
137
common/xudp/xudp.go
Normal file
137
common/xudp/xudp.go
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
package xudp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
var addrParser = protocol.NewAddressParser(
|
||||||
|
protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv4), net.AddressFamilyIPv4),
|
||||||
|
protocol.AddressFamilyByte(byte(protocol.AddressTypeDomain), net.AddressFamilyDomain),
|
||||||
|
protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv6), net.AddressFamilyIPv6),
|
||||||
|
protocol.PortThenAddress(),
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewPacketWriter(writer buf.Writer, dest net.Destination) *PacketWriter {
|
||||||
|
return &PacketWriter{
|
||||||
|
Writer: writer,
|
||||||
|
Dest: dest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketWriter struct {
|
||||||
|
Writer buf.Writer
|
||||||
|
Dest net.Destination
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||||
|
defer buf.ReleaseMulti(mb)
|
||||||
|
mb2Write := make(buf.MultiBuffer, 0, len(mb))
|
||||||
|
for _, b := range mb {
|
||||||
|
length := b.Len()
|
||||||
|
if length == 0 || length+666 > buf.Size {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
eb := buf.New()
|
||||||
|
eb.Write([]byte{0, 0, 0, 0})
|
||||||
|
if w.Dest.Network == net.Network_UDP {
|
||||||
|
eb.WriteByte(1) // New
|
||||||
|
eb.WriteByte(1) // Opt
|
||||||
|
eb.WriteByte(2) // UDP
|
||||||
|
addrParser.WriteAddressPort(eb, w.Dest.Address, w.Dest.Port)
|
||||||
|
w.Dest.Network = net.Network_Unknown
|
||||||
|
} else {
|
||||||
|
eb.WriteByte(2) // Keep
|
||||||
|
eb.WriteByte(1)
|
||||||
|
if b.UDP != nil {
|
||||||
|
eb.WriteByte(2)
|
||||||
|
addrParser.WriteAddressPort(eb, b.UDP.Address, b.UDP.Port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l := eb.Len() - 2
|
||||||
|
eb.SetByte(0, byte(l>>8))
|
||||||
|
eb.SetByte(1, byte(l))
|
||||||
|
eb.WriteByte(byte(length >> 8))
|
||||||
|
eb.WriteByte(byte(length))
|
||||||
|
eb.Write(b.Bytes())
|
||||||
|
|
||||||
|
mb2Write = append(mb2Write, eb)
|
||||||
|
}
|
||||||
|
if mb2Write.IsEmpty() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return w.Writer.WriteMultiBuffer(mb2Write)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPacketReader(reader io.Reader) *PacketReader {
|
||||||
|
return &PacketReader{
|
||||||
|
Reader: reader,
|
||||||
|
cache: make([]byte, 2),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketReader struct {
|
||||||
|
Reader io.Reader
|
||||||
|
cache []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||||
|
for {
|
||||||
|
if _, err := io.ReadFull(r.Reader, r.cache); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
l := int32(r.cache[0])<<8 | int32(r.cache[1])
|
||||||
|
if l < 4 {
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
b := buf.New()
|
||||||
|
if _, err := b.ReadFullFrom(r.Reader, l); err != nil {
|
||||||
|
b.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
discard := false
|
||||||
|
switch b.Byte(2) {
|
||||||
|
case 2:
|
||||||
|
if l != 4 {
|
||||||
|
b.Advance(5)
|
||||||
|
addr, port, err := addrParser.ReadAddressPort(nil, b)
|
||||||
|
if err != nil {
|
||||||
|
b.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
b.UDP = &net.Destination{
|
||||||
|
Network: net.Network_UDP,
|
||||||
|
Address: addr,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
discard = true
|
||||||
|
default:
|
||||||
|
b.Release()
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
if b.Byte(3) == 1 {
|
||||||
|
if _, err := io.ReadFull(r.Reader, r.cache); err != nil {
|
||||||
|
b.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
length := int32(r.cache[0])<<8 | int32(r.cache[1])
|
||||||
|
if length > 0 {
|
||||||
|
b.Clear()
|
||||||
|
if _, err := b.ReadFullFrom(r.Reader, length); err != nil {
|
||||||
|
b.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !discard {
|
||||||
|
return buf.MultiBuffer{b}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Release()
|
||||||
|
}
|
||||||
|
}
|
@@ -22,9 +22,13 @@ type ConfigFormat struct {
|
|||||||
// ConfigLoader is a utility to load Xray config from external source.
|
// ConfigLoader is a utility to load Xray config from external source.
|
||||||
type ConfigLoader func(input interface{}) (*Config, error)
|
type ConfigLoader func(input interface{}) (*Config, error)
|
||||||
|
|
||||||
|
// ConfigBuilder is a builder to build core.Config from filenames and formats
|
||||||
|
type ConfigBuilder func(files []string, formats []string) (*Config, error)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
configLoaderByName = make(map[string]*ConfigFormat)
|
configLoaderByName = make(map[string]*ConfigFormat)
|
||||||
configLoaderByExt = make(map[string]*ConfigFormat)
|
configLoaderByExt = make(map[string]*ConfigFormat)
|
||||||
|
ConfigBuilderForFiles ConfigBuilder
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegisterConfigLoader add a new ConfigLoader.
|
// RegisterConfigLoader add a new ConfigLoader.
|
||||||
@@ -46,6 +50,21 @@ func RegisterConfigLoader(format *ConfigFormat) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetFormatByExtension(ext string) string {
|
||||||
|
switch strings.ToLower(ext) {
|
||||||
|
case "pb", "protobuf":
|
||||||
|
return "protobuf"
|
||||||
|
case "yaml", "yml":
|
||||||
|
return "yaml"
|
||||||
|
case "toml":
|
||||||
|
return "toml"
|
||||||
|
case "json":
|
||||||
|
return "json"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getExtension(filename string) string {
|
func getExtension(filename string) string {
|
||||||
idx := strings.LastIndexByte(filename, '.')
|
idx := strings.LastIndexByte(filename, '.')
|
||||||
if idx == -1 {
|
if idx == -1 {
|
||||||
@@ -54,23 +73,48 @@ func getExtension(filename string) string {
|
|||||||
return filename[idx+1:]
|
return filename[idx+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfig loads config with given format from given source.
|
func getFormat(filename string) string {
|
||||||
// input accepts 2 different types:
|
return GetFormatByExtension(getExtension(filename))
|
||||||
// * []string slice of multiple filename/url(s) to open to read
|
}
|
||||||
// * io.Reader that reads a config content (the original way)
|
|
||||||
func LoadConfig(formatName string, filename string, input interface{}) (*Config, error) {
|
func LoadConfig(formatName string, input interface{}) (*Config, error) {
|
||||||
ext := getExtension(filename)
|
switch v := input.(type) {
|
||||||
if len(ext) > 0 {
|
case cmdarg.Arg:
|
||||||
if f, found := configLoaderByExt[ext]; found {
|
|
||||||
return f.Loader(input)
|
formats := make([]string, len(v))
|
||||||
|
hasProtobuf := false
|
||||||
|
for i, file := range v {
|
||||||
|
f := getFormat(file)
|
||||||
|
if f == "" {
|
||||||
|
f = formatName
|
||||||
|
}
|
||||||
|
if f == "protobuf" {
|
||||||
|
hasProtobuf = true
|
||||||
|
}
|
||||||
|
formats[i] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
// only one protobuf config file is allowed
|
||||||
|
if hasProtobuf {
|
||||||
|
if len(v) == 1 {
|
||||||
|
return configLoaderByName["protobuf"].Loader(v)
|
||||||
|
} else {
|
||||||
|
return nil, newError("Only one protobuf config file is allowed").AtWarning()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// to avoid import cycle
|
||||||
|
return ConfigBuilderForFiles(v, formats)
|
||||||
|
|
||||||
|
case io.Reader:
|
||||||
|
if f, found := configLoaderByName[formatName]; found {
|
||||||
|
return f.Loader(v)
|
||||||
|
} else {
|
||||||
|
return nil, newError("Unable to load config in", formatName).AtWarning()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, found := configLoaderByName[formatName]; found {
|
return nil, newError("Unable to load config").AtWarning()
|
||||||
return f.Loader(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, newError("Unable to load config in ", formatName).AtWarning()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadProtobufConfig(data []byte) (*Config, error) {
|
func loadProtobufConfig(data []byte) (*Config, error) {
|
||||||
|
@@ -18,7 +18,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "1.2.2"
|
version = "1.3.0"
|
||||||
build = "Custom"
|
build = "Custom"
|
||||||
codename = "Xray, Penetrates Everything."
|
codename = "Xray, Penetrates Everything."
|
||||||
intro = "A unified platform for anti-censorship."
|
intro = "A unified platform for anti-censorship."
|
||||||
|
@@ -25,7 +25,7 @@ func CreateObject(v *Instance, config interface{}) (interface{}, error) {
|
|||||||
//
|
//
|
||||||
// xray:api:stable
|
// xray:api:stable
|
||||||
func StartInstance(configFormat string, configBytes []byte) (*Instance, error) {
|
func StartInstance(configFormat string, configBytes []byte) (*Instance, error) {
|
||||||
config, err := LoadConfig(configFormat, "", bytes.NewReader(configBytes))
|
config, err := LoadConfig(configFormat, bytes.NewReader(configBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
31
core/xray.go
31
core/xray.go
@@ -2,14 +2,10 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime/debug"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
"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"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/features"
|
"github.com/xtls/xray-core/features"
|
||||||
@@ -184,30 +180,7 @@ func NewWithContext(ctx context.Context, config *Config) (*Instance, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
|
func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
|
||||||
cone := true
|
server.ctx = context.WithValue(server.ctx, "cone", os.Getenv("XRAY_CONE_DISABLED") != "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 {
|
if config.Transport != nil {
|
||||||
features.PrintDeprecatedFeatureWarning("global transport settings")
|
features.PrintDeprecatedFeatureWarning("global transport settings")
|
||||||
|
10
go.mod
10
go.mod
@@ -9,17 +9,17 @@ require (
|
|||||||
github.com/google/go-cmp v0.5.4
|
github.com/google/go-cmp v0.5.4
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/lucas-clemente/quic-go v0.19.3
|
github.com/lucas-clemente/quic-go v0.19.3
|
||||||
github.com/miekg/dns v1.1.35
|
github.com/miekg/dns v1.1.37
|
||||||
github.com/pelletier/go-toml v1.8.1
|
github.com/pelletier/go-toml v1.8.1
|
||||||
github.com/pires/go-proxyproto v0.3.3
|
github.com/pires/go-proxyproto v0.4.2
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c
|
github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499
|
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499
|
||||||
go.starlark.net v0.0.0-20210114021256-8756d3ec1770
|
go.starlark.net v0.0.0-20210126161401-bc864be25151
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
||||||
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||||
google.golang.org/grpc v1.35.0
|
google.golang.org/grpc v1.35.0
|
||||||
google.golang.org/protobuf v1.25.0
|
google.golang.org/protobuf v1.25.0
|
||||||
h12.io/socks v1.0.2
|
h12.io/socks v1.0.2
|
||||||
|
20
go.sum
20
go.sum
@@ -107,8 +107,8 @@ github.com/marten-seemann/qtls-go1-15 v0.1.1 h1:LIH6K34bPVttyXnUWixk0bzH6/N07Vxb
|
|||||||
github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
|
github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||||
github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
|
github.com/miekg/dns v1.1.37 h1:+kky2ArpBqk0S/74RkwFjmKM9jja7AB1RN7VUuVq0iM=
|
||||||
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
github.com/miekg/dns v1.1.37/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||||
@@ -127,8 +127,8 @@ github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNC
|
|||||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
github.com/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 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
|
||||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
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.4.2 h1:VRAvsUCTrmiahoU5fqQqkbY0GWcJ1Q0F7b7CkFaipSU=
|
||||||
github.com/pires/go-proxyproto v0.3.3/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
github.com/pires/go-proxyproto v0.4.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
@@ -180,8 +180,8 @@ github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 h1:QHESTXtfgc1ABV+ArlbPVqU
|
|||||||
github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499/go.mod h1:5TB2+k58gx4A4g2Nf5miSHNDF6CuAzHKpWBooLAshTs=
|
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.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.starlark.net v0.0.0-20210114021256-8756d3ec1770 h1:S8VZYGh3JOUhV0QWJcoZDIXBLoArFNkMbqsL23SzaSE=
|
go.starlark.net v0.0.0-20210126161401-bc864be25151 h1:BkNycm5DBve8zINASgjl15CPNQq/xuZ0ViAlir4sUcw=
|
||||||
go.starlark.net v0.0.0-20210114021256-8756d3ec1770/go.mod h1:vxxlMsgCAPH7BR2LtxjJC4WhhZhCGd/b01+CIpj8H4k=
|
go.starlark.net v0.0.0-20210126161401-bc864be25151/go.mod h1:vxxlMsgCAPH7BR2LtxjJC4WhhZhCGd/b01+CIpj8H4k=
|
||||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
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/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=
|
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
@@ -212,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-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-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-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
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-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-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@@ -244,8 +244,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-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-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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78 h1:nVuTkr9L6Bq62qpUqKo/RnZCFfzDBL0bYo6w9OJUqZY=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||||
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
@@ -21,7 +21,7 @@ func init() {
|
|||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
|
||||||
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "release", "config", "geoip.dat")))
|
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
|
||||||
}
|
}
|
||||||
|
|
||||||
geositeFilePath := filepath.Join(wd, "geosite.dat")
|
geositeFilePath := filepath.Join(wd, "geosite.dat")
|
||||||
@@ -112,6 +112,11 @@ func TestDNSConfigParsing(t *testing.T) {
|
|||||||
Domain: "example.com",
|
Domain: "example.com",
|
||||||
ProxiedDomain: "google.com",
|
ProxiedDomain: "google.com",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Type: dns.DomainMatchingType_Full,
|
||||||
|
Domain: "example.com",
|
||||||
|
Ip: [][]byte{{127, 0, 0, 1}},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Type: dns.DomainMatchingType_Full,
|
Type: dns.DomainMatchingType_Full,
|
||||||
Domain: "example.com",
|
Domain: "example.com",
|
||||||
@@ -127,11 +132,6 @@ func TestDNSConfigParsing(t *testing.T) {
|
|||||||
Domain: ".*\\.com",
|
Domain: ".*\\.com",
|
||||||
Ip: [][]byte{{8, 8, 4, 4}},
|
Ip: [][]byte{{8, 8, 4, 4}},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Type: dns.DomainMatchingType_Full,
|
|
||||||
Domain: "example.com",
|
|
||||||
Ip: [][]byte{{127, 0, 0, 1}},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
ClientIp: []byte{10, 0, 0, 1},
|
ClientIp: []byte{10, 0, 0, 1},
|
||||||
},
|
},
|
||||||
|
@@ -460,6 +460,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||||||
type RawFieldRule struct {
|
type RawFieldRule struct {
|
||||||
RouterRule
|
RouterRule
|
||||||
Domain *StringList `json:"domain"`
|
Domain *StringList `json:"domain"`
|
||||||
|
Domains *StringList `json:"domains"`
|
||||||
IP *StringList `json:"ip"`
|
IP *StringList `json:"ip"`
|
||||||
Port *PortList `json:"port"`
|
Port *PortList `json:"port"`
|
||||||
Network *NetworkList `json:"network"`
|
Network *NetworkList `json:"network"`
|
||||||
@@ -500,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 {
|
if rawFieldRule.IP != nil {
|
||||||
geoipList, err := toCidrList(*rawFieldRule.IP)
|
geoipList, err := toCidrList(*rawFieldRule.IP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
44
infra/conf/serial/builder.go
Normal file
44
infra/conf/serial/builder.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package serial
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/infra/conf"
|
||||||
|
"github.com/xtls/xray-core/main/confloader"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BuildConfig(files []string, formats []string) (*core.Config, error) {
|
||||||
|
|
||||||
|
cf := &conf.Config{}
|
||||||
|
for i, file := range files {
|
||||||
|
newError("Reading config: ", file).AtInfo().WriteToLog()
|
||||||
|
r, err := confloader.LoadConfig(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to read config: ", file).Base(err)
|
||||||
|
}
|
||||||
|
c, err := ReaderDecoderByFormat[formats[i]](r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to decode config: ", file).Base(err)
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
*cf = *c
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cf.Override(c, file)
|
||||||
|
}
|
||||||
|
return cf.Build()
|
||||||
|
}
|
||||||
|
|
||||||
|
type readerDecoder func(io.Reader) (*conf.Config, error)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ReaderDecoderByFormat = make(map[string]readerDecoder)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ReaderDecoderByFormat["json"] = DecodeJSONConfig
|
||||||
|
ReaderDecoderByFormat["yaml"] = DecodeYAMLConfig
|
||||||
|
ReaderDecoderByFormat["toml"] = DecodeTOMLConfig
|
||||||
|
|
||||||
|
core.ConfigBuilderForFiles = BuildConfig
|
||||||
|
}
|
@@ -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 {
|
type ShadowsocksServerConfig struct {
|
||||||
Cipher string `json:"method"`
|
Cipher string `json:"method"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
UDP bool `json:"udp"`
|
Level byte `json:"level"`
|
||||||
Level byte `json:"level"`
|
Email string `json:"email"`
|
||||||
Email string `json:"email"`
|
Users []*ShadowsocksUserConfig `json:"clients"`
|
||||||
NetworkList *NetworkList `json:"network"`
|
NetworkList *NetworkList `json:"network"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
|
func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
|
||||||
config := new(shadowsocks.ServerConfig)
|
config := new(shadowsocks.ServerConfig)
|
||||||
config.UdpEnabled = v.UDP
|
|
||||||
config.Network = v.NetworkList.Build()
|
config.Network = v.NetworkList.Build()
|
||||||
|
|
||||||
if v.Password == "" {
|
if v.Users != nil {
|
||||||
return nil, newError("Shadowsocks password is not specified.")
|
for _, user := range v.Users {
|
||||||
}
|
account := &shadowsocks.Account{
|
||||||
account := &shadowsocks.Account{
|
Password: user.Password,
|
||||||
Password: v.Password,
|
CipherType: cipherFromString(user.Cipher),
|
||||||
}
|
}
|
||||||
account.CipherType = cipherFromString(v.Cipher)
|
if account.Password == "" {
|
||||||
if account.CipherType == shadowsocks.CipherType_UNKNOWN {
|
return nil, newError("Shadowsocks password is not specified.")
|
||||||
return nil, newError("unknown cipher method: ", v.Cipher)
|
}
|
||||||
}
|
if account.CipherType < 5 || account.CipherType > 7 {
|
||||||
|
return nil, newError("unsupported cipher method: ", user.Cipher)
|
||||||
config.User = &protocol.User{
|
}
|
||||||
Email: v.Email,
|
config.Users = append(config.Users, &protocol.User{
|
||||||
Level: uint32(v.Level),
|
Email: user.Email,
|
||||||
Account: serial.ToTypedMessage(account),
|
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
|
return config, nil
|
||||||
@@ -73,7 +98,6 @@ type ShadowsocksServerTarget struct {
|
|||||||
Cipher string `json:"method"`
|
Cipher string `json:"method"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Ota bool `json:"ota"`
|
|
||||||
Level byte `json:"level"`
|
Level byte `json:"level"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,17 +18,17 @@ func TestShadowsocksServerConfigParsing(t *testing.T) {
|
|||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
Input: `{
|
Input: `{
|
||||||
"method": "aes-128-cfb",
|
"method": "aes-128-gcm",
|
||||||
"password": "xray-password"
|
"password": "xray-password"
|
||||||
}`,
|
}`,
|
||||||
Parser: loadJSON(creator),
|
Parser: loadJSON(creator),
|
||||||
Output: &shadowsocks.ServerConfig{
|
Output: &shadowsocks.ServerConfig{
|
||||||
User: &protocol.User{
|
Users: []*protocol.User{{
|
||||||
Account: serial.ToTypedMessage(&shadowsocks.Account{
|
Account: serial.ToTypedMessage(&shadowsocks.Account{
|
||||||
CipherType: shadowsocks.CipherType_AES_128_CFB,
|
CipherType: shadowsocks.CipherType_AES_128_GCM,
|
||||||
Password: "xray-password",
|
Password: "xray-password",
|
||||||
}),
|
}),
|
||||||
},
|
}},
|
||||||
Network: []net.Network{net.Network_TCP},
|
Network: []net.Network{net.Network_TCP},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -264,6 +264,7 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
|
|||||||
return nil, newError("failed to parse certificate").Base(err)
|
return nil, newError("failed to parse certificate").Base(err)
|
||||||
}
|
}
|
||||||
certificate.Certificate = cert
|
certificate.Certificate = cert
|
||||||
|
certificate.CertificatePath = c.CertFile
|
||||||
|
|
||||||
if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
|
if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
|
||||||
key, err := readFileOrString(c.KeyFile, c.KeyStr)
|
key, err := readFileOrString(c.KeyFile, c.KeyStr)
|
||||||
@@ -271,6 +272,7 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
|
|||||||
return nil, newError("failed to parse key").Base(err)
|
return nil, newError("failed to parse key").Base(err)
|
||||||
}
|
}
|
||||||
certificate.Key = key
|
certificate.Key = key
|
||||||
|
certificate.KeyPath = c.KeyFile
|
||||||
}
|
}
|
||||||
|
|
||||||
switch strings.ToLower(c.Usage) {
|
switch strings.ToLower(c.Usage) {
|
||||||
@@ -348,6 +350,7 @@ func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) {
|
|||||||
return nil, newError("failed to parse certificate").Base(err)
|
return nil, newError("failed to parse certificate").Base(err)
|
||||||
}
|
}
|
||||||
certificate.Certificate = cert
|
certificate.Certificate = cert
|
||||||
|
certificate.CertificatePath = c.CertFile
|
||||||
|
|
||||||
if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
|
if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
|
||||||
key, err := readFileOrString(c.KeyFile, c.KeyStr)
|
key, err := readFileOrString(c.KeyFile, c.KeyStr)
|
||||||
@@ -355,6 +358,7 @@ func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) {
|
|||||||
return nil, newError("failed to parse key").Base(err)
|
return nil, newError("failed to parse key").Base(err)
|
||||||
}
|
}
|
||||||
certificate.Key = key
|
certificate.Key = key
|
||||||
|
certificate.KeyPath = c.KeyFile
|
||||||
}
|
}
|
||||||
|
|
||||||
switch strings.ToLower(c.Usage) {
|
switch strings.ToLower(c.Usage) {
|
||||||
|
@@ -85,6 +85,7 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
|
|||||||
|
|
||||||
// TrojanInboundFallback is fallback configuration
|
// TrojanInboundFallback is fallback configuration
|
||||||
type TrojanInboundFallback struct {
|
type TrojanInboundFallback struct {
|
||||||
|
Name string `json:"name"`
|
||||||
Alpn string `json:"alpn"`
|
Alpn string `json:"alpn"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
@@ -144,6 +145,7 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
|
|||||||
_ = json.Unmarshal(fb.Dest, &s)
|
_ = json.Unmarshal(fb.Dest, &s)
|
||||||
}
|
}
|
||||||
config.Fallbacks = append(config.Fallbacks, &trojan.Fallback{
|
config.Fallbacks = append(config.Fallbacks, &trojan.Fallback{
|
||||||
|
Name: fb.Name,
|
||||||
Alpn: fb.Alpn,
|
Alpn: fb.Alpn,
|
||||||
Path: fb.Path,
|
Path: fb.Path,
|
||||||
Type: fb.Type,
|
Type: fb.Type,
|
||||||
|
@@ -58,29 +58,38 @@ func toProtocolList(s []string) ([]proxyman.KnownProtocols, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SniffingConfig struct {
|
type SniffingConfig struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
DestOverride *StringList `json:"destOverride"`
|
DestOverride *StringList `json:"destOverride"`
|
||||||
|
DomainsExcluded *StringList `json:"domainsExcluded"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
|
func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
|
||||||
var p []string
|
var p []string
|
||||||
if c.DestOverride != nil {
|
if c.DestOverride != nil {
|
||||||
for _, domainOverride := range *c.DestOverride {
|
for _, protocol := range *c.DestOverride {
|
||||||
switch strings.ToLower(domainOverride) {
|
switch strings.ToLower(protocol) {
|
||||||
case "http":
|
case "http":
|
||||||
p = append(p, "http")
|
p = append(p, "http")
|
||||||
case "tls", "https", "ssl":
|
case "tls", "https", "ssl":
|
||||||
p = append(p, "tls")
|
p = append(p, "tls")
|
||||||
default:
|
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{
|
return &proxyman.SniffingConfig{
|
||||||
Enabled: c.Enabled,
|
Enabled: c.Enabled,
|
||||||
DestinationOverride: p,
|
DestinationOverride: p,
|
||||||
|
DomainsExcluded: d,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
main/run.go
20
main/run.go
@@ -11,7 +11,6 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strings"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/cmdarg"
|
"github.com/xtls/xray-core/common/cmdarg"
|
||||||
@@ -158,30 +157,25 @@ func getConfigFilePath() cmdarg.Arg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getConfigFormat() string {
|
func getConfigFormat() string {
|
||||||
switch strings.ToLower(*format) {
|
f := core.GetFormatByExtension(*format)
|
||||||
case "pb", "protobuf":
|
if f == "" {
|
||||||
return "protobuf"
|
f = "json"
|
||||||
case "yaml", "yml":
|
|
||||||
return "yaml"
|
|
||||||
case "toml":
|
|
||||||
return "toml"
|
|
||||||
default:
|
|
||||||
return "json"
|
|
||||||
}
|
}
|
||||||
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
func startXray() (core.Server, error) {
|
func startXray() (core.Server, error) {
|
||||||
configFiles := getConfigFilePath()
|
configFiles := getConfigFilePath()
|
||||||
|
|
||||||
config, err := core.LoadConfig(getConfigFormat(), configFiles[0], configFiles)
|
//config, err := core.LoadConfig(getConfigFormat(), configFiles[0], configFiles)
|
||||||
|
|
||||||
//config, err := core.LoadConfigs(getConfigFormat(), configFiles)
|
c, err := core.LoadConfig(getConfigFormat(), configFiles)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to load config files: [", configFiles.String(), "]").Base(err)
|
return nil, newError("failed to load config files: [", configFiles.String(), "]").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
server, err := core.New(config)
|
server, err := core.New(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to create server").Base(err)
|
return nil, newError("failed to create server").Base(err)
|
||||||
}
|
}
|
||||||
|
@@ -277,17 +277,17 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
w.mark,
|
w.mark,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
newError(err).WriteToLog()
|
||||||
b.Release()
|
b.Release()
|
||||||
buf.ReleaseMulti(mb)
|
continue
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
w.conns[*b.UDP] = conn
|
w.conns[*b.UDP] = conn
|
||||||
}
|
}
|
||||||
_, err = conn.WriteTo(b.Bytes(), w.back)
|
_, err = conn.WriteTo(b.Bytes(), w.back)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.Close()
|
|
||||||
w.conns[*b.UDP] = nil
|
|
||||||
newError(err).WriteToLog()
|
newError(err).WriteToLog()
|
||||||
|
w.conns[*b.UDP] = nil
|
||||||
|
conn.Close()
|
||||||
}
|
}
|
||||||
b.Release()
|
b.Release()
|
||||||
} else {
|
} else {
|
||||||
|
@@ -7,66 +7,60 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FakeUDP(addr *net.UDPAddr, mark int) (net.PacketConn, error) {
|
func FakeUDP(addr *net.UDPAddr, mark int) (net.PacketConn, error) {
|
||||||
|
var af int
|
||||||
|
var sockaddr syscall.Sockaddr
|
||||||
|
|
||||||
localSocketAddress, af, err := udpAddrToSocketAddr(addr)
|
if len(addr.IP) == 4 {
|
||||||
if err != nil {
|
af = syscall.AF_INET
|
||||||
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("build local socket address: %s", err)}
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileDescriptor, err := syscall.Socket(af, syscall.SOCK_DGRAM, 0)
|
var fd int
|
||||||
if err != nil {
|
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)}
|
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("socket open: %s", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if mark != 0 {
|
if mark != 0 {
|
||||||
if err = syscall.SetsockoptInt(fileDescriptor, syscall.SOL_SOCKET, syscall.SO_MARK, mark); err != nil {
|
if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, mark); err != nil {
|
||||||
syscall.Close(fileDescriptor)
|
syscall.Close(fd)
|
||||||
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("set socket option: SO_MARK: %s", err)}
|
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("set socket option: SO_MARK: %s", err)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = syscall.SetsockoptInt(fileDescriptor, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
|
if err = syscall.SetsockoptInt(fd, syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil {
|
||||||
syscall.Close(fileDescriptor)
|
syscall.Close(fd)
|
||||||
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("set socket option: SO_REUSEADDR: %s", err)}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = syscall.SetsockoptInt(fileDescriptor, syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil {
|
|
||||||
syscall.Close(fileDescriptor)
|
|
||||||
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("set socket option: IP_TRANSPARENT: %s", err)}
|
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("set socket option: IP_TRANSPARENT: %s", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = syscall.Bind(fileDescriptor, localSocketAddress); err != nil {
|
syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||||
syscall.Close(fileDescriptor)
|
|
||||||
|
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)}
|
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("socket bind: %s", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
fdFile := os.NewFile(uintptr(fileDescriptor), fmt.Sprintf("net-udp-fake-%s", addr.String()))
|
fdFile := os.NewFile(uintptr(fd), fmt.Sprintf("net-udp-fake-%s", addr.String()))
|
||||||
defer fdFile.Close()
|
defer fdFile.Close()
|
||||||
|
|
||||||
packetConn, err := net.FilePacketConn(fdFile)
|
packetConn, err := net.FilePacketConn(fdFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
syscall.Close(fileDescriptor)
|
syscall.Close(fd)
|
||||||
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("convert file descriptor to connection: %s", err)}
|
return nil, &net.OpError{Op: "fake", Err: fmt.Errorf("convert file descriptor to connection: %s", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
return packetConn, nil
|
return packetConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func udpAddrToSocketAddr(addr *net.UDPAddr) (syscall.Sockaddr, int, error) {
|
|
||||||
switch {
|
|
||||||
case addr.IP.To4() != nil:
|
|
||||||
ip := [4]byte{}
|
|
||||||
copy(ip[:], addr.IP.To4())
|
|
||||||
|
|
||||||
return &syscall.SockaddrInet4{Addr: ip, Port: addr.Port}, syscall.AF_INET, nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
ip := [16]byte{}
|
|
||||||
copy(ip[:], addr.IP.To16())
|
|
||||||
|
|
||||||
return &syscall.SockaddrInet6{Addr: ip, Port: addr.Port, ZoneId: 0}, syscall.AF_INET6, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -7,6 +7,8 @@ import (
|
|||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"io"
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
"golang.org/x/crypto/hkdf"
|
"golang.org/x/crypto/hkdf"
|
||||||
@@ -31,6 +33,31 @@ func (a *MemoryAccount) Equals(another protocol.Account) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *MemoryAccount) GetCipherName() string {
|
||||||
|
switch a.Cipher.(type) {
|
||||||
|
case *AesCfb:
|
||||||
|
keyBytes := a.Cipher.(*AesCfb).KeyBytes
|
||||||
|
return "AES_" + strconv.FormatInt(int64(keyBytes*8), 10) + "_CFB"
|
||||||
|
case *ChaCha20:
|
||||||
|
if a.Cipher.(*ChaCha20).IVBytes == 8 {
|
||||||
|
return "CHACHA20"
|
||||||
|
}
|
||||||
|
return "CHACHA20_IETF"
|
||||||
|
case *AEADCipher:
|
||||||
|
switch reflect.ValueOf(a.Cipher.(*AEADCipher).AEADAuthCreator).Pointer() {
|
||||||
|
case reflect.ValueOf(createAesGcm).Pointer():
|
||||||
|
keyBytes := a.Cipher.(*AEADCipher).KeyBytes
|
||||||
|
return "AES_" + strconv.FormatInt(int64(keyBytes*8), 10) + "_GCM"
|
||||||
|
case reflect.ValueOf(createChacha20Poly1305).Pointer():
|
||||||
|
return "CHACHA20_POLY1305"
|
||||||
|
}
|
||||||
|
case *NoneCipher:
|
||||||
|
return "NONE"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func createAesGcm(key []byte) cipher.AEAD {
|
func createAesGcm(key []byte) cipher.AEAD {
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
@@ -154,13 +154,8 @@ type ServerConfig struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// UdpEnabled specified whether or not to enable UDP for Shadowsocks.
|
Users []*protocol.User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
|
||||||
// Deprecated. Use 'network' field.
|
Network []net.Network `protobuf:"varint,2,rep,packed,name=network,proto3,enum=xray.common.net.Network" json:"network,omitempty"`
|
||||||
//
|
|
||||||
// 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"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ServerConfig) Reset() {
|
func (x *ServerConfig) Reset() {
|
||||||
@@ -195,17 +190,9 @@ func (*ServerConfig) Descriptor() ([]byte, []int) {
|
|||||||
return file_proxy_shadowsocks_config_proto_rawDescGZIP(), []int{1}
|
return file_proxy_shadowsocks_config_proto_rawDescGZIP(), []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Do not use.
|
func (x *ServerConfig) GetUsers() []*protocol.User {
|
||||||
func (x *ServerConfig) GetUdpEnabled() bool {
|
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.UdpEnabled
|
return x.Users
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ServerConfig) GetUser() *protocol.User {
|
|
||||||
if x != nil {
|
|
||||||
return x.User
|
|
||||||
}
|
}
|
||||||
return nil
|
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,
|
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,
|
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,
|
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,
|
0x65, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x22, 0x74, 0x0a,
|
||||||
0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23,
|
0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a,
|
||||||
0x0a, 0x0b, 0x75, 0x64, 0x70, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20,
|
0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78,
|
||||||
0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x75, 0x64, 0x70, 0x45, 0x6e, 0x61, 0x62,
|
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x6c, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28,
|
0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12,
|
||||||
0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
0x32, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e,
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75,
|
0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e,
|
||||||
0x73, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x03,
|
0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77,
|
||||||
0x20, 0x03, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
0x6f, 0x72, 0x6b, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
|
||||||
0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07,
|
0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20,
|
||||||
0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e,
|
0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||||
0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65,
|
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||||
0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65,
|
||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53,
|
0x72, 0x2a, 0x9f, 0x01, 0x0a, 0x0a, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65,
|
||||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73,
|
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a,
|
||||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x2a, 0x9f, 0x01, 0x0a, 0x0a, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72,
|
0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x43, 0x46, 0x42, 0x10, 0x01, 0x12, 0x0f,
|
||||||
0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
|
0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x43, 0x46, 0x42, 0x10, 0x02, 0x12,
|
||||||
0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x43, 0x46, 0x42,
|
0x0c, 0x0a, 0x08, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x10, 0x03, 0x12, 0x11, 0x0a,
|
||||||
0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x43, 0x46,
|
0x0d, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x49, 0x45, 0x54, 0x46, 0x10, 0x04,
|
||||||
0x42, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x10,
|
0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f, 0x47, 0x43, 0x4d, 0x10,
|
||||||
0x03, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x49, 0x45,
|
0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36, 0x5f, 0x47, 0x43, 0x4d,
|
||||||
0x54, 0x46, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x31, 0x32, 0x38, 0x5f,
|
0x10, 0x06, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41, 0x32, 0x30, 0x5f, 0x50,
|
||||||
0x47, 0x43, 0x4d, 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x45, 0x53, 0x5f, 0x32, 0x35, 0x36,
|
0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x10, 0x07, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e,
|
||||||
0x5f, 0x47, 0x43, 0x4d, 0x10, 0x06, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x43, 0x48, 0x41,
|
0x45, 0x10, 0x08, 0x42, 0x64, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x32, 0x30, 0x5f, 0x50, 0x4f, 0x4c, 0x59, 0x31, 0x33, 0x30, 0x35, 0x10, 0x07, 0x12, 0x08, 0x0a,
|
0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b,
|
||||||
0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x08, 0x42, 0x64, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
0x73, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77,
|
0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70,
|
||||||
0x73, 0x6f, 0x63, 0x6b, 0x73, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73,
|
||||||
0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
|
0xaa, 0x02, 0x16, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x53, 0x68,
|
||||||
0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73,
|
0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x6f, 0x63, 0x6b, 0x73, 0xaa, 0x02, 0x16, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78,
|
0x33,
|
||||||
0x79, 0x2e, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x62, 0x06, 0x70,
|
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -342,7 +327,7 @@ var file_proxy_shadowsocks_config_proto_goTypes = []interface{}{
|
|||||||
}
|
}
|
||||||
var file_proxy_shadowsocks_config_proto_depIdxs = []int32{
|
var file_proxy_shadowsocks_config_proto_depIdxs = []int32{
|
||||||
0, // 0: xray.proxy.shadowsocks.Account.cipher_type:type_name -> xray.proxy.shadowsocks.CipherType
|
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
|
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
|
6, // 3: xray.proxy.shadowsocks.ClientConfig.server:type_name -> xray.common.protocol.ServerEndpoint
|
||||||
4, // [4:4] is the sub-list for method output_type
|
4, // [4:4] is the sub-list for method output_type
|
||||||
|
@@ -28,11 +28,8 @@ enum CipherType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message ServerConfig {
|
message ServerConfig {
|
||||||
// UdpEnabled specified whether or not to enable UDP for Shadowsocks.
|
repeated xray.common.protocol.User users = 1;
|
||||||
// Deprecated. Use 'network' field.
|
repeated xray.common.net.Network network = 2;
|
||||||
bool udp_enabled = 1 [deprecated = true];
|
|
||||||
xray.common.protocol.User user = 2;
|
|
||||||
repeated xray.common.net.Network network = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message ClientConfig {
|
message ClientConfig {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package shadowsocks
|
package shadowsocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/cipher"
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
@@ -10,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"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/dice"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
@@ -28,12 +30,33 @@ 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.
|
// 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(validator *Validator, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
|
||||||
account := user.Account.(*MemoryAccount)
|
|
||||||
|
|
||||||
hashkdf := hmac.New(sha256.New, []byte("SSBSKDF"))
|
hashkdf := hmac.New(sha256.New, []byte("SSBSKDF"))
|
||||||
hashkdf.Write(account.Key)
|
|
||||||
|
|
||||||
behaviorSeed := crc32.ChecksumIEEE(hashkdf.Sum(nil))
|
behaviorSeed := crc32.ChecksumIEEE(hashkdf.Sum(nil))
|
||||||
|
|
||||||
@@ -44,28 +67,69 @@ func ReadTCPSession(user *protocol.MemoryUser, reader io.Reader) (*protocol.Requ
|
|||||||
DrainSize := BaseDrainSize + 16 + 38 + RandDrainRolled
|
DrainSize := BaseDrainSize + 16 + 38 + RandDrainRolled
|
||||||
readSizeRemain := DrainSize
|
readSizeRemain := DrainSize
|
||||||
|
|
||||||
|
var r2 buf.Reader
|
||||||
buffer := buf.New()
|
buffer := buf.New()
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
|
|
||||||
ivLen := account.Cipher.IVSize()
|
var user *protocol.MemoryUser
|
||||||
var iv []byte
|
var ivLen int32
|
||||||
if ivLen > 0 {
|
var err error
|
||||||
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)...)
|
count := validator.Count()
|
||||||
}
|
if count == 0 {
|
||||||
|
|
||||||
r, err := account.Cipher.NewDecryptionReader(account.Key, iv, reader)
|
|
||||||
if err != nil {
|
|
||||||
readSizeRemain -= int(buffer.Len())
|
readSizeRemain -= int(buffer.Len())
|
||||||
DrainConnN(reader, readSizeRemain)
|
DrainConnN(reader, readSizeRemain)
|
||||||
return nil, nil, newError("failed to initialize decoding stream").Base(err).AtError()
|
return nil, nil, newError("invalid user")
|
||||||
|
} else if count > 1 {
|
||||||
|
var aead cipher.AEAD
|
||||||
|
|
||||||
|
if _, err := buffer.ReadFullFrom(reader, 50); err != nil {
|
||||||
|
readSizeRemain -= int(buffer.Len())
|
||||||
|
DrainConnN(reader, readSizeRemain)
|
||||||
|
return nil, nil, newError("failed to read 50 bytes").Base(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
bs := buffer.Bytes()
|
||||||
|
user, aead, _, ivLen, err = validator.Get(bs, protocol.RequestCommandTCP)
|
||||||
|
|
||||||
|
if user != 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)
|
||||||
|
} else {
|
||||||
|
readSizeRemain -= int(buffer.Len())
|
||||||
|
DrainConnN(reader, readSizeRemain)
|
||||||
|
return nil, nil, newError("failed to match an user").Base(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
user, ivLen = validator.GetOnlyUser()
|
||||||
|
account := user.Account.(*MemoryAccount)
|
||||||
|
hashkdf.Write(account.Key)
|
||||||
|
var iv []byte
|
||||||
|
if ivLen > 0 {
|
||||||
|
if _, err := buffer.ReadFullFrom(reader, ivLen); err != nil {
|
||||||
|
readSizeRemain -= int(buffer.Len())
|
||||||
|
DrainConnN(reader, readSizeRemain)
|
||||||
|
return nil, nil, newError("failed to read IV").Base(err)
|
||||||
|
}
|
||||||
|
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
|
||||||
}
|
}
|
||||||
br := &buf.BufferedReader{Reader: r}
|
|
||||||
|
br := &buf.BufferedReader{Reader: r2}
|
||||||
|
|
||||||
request := &protocol.RequestHeader{
|
request := &protocol.RequestHeader{
|
||||||
Version: Version,
|
Version: Version,
|
||||||
@@ -185,18 +249,41 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buff
|
|||||||
return buffer, nil
|
return buffer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecodeUDPPacket(user *protocol.MemoryUser, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
|
func DecodeUDPPacket(validator *Validator, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
|
||||||
account := user.Account.(*MemoryAccount)
|
bs := payload.Bytes()
|
||||||
|
if len(bs) <= 32 {
|
||||||
var iv []byte
|
return nil, nil, newError("len(bs) <= 32")
|
||||||
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 err := account.Cipher.DecodePacket(account.Key, payload); err != nil {
|
var user *protocol.MemoryUser
|
||||||
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
|
var err error
|
||||||
|
|
||||||
|
count := validator.Count()
|
||||||
|
if count == 0 {
|
||||||
|
return nil, nil, newError("invalid user")
|
||||||
|
} else if count > 1 {
|
||||||
|
var d []byte
|
||||||
|
user, _, d, _, err = validator.Get(bs, protocol.RequestCommandUDP)
|
||||||
|
|
||||||
|
if user != nil {
|
||||||
|
payload.Clear()
|
||||||
|
payload.Write(d)
|
||||||
|
} else {
|
||||||
|
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
user, _ = validator.GetOnlyUser()
|
||||||
|
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()))
|
||||||
|
}
|
||||||
|
if err = account.Cipher.DecodePacket(account.Key, payload); err != nil {
|
||||||
|
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request := &protocol.RequestHeader{
|
request := &protocol.RequestHeader{
|
||||||
@@ -230,7 +317,10 @@ func (v *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|||||||
buffer.Release()
|
buffer.Release()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
u, payload, err := DecodeUDPPacket(v.User, buffer)
|
validator := new(Validator)
|
||||||
|
validator.Add(v.User)
|
||||||
|
|
||||||
|
u, payload, err := DecodeUDPPacket(validator, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
buffer.Release()
|
buffer.Release()
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -28,7 +28,7 @@ func TestUDPEncoding(t *testing.T) {
|
|||||||
Email: "love@example.com",
|
Email: "love@example.com",
|
||||||
Account: toAccount(&Account{
|
Account: toAccount(&Account{
|
||||||
Password: "shadowsocks-password",
|
Password: "shadowsocks-password",
|
||||||
CipherType: CipherType_AES_128_CFB,
|
CipherType: CipherType_AES_128_GCM,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -38,14 +38,16 @@ func TestUDPEncoding(t *testing.T) {
|
|||||||
encodedData, err := EncodeUDPPacket(request, data.Bytes())
|
encodedData, err := EncodeUDPPacket(request, data.Bytes())
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
decodedRequest, decodedData, err := DecodeUDPPacket(request.User, encodedData)
|
validator := new(Validator)
|
||||||
|
validator.Add(request.User)
|
||||||
|
decodedRequest, decodedData, err := DecodeUDPPacket(validator, encodedData)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
if r := cmp.Diff(decodedData.Bytes(), data.Bytes()); r != "" {
|
if r := cmp.Diff(decodedData.Bytes(), data.Bytes()); r != "" {
|
||||||
t.Error("data: ", r)
|
t.Error("data: ", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r := cmp.Diff(decodedRequest, request); r != "" {
|
if r := cmp.Diff(decodedRequest, request, cmp.Comparer(func(a1, a2 protocol.Account) bool { return a1.Equals(a2) })); r != "" {
|
||||||
t.Error("request: ", r)
|
t.Error("request: ", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +67,7 @@ func TestTCPRequest(t *testing.T) {
|
|||||||
Email: "love@example.com",
|
Email: "love@example.com",
|
||||||
Account: toAccount(&Account{
|
Account: toAccount(&Account{
|
||||||
Password: "tcp-password",
|
Password: "tcp-password",
|
||||||
CipherType: CipherType_CHACHA20,
|
CipherType: CipherType_CHACHA20_POLY1305,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -81,7 +83,7 @@ func TestTCPRequest(t *testing.T) {
|
|||||||
Email: "love@example.com",
|
Email: "love@example.com",
|
||||||
Account: toAccount(&Account{
|
Account: toAccount(&Account{
|
||||||
Password: "password",
|
Password: "password",
|
||||||
CipherType: CipherType_AES_256_CFB,
|
CipherType: CipherType_AES_256_GCM,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -97,7 +99,7 @@ func TestTCPRequest(t *testing.T) {
|
|||||||
Email: "love@example.com",
|
Email: "love@example.com",
|
||||||
Account: toAccount(&Account{
|
Account: toAccount(&Account{
|
||||||
Password: "password",
|
Password: "password",
|
||||||
CipherType: CipherType_CHACHA20_IETF,
|
CipherType: CipherType_AES_128_GCM,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -117,9 +119,11 @@ func TestTCPRequest(t *testing.T) {
|
|||||||
|
|
||||||
common.Must(writer.WriteMultiBuffer(buf.MultiBuffer{data}))
|
common.Must(writer.WriteMultiBuffer(buf.MultiBuffer{data}))
|
||||||
|
|
||||||
decodedRequest, reader, err := ReadTCPSession(request.User, cache)
|
validator := new(Validator)
|
||||||
|
validator.Add(request.User)
|
||||||
|
decodedRequest, reader, err := ReadTCPSession(validator, cache)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if r := cmp.Diff(decodedRequest, request); r != "" {
|
if r := cmp.Diff(decodedRequest, request, cmp.Comparer(func(a1, a2 protocol.Account) bool { return a1.Equals(a2) })); r != "" {
|
||||||
t.Error("request: ", r)
|
t.Error("request: ", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +143,7 @@ func TestUDPReaderWriter(t *testing.T) {
|
|||||||
user := &protocol.MemoryUser{
|
user := &protocol.MemoryUser{
|
||||||
Account: toAccount(&Account{
|
Account: toAccount(&Account{
|
||||||
Password: "test-password",
|
Password: "test-password",
|
||||||
CipherType: CipherType_CHACHA20_IETF,
|
CipherType: CipherType_CHACHA20_POLY1305,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
cache := buf.New()
|
cache := buf.New()
|
||||||
|
@@ -22,26 +22,29 @@ import (
|
|||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
config *ServerConfig
|
config *ServerConfig
|
||||||
user *protocol.MemoryUser
|
validator *Validator
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
cone bool
|
cone bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer create a new Shadowsocks server.
|
// NewServer create a new Shadowsocks server.
|
||||||
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||||
if config.GetUser() == nil {
|
validator := new(Validator)
|
||||||
return nil, newError("user is not specified")
|
for _, user := range config.Users {
|
||||||
}
|
u, err := user.ToMemoryUser()
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to get shadowsocks user").Base(err).AtError()
|
||||||
|
}
|
||||||
|
|
||||||
mUser, err := config.User.ToMemoryUser()
|
if err := validator.Add(u); err != nil {
|
||||||
if err != nil {
|
return nil, newError("failed to add user").Base(err).AtError()
|
||||||
return nil, newError("failed to parse user account").Base(err)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
s := &Server{
|
s := &Server{
|
||||||
config: config,
|
config: config,
|
||||||
user: mUser,
|
validator: validator,
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
cone: ctx.Value("cone").(bool),
|
cone: ctx.Value("cone").(bool),
|
||||||
}
|
}
|
||||||
@@ -49,14 +52,21 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddUser implements proxy.UserManager.AddUser().
|
||||||
|
func (s *Server) AddUser(ctx context.Context, u *protocol.MemoryUser) error {
|
||||||
|
return s.validator.Add(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveUser implements proxy.UserManager.RemoveUser().
|
||||||
|
func (s *Server) RemoveUser(ctx context.Context, e string) error {
|
||||||
|
return s.validator.Del(e)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) Network() []net.Network {
|
func (s *Server) Network() []net.Network {
|
||||||
list := s.config.Network
|
list := s.config.Network
|
||||||
if len(list) == 0 {
|
if len(list) == 0 {
|
||||||
list = append(list, net.Network_TCP)
|
list = append(list, net.Network_TCP)
|
||||||
}
|
}
|
||||||
if s.config.UdpEnabled {
|
|
||||||
list = append(list, net.Network_UDP)
|
|
||||||
}
|
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,13 +75,13 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
|
|||||||
case net.Network_TCP:
|
case net.Network_TCP:
|
||||||
return s.handleConnection(ctx, conn, dispatcher)
|
return s.handleConnection(ctx, conn, dispatcher)
|
||||||
case net.Network_UDP:
|
case net.Network_UDP:
|
||||||
return s.handlerUDPPayload(ctx, conn, dispatcher)
|
return s.handleUDPPayload(ctx, conn, dispatcher)
|
||||||
default:
|
default:
|
||||||
return newError("unknown network: ", network)
|
return newError("unknown network: ", network)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection, dispatcher routing.Dispatcher) error {
|
func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection, dispatcher routing.Dispatcher) error {
|
||||||
udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
|
udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
|
||||||
request := protocol.RequestHeaderFromContext(ctx)
|
request := protocol.RequestHeaderFromContext(ctx)
|
||||||
if request == nil {
|
if request == nil {
|
||||||
@@ -103,7 +113,10 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
|
|||||||
if inbound == nil {
|
if inbound == nil {
|
||||||
panic("no inbound metadata")
|
panic("no inbound metadata")
|
||||||
}
|
}
|
||||||
inbound.User = s.user
|
|
||||||
|
if s.validator.Count() == 1 {
|
||||||
|
inbound.User, _ = s.validator.GetOnlyUser()
|
||||||
|
}
|
||||||
|
|
||||||
var dest *net.Destination
|
var dest *net.Destination
|
||||||
|
|
||||||
@@ -115,9 +128,23 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, payload := range mpayload {
|
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 {
|
||||||
|
validator := new(Validator)
|
||||||
|
validator.Add(inbound.User)
|
||||||
|
request, data, err = DecodeUDPPacket(validator, payload)
|
||||||
|
} else {
|
||||||
|
request, data, err = DecodeUDPPacket(s.validator, payload)
|
||||||
|
if err == nil {
|
||||||
|
inbound.User = request.User
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
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))
|
newError("dropping invalid UDP packet from: ", inbound.Source).Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
log.Record(&log.AccessMessage{
|
log.Record(&log.AccessMessage{
|
||||||
From: inbound.Source,
|
From: inbound.Source,
|
||||||
@@ -159,11 +186,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 {
|
func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, dispatcher routing.Dispatcher) error {
|
||||||
sessionPolicy := s.policyManager.ForLevel(s.user.Level)
|
sessionPolicy := s.policyManager.ForLevel(0)
|
||||||
conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake))
|
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)}
|
bufferedReader := buf.BufferedReader{Reader: buf.NewReader(conn)}
|
||||||
request, bodyReader, err := ReadTCPSession(s.user, &bufferedReader)
|
request, bodyReader, err := ReadTCPSession(s.validator, &bufferedReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Record(&log.AccessMessage{
|
log.Record(&log.AccessMessage{
|
||||||
From: conn.RemoteAddr(),
|
From: conn.RemoteAddr(),
|
||||||
@@ -179,7 +208,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
|
|||||||
if inbound == nil {
|
if inbound == nil {
|
||||||
panic("no inbound metadata")
|
panic("no inbound metadata")
|
||||||
}
|
}
|
||||||
inbound.User = s.user
|
inbound.User = request.User
|
||||||
|
|
||||||
dest := request.Destination()
|
dest := request.Destination()
|
||||||
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
||||||
@@ -191,6 +220,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
|
|||||||
})
|
})
|
||||||
newError("tunnelling request to ", dest).WriteToLog(session.ExportIDToError(ctx))
|
newError("tunnelling request to ", dest).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
|
||||||
|
sessionPolicy = s.policyManager.ForLevel(request.User.Level)
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||||
|
|
||||||
|
113
proxy/shadowsocks/validator.go
Normal file
113
proxy/shadowsocks/validator.go
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package shadowsocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/cipher"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Validator stores valid Shadowsocks users.
|
||||||
|
type Validator struct {
|
||||||
|
// Considering email's usage here, map + sync.Mutex/RWMutex may have better performance.
|
||||||
|
email sync.Map
|
||||||
|
users sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a Shadowsocks user, Email must be empty or unique.
|
||||||
|
func (v *Validator) Add(u *protocol.MemoryUser) error {
|
||||||
|
account := u.Account.(*MemoryAccount)
|
||||||
|
|
||||||
|
if !account.Cipher.IsAEAD() && v.Count() > 0 {
|
||||||
|
return newError("The cipher do not support Single-port Multi-user")
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Email != "" {
|
||||||
|
_, loaded := v.email.LoadOrStore(strings.ToLower(u.Email), u)
|
||||||
|
if loaded {
|
||||||
|
return newError("User ", u.Email, " already exists.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v.users.Store(string(account.Key)+"&"+account.GetCipherName(), u)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Del a Shadowsocks user with a non-empty Email.
|
||||||
|
func (v *Validator) Del(e string) error {
|
||||||
|
if e == "" {
|
||||||
|
return newError("Email must not be empty.")
|
||||||
|
}
|
||||||
|
le := strings.ToLower(e)
|
||||||
|
u, _ := v.email.Load(le)
|
||||||
|
if u == nil {
|
||||||
|
return newError("User ", e, " not found.")
|
||||||
|
}
|
||||||
|
account := u.(*protocol.MemoryUser).Account.(*MemoryAccount)
|
||||||
|
v.email.Delete(le)
|
||||||
|
v.users.Delete(string(account.Key) + "&" + account.GetCipherName())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the number of Shadowsocks users
|
||||||
|
func (v *Validator) Count() int {
|
||||||
|
length := 0
|
||||||
|
v.users.Range(func(_, _ interface{}) bool {
|
||||||
|
length++
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return length
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a Shadowsocks user and the user's cipher.
|
||||||
|
func (v *Validator) Get(bs []byte, command protocol.RequestCommand) (u *protocol.MemoryUser, aead cipher.AEAD, ret []byte, ivLen int32, err error) {
|
||||||
|
var dataSize int
|
||||||
|
|
||||||
|
switch command {
|
||||||
|
case protocol.RequestCommandTCP:
|
||||||
|
dataSize = 16
|
||||||
|
case protocol.RequestCommandUDP:
|
||||||
|
dataSize = 8192
|
||||||
|
}
|
||||||
|
|
||||||
|
var aeadCipher *AEADCipher
|
||||||
|
subkey := make([]byte, 32)
|
||||||
|
data := make([]byte, dataSize)
|
||||||
|
|
||||||
|
v.users.Range(func(key, user interface{}) bool {
|
||||||
|
account := user.(*protocol.MemoryUser).Account.(*MemoryAccount)
|
||||||
|
aeadCipher = account.Cipher.(*AEADCipher)
|
||||||
|
ivLen = aeadCipher.IVSize()
|
||||||
|
subkey = subkey[:aeadCipher.KeyBytes]
|
||||||
|
hkdfSHA1(account.Key, bs[:ivLen], subkey)
|
||||||
|
aead = aeadCipher.AEADAuthCreator(subkey)
|
||||||
|
|
||||||
|
switch command {
|
||||||
|
case protocol.RequestCommandTCP:
|
||||||
|
ret, err = aead.Open(data[:0], data[4:16], bs[ivLen:ivLen+18], nil)
|
||||||
|
case protocol.RequestCommandUDP:
|
||||||
|
ret, err = aead.Open(data[:0], data[8180:8192], bs[ivLen:], nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
u = user.(*protocol.MemoryUser)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the only user without authentication
|
||||||
|
func (v *Validator) GetOnlyUser() (u *protocol.MemoryUser, ivLen int32) {
|
||||||
|
v.users.Range(func(_, user interface{}) bool {
|
||||||
|
u = user.(*protocol.MemoryUser)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
ivLen = u.Account.(*MemoryAccount).Cipher.IVSize()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
@@ -422,16 +422,6 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
|
|||||||
defer b.Release()
|
defer b.Release()
|
||||||
|
|
||||||
common.Must2(b.Write([]byte{socks5Version, 0x01, authByte}))
|
common.Must2(b.Write([]byte{socks5Version, 0x01, authByte}))
|
||||||
if authByte == authPassword {
|
|
||||||
account := request.User.Account.(*Account)
|
|
||||||
|
|
||||||
common.Must(b.WriteByte(0x01))
|
|
||||||
common.Must(b.WriteByte(byte(len(account.Username))))
|
|
||||||
common.Must2(b.WriteString(account.Username))
|
|
||||||
common.Must(b.WriteByte(byte(len(account.Password))))
|
|
||||||
common.Must2(b.WriteString(account.Password))
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {
|
if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -449,6 +439,17 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
|
|||||||
}
|
}
|
||||||
|
|
||||||
if authByte == authPassword {
|
if authByte == authPassword {
|
||||||
|
b.Clear()
|
||||||
|
account := request.User.Account.(*Account)
|
||||||
|
common.Must(b.WriteByte(0x01))
|
||||||
|
common.Must(b.WriteByte(byte(len(account.Username))))
|
||||||
|
common.Must2(b.WriteString(account.Username))
|
||||||
|
common.Must(b.WriteByte(byte(len(account.Password))))
|
||||||
|
common.Must2(b.WriteString(account.Password))
|
||||||
|
if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
b.Clear()
|
b.Clear()
|
||||||
if _, err := b.ReadFullFrom(reader, 2); err != nil {
|
if _, err := b.ReadFullFrom(reader, 2); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -465,8 +466,12 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
|
|||||||
command = byte(cmdUDPAssociate)
|
command = byte(cmdUDPAssociate)
|
||||||
}
|
}
|
||||||
common.Must2(b.Write([]byte{socks5Version, command, 0x00 /* reserved */}))
|
common.Must2(b.Write([]byte{socks5Version, command, 0x00 /* reserved */}))
|
||||||
if err := addrParser.WriteAddressPort(b, request.Address, request.Port); err != nil {
|
if request.Command == protocol.RequestCommandUDP {
|
||||||
return nil, err
|
common.Must2(b.Write([]byte{1, 0, 0, 0, 0, 0, 0 /* RFC 1928 */}))
|
||||||
|
} else {
|
||||||
|
if err := addrParser.WriteAddressPort(b, request.Address, request.Port); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {
|
if err := buf.WriteAllBytes(writer, b.Bytes()); err != nil {
|
||||||
|
@@ -86,11 +86,12 @@ type Fallback struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Alpn string `protobuf:"bytes,1,opt,name=alpn,proto3" json:"alpn,omitempty"`
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
Alpn string `protobuf:"bytes,2,opt,name=alpn,proto3" json:"alpn,omitempty"`
|
||||||
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
|
Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
|
||||||
Dest string `protobuf:"bytes,4,opt,name=dest,proto3" json:"dest,omitempty"`
|
Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"`
|
||||||
Xver uint64 `protobuf:"varint,5,opt,name=xver,proto3" json:"xver,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() {
|
func (x *Fallback) Reset() {
|
||||||
@@ -125,6 +126,13 @@ func (*Fallback) Descriptor() ([]byte, []int) {
|
|||||||
return file_proxy_trojan_config_proto_rawDescGZIP(), []int{1}
|
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 {
|
func (x *Fallback) GetAlpn() string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Alpn
|
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,
|
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, 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,
|
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,
|
0x28, 0x09, 0x52, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0x82, 0x01, 0x0a, 0x08, 0x46, 0x61, 0x6c,
|
||||||
0x62, 0x61, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x18, 0x01, 0x20, 0x01,
|
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
|
||||||
0x28, 0x09, 0x52, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68,
|
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x6c, 0x70,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04,
|
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x12, 0x12, 0x0a,
|
||||||
0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74,
|
||||||
0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01,
|
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20,
|
||||||
0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65,
|
0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65,
|
||||||
0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76,
|
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a,
|
||||||
0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a,
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e,
|
0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
|
||||||
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f,
|
||||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18,
|
0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x0c, 0x53,
|
||||||
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x05, 0x75,
|
||||||
0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65,
|
0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61,
|
||||||
0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x09, 0x66, 0x61, 0x6c, 0x6c,
|
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||||
0x62, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72,
|
0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a,
|
||||||
0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x2e,
|
0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
|
||||||
0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61,
|
0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72,
|
||||||
0x63, 0x6b, 0x73, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x6f, 0x6a, 0x61, 0x6e, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x09, 0x66,
|
||||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26,
|
0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e,
|
||||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, 0x61,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f,
|
0x6e, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||||
0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72,
|
0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70,
|
||||||
0x6f, 0x78, 0x79, 0x2e, 0x54, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
0x72, 0x6f, 0x78, 0x79, 0x2f, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72,
|
||||||
0x6f, 0x33,
|
0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x54, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x62,
|
||||||
|
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -15,11 +15,12 @@ message Account {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message Fallback {
|
message Fallback {
|
||||||
string alpn = 1;
|
string name = 1;
|
||||||
string path = 2;
|
string alpn = 2;
|
||||||
string type = 3;
|
string path = 3;
|
||||||
string dest = 4;
|
string type = 4;
|
||||||
uint64 xver = 5;
|
string dest = 5;
|
||||||
|
uint64 xver = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ClientConfig {
|
message ClientConfig {
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ func init() {
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
validator *Validator
|
validator *Validator
|
||||||
fallbacks map[string]map[string]*Fallback // or nil
|
fallbacks map[string]map[string]map[string]*Fallback // or nil
|
||||||
cone bool
|
cone bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,19 +73,48 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.Fallbacks != nil {
|
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 {
|
for _, fb := range config.Fallbacks {
|
||||||
if server.fallbacks[fb.Alpn] == nil {
|
if server.fallbacks[fb.Name] == nil {
|
||||||
server.fallbacks[fb.Alpn] = make(map[string]*Fallback)
|
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 {
|
if server.fallbacks[""] != nil {
|
||||||
for alpn, pfb := range server.fallbacks {
|
for name, apfb := range server.fallbacks {
|
||||||
if alpn != "" { // && alpn != "h2" {
|
if name != "" {
|
||||||
for path, fb := range server.fallbacks[""] {
|
for alpn := range server.fallbacks[""] {
|
||||||
if pfb[path] == nil {
|
if apfb[alpn] == nil {
|
||||||
pfb[path] = fb
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,8 +171,8 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
|
|||||||
|
|
||||||
var user *protocol.MemoryUser
|
var user *protocol.MemoryUser
|
||||||
|
|
||||||
apfb := s.fallbacks
|
napfb := s.fallbacks
|
||||||
isfb := apfb != nil
|
isfb := napfb != nil
|
||||||
|
|
||||||
shouldFallback := false
|
shouldFallback := false
|
||||||
if firstLen < 58 || first.Byte(56) != '\r' {
|
if firstLen < 58 || first.Byte(56) != '\r' {
|
||||||
@@ -173,7 +203,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isfb && shouldFallback {
|
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 {
|
} else if shouldFallback {
|
||||||
return newError("invalid protocol or invalid user")
|
return newError("invalid protocol or invalid user")
|
||||||
}
|
}
|
||||||
@@ -361,25 +391,53 @@ func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Sess
|
|||||||
return nil
|
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 {
|
if err := connection.SetReadDeadline(time.Time{}); err != nil {
|
||||||
newError("unable to set back read deadline").Base(err).AtWarning().WriteToLog(sid)
|
newError("unable to set back read deadline").Base(err).AtWarning().WriteToLog(sid)
|
||||||
}
|
}
|
||||||
newError("fallback starts").Base(err).AtInfo().WriteToLog(sid)
|
newError("fallback starts").Base(err).AtInfo().WriteToLog(sid)
|
||||||
|
|
||||||
|
name := ""
|
||||||
alpn := ""
|
alpn := ""
|
||||||
if len(apfb) > 1 || apfb[""] == nil {
|
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
||||||
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
cs := tlsConn.ConnectionState()
|
||||||
alpn = tlsConn.ConnectionState().NegotiatedProtocol
|
name = cs.ServerName
|
||||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
alpn = cs.NegotiatedProtocol
|
||||||
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
|
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
||||||
alpn = xtlsConn.ConnectionState().NegotiatedProtocol
|
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
||||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
|
||||||
}
|
cs := xtlsConn.ConnectionState()
|
||||||
if apfb[alpn] == nil {
|
name = cs.ServerName
|
||||||
alpn = ""
|
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]
|
pfb := apfb[alpn]
|
||||||
if pfb == nil {
|
if pfb == nil {
|
||||||
return newError(`failed to find the default "alpn" config`).AtWarning()
|
return newError(`failed to find the default "alpn" config`).AtWarning()
|
||||||
@@ -442,38 +500,48 @@ func (s *Server) fallback(ctx context.Context, sid errors.ExportOption, err erro
|
|||||||
postRequest := func() error {
|
postRequest := func() error {
|
||||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||||
if fb.Xver != 0 {
|
if fb.Xver != 0 {
|
||||||
|
ipType := 4
|
||||||
remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String())
|
remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
ipType = 0
|
||||||
}
|
}
|
||||||
localAddr, localPort, err := net.SplitHostPort(connection.LocalAddr().String())
|
localAddr, localPort, err := net.SplitHostPort(connection.LocalAddr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
ipType = 0
|
||||||
}
|
}
|
||||||
ipv4 := true
|
if ipType == 4 {
|
||||||
for i := 0; i < len(remoteAddr); i++ {
|
for i := 0; i < len(remoteAddr); i++ {
|
||||||
if remoteAddr[i] == ':' {
|
if remoteAddr[i] == ':' {
|
||||||
ipv4 = false
|
ipType = 6
|
||||||
break
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pro := buf.New()
|
pro := buf.New()
|
||||||
defer pro.Release()
|
defer pro.Release()
|
||||||
switch fb.Xver {
|
switch fb.Xver {
|
||||||
case 1:
|
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")))
|
common.Must2(pro.Write([]byte("PROXY TCP4 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n")))
|
||||||
} else {
|
} else {
|
||||||
common.Must2(pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n")))
|
common.Must2(pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n")))
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
common.Must2(pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21"))) // signature + v2 + PROXY
|
common.Must2(pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"))) // signature
|
||||||
if ipv4 {
|
if ipType == 0 {
|
||||||
common.Must2(pro.Write([]byte("\x11\x00\x0C"))) // AF_INET + STREAM + 12 bytes
|
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(remoteAddr).To4()))
|
||||||
common.Must2(pro.Write(net.ParseIP(localAddr).To4()))
|
common.Must2(pro.Write(net.ParseIP(localAddr).To4()))
|
||||||
} else {
|
} 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(remoteAddr).To16()))
|
||||||
common.Must2(pro.Write(net.ParseIP(localAddr).To16()))
|
common.Must2(pro.Write(net.ParseIP(localAddr).To16()))
|
||||||
}
|
}
|
||||||
|
@@ -278,10 +278,7 @@ func (m *Addons) Unmarshal(dAtA []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if skippy < 0 {
|
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||||
return ErrInvalidLengthAddons
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) < 0 {
|
|
||||||
return ErrInvalidLengthAddons
|
return ErrInvalidLengthAddons
|
||||||
}
|
}
|
||||||
if (iNdEx + skippy) > l {
|
if (iNdEx + skippy) > l {
|
||||||
|
@@ -232,6 +232,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
|
|||||||
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
||||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
||||||
}
|
}
|
||||||
|
name = strings.ToLower(name)
|
||||||
|
alpn = strings.ToLower(alpn)
|
||||||
|
|
||||||
if len(napfb) > 1 || napfb[""] == nil {
|
if len(napfb) > 1 || napfb[""] == nil {
|
||||||
if name != "" && napfb[name] == nil {
|
if name != "" && napfb[name] == nil {
|
||||||
@@ -333,39 +335,48 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
|
|||||||
postRequest := func() error {
|
postRequest := func() error {
|
||||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||||
if fb.Xver != 0 {
|
if fb.Xver != 0 {
|
||||||
|
ipType := 4
|
||||||
remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String())
|
remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
ipType = 0
|
||||||
}
|
}
|
||||||
localAddr, localPort, err := net.SplitHostPort(connection.LocalAddr().String())
|
localAddr, localPort, err := net.SplitHostPort(connection.LocalAddr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
ipType = 0
|
||||||
}
|
}
|
||||||
ipv4 := true
|
if ipType == 4 {
|
||||||
for i := 0; i < len(remoteAddr); i++ {
|
for i := 0; i < len(remoteAddr); i++ {
|
||||||
if remoteAddr[i] == ':' {
|
if remoteAddr[i] == ':' {
|
||||||
ipv4 = false
|
ipType = 6
|
||||||
break
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pro := buf.New()
|
pro := buf.New()
|
||||||
defer pro.Release()
|
defer pro.Release()
|
||||||
switch fb.Xver {
|
switch fb.Xver {
|
||||||
case 1:
|
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"))
|
pro.Write([]byte("PROXY TCP4 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n"))
|
||||||
} else {
|
} else {
|
||||||
pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n"))
|
pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21")) // signature + v2 + PROXY
|
pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A")) // signature
|
||||||
if ipv4 {
|
if ipType == 0 {
|
||||||
pro.Write([]byte("\x11\x00\x0C")) // AF_INET + STREAM + 12 bytes
|
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(remoteAddr).To4())
|
||||||
pro.Write(net.ParseIP(localAddr).To4())
|
pro.Write(net.ParseIP(localAddr).To4())
|
||||||
} else {
|
} 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(remoteAddr).To16())
|
||||||
pro.Write(net.ParseIP(localAddr).To16())
|
pro.Write(net.ParseIP(localAddr).To16())
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/common/signal"
|
"github.com/xtls/xray-core/common/signal"
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
|
"github.com/xtls/xray-core/common/xudp"
|
||||||
core "github.com/xtls/xray-core/core"
|
core "github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/policy"
|
"github.com/xtls/xray-core/features/policy"
|
||||||
"github.com/xtls/xray-core/features/stats"
|
"github.com/xtls/xray-core/features/stats"
|
||||||
@@ -48,6 +49,7 @@ type Handler struct {
|
|||||||
serverList *protocol.ServerList
|
serverList *protocol.ServerList
|
||||||
serverPicker protocol.ServerPicker
|
serverPicker protocol.ServerPicker
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
|
cone bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new VLess outbound handler.
|
// New creates a new VLess outbound handler.
|
||||||
@@ -66,6 +68,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
|||||||
serverList: serverList,
|
serverList: serverList,
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
|
cone: ctx.Value("cone").(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
return handler, nil
|
return handler, nil
|
||||||
@@ -175,6 +178,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
clientReader := link.Reader // .(*pipe.Reader)
|
clientReader := link.Reader // .(*pipe.Reader)
|
||||||
clientWriter := link.Writer // .(*pipe.Writer)
|
clientWriter := link.Writer // .(*pipe.Writer)
|
||||||
|
|
||||||
|
if request.Command == protocol.RequestCommandUDP && h.cone {
|
||||||
|
request.Command = protocol.RequestCommandMux
|
||||||
|
request.Address = net.DomainAddress("v1.mux.cool")
|
||||||
|
request.Port = net.Port(666)
|
||||||
|
}
|
||||||
|
|
||||||
postRequest := func() error {
|
postRequest := func() error {
|
||||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||||
|
|
||||||
@@ -185,6 +194,9 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
|
|
||||||
// default: serverWriter := bufferWriter
|
// default: serverWriter := bufferWriter
|
||||||
serverWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons)
|
serverWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons)
|
||||||
|
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||||
|
serverWriter = xudp.NewPacketWriter(serverWriter, target)
|
||||||
|
}
|
||||||
if err := buf.CopyOnceTimeout(clientReader, serverWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
|
if err := buf.CopyOnceTimeout(clientReader, serverWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
|
||||||
return err // ...
|
return err // ...
|
||||||
}
|
}
|
||||||
@@ -216,6 +228,9 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
|
|
||||||
// default: serverReader := buf.NewReader(conn)
|
// default: serverReader := buf.NewReader(conn)
|
||||||
serverReader := encoding.DecodeBodyAddons(conn, request, responseAddons)
|
serverReader := encoding.DecodeBodyAddons(conn, request, responseAddons)
|
||||||
|
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||||
|
serverReader = xudp.NewPacketReader(conn)
|
||||||
|
}
|
||||||
|
|
||||||
if rawConn != nil {
|
if rawConn != nil {
|
||||||
var counter stats.Counter
|
var counter stats.Counter
|
||||||
|
@@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/common/signal"
|
"github.com/xtls/xray-core/common/signal"
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
|
"github.com/xtls/xray-core/common/xudp"
|
||||||
core "github.com/xtls/xray-core/core"
|
core "github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/policy"
|
"github.com/xtls/xray-core/features/policy"
|
||||||
"github.com/xtls/xray-core/proxy/vmess"
|
"github.com/xtls/xray-core/proxy/vmess"
|
||||||
@@ -28,6 +29,7 @@ type Handler struct {
|
|||||||
serverList *protocol.ServerList
|
serverList *protocol.ServerList
|
||||||
serverPicker protocol.ServerPicker
|
serverPicker protocol.ServerPicker
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
|
cone bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new VMess outbound handler.
|
// New creates a new VMess outbound handler.
|
||||||
@@ -46,6 +48,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
|||||||
serverList: serverList,
|
serverList: serverList,
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
|
cone: ctx.Value("cone").(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
return handler, nil
|
return handler, nil
|
||||||
@@ -122,6 +125,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||||
|
|
||||||
|
if request.Command == protocol.RequestCommandUDP && h.cone {
|
||||||
|
request.Command = protocol.RequestCommandMux
|
||||||
|
request.Address = net.DomainAddress("v1.mux.cool")
|
||||||
|
request.Port = net.Port(666)
|
||||||
|
}
|
||||||
|
|
||||||
requestDone := func() error {
|
requestDone := func() error {
|
||||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||||
|
|
||||||
@@ -131,6 +140,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
}
|
}
|
||||||
|
|
||||||
bodyWriter := session.EncodeRequestBody(request, writer)
|
bodyWriter := session.EncodeRequestBody(request, writer)
|
||||||
|
bodyWriter2 := bodyWriter
|
||||||
|
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||||
|
bodyWriter = xudp.NewPacketWriter(bodyWriter, target)
|
||||||
|
}
|
||||||
if err := buf.CopyOnceTimeout(input, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
|
if err := buf.CopyOnceTimeout(input, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
|
||||||
return newError("failed to write first payload").Base(err)
|
return newError("failed to write first payload").Base(err)
|
||||||
}
|
}
|
||||||
@@ -144,7 +157,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
}
|
}
|
||||||
|
|
||||||
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
if err := bodyWriter.WriteMultiBuffer(buf.MultiBuffer{}); err != nil {
|
if err := bodyWriter2.WriteMultiBuffer(buf.MultiBuffer{}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,6 +176,9 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
h.handleCommand(rec.Destination(), header.Command)
|
h.handleCommand(rec.Destination(), header.Command)
|
||||||
|
|
||||||
bodyReader := session.DecodeResponseBody(request, reader)
|
bodyReader := session.DecodeResponseBody(request, reader)
|
||||||
|
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||||
|
bodyReader = xudp.NewPacketReader(&buf.BufferedReader{Reader: bodyReader})
|
||||||
|
}
|
||||||
|
|
||||||
return buf.Copy(bodyReader, output, buf.UpdateActivity(timer))
|
return buf.Copy(bodyReader, output, buf.UpdateActivity(timer))
|
||||||
}
|
}
|
||||||
|
@@ -118,7 +118,7 @@ func genTestBinaryPath() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetSourcePath() string {
|
func GetSourcePath() string {
|
||||||
return filepath.Join("example.com", "core", "main")
|
return filepath.Join("github.com", "xtls", "xray-core", "main")
|
||||||
}
|
}
|
||||||
|
|
||||||
func CloseAllServers(servers []*exec.Cmd) {
|
func CloseAllServers(servers []*exec.Cmd) {
|
||||||
|
@@ -17,6 +17,8 @@ func BuildXray() error {
|
|||||||
|
|
||||||
fmt.Printf("Building Xray into path (%s)\n", testBinaryPath)
|
fmt.Printf("Building Xray into path (%s)\n", testBinaryPath)
|
||||||
cmd := exec.Command("go", "build", "-o="+testBinaryPath, GetSourcePath())
|
cmd := exec.Command("go", "build", "-o="+testBinaryPath, GetSourcePath())
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,10 +52,10 @@ func TestShadowsocksAES256TCP(t *testing.T) {
|
|||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
||||||
User: &protocol.User{
|
Users: []*protocol.User{{
|
||||||
Account: account,
|
Account: account,
|
||||||
Level: 1,
|
Level: 1,
|
||||||
},
|
}},
|
||||||
Network: []net.Network{net.Network_TCP},
|
Network: []net.Network{net.Network_TCP},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -150,10 +150,10 @@ func TestShadowsocksAES128UDP(t *testing.T) {
|
|||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
||||||
User: &protocol.User{
|
Users: []*protocol.User{{
|
||||||
Account: account,
|
Account: account,
|
||||||
Level: 1,
|
Level: 1,
|
||||||
},
|
}},
|
||||||
Network: []net.Network{net.Network_UDP},
|
Network: []net.Network{net.Network_UDP},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -276,10 +276,10 @@ func TestShadowsocksChacha20TCP(t *testing.T) {
|
|||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
||||||
User: &protocol.User{
|
Users: []*protocol.User{{
|
||||||
Account: account,
|
Account: account,
|
||||||
Level: 1,
|
Level: 1,
|
||||||
},
|
}},
|
||||||
Network: []net.Network{net.Network_TCP},
|
Network: []net.Network{net.Network_TCP},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -369,10 +369,10 @@ func TestShadowsocksChacha20Poly1305TCP(t *testing.T) {
|
|||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
||||||
User: &protocol.User{
|
Users: []*protocol.User{{
|
||||||
Account: account,
|
Account: account,
|
||||||
Level: 1,
|
Level: 1,
|
||||||
},
|
}},
|
||||||
Network: []net.Network{net.Network_TCP},
|
Network: []net.Network{net.Network_TCP},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -461,10 +461,10 @@ func TestShadowsocksAES256GCMTCP(t *testing.T) {
|
|||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
||||||
User: &protocol.User{
|
Users: []*protocol.User{{
|
||||||
Account: account,
|
Account: account,
|
||||||
Level: 1,
|
Level: 1,
|
||||||
},
|
}},
|
||||||
Network: []net.Network{net.Network_TCP},
|
Network: []net.Network{net.Network_TCP},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -560,10 +560,10 @@ func TestShadowsocksAES128GCMUDP(t *testing.T) {
|
|||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
||||||
User: &protocol.User{
|
Users: []*protocol.User{{
|
||||||
Account: account,
|
Account: account,
|
||||||
Level: 1,
|
Level: 1,
|
||||||
},
|
}},
|
||||||
Network: []net.Network{net.Network_UDP},
|
Network: []net.Network{net.Network_UDP},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -658,10 +658,10 @@ func TestShadowsocksAES128GCMUDPMux(t *testing.T) {
|
|||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
||||||
User: &protocol.User{
|
Users: []*protocol.User{{
|
||||||
Account: account,
|
Account: account,
|
||||||
Level: 1,
|
Level: 1,
|
||||||
},
|
}},
|
||||||
Network: []net.Network{net.Network_TCP},
|
Network: []net.Network{net.Network_TCP},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -757,10 +757,10 @@ func TestShadowsocksNone(t *testing.T) {
|
|||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{
|
||||||
User: &protocol.User{
|
Users: []*protocol.User{{
|
||||||
Account: account,
|
Account: account,
|
||||||
Level: 1,
|
Level: 1,
|
||||||
},
|
}},
|
||||||
Network: []net.Network{net.Network_TCP},
|
Network: []net.Network{net.Network_TCP},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
@@ -2,10 +2,8 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -37,7 +35,6 @@ func (l *Listener) Addr() net.Addr {
|
|||||||
|
|
||||||
func (l *Listener) Close() error {
|
func (l *Listener) Close() error {
|
||||||
if l.locker != nil {
|
if l.locker != nil {
|
||||||
fmt.Fprintln(os.Stderr, "RELEASE LOCK")
|
|
||||||
l.locker.Release()
|
l.locker.Release()
|
||||||
}
|
}
|
||||||
return l.server.Close()
|
return l.server.Close()
|
||||||
@@ -89,11 +86,11 @@ func (l *Listener) ServeHTTP(writer http.ResponseWriter, request *http.Request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forwardedAddrs := http_proto.ParseXForwardedFor(request.Header)
|
forwardedAddress := http_proto.ParseXForwardedFor(request.Header)
|
||||||
if len(forwardedAddrs) > 0 && forwardedAddrs[0].Family().IsIP() {
|
if len(forwardedAddress) > 0 && forwardedAddress[0].Family().IsIP() {
|
||||||
remoteAddr = &net.TCPAddr{
|
remoteAddr = &net.TCPAddr{
|
||||||
IP: forwardedAddrs[0].IP(),
|
IP: forwardedAddress[0].IP(),
|
||||||
Port: int(0),
|
Port: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +162,7 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
|||||||
Net: "unix",
|
Net: "unix",
|
||||||
}, streamSettings.SocketSettings)
|
}, streamSettings.SocketSettings)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
locker := ctx.Value(address.Domain())
|
locker := ctx.Value(address.Domain())
|
||||||
@@ -178,7 +175,7 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
|||||||
Port: int(port),
|
Port: int(port),
|
||||||
}, streamSettings.SocketSettings)
|
}, streamSettings.SocketSettings)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,12 +183,12 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
|||||||
if config == nil {
|
if config == nil {
|
||||||
err = server.Serve(streamListener)
|
err = server.Serve(streamListener)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
newError("stoping serving H2C").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
newError("stopping serving H2C").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = server.ServeTLS(streamListener, "", "")
|
err = server.ServeTLS(streamListener, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
newError("stoping serving TLS").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
newError("stopping serving TLS").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/ocsp"
|
"github.com/xtls/xray-core/common/ocsp"
|
||||||
|
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||||
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
)
|
)
|
||||||
@@ -42,8 +43,8 @@ func (c *Config) loadSelfCertPool() (*x509.CertPool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BuildCertificates builds a list of TLS certificates from proto definition.
|
// BuildCertificates builds a list of TLS certificates from proto definition.
|
||||||
func (c *Config) BuildCertificates() []tls.Certificate {
|
func (c *Config) BuildCertificates() []*tls.Certificate {
|
||||||
certs := make([]tls.Certificate, 0, len(c.Certificate))
|
certs := make([]*tls.Certificate, 0, len(c.Certificate))
|
||||||
for _, entry := range c.Certificate {
|
for _, entry := range c.Certificate {
|
||||||
if entry.Usage != Certificate_ENCIPHERMENT {
|
if entry.Usage != Certificate_ENCIPHERMENT {
|
||||||
continue
|
continue
|
||||||
@@ -53,19 +54,54 @@ func (c *Config) BuildCertificates() []tls.Certificate {
|
|||||||
newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
|
newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
certs = append(certs, keyPair)
|
keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
|
||||||
|
if err != nil {
|
||||||
|
newError("ignoring invalid certificate").Base(err).AtWarning().WriteToLog()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
certs = append(certs, &keyPair)
|
||||||
if entry.OcspStapling != 0 {
|
if entry.OcspStapling != 0 {
|
||||||
go func(cert *tls.Certificate) {
|
index := len(certs) - 1
|
||||||
|
go func(cert *tls.Certificate, index int) {
|
||||||
t := time.NewTicker(time.Duration(entry.OcspStapling) * time.Second)
|
t := time.NewTicker(time.Duration(entry.OcspStapling) * time.Second)
|
||||||
for {
|
for {
|
||||||
if newData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
|
if entry.CertificatePath != "" && entry.KeyPath != "" {
|
||||||
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
|
newCert, err := filesystem.ReadFile(entry.CertificatePath)
|
||||||
} else if string(newData) != string(cert.OCSPStaple) {
|
if err != nil {
|
||||||
cert.OCSPStaple = newData
|
newError("failed to parse certificate").Base(err).AtError().WriteToLog()
|
||||||
|
<-t.C
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newKey, err := filesystem.ReadFile(entry.KeyPath)
|
||||||
|
if err != nil {
|
||||||
|
newError("failed to parse key").Base(err).AtError().WriteToLog()
|
||||||
|
<-t.C
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if string(newCert) != string(entry.Certificate) && string(newKey) != string(entry.Key) {
|
||||||
|
newKeyPair, err := tls.X509KeyPair(newCert, newKey)
|
||||||
|
if err != nil {
|
||||||
|
newError("ignoring invalid X509 key pair").Base(err).AtError().WriteToLog()
|
||||||
|
<-t.C
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if newKeyPair.Leaf, err = x509.ParseCertificate(newKeyPair.Certificate[0]); err != nil {
|
||||||
|
newError("ignoring invalid certificate").Base(err).AtError().WriteToLog()
|
||||||
|
<-t.C
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cert = &newKeyPair
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if newOCSPData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
|
||||||
|
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
|
||||||
|
} else if string(newOCSPData) != string(cert.OCSPStaple) {
|
||||||
|
cert.OCSPStaple = newOCSPData
|
||||||
|
}
|
||||||
|
certs[index] = cert
|
||||||
<-t.C
|
<-t.C
|
||||||
}
|
}
|
||||||
}(&certs[len(certs)-1])
|
}(certs[len(certs)-1], index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return certs
|
return certs
|
||||||
@@ -169,6 +205,33 @@ func getGetCertificateFunc(c *tls.Config, ca []*Certificate) func(hello *tls.Cli
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getNewGetCertficateFunc(certs []*tls.Certificate) func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
|
return func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
|
if len(certs) == 0 {
|
||||||
|
return nil, newError("empty certs")
|
||||||
|
}
|
||||||
|
sni := strings.ToLower(hello.ServerName)
|
||||||
|
if len(certs) == 1 || sni == "" {
|
||||||
|
return certs[0], nil
|
||||||
|
}
|
||||||
|
gsni := "*"
|
||||||
|
if index := strings.IndexByte(sni, '.'); index != -1 {
|
||||||
|
gsni += sni[index:]
|
||||||
|
}
|
||||||
|
for _, keyPair := range certs {
|
||||||
|
if keyPair.Leaf.Subject.CommonName == sni || keyPair.Leaf.Subject.CommonName == gsni {
|
||||||
|
return keyPair, nil
|
||||||
|
}
|
||||||
|
for _, name := range keyPair.Leaf.DNSNames {
|
||||||
|
if name == sni || name == gsni {
|
||||||
|
return keyPair, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return certs[0], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) IsExperiment8357() bool {
|
func (c *Config) IsExperiment8357() bool {
|
||||||
return strings.HasPrefix(c.ServerName, exp8357)
|
return strings.HasPrefix(c.ServerName, exp8357)
|
||||||
}
|
}
|
||||||
@@ -210,12 +273,11 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
|
|||||||
opt(config)
|
opt(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Certificates = c.BuildCertificates()
|
|
||||||
config.BuildNameToCertificate()
|
|
||||||
|
|
||||||
caCerts := c.getCustomCA()
|
caCerts := c.getCustomCA()
|
||||||
if len(caCerts) > 0 {
|
if len(caCerts) > 0 {
|
||||||
config.GetCertificate = getGetCertificateFunc(config, caCerts)
|
config.GetCertificate = getGetCertificateFunc(config, caCerts)
|
||||||
|
} else {
|
||||||
|
config.GetCertificate = getNewGetCertficateFunc(c.BuildCertificates())
|
||||||
}
|
}
|
||||||
|
|
||||||
if sn := c.parseServerName(); len(sn) > 0 {
|
if sn := c.parseServerName(); len(sn) > 0 {
|
||||||
|
@@ -85,6 +85,10 @@ type Certificate struct {
|
|||||||
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
||||||
Usage Certificate_Usage `protobuf:"varint,3,opt,name=usage,proto3,enum=xray.transport.internet.tls.Certificate_Usage" json:"usage,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"`
|
OcspStapling int64 `protobuf:"varint,4,opt,name=ocsp_stapling,json=ocspStapling,proto3" json:"ocsp_stapling,omitempty"`
|
||||||
|
// TLS certificate path
|
||||||
|
CertificatePath string `protobuf:"bytes,5,opt,name=certificate_path,json=certificatePath,proto3" json:"certificate_path,omitempty"`
|
||||||
|
// TLS Key path
|
||||||
|
KeyPath string `protobuf:"bytes,6,opt,name=key_path,json=keyPath,proto3" json:"key_path,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Certificate) Reset() {
|
func (x *Certificate) Reset() {
|
||||||
@@ -147,6 +151,20 @@ func (x *Certificate) GetOcspStapling() int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Certificate) GetCertificatePath() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.CertificatePath
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Certificate) GetKeyPath() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.KeyPath
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -284,7 +302,7 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
|||||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x74, 0x6c, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
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,
|
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,
|
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74,
|
||||||
0x6c, 0x73, 0x22, 0xf2, 0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
0x6c, 0x73, 0x22, 0xb8, 0x02, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
||||||
0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
|
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,
|
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,
|
0x63, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
@@ -295,48 +313,52 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
|||||||
0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d,
|
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,
|
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,
|
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,
|
0x67, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
|
||||||
0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10,
|
0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x65, 0x72,
|
||||||
0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59,
|
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08,
|
||||||
0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f,
|
0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||||
0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xd3, 0x03, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
0x6b, 0x65, 0x79, 0x50, 0x61, 0x74, 0x68, 0x22, 0x44, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65,
|
||||||
0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x73, 0x65,
|
0x12, 0x10, 0x0a, 0x0c, 0x45, 0x4e, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54,
|
||||||
0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f,
|
0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f,
|
||||||
0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x63, 0x65, 0x72,
|
0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48,
|
||||||
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28,
|
0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xd3, 0x03,
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e,
|
0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f,
|
||||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x2e, 0x43, 0x65, 0x72,
|
0x77, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
|
||||||
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
|
0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12,
|
||||||
0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
|
0x4a, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02,
|
||||||
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76,
|
0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
||||||
0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70,
|
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74,
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6e,
|
0x6c, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b,
|
||||||
0x65, 0x78, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x3a, 0x0a, 0x19, 0x65,
|
0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73,
|
||||||
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65,
|
0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17,
|
0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d,
|
||||||
0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73,
|
0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20,
|
||||||
0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62,
|
0x03, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||||
0x6c, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06,
|
0x6c, 0x12, 0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73,
|
||||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x79, 0x73,
|
0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05,
|
||||||
0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x76,
|
0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x73, 0x73,
|
||||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x69,
|
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a,
|
||||||
0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f,
|
0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f,
|
||||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d,
|
0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61,
|
||||||
0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x69, 0x70,
|
0x62, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1f, 0x0a,
|
||||||
0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09,
|
0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01,
|
||||||
0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x3d,
|
0x28, 0x09, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f,
|
||||||
0x0a, 0x1b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
|
0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20,
|
||||||
0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20,
|
0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
|
||||||
0x01, 0x28, 0x08, 0x52, 0x18, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65,
|
0x23, 0x0a, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73,
|
||||||
0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x42, 0x73, 0x0a,
|
0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75,
|
||||||
0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
0x69, 0x74, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73,
|
||||||
0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73,
|
0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69,
|
||||||
0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
|
0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x70, 0x72, 0x65, 0x66, 0x65,
|
||||||
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72,
|
0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69,
|
||||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
0x74, 0x65, 0x73, 0x42, 0x73, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e,
|
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54,
|
0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
||||||
0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
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 (
|
var (
|
||||||
|
@@ -22,6 +22,12 @@ message Certificate {
|
|||||||
Usage usage = 3;
|
Usage usage = 3;
|
||||||
|
|
||||||
int64 ocsp_stapling = 4;
|
int64 ocsp_stapling = 4;
|
||||||
|
|
||||||
|
// TLS certificate path
|
||||||
|
string certificate_path = 5;
|
||||||
|
|
||||||
|
// TLS Key path
|
||||||
|
string key_path = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
|
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/ocsp"
|
"github.com/xtls/xray-core/common/ocsp"
|
||||||
|
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||||
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
)
|
)
|
||||||
@@ -41,8 +42,8 @@ func (c *Config) loadSelfCertPool() (*x509.CertPool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BuildCertificates builds a list of TLS certificates from proto definition.
|
// BuildCertificates builds a list of TLS certificates from proto definition.
|
||||||
func (c *Config) BuildCertificates() []xtls.Certificate {
|
func (c *Config) BuildCertificates() []*xtls.Certificate {
|
||||||
certs := make([]xtls.Certificate, 0, len(c.Certificate))
|
certs := make([]*xtls.Certificate, 0, len(c.Certificate))
|
||||||
for _, entry := range c.Certificate {
|
for _, entry := range c.Certificate {
|
||||||
if entry.Usage != Certificate_ENCIPHERMENT {
|
if entry.Usage != Certificate_ENCIPHERMENT {
|
||||||
continue
|
continue
|
||||||
@@ -52,19 +53,54 @@ func (c *Config) BuildCertificates() []xtls.Certificate {
|
|||||||
newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
|
newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
certs = append(certs, keyPair)
|
keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
|
||||||
|
if err != nil {
|
||||||
|
newError("ignoring invalid certificate").Base(err).AtWarning().WriteToLog()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
certs = append(certs, &keyPair)
|
||||||
if entry.OcspStapling != 0 {
|
if entry.OcspStapling != 0 {
|
||||||
go func(cert *xtls.Certificate) {
|
index := len(certs) - 1
|
||||||
|
go func(cert *xtls.Certificate, index int) {
|
||||||
t := time.NewTicker(time.Duration(entry.OcspStapling) * time.Second)
|
t := time.NewTicker(time.Duration(entry.OcspStapling) * time.Second)
|
||||||
for {
|
for {
|
||||||
if newData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
|
if entry.CertificatePath != "" && entry.KeyPath != "" {
|
||||||
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
|
newCert, err := filesystem.ReadFile(entry.CertificatePath)
|
||||||
} else if string(newData) != string(cert.OCSPStaple) {
|
if err != nil {
|
||||||
cert.OCSPStaple = newData
|
newError("failed to parse certificate").Base(err).AtError().WriteToLog()
|
||||||
|
<-t.C
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newKey, err := filesystem.ReadFile(entry.KeyPath)
|
||||||
|
if err != nil {
|
||||||
|
newError("failed to parse key").Base(err).AtError().WriteToLog()
|
||||||
|
<-t.C
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if string(newCert) != string(entry.Certificate) && string(newKey) != string(entry.Key) {
|
||||||
|
newKeyPair, err := xtls.X509KeyPair(newCert, newKey)
|
||||||
|
if err != nil {
|
||||||
|
newError("ignoring invalid X509 key pair").Base(err).AtError().WriteToLog()
|
||||||
|
<-t.C
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if newKeyPair.Leaf, err = x509.ParseCertificate(newKeyPair.Certificate[0]); err != nil {
|
||||||
|
newError("ignoring invalid certificate").Base(err).AtError().WriteToLog()
|
||||||
|
<-t.C
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cert = &newKeyPair
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if newOCSPData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
|
||||||
|
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
|
||||||
|
} else if string(newOCSPData) != string(cert.OCSPStaple) {
|
||||||
|
cert.OCSPStaple = newOCSPData
|
||||||
|
}
|
||||||
|
certs[index] = cert
|
||||||
<-t.C
|
<-t.C
|
||||||
}
|
}
|
||||||
}(&certs[len(certs)-1])
|
}(certs[len(certs)-1], index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return certs
|
return certs
|
||||||
@@ -168,6 +204,33 @@ func getGetCertificateFunc(c *xtls.Config, ca []*Certificate) func(hello *xtls.C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getNewGetCertficateFunc(certs []*xtls.Certificate) func(hello *xtls.ClientHelloInfo) (*xtls.Certificate, error) {
|
||||||
|
return func(hello *xtls.ClientHelloInfo) (*xtls.Certificate, error) {
|
||||||
|
if len(certs) == 0 {
|
||||||
|
return nil, newError("empty certs")
|
||||||
|
}
|
||||||
|
sni := strings.ToLower(hello.ServerName)
|
||||||
|
if len(certs) == 1 || sni == "" {
|
||||||
|
return certs[0], nil
|
||||||
|
}
|
||||||
|
gsni := "*"
|
||||||
|
if index := strings.IndexByte(sni, '.'); index != -1 {
|
||||||
|
gsni += sni[index:]
|
||||||
|
}
|
||||||
|
for _, keyPair := range certs {
|
||||||
|
if keyPair.Leaf.Subject.CommonName == sni || keyPair.Leaf.Subject.CommonName == gsni {
|
||||||
|
return keyPair, nil
|
||||||
|
}
|
||||||
|
for _, name := range keyPair.Leaf.DNSNames {
|
||||||
|
if name == sni || name == gsni {
|
||||||
|
return keyPair, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return certs[0], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) parseServerName() string {
|
func (c *Config) parseServerName() string {
|
||||||
return c.ServerName
|
return c.ServerName
|
||||||
}
|
}
|
||||||
@@ -201,12 +264,11 @@ func (c *Config) GetXTLSConfig(opts ...Option) *xtls.Config {
|
|||||||
opt(config)
|
opt(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Certificates = c.BuildCertificates()
|
|
||||||
config.BuildNameToCertificate()
|
|
||||||
|
|
||||||
caCerts := c.getCustomCA()
|
caCerts := c.getCustomCA()
|
||||||
if len(caCerts) > 0 {
|
if len(caCerts) > 0 {
|
||||||
config.GetCertificate = getGetCertificateFunc(config, caCerts)
|
config.GetCertificate = getGetCertificateFunc(config, caCerts)
|
||||||
|
} else {
|
||||||
|
config.GetCertificate = getNewGetCertficateFunc(c.BuildCertificates())
|
||||||
}
|
}
|
||||||
|
|
||||||
if sn := c.parseServerName(); len(sn) > 0 {
|
if sn := c.parseServerName(); len(sn) > 0 {
|
||||||
|
@@ -85,6 +85,10 @@ type Certificate struct {
|
|||||||
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
||||||
Usage Certificate_Usage `protobuf:"varint,3,opt,name=usage,proto3,enum=xray.transport.internet.xtls.Certificate_Usage" json:"usage,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"`
|
OcspStapling int64 `protobuf:"varint,4,opt,name=ocsp_stapling,json=ocspStapling,proto3" json:"ocsp_stapling,omitempty"`
|
||||||
|
// TLS certificate path
|
||||||
|
CertificatePath string `protobuf:"bytes,5,opt,name=certificate_path,json=certificatePath,proto3" json:"certificate_path,omitempty"`
|
||||||
|
// TLS Key path
|
||||||
|
KeyPath string `protobuf:"bytes,6,opt,name=key_path,json=keyPath,proto3" json:"key_path,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Certificate) Reset() {
|
func (x *Certificate) Reset() {
|
||||||
@@ -147,6 +151,20 @@ func (x *Certificate) GetOcspStapling() int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Certificate) GetCertificatePath() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.CertificatePath
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Certificate) GetKeyPath() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.KeyPath
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -284,7 +302,7 @@ var file_transport_internet_xtls_config_proto_rawDesc = []byte{
|
|||||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
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,
|
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,
|
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
||||||
0x78, 0x74, 0x6c, 0x73, 0x22, 0xf3, 0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
|
0x78, 0x74, 0x6c, 0x73, 0x22, 0xb9, 0x02, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
|
||||||
0x63, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
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,
|
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,
|
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20,
|
||||||
@@ -295,49 +313,53 @@ var file_transport_internet_xtls_config_proto_rawDesc = []byte{
|
|||||||
0x74, 0x65, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12,
|
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,
|
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,
|
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,
|
0x6c, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
||||||
0x0c, 0x45, 0x4e, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12,
|
0x61, 0x74, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
|
||||||
0x14, 0x0a, 0x10, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x56, 0x45, 0x52,
|
0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12,
|
||||||
0x49, 0x46, 0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49,
|
0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||||
0x54, 0x59, 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xd4, 0x03, 0x0a, 0x06, 0x43,
|
0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x50, 0x61, 0x74, 0x68, 0x22, 0x44, 0x0a, 0x05, 0x55, 0x73,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69,
|
0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x4e, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d,
|
||||||
0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61,
|
0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49,
|
||||||
0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x4b, 0x0a, 0x0b,
|
0x54, 0x59, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41,
|
||||||
0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28,
|
0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02,
|
||||||
0x0b, 0x32, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
0x22, 0xd4, 0x03, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61,
|
||||||
0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x78, 0x74, 0x6c, 0x73,
|
0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20,
|
||||||
0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x65,
|
0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75,
|
||||||
0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72,
|
0x72, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
|
||||||
0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
|
0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74,
|
||||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x65,
|
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
||||||
0x78, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28,
|
0x74, 0x2e, 0x78, 0x74, 0x6c, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
||||||
0x09, 0x52, 0x0c, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12,
|
0x74, 0x65, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12,
|
||||||
0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03,
|
||||||
0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65,
|
||||||
0x28, 0x08, 0x52, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||||
0x6e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x64,
|
0x6c, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x72, 0x6f,
|
||||||
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x72, 0x6f,
|
0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f,
|
||||||
0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
|
0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69,
|
||||||
0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d,
|
0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||||
0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
|
0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f,
|
||||||
0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b,
|
0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x79, 0x73,
|
||||||
0x6d, 0x61, 0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28,
|
0x74, 0x65, 0x6d, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11,
|
||||||
0x09, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a,
|
0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f,
|
||||||
0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x09,
|
0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74,
|
0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69,
|
||||||
0x65, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72,
|
0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||||
0x76, 0x65, 0x72, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65,
|
0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73,
|
||||||
0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x53,
|
0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75,
|
||||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65,
|
0x69, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68,
|
||||||
0x73, 0x42, 0x76, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72,
|
0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x70, 0x72, 0x65, 0x66,
|
||||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72,
|
||||||
0x2e, 0x78, 0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x70,
|
||||||
0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
|
0x72, 0x65, 0x66, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65,
|
||||||
0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74,
|
0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x42, 0x76, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||||
0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1c, 0x58, 0x72, 0x61,
|
0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e,
|
||||||
0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65,
|
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x78, 0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x31, 0x67,
|
||||||
0x72, 0x6e, 0x65, 0x74, 0x2e, 0x58, 0x74, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78,
|
||||||
0x33,
|
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 (
|
var (
|
||||||
|
@@ -22,6 +22,12 @@ message Certificate {
|
|||||||
Usage usage = 3;
|
Usage usage = 3;
|
||||||
|
|
||||||
int64 ocsp_stapling = 4;
|
int64 ocsp_stapling = 4;
|
||||||
|
|
||||||
|
// TLS certificate path
|
||||||
|
string certificate_path = 5;
|
||||||
|
|
||||||
|
// TLS Key path
|
||||||
|
string key_path = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
|
Reference in New Issue
Block a user