Add XTLS RPRX's Vision (#1235)

* Add XTLS RPRX's Vision

* Add helpful warning when security is wrong

* Add XTLS padding (draft)

* Fix  number of packet to filter

* Xtls padding version 1.0 and unpadding logic
This commit is contained in:
yuhan6665 2022-10-29 00:51:59 -04:00 committed by GitHub
parent 341d317d0c
commit 5e695327b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 420 additions and 56 deletions

View file

@ -442,7 +442,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
var rawConn syscall.RawConn
switch requestAddons.Flow {
case vless.XRO, vless.XRD:
case vless.XRO, vless.XRD, vless.XRV:
if account.Flow == requestAddons.Flow {
switch request.Command {
case protocol.RequestCommandMux:
@ -450,7 +450,14 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
case protocol.RequestCommandUDP:
return newError(requestAddons.Flow + " doesn't support UDP").AtWarning()
case protocol.RequestCommandTCP:
if xtlsConn, ok := iConn.(*xtls.Conn); ok {
if requestAddons.Flow == vless.XRV {
if _, ok := iConn.(*xtls.Conn); ok {
return newError(`failed to use ` + requestAddons.Flow + `, vision "security" must be "tls"`).AtWarning()
}
if sc, ok := iConn.(*tls.Conn).NetConn().(syscall.Conn); ok {
rawConn, _ = sc.SyscallConn()
}
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
xtlsConn.RPRX = true
xtlsConn.SHOW = xtls_show
xtlsConn.MARK = "XTLS"
@ -494,6 +501,10 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
serverReader := link.Reader // .(*pipe.Reader)
serverWriter := link.Writer // .(*pipe.Writer)
isTLS13 := false
isTLS12 := false
isTLS := false
numberOfPacketToFilter := 8
postRequest := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
@ -508,7 +519,13 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
if statConn != nil {
counter = statConn.ReadCounter
}
err = encoding.ReadV(clientReader, serverWriter, timer, iConn.(*xtls.Conn), rawConn, counter, nil)
if requestAddons.Flow == vless.XRV {
//TODO enable splice
ctx = session.ContextWithInbound(ctx, nil)
err = encoding.XtlsRead(clientReader, serverWriter, timer, iConn.(*tls.Conn), rawConn, counter, ctx, account.ID.Bytes(), &numberOfPacketToFilter, &isTLS13, &isTLS12, &isTLS)
} else {
err = encoding.ReadV(clientReader, serverWriter, timer, iConn.(*xtls.Conn), rawConn, counter, ctx)
}
} else {
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBufer
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
@ -531,26 +548,42 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
// default: clientWriter := bufferWriter
clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, responseAddons)
{
multiBuffer, err := serverReader.ReadMultiBuffer()
if err != nil {
return err // ...
}
if err := clientWriter.WriteMultiBuffer(multiBuffer); err != nil {
return err // ...
userUUID := account.ID.Bytes()
multiBuffer, err1 := serverReader.ReadMultiBuffer()
if err1 != nil {
return err1 // ...
}
if requestAddons.Flow == vless.XRV {
encoding.XtlsFilterTls13(multiBuffer, &numberOfPacketToFilter, &isTLS13, &isTLS12, &isTLS, ctx)
if isTLS {
for i, b := range multiBuffer {
multiBuffer[i] = encoding.XtlsPadding(b, 0x00, &userUUID, ctx)
}
}
}
if err := clientWriter.WriteMultiBuffer(multiBuffer); err != nil {
return err // ...
}
// Flush; bufferWriter.WriteMultiBufer now is bufferWriter.writer.WriteMultiBuffer
if err := bufferWriter.SetBuffered(false); err != nil {
return newError("failed to write A response payload").Base(err).AtWarning()
}
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBufer
if err := buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer)); err != nil {
var err error
if rawConn != nil && requestAddons.Flow == vless.XRV {
var counter stats.Counter
if statConn != nil {
counter = statConn.WriteCounter
}
err = encoding.XtlsWrite(serverReader, clientWriter, timer, iConn.(*tls.Conn), counter, ctx, &userUUID, &numberOfPacketToFilter, &isTLS13, &isTLS12, &isTLS)
} else {
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBufer
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))
}
if err != nil {
return newError("failed to transfer response payload").Base(err).AtInfo()
}
// Indicates the end of response payload.
switch responseAddons.Flow {
default: