From c3faa8b7ac76f909e6ddc284b510f967ca121b31 Mon Sep 17 00:00:00 2001 From: yuhan6665 <1588741+yuhan6665@users.noreply.github.com> Date: Mon, 6 Feb 2023 01:45:09 -0500 Subject: [PATCH] Insert padding with empty content to camouflage VLESS header (#1610) This only affects the Vision client for protocols expecting server to send data first. The change is compatible with existing version of Vision server. --- proxy/vless/encoding/encoding.go | 24 +++++++++++++++--------- proxy/vless/outbound/outbound.go | 7 +++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/proxy/vless/encoding/encoding.go b/proxy/vless/encoding/encoding.go index dea27044..1e8aaa92 100644 --- a/proxy/vless/encoding/encoding.go +++ b/proxy/vless/encoding/encoding.go @@ -506,25 +506,31 @@ func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBu // XtlsPadding add padding to eliminate length siganature during tls handshake func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, ctx context.Context) *buf.Buffer { - var length int32 = 0 - if b.Len() < 900 { + var contantLen int32 = 0 + var paddingLen int32 = 0 + if b != nil { + contantLen = b.Len() + } + if contantLen < 900 { l, err := rand.Int(rand.Reader, big.NewInt(500)) if err != nil { newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx)) } - length = int32(l.Int64()) + 900 - b.Len() + paddingLen = int32(l.Int64()) + 900 - contantLen } newbuffer := buf.New() if userUUID != nil { newbuffer.Write(*userUUID) *userUUID = nil } - newbuffer.Write([]byte{command, byte(b.Len() >> 8), byte(b.Len()), byte(length >> 8), byte(length)}) - newbuffer.Write(b.Bytes()) - newbuffer.Extend(length) - newError("XtlsPadding ", b.Len(), " ", length, " ", command).WriteToLog(session.ExportIDToError(ctx)) - b.Release() - b = nil + newbuffer.Write([]byte{command, byte(contantLen >> 8), byte(contantLen), byte(paddingLen >> 8), byte(paddingLen)}) + if (b != nil) { + newbuffer.Write(b.Bytes()) + b.Release() + b = nil + } + newbuffer.Extend(paddingLen) + newError("XtlsPadding ", contantLen, " ", paddingLen, " ", command).WriteToLog(session.ExportIDToError(ctx)) return newbuffer } diff --git a/proxy/vless/outbound/outbound.go b/proxy/vless/outbound/outbound.go index 82505911..f001a6b3 100644 --- a/proxy/vless/outbound/outbound.go +++ b/proxy/vless/outbound/outbound.go @@ -249,6 +249,13 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte } } else if err1 != buf.ErrReadTimeout { return err1 + } else if requestAddons.Flow == vless.XRV { + mb := make(buf.MultiBuffer, 1) + mb[0] = encoding.XtlsPadding(nil, 0x01, &userUUID, ctx) // it must not be tls so padding finish with it (command 1) + newError("Insert padding with empty content to camouflage VLESS header ", mb.Len()).WriteToLog(session.ExportIDToError(ctx)) + if err := serverWriter.WriteMultiBuffer(mb); err != nil { + return err + } } } else { newError("Reader is not timeout reader, will send out vless header separately from first payload").AtDebug().WriteToLog(session.ExportIDToError(ctx))