mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-12-27 07:59:47 +00:00
Collect stats and possible padding (previously Vision Reader Writer) to all traffic
This commit is contained in:
parent
3da6cefbca
commit
855b773973
@ -126,8 +126,8 @@ type TrafficState struct {
|
|||||||
WriterSwitchToDirectCopy bool
|
WriterSwitchToDirectCopy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTrafficState(userUUID []byte) *TrafficState {
|
func NewTrafficState(userUUID []byte, flow string) *TrafficState {
|
||||||
return &TrafficState{
|
var state = TrafficState{
|
||||||
UserUUID: userUUID,
|
UserUUID: userUUID,
|
||||||
StartTime: time.Time{},
|
StartTime: time.Time{},
|
||||||
ByteSent: 0,
|
ByteSent: 0,
|
||||||
@ -140,15 +140,18 @@ func NewTrafficState(userUUID []byte) *TrafficState {
|
|||||||
IsTLS: false,
|
IsTLS: false,
|
||||||
Cipher: 0,
|
Cipher: 0,
|
||||||
RemainingServerHello: -1,
|
RemainingServerHello: -1,
|
||||||
WithinPaddingBuffers: true,
|
|
||||||
ReaderSwitchToDirectCopy: false,
|
ReaderSwitchToDirectCopy: false,
|
||||||
RemainingCommand: -1,
|
RemainingCommand: -1,
|
||||||
RemainingContent: -1,
|
RemainingContent: -1,
|
||||||
RemainingPadding: -1,
|
RemainingPadding: -1,
|
||||||
CurrentCommand: 0,
|
CurrentCommand: 0,
|
||||||
IsPadding: true,
|
|
||||||
WriterSwitchToDirectCopy: false,
|
WriterSwitchToDirectCopy: false,
|
||||||
|
};
|
||||||
|
if len(flow) > 0 {
|
||||||
|
state.IsPadding = true;
|
||||||
|
state.WithinPaddingBuffers = true;
|
||||||
}
|
}
|
||||||
|
return &state
|
||||||
}
|
}
|
||||||
|
|
||||||
// VisionReader is used to read xtls vision protocol
|
// VisionReader is used to read xtls vision protocol
|
||||||
|
@ -55,23 +55,21 @@ func DecodeHeaderAddons(buffer *buf.Buffer, reader io.Reader) (*Addons, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EncodeBodyAddons returns a Writer that auto-encrypt content written by caller.
|
// EncodeBodyAddons returns a Writer that auto-encrypt content written by caller.
|
||||||
func EncodeBodyAddons(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons, state *proxy.TrafficState, context context.Context) buf.Writer {
|
func EncodeBodyAddons(writer buf.Writer, request *protocol.RequestHeader, requestAddons *Addons, state *proxy.TrafficState, context context.Context) buf.Writer {
|
||||||
|
w := proxy.NewVisionWriter(writer, state, context)
|
||||||
if request.Command == protocol.RequestCommandUDP {
|
if request.Command == protocol.RequestCommandUDP {
|
||||||
return NewMultiLengthPacketWriter(writer.(buf.Writer))
|
return NewMultiLengthPacketWriter(w)
|
||||||
}
|
|
||||||
w := buf.NewWriter(writer)
|
|
||||||
if requestAddons.Flow == vless.XRV {
|
|
||||||
w = proxy.NewVisionWriter(w, state, context)
|
|
||||||
}
|
}
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeBodyAddons returns a Reader from which caller can fetch decrypted body.
|
// DecodeBodyAddons returns a Reader from which caller can fetch decrypted body.
|
||||||
func DecodeBodyAddons(reader io.Reader, request *protocol.RequestHeader, addons *Addons) buf.Reader {
|
func DecodeBodyAddons(reader io.Reader, request *protocol.RequestHeader, addons *Addons, state *proxy.TrafficState, context context.Context) buf.Reader {
|
||||||
|
r := proxy.NewVisionReader(buf.NewReader(reader), state, context)
|
||||||
if request.Command == protocol.RequestCommandUDP {
|
if request.Command == protocol.RequestCommandUDP {
|
||||||
return NewLengthPacketReader(reader)
|
return NewLengthPacketReader(&buf.BufferedReader{Reader: r})
|
||||||
}
|
}
|
||||||
return buf.NewReader(reader)
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMultiLengthPacketWriter(writer buf.Writer) *MultiLengthPacketWriter {
|
func NewMultiLengthPacketWriter(writer buf.Writer) *MultiLengthPacketWriter {
|
||||||
@ -204,39 +202,39 @@ func PopulateSeed(seed string, addons *Addons) {
|
|||||||
|
|
||||||
func CheckSeed(requestAddons *Addons, responseAddons *Addons) error {
|
func CheckSeed(requestAddons *Addons, responseAddons *Addons) error {
|
||||||
if !bytes.Equal(requestAddons.Seed, responseAddons.Seed) {
|
if !bytes.Equal(requestAddons.Seed, responseAddons.Seed) {
|
||||||
return newError("Seed bytes not match", requestAddons.Seed, responseAddons.Seed)
|
return errors.New("Seed bytes not match", requestAddons.Seed, responseAddons.Seed)
|
||||||
}
|
}
|
||||||
if requestAddons.Mode != responseAddons.Mode {
|
if requestAddons.Mode != responseAddons.Mode {
|
||||||
return newError("Mode not match", requestAddons.Mode, responseAddons.Mode)
|
return errors.New("Mode not match", requestAddons.Mode, responseAddons.Mode)
|
||||||
}
|
}
|
||||||
if requestAddons.Duration != responseAddons.Duration {
|
if requestAddons.Duration != responseAddons.Duration {
|
||||||
return newError("Duration not match", requestAddons.Duration, responseAddons.Duration)
|
return errors.New("Duration not match", requestAddons.Duration, responseAddons.Duration)
|
||||||
}
|
}
|
||||||
if requestAddons.Padding != nil && responseAddons.Padding != nil {
|
if requestAddons.Padding != nil && responseAddons.Padding != nil {
|
||||||
if requestAddons.Padding.RegularMin != responseAddons.Padding.RegularMin ||
|
if requestAddons.Padding.RegularMin != responseAddons.Padding.RegularMin ||
|
||||||
requestAddons.Padding.RegularMax != responseAddons.Padding.RegularMax ||
|
requestAddons.Padding.RegularMax != responseAddons.Padding.RegularMax ||
|
||||||
requestAddons.Padding.LongMin != responseAddons.Padding.LongMin ||
|
requestAddons.Padding.LongMin != responseAddons.Padding.LongMin ||
|
||||||
requestAddons.Padding.LongMax != responseAddons.Padding.LongMax {
|
requestAddons.Padding.LongMax != responseAddons.Padding.LongMax {
|
||||||
return newError("Padding not match")
|
return errors.New("Padding not match")
|
||||||
}
|
}
|
||||||
} else if requestAddons.Padding != nil || responseAddons.Padding != nil {
|
} else if requestAddons.Padding != nil || responseAddons.Padding != nil {
|
||||||
return newError("Padding of one is nil but the other is not nil")
|
return errors.New("Padding of one is nil but the other is not nil")
|
||||||
}
|
}
|
||||||
if requestAddons.Delay != nil && responseAddons.Delay != nil {
|
if requestAddons.Delay != nil && responseAddons.Delay != nil {
|
||||||
if requestAddons.Delay.IsRandom != responseAddons.Delay.IsRandom ||
|
if requestAddons.Delay.IsRandom != responseAddons.Delay.IsRandom ||
|
||||||
requestAddons.Delay.MinMillis != responseAddons.Delay.MinMillis ||
|
requestAddons.Delay.MinMillis != responseAddons.Delay.MinMillis ||
|
||||||
requestAddons.Delay.MaxMillis != responseAddons.Delay.MaxMillis {
|
requestAddons.Delay.MaxMillis != responseAddons.Delay.MaxMillis {
|
||||||
return newError("Delay not match")
|
return errors.New("Delay not match")
|
||||||
}
|
}
|
||||||
} else if requestAddons.Delay != nil || responseAddons.Delay != nil {
|
} else if requestAddons.Delay != nil || responseAddons.Delay != nil {
|
||||||
return newError("Delay of one is nil but the other is not nil")
|
return errors.New("Delay of one is nil but the other is not nil")
|
||||||
}
|
}
|
||||||
if requestAddons.Scheduler != nil && responseAddons.Scheduler != nil {
|
if requestAddons.Scheduler != nil && responseAddons.Scheduler != nil {
|
||||||
if requestAddons.Scheduler.TimeoutMillis != responseAddons.Scheduler.TimeoutMillis {
|
if requestAddons.Scheduler.TimeoutMillis != responseAddons.Scheduler.TimeoutMillis {
|
||||||
return newError("Scheduler not match")
|
return errors.New("Scheduler not match")
|
||||||
}
|
}
|
||||||
} else if requestAddons.Scheduler != nil || responseAddons.Scheduler != nil {
|
} else if requestAddons.Scheduler != nil || responseAddons.Scheduler != nil {
|
||||||
return newError("Scheduler of one is nil but the other is not nil")
|
return errors.New("Scheduler of one is nil but the other is not nil")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -460,7 +460,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
}
|
}
|
||||||
encoding.PopulateSeed(account.Seed, responseAddons)
|
encoding.PopulateSeed(account.Seed, responseAddons)
|
||||||
if check := encoding.CheckSeed(requestAddons, responseAddons); check != nil {
|
if check := encoding.CheckSeed(requestAddons, responseAddons); check != nil {
|
||||||
return newError("Seed configuration mis-match").Base(check).AtWarning()
|
return errors.New("Seed configuration mis-match").Base(check).AtWarning()
|
||||||
}
|
}
|
||||||
|
|
||||||
var input *bytes.Reader
|
var input *bytes.Reader
|
||||||
@ -531,18 +531,17 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
|
|
||||||
serverReader := link.Reader // .(*pipe.Reader)
|
serverReader := link.Reader // .(*pipe.Reader)
|
||||||
serverWriter := link.Writer // .(*pipe.Writer)
|
serverWriter := link.Writer // .(*pipe.Writer)
|
||||||
trafficState := proxy.NewTrafficState(account.ID.Bytes())
|
trafficState := proxy.NewTrafficState(account.ID.Bytes(), account.Flow)
|
||||||
postRequest := func() error {
|
postRequest := func() error {
|
||||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||||
|
|
||||||
// default: clientReader := reader
|
// default: clientReader := reader
|
||||||
clientReader := encoding.DecodeBodyAddons(reader, request, requestAddons)
|
clientReader := encoding.DecodeBodyAddons(reader, request, requestAddons, trafficState, ctx)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if requestAddons.Flow == vless.XRV {
|
if requestAddons.Flow == vless.XRV {
|
||||||
ctx1 := session.ContextWithInbound(ctx, nil) // TODO enable splice
|
ctx1 := session.ContextWithInbound(ctx, nil) // TODO enable splice
|
||||||
clientReader = proxy.NewVisionReader(clientReader, trafficState, ctx1)
|
|
||||||
err = encoding.XtlsRead(clientReader, serverWriter, timer, connection, input, rawInput, trafficState, nil, ctx1)
|
err = encoding.XtlsRead(clientReader, serverWriter, timer, connection, input, rawInput, trafficState, nil, ctx1)
|
||||||
} else {
|
} else {
|
||||||
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBuffer
|
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBuffer
|
||||||
|
@ -179,7 +179,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
|
|
||||||
clientReader := link.Reader // .(*pipe.Reader)
|
clientReader := link.Reader // .(*pipe.Reader)
|
||||||
clientWriter := link.Writer // .(*pipe.Writer)
|
clientWriter := link.Writer // .(*pipe.Writer)
|
||||||
trafficState := proxy.NewTrafficState(account.ID.Bytes())
|
trafficState := proxy.NewTrafficState(account.ID.Bytes(), account.Flow)
|
||||||
if request.Command == protocol.RequestCommandUDP && (requestAddons.Flow == vless.XRV || (h.cone && request.Port != 53 && request.Port != 443)) {
|
if request.Command == protocol.RequestCommandUDP && (requestAddons.Flow == vless.XRV || (h.cone && request.Port != 53 && request.Port != 443)) {
|
||||||
request.Command = protocol.RequestCommandMux
|
request.Command = protocol.RequestCommandMux
|
||||||
request.Address = net.DomainAddress("v1.mux.cool")
|
request.Address = net.DomainAddress("v1.mux.cool")
|
||||||
@ -260,16 +260,9 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
}
|
}
|
||||||
|
|
||||||
// default: serverReader := buf.NewReader(conn)
|
// default: serverReader := buf.NewReader(conn)
|
||||||
serverReader := encoding.DecodeBodyAddons(conn, request, responseAddons)
|
serverReader := encoding.DecodeBodyAddons(conn, request, responseAddons, trafficState, ctx)
|
||||||
if requestAddons.Flow == vless.XRV {
|
|
||||||
serverReader = proxy.NewVisionReader(serverReader, trafficState, ctx)
|
|
||||||
}
|
|
||||||
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||||
if requestAddons.Flow == vless.XRV {
|
serverReader = xudp.NewPacketReader(&buf.BufferedReader{Reader: serverReader})
|
||||||
serverReader = xudp.NewPacketReader(&buf.BufferedReader{Reader: serverReader})
|
|
||||||
} else {
|
|
||||||
serverReader = xudp.NewPacketReader(conn)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if requestAddons.Flow == vless.XRV {
|
if requestAddons.Flow == vless.XRV {
|
||||||
|
Loading…
Reference in New Issue
Block a user