Skip to content

Commit 03131c7

Browse files
authored
XTLS Vision: Use separate uplink/downlink flag for direct copy (#4329)
Fixes #4033
1 parent 7b59379 commit 03131c7

File tree

5 files changed

+44
-24
lines changed

5 files changed

+44
-24
lines changed

proxy/proxy.go

+24-8
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,17 @@ type TrafficState struct {
110110

111111
// reader link state
112112
WithinPaddingBuffers bool
113-
ReaderSwitchToDirectCopy bool
113+
DownlinkReaderDirectCopy bool
114+
UplinkReaderDirectCopy bool
114115
RemainingCommand int32
115116
RemainingContent int32
116117
RemainingPadding int32
117118
CurrentCommand int
118119

119120
// write link state
120121
IsPadding bool
121-
WriterSwitchToDirectCopy bool
122+
DownlinkWriterDirectCopy bool
123+
UplinkWriterDirectCopy bool
122124
}
123125

124126
func NewTrafficState(userUUID []byte) *TrafficState {
@@ -131,13 +133,15 @@ func NewTrafficState(userUUID []byte) *TrafficState {
131133
Cipher: 0,
132134
RemainingServerHello: -1,
133135
WithinPaddingBuffers: true,
134-
ReaderSwitchToDirectCopy: false,
136+
DownlinkReaderDirectCopy: false,
137+
UplinkReaderDirectCopy: false,
135138
RemainingCommand: -1,
136139
RemainingContent: -1,
137140
RemainingPadding: -1,
138141
CurrentCommand: 0,
139142
IsPadding: true,
140-
WriterSwitchToDirectCopy: false,
143+
DownlinkWriterDirectCopy: false,
144+
UplinkWriterDirectCopy: false,
141145
}
142146
}
143147

@@ -147,13 +151,15 @@ type VisionReader struct {
147151
buf.Reader
148152
trafficState *TrafficState
149153
ctx context.Context
154+
isUplink bool
150155
}
151156

152-
func NewVisionReader(reader buf.Reader, state *TrafficState, context context.Context) *VisionReader {
157+
func NewVisionReader(reader buf.Reader, state *TrafficState, isUplink bool, context context.Context) *VisionReader {
153158
return &VisionReader{
154159
Reader: reader,
155160
trafficState: state,
156161
ctx: context,
162+
isUplink: isUplink,
157163
}
158164
}
159165

@@ -175,7 +181,11 @@ func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
175181
w.trafficState.WithinPaddingBuffers = false
176182
} else if w.trafficState.CurrentCommand == 2 {
177183
w.trafficState.WithinPaddingBuffers = false
178-
w.trafficState.ReaderSwitchToDirectCopy = true
184+
if w.isUplink {
185+
w.trafficState.UplinkReaderDirectCopy = true
186+
} else {
187+
w.trafficState.DownlinkReaderDirectCopy = true
188+
}
179189
} else {
180190
errors.LogInfo(w.ctx, "XtlsRead unknown command ", w.trafficState.CurrentCommand, buffer.Len())
181191
}
@@ -194,16 +204,18 @@ type VisionWriter struct {
194204
trafficState *TrafficState
195205
ctx context.Context
196206
writeOnceUserUUID []byte
207+
isUplink bool
197208
}
198209

199-
func NewVisionWriter(writer buf.Writer, state *TrafficState, context context.Context) *VisionWriter {
210+
func NewVisionWriter(writer buf.Writer, state *TrafficState, isUplink bool, context context.Context) *VisionWriter {
200211
w := make([]byte, len(state.UserUUID))
201212
copy(w, state.UserUUID)
202213
return &VisionWriter{
203214
Writer: writer,
204215
trafficState: state,
205216
ctx: context,
206217
writeOnceUserUUID: w,
218+
isUplink: isUplink,
207219
}
208220
}
209221

@@ -221,7 +233,11 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
221233
for i, b := range mb {
222234
if w.trafficState.IsTLS && b.Len() >= 6 && bytes.Equal(TlsApplicationDataStart, b.BytesTo(3)) {
223235
if w.trafficState.EnableXtls {
224-
w.trafficState.WriterSwitchToDirectCopy = true
236+
if w.isUplink {
237+
w.trafficState.UplinkWriterDirectCopy = true
238+
} else {
239+
w.trafficState.DownlinkWriterDirectCopy = true
240+
}
225241
}
226242
var command byte = CommandPaddingContinue
227243
if i == len(mb)-1 {

proxy/vless/encoding/addons.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,13 @@ func DecodeHeaderAddons(buffer *buf.Buffer, reader io.Reader) (*Addons, error) {
6161
}
6262

6363
// EncodeBodyAddons returns a Writer that auto-encrypt content written by caller.
64-
func EncodeBodyAddons(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons, state *proxy.TrafficState, context context.Context) buf.Writer {
64+
func EncodeBodyAddons(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons, state *proxy.TrafficState, isUplink bool, context context.Context) buf.Writer {
6565
if request.Command == protocol.RequestCommandUDP {
6666
return NewMultiLengthPacketWriter(writer.(buf.Writer))
6767
}
6868
w := buf.NewWriter(writer)
6969
if requestAddons.Flow == vless.XRV {
70-
w = proxy.NewVisionWriter(w, state, context)
70+
w = proxy.NewVisionWriter(w, state, isUplink, context)
7171
}
7272
return w
7373
}

proxy/vless/encoding/encoding.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,10 @@ func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader) (*A
172172
}
173173

174174
// XtlsRead filter and read xtls protocol
175-
func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, conn net.Conn, input *bytes.Reader, rawInput *bytes.Buffer, trafficState *proxy.TrafficState, ob *session.Outbound, ctx context.Context) error {
175+
func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, conn net.Conn, input *bytes.Reader, rawInput *bytes.Buffer, trafficState *proxy.TrafficState, ob *session.Outbound, isUplink bool, ctx context.Context) error {
176176
err := func() error {
177177
for {
178-
if trafficState.ReaderSwitchToDirectCopy {
178+
if isUplink && trafficState.UplinkReaderDirectCopy || !isUplink && trafficState.DownlinkReaderDirectCopy {
179179
var writerConn net.Conn
180180
var inTimer *signal.ActivityTimer
181181
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil {
@@ -193,7 +193,7 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer,
193193
buffer, err := reader.ReadMultiBuffer()
194194
if !buffer.IsEmpty() {
195195
timer.Update()
196-
if trafficState.ReaderSwitchToDirectCopy {
196+
if isUplink && trafficState.UplinkReaderDirectCopy || !isUplink && trafficState.DownlinkReaderDirectCopy {
197197
// XTLS Vision processes struct TLS Conn's input and rawInput
198198
if inputBuffer, err := buf.ReadFrom(input); err == nil {
199199
if !inputBuffer.IsEmpty() {
@@ -222,12 +222,12 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer,
222222
}
223223

224224
// XtlsWrite filter and write xtls protocol
225-
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, trafficState *proxy.TrafficState, ob *session.Outbound, ctx context.Context) error {
225+
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, trafficState *proxy.TrafficState, ob *session.Outbound, isUplink bool, ctx context.Context) error {
226226
err := func() error {
227227
var ct stats.Counter
228228
for {
229229
buffer, err := reader.ReadMultiBuffer()
230-
if trafficState.WriterSwitchToDirectCopy {
230+
if isUplink && trafficState.UplinkWriterDirectCopy || !isUplink && trafficState.DownlinkWriterDirectCopy {
231231
if inbound := session.InboundFromContext(ctx); inbound != nil {
232232
if inbound.CanSpliceCopy == 2 {
233233
inbound.CanSpliceCopy = 1
@@ -239,7 +239,11 @@ func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdate
239239
rawConn, _, writerCounter := proxy.UnwrapRawConn(conn)
240240
writer = buf.NewWriter(rawConn)
241241
ct = writerCounter
242-
trafficState.WriterSwitchToDirectCopy = false
242+
if isUplink {
243+
trafficState.UplinkWriterDirectCopy = false
244+
} else {
245+
trafficState.DownlinkWriterDirectCopy = false
246+
}
243247
}
244248
if !buffer.IsEmpty() {
245249
if ct != nil {

proxy/vless/inbound/inbound.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -538,8 +538,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
538538

539539
if requestAddons.Flow == vless.XRV {
540540
ctx1 := session.ContextWithInbound(ctx, nil) // TODO enable splice
541-
clientReader = proxy.NewVisionReader(clientReader, trafficState, ctx1)
542-
err = encoding.XtlsRead(clientReader, serverWriter, timer, connection, input, rawInput, trafficState, nil, ctx1)
541+
clientReader = proxy.NewVisionReader(clientReader, trafficState, true, ctx1)
542+
err = encoding.XtlsRead(clientReader, serverWriter, timer, connection, input, rawInput, trafficState, nil, true, ctx1)
543543
} else {
544544
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBuffer
545545
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
@@ -561,7 +561,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
561561
}
562562

563563
// default: clientWriter := bufferWriter
564-
clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, ctx)
564+
clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, false, ctx)
565565
multiBuffer, err1 := serverReader.ReadMultiBuffer()
566566
if err1 != nil {
567567
return err1 // ...
@@ -576,7 +576,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
576576

577577
var err error
578578
if requestAddons.Flow == vless.XRV {
579-
err = encoding.XtlsWrite(serverReader, clientWriter, timer, connection, trafficState, nil, ctx)
579+
err = encoding.XtlsWrite(serverReader, clientWriter, timer, connection, trafficState, nil, false, ctx)
580580
} else {
581581
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBuffer
582582
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))

proxy/vless/outbound/outbound.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
194194
}
195195

196196
// default: serverWriter := bufferWriter
197-
serverWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, ctx)
197+
serverWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, true, ctx)
198198
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
199199
serverWriter = xudp.NewPacketWriter(serverWriter, target, xudp.GetGlobalID(ctx))
200200
}
@@ -234,7 +234,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
234234
}
235235
}
236236
ctx1 := session.ContextWithInbound(ctx, nil) // TODO enable splice
237-
err = encoding.XtlsWrite(clientReader, serverWriter, timer, conn, trafficState, ob, ctx1)
237+
err = encoding.XtlsWrite(clientReader, serverWriter, timer, conn, trafficState, ob, true, ctx1)
238238
} else {
239239
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBuffer
240240
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
@@ -261,7 +261,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
261261
// default: serverReader := buf.NewReader(conn)
262262
serverReader := encoding.DecodeBodyAddons(conn, request, responseAddons)
263263
if requestAddons.Flow == vless.XRV {
264-
serverReader = proxy.NewVisionReader(serverReader, trafficState, ctx)
264+
serverReader = proxy.NewVisionReader(serverReader, trafficState, false, ctx)
265265
}
266266
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
267267
if requestAddons.Flow == vless.XRV {
@@ -272,7 +272,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
272272
}
273273

274274
if requestAddons.Flow == vless.XRV {
275-
err = encoding.XtlsRead(serverReader, clientWriter, timer, conn, input, rawInput, trafficState, ob, ctx)
275+
err = encoding.XtlsRead(serverReader, clientWriter, timer, conn, input, rawInput, trafficState, ob, false, ctx)
276276
} else {
277277
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBuffer
278278
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))

0 commit comments

Comments
 (0)