Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/dispatcher/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
handler = h
} else {
errors.LogWarning(ctx, "non existing outTag: ", outTag)
return
}
} else {
errors.LogInfo(ctx, "default route for ", destination)
Expand Down
2 changes: 2 additions & 0 deletions app/proxyman/outbound/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
}
h.proxyConfig = proxyConfig

ctx = session.ContextWithHandler(ctx, h)

rawProxyHandler, err := common.CreateObject(ctx, proxyConfig)
if err != nil {
return nil, err
Expand Down
32 changes: 16 additions & 16 deletions app/reverse/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ func (b *Bridge) Close() error {
}

type BridgeWorker struct {
tag string
worker *mux.ServerWorker
dispatcher routing.Dispatcher
state Control_State
Tag string
Worker *mux.ServerWorker
Dispatcher routing.Dispatcher
State Control_State
}

func NewBridgeWorker(domain string, tag string, d routing.Dispatcher) (*BridgeWorker, error) {
Expand All @@ -115,15 +115,15 @@ func NewBridgeWorker(domain string, tag string, d routing.Dispatcher) (*BridgeWo
}

w := &BridgeWorker{
dispatcher: d,
tag: tag,
Dispatcher: d,
Tag: tag,
}

worker, err := mux.NewServerWorker(context.Background(), w, link)
if err != nil {
return nil, err
}
w.worker = worker
w.Worker = worker

return w, nil
}
Expand All @@ -141,11 +141,11 @@ func (w *BridgeWorker) Close() error {
}

func (w *BridgeWorker) IsActive() bool {
return w.state == Control_ACTIVE && !w.worker.Closed()
return w.State == Control_ACTIVE && !w.Worker.Closed()
}

func (w *BridgeWorker) Connections() uint32 {
return w.worker.ActiveConnections()
return w.Worker.ActiveConnections()
}

func (w *BridgeWorker) handleInternalConn(link *transport.Link) {
Expand All @@ -161,8 +161,8 @@ func (w *BridgeWorker) handleInternalConn(link *transport.Link) {
errors.LogInfoInner(context.Background(), err, "failed to parse proto message")
break
}
if ctl.State != w.state {
w.state = ctl.State
if ctl.State != w.State {
w.State = ctl.State
}
}
}
Expand All @@ -171,9 +171,9 @@ func (w *BridgeWorker) handleInternalConn(link *transport.Link) {
func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destination) (*transport.Link, error) {
if !isInternalDomain(dest) {
ctx = session.ContextWithInbound(ctx, &session.Inbound{
Tag: w.tag,
Tag: w.Tag,
})
return w.dispatcher.Dispatch(ctx, dest)
return w.Dispatcher.Dispatch(ctx, dest)
}

opt := []pipe.Option{pipe.WithSizeLimit(16 * 1024)}
Expand All @@ -194,12 +194,12 @@ func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destination) (*tra
func (w *BridgeWorker) DispatchLink(ctx context.Context, dest net.Destination, link *transport.Link) error {
if !isInternalDomain(dest) {
ctx = session.ContextWithInbound(ctx, &session.Inbound{
Tag: w.tag,
Tag: w.Tag,
})
return w.dispatcher.DispatchLink(ctx, dest, link)
return w.Dispatcher.DispatchLink(ctx, dest, link)
}

link = w.dispatcher.(*dispatcher.DefaultDispatcher).WrapLink(ctx, link)
link = w.Dispatcher.(*dispatcher.DefaultDispatcher).WrapLink(ctx, link)
w.handleInternalConn(link)

return nil
Expand Down
1 change: 0 additions & 1 deletion app/reverse/portal.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ func (p *Portal) HandleConnection(ctx context.Context, link *transport.Link) err
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
}


return p.client.Dispatch(ctx, link)
}

Expand Down
2 changes: 1 addition & 1 deletion app/reverse/reverse.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
)

const (
internalDomain = "reverse.internal.v2fly.org" // make reverse proxy compatible with v2fly
internalDomain = "reverse"
)

func isDomain(dest net.Destination, domain string) bool {
Expand Down
3 changes: 2 additions & 1 deletion common/protocol/headers.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ const (
RequestCommandTCP = RequestCommand(0x01)
RequestCommandUDP = RequestCommand(0x02)
RequestCommandMux = RequestCommand(0x03)
RequestCommandRvs = RequestCommand(0x04)
)

func (c RequestCommand) TransferType() TransferType {
switch c {
case RequestCommandTCP, RequestCommandMux:
case RequestCommandTCP, RequestCommandMux, RequestCommandRvs:
return TransferTypeStream
case RequestCommandUDP:
return TransferTypePacket
Expand Down
26 changes: 19 additions & 7 deletions common/session/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/xtls/xray-core/common/ctx"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/routing"
)

Expand All @@ -16,13 +17,13 @@ const (
inboundSessionKey ctx.SessionKey = 1
outboundSessionKey ctx.SessionKey = 2
contentSessionKey ctx.SessionKey = 3
muxPreferredSessionKey ctx.SessionKey = 4 // unused
sockoptSessionKey ctx.SessionKey = 5 // used by dokodemo to only receive sockopt.Mark
trackedConnectionErrorKey ctx.SessionKey = 6 // used by observer to get outbound error
dispatcherKey ctx.SessionKey = 7 // used by ss2022 inbounds to get dispatcher
timeoutOnlyKey ctx.SessionKey = 8 // mux context's child contexts to only cancel when its own traffic times out
allowedNetworkKey ctx.SessionKey = 9 // muxcool server control incoming request tcp/udp
handlerSessionKey ctx.SessionKey = 10 // unused
muxPreferredSessionKey ctx.SessionKey = 4 // unused
sockoptSessionKey ctx.SessionKey = 5 // used by dokodemo to only receive sockopt.Mark
trackedConnectionErrorKey ctx.SessionKey = 6 // used by observer to get outbound error
dispatcherKey ctx.SessionKey = 7 // used by ss2022 inbounds to get dispatcher
timeoutOnlyKey ctx.SessionKey = 8 // mux context's child contexts to only cancel when its own traffic times out
allowedNetworkKey ctx.SessionKey = 9 // muxcool server control incoming request tcp/udp
handlerSessionKey ctx.SessionKey = 10 // outbound gets full handler
mitmAlpn11Key ctx.SessionKey = 11 // used by TLS dialer
mitmServerNameKey ctx.SessionKey = 12 // used by TLS dialer
)
Expand Down Expand Up @@ -163,6 +164,17 @@ func AllowedNetworkFromContext(ctx context.Context) net.Network {
return net.Network_Unknown
}

func ContextWithHandler(ctx context.Context, handler outbound.Handler) context.Context {
return context.WithValue(ctx, handlerSessionKey, handler)
}

func HandlerFromContext(ctx context.Context) outbound.Handler {
if val, ok := ctx.Value(handlerSessionKey).(outbound.Handler); ok {
return val
}
return nil
}

func ContextWithMitmAlpn11(ctx context.Context, alpn11 bool) context.Context {
return context.WithValue(ctx, mitmAlpn11Key, alpn11)
}
Expand Down
50 changes: 44 additions & 6 deletions infra/conf/vless.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ 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 == "" {
return nil, errors.New(`VLESS clients: "tag" can't be empty for "reverse"`)
}

user.Account = serial.ToTypedMessage(account)
config.Clients[idx] = user
}
Expand Down Expand Up @@ -199,13 +203,30 @@ type VLessOutboundVnext struct {
}

type VLessOutboundConfig struct {
Vnext []*VLessOutboundVnext `json:"vnext"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level uint32 `json:"level"`
Email string `json:"email"`
Id string `json:"id"`
Flow string `json:"flow"`
Seed string `json:"seed"`
Encryption string `json:"encryption"`
Reverse *vless.Reverse `json:"reverse"`
Vnext []*VLessOutboundVnext `json:"vnext"`
}

// Build implements Buildable
func (c *VLessOutboundConfig) Build() (proto.Message, error) {
config := new(outbound.Config)

if c.Address != nil {
c.Vnext = []*VLessOutboundVnext{
{
Address: c.Address,
Port: c.Port,
Users: []json.RawMessage{{}},
},
}
}
if len(c.Vnext) != 1 {
return nil, errors.New(`VLESS settings: "vnext" should have one and only one member`)
}
Expand All @@ -224,12 +245,25 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
}
for idx, rawUser := range rec.Users {
user := new(protocol.User)
if err := json.Unmarshal(rawUser, user); err != nil {
return nil, errors.New(`VLESS users: invalid user`).Base(err)
if c.Address != nil {
user.Level = c.Level
user.Email = c.Email
} else {
if err := json.Unmarshal(rawUser, user); err != nil {
return nil, errors.New(`VLESS users: invalid user`).Base(err)
}
}
account := new(vless.Account)
if err := json.Unmarshal(rawUser, account); err != nil {
return nil, errors.New(`VLESS users: invalid user`).Base(err)
if c.Address != nil {
account.Id = c.Id
account.Flow = c.Flow
//account.Seed = c.Seed
account.Encryption = c.Encryption
account.Reverse = c.Reverse
} else {
if err := json.Unmarshal(rawUser, account); err != nil {
return nil, errors.New(`VLESS users: invalid user`).Base(err)
}
}

u, err := uuid.ParseString(account.Id)
Expand Down Expand Up @@ -288,6 +322,10 @@ 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[idx] = user
}
Expand Down
4 changes: 4 additions & 0 deletions proxy/vless/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func (a *Account) AsAccount() (protocol.Account, error) {
XorMode: a.XorMode,
Seconds: a.Seconds,
Padding: a.Padding,
Reverse: a.Reverse,
}, nil
}

Expand All @@ -35,6 +36,8 @@ type MemoryAccount struct {
XorMode uint32
Seconds uint32
Padding string

Reverse *Reverse
}

// Equals implements protocol.Account.Equals().
Expand All @@ -54,5 +57,6 @@ func (a *MemoryAccount) ToProto() proto.Message {
XorMode: a.XorMode,
Seconds: a.Seconds,
Padding: a.Padding,
Reverse: a.Reverse,
}
}
Loading
Loading