mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-05-08 14:13:22 +00:00
VLESS Reverse Proxy: Add "sniffing" to outbound's "reverse" (which is actually an inbound) (#5837)
Closes https://github.com/XTLS/Xray-core/issues/5662 --------- Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
This commit is contained in:
2
go.sum
2
go.sum
@@ -129,8 +129,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb h1:whnFRlWMcXI9d+ZbWg+4sHnLp52d5yiIPUxMBSt4X9A=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb/go.mod h1:rpwXGsirqLqN2L0JDJQlwOboGHmptD5ZD6T2VmcqhTw=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
|
||||
@@ -78,9 +78,14 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
||||
return nil, errors.New(`VLESS clients: "encryption" should not be in inbound settings`)
|
||||
}
|
||||
|
||||
if account.Reverse != nil && account.Reverse.Tag == "" {
|
||||
if account.Reverse != nil {
|
||||
if account.Reverse.Tag == "" {
|
||||
return nil, errors.New(`VLESS clients: "tag" can't be empty for "reverse"`)
|
||||
}
|
||||
if account.Reverse.Sniffing != nil { // may not be reached: error json unmarshal
|
||||
return nil, errors.New(`VLESS clients: inbound's "reverse" can't have "sniffing"`)
|
||||
}
|
||||
}
|
||||
|
||||
user.Account = serial.ToTypedMessage(account)
|
||||
config.Clients[idx] = user
|
||||
@@ -197,6 +202,28 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type VLessReverseConfig struct {
|
||||
Tag string `json:"tag"`
|
||||
Sniffing *SniffingConfig `json:"sniffing"`
|
||||
}
|
||||
|
||||
func (c *VLessReverseConfig) Build() (*vless.Reverse, error) {
|
||||
if c.Tag == "" {
|
||||
return nil, errors.New(`VLESS reverse: "tag" can't be empty`)
|
||||
}
|
||||
r := &vless.Reverse{
|
||||
Tag: c.Tag,
|
||||
}
|
||||
if c.Sniffing != nil {
|
||||
sc, err := c.Sniffing.Build()
|
||||
if err != nil {
|
||||
return nil, errors.New(`VLESS reverse: invalid "sniffing" config`).Base(err)
|
||||
}
|
||||
r.Sniffing = sc
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
type VLessOutboundVnext struct {
|
||||
Address *Address `json:"address"`
|
||||
Port uint16 `json:"port"`
|
||||
@@ -212,7 +239,7 @@ type VLessOutboundConfig struct {
|
||||
Flow string `json:"flow"`
|
||||
Seed string `json:"seed"`
|
||||
Encryption string `json:"encryption"`
|
||||
Reverse *vless.Reverse `json:"reverse"`
|
||||
Reverse *VLessReverseConfig `json:"reverse"`
|
||||
Testpre uint32 `json:"testpre"`
|
||||
Testseed []uint32 `json:"testseed"`
|
||||
Vnext []*VLessOutboundVnext `json:"vnext"`
|
||||
@@ -260,13 +287,22 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
|
||||
account.Flow = c.Flow
|
||||
//account.Seed = c.Seed
|
||||
account.Encryption = c.Encryption
|
||||
account.Reverse = c.Reverse
|
||||
if c.Reverse != nil {
|
||||
rvs, err := c.Reverse.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
account.Reverse = rvs
|
||||
}
|
||||
account.Testpre = c.Testpre
|
||||
account.Testseed = c.Testseed
|
||||
} else {
|
||||
if err := json.Unmarshal(rawUser, account); err != nil {
|
||||
return nil, errors.New(`VLESS users: invalid user`).Base(err)
|
||||
}
|
||||
if account.Reverse != nil { // may not be reached: error json unmarshal
|
||||
return nil, errors.New(`VLESS users: please use simplified outbound's config style to use "reverse"`)
|
||||
}
|
||||
}
|
||||
|
||||
u, err := uuid.ParseString(account.Id)
|
||||
@@ -326,10 +362,6 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
|
||||
return nil, errors.New(`VLESS users: unsupported "encryption": ` + account.Encryption)
|
||||
}
|
||||
|
||||
if account.Reverse != nil && account.Reverse.Tag == "" {
|
||||
return nil, errors.New(`VLESS clients: "tag" can't be empty for "reverse"`)
|
||||
}
|
||||
|
||||
user.Account = serial.ToTypedMessage(account)
|
||||
spec.User = user
|
||||
break
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
package vless
|
||||
|
||||
import (
|
||||
proxyman "github.com/xtls/xray-core/app/proxyman"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
@@ -24,6 +25,7 @@ const (
|
||||
type Reverse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||
Sniffing *proxyman.SniffingConfig `protobuf:"bytes,2,opt,name=sniffing,proto3" json:"sniffing,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -65,6 +67,13 @@ func (x *Reverse) GetTag() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Reverse) GetSniffing() *proxyman.SniffingConfig {
|
||||
if x != nil {
|
||||
return x.Sniffing
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Account struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// ID of the account, in the form of a UUID, e.g., "66ad4540-b58c-4ad2-9926-ea63445a9b57".
|
||||
@@ -179,9 +188,10 @@ var File_proxy_vless_account_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_proxy_vless_account_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x19proxy/vless/account.proto\x12\x10xray.proxy.vless\"\x1b\n" +
|
||||
"\x19proxy/vless/account.proto\x12\x10xray.proxy.vless\x1a\x19app/proxyman/config.proto\"Z\n" +
|
||||
"\aReverse\x12\x10\n" +
|
||||
"\x03tag\x18\x01 \x01(\tR\x03tag\"\x86\x02\n" +
|
||||
"\x03tag\x18\x01 \x01(\tR\x03tag\x12=\n" +
|
||||
"\bsniffing\x18\x02 \x01(\v2!.xray.app.proxyman.SniffingConfigR\bsniffing\"\x86\x02\n" +
|
||||
"\aAccount\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +
|
||||
"\x04flow\x18\x02 \x01(\tR\x04flow\x12\x1e\n" +
|
||||
@@ -212,14 +222,16 @@ var file_proxy_vless_account_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_proxy_vless_account_proto_goTypes = []any{
|
||||
(*Reverse)(nil), // 0: xray.proxy.vless.Reverse
|
||||
(*Account)(nil), // 1: xray.proxy.vless.Account
|
||||
(*proxyman.SniffingConfig)(nil), // 2: xray.app.proxyman.SniffingConfig
|
||||
}
|
||||
var file_proxy_vless_account_proto_depIdxs = []int32{
|
||||
0, // 0: xray.proxy.vless.Account.reverse:type_name -> xray.proxy.vless.Reverse
|
||||
1, // [1:1] is the sub-list for method output_type
|
||||
1, // [1:1] is the sub-list for method input_type
|
||||
1, // [1:1] is the sub-list for extension type_name
|
||||
1, // [1:1] is the sub-list for extension extendee
|
||||
0, // [0:1] is the sub-list for field type_name
|
||||
2, // 0: xray.proxy.vless.Reverse.sniffing:type_name -> xray.app.proxyman.SniffingConfig
|
||||
0, // 1: xray.proxy.vless.Account.reverse:type_name -> xray.proxy.vless.Reverse
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proxy_vless_account_proto_init() }
|
||||
|
||||
@@ -6,8 +6,11 @@ option go_package = "github.com/xtls/xray-core/proxy/vless";
|
||||
option java_package = "com.xray.proxy.vless";
|
||||
option java_multiple_files = true;
|
||||
|
||||
import "app/proxyman/config.proto";
|
||||
|
||||
message Reverse {
|
||||
string tag = 1;
|
||||
xray.app.proxyman.SniffingConfig sniffing = 2;
|
||||
}
|
||||
|
||||
message Account {
|
||||
|
||||
@@ -97,13 +97,25 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||
}
|
||||
|
||||
if a.Reverse != nil {
|
||||
rvsCtx := session.ContextWithInbound(ctx, &session.Inbound{
|
||||
Tag: a.Reverse.Tag,
|
||||
User: handler.server.User, // TODO: email
|
||||
})
|
||||
if sc := a.Reverse.Sniffing; sc != nil && sc.Enabled {
|
||||
rvsCtx = session.ContextWithContent(rvsCtx, &session.Content{
|
||||
SniffingRequest: session.SniffingRequest{
|
||||
Enabled: sc.Enabled,
|
||||
OverrideDestinationForProtocol: sc.DestinationOverride,
|
||||
ExcludeForDomain: sc.DomainsExcluded,
|
||||
MetadataOnly: sc.MetadataOnly,
|
||||
RouteOnly: sc.RouteOnly,
|
||||
},
|
||||
})
|
||||
}
|
||||
handler.reverse = &Reverse{
|
||||
tag: a.Reverse.Tag,
|
||||
dispatcher: v.GetFeature(routing.DispatcherType()).(routing.Dispatcher),
|
||||
ctx: session.ContextWithInbound(ctx, &session.Inbound{
|
||||
Tag: a.Reverse.Tag,
|
||||
User: handler.server.User, // TODO: email
|
||||
}),
|
||||
ctx: rvsCtx,
|
||||
handler: handler,
|
||||
}
|
||||
handler.reverse.monitorTask = &task.Periodic{
|
||||
|
||||
Reference in New Issue
Block a user