mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-05-18 09:59:19 +03:00
Compare commits
2 Commits
9786ff6800
...
9554e53a4f
Author | SHA1 | Date | |
---|---|---|---|
yuhan6665 | 9554e53a4f | ||
yuhan6665 | adf061c26a |
|
@ -146,7 +146,7 @@ func NewTrafficState(userUUID []byte, flow string) *TrafficState {
|
|||
return &state
|
||||
}
|
||||
|
||||
// VisionReader is used to read xtls vision protocol
|
||||
// VisionReader is used to read seed protocol
|
||||
// Note Vision probably only make sense as the inner most layer of reader, since it need assess traffic state from origin proxy traffic
|
||||
type VisionReader struct {
|
||||
buf.Reader
|
||||
|
@ -171,7 +171,7 @@ func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|||
w.trafficState.StartTime = time.Now()
|
||||
}
|
||||
w.trafficState.ByteReceived += int64(buffer.Len())
|
||||
if w.trafficState.WithinPaddingBuffers || !ShouldStopSeed(w.addons, w.trafficState) {
|
||||
if w.trafficState.WithinPaddingBuffers || w.trafficState.NumberOfPacketReceived <= 8 || !ShouldStopSeed(w.addons, w.trafficState) {
|
||||
mb2 := make(buf.MultiBuffer, 0, len(buffer))
|
||||
for _, b := range buffer {
|
||||
newbuffer := XtlsUnpadding(b, w.trafficState, w.ctx)
|
||||
|
@ -199,7 +199,7 @@ func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|||
return buffer, err
|
||||
}
|
||||
|
||||
// VisionWriter is used to write xtls vision protocol
|
||||
// VisionWriter is used to write seed protocol
|
||||
// Note Vision probably only make sense as the inner most layer of writer, since it need assess traffic state from origin proxy traffic
|
||||
type VisionWriter struct {
|
||||
buf.Writer
|
||||
|
@ -207,6 +207,7 @@ type VisionWriter struct {
|
|||
trafficState *TrafficState
|
||||
ctx context.Context
|
||||
writeOnceUserUUID []byte
|
||||
scheduler *Scheduler
|
||||
}
|
||||
|
||||
func NewVisionWriter(writer buf.Writer, addon *Addons, state *TrafficState, context context.Context) *VisionWriter {
|
||||
|
@ -218,6 +219,7 @@ func NewVisionWriter(writer buf.Writer, addon *Addons, state *TrafficState, cont
|
|||
trafficState: state,
|
||||
ctx: context,
|
||||
writeOnceUserUUID: w,
|
||||
scheduler: NewScheduler(writer, addon, state, context),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,7 +272,14 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||
if w.trafficState.StartTime.IsZero() {
|
||||
w.trafficState.StartTime = time.Now()
|
||||
}
|
||||
return w.Writer.WriteMultiBuffer(mb)
|
||||
w.scheduler.Buffer <- mb
|
||||
if w.addons.Scheduler == nil {
|
||||
w.scheduler.Trigger <- -1 // send all buffers
|
||||
}
|
||||
if len(w.scheduler.Error) > 0 {
|
||||
return <-w.scheduler.Error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReshapeMultiBuffer prepare multi buffer for padding stucture (max 21 bytes)
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
)
|
||||
|
||||
type Scheduler struct {
|
||||
Buffer chan buf.MultiBuffer
|
||||
Trigger chan int
|
||||
Error chan error
|
||||
bufferReadLock *sync.Mutex
|
||||
writer buf.Writer
|
||||
addons *Addons
|
||||
trafficState *TrafficState
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func NewScheduler(w buf.Writer, addon *Addons, state *TrafficState, context context.Context) *Scheduler {
|
||||
var s = Scheduler{
|
||||
Buffer: make(chan buf.MultiBuffer, 100),
|
||||
Trigger: make(chan int),
|
||||
Error: make(chan error, 100),
|
||||
bufferReadLock: new(sync.Mutex),
|
||||
writer: w,
|
||||
addons: addon,
|
||||
trafficState: state,
|
||||
ctx: context,
|
||||
}
|
||||
go s.mainLoop()
|
||||
if s.addons.Scheduler != nil {
|
||||
go s.exampleIndependentScheduler()
|
||||
}
|
||||
return &s
|
||||
}
|
||||
|
||||
func(s *Scheduler) mainLoop() {
|
||||
for trigger := range s.Trigger {
|
||||
go func() { // each trigger has independent delay, trigger does not block
|
||||
var d = 0 * time.Millisecond
|
||||
if s.addons.Delay != nil {
|
||||
l, err := rand.Int(rand.Reader, big.NewInt(int64(s.addons.Delay.MaxMillis - s.addons.Delay.MinMillis)))
|
||||
if err != nil {
|
||||
newError("failed to generate delay", trigger).Base(err).WriteToLog(session.ExportIDToError(s.ctx))
|
||||
}
|
||||
d = time.Duration(uint32(l.Int64()) + s.addons.Delay.MinMillis) * time.Millisecond
|
||||
time.Sleep(d)
|
||||
}
|
||||
|
||||
s.bufferReadLock.Lock() // guard against multiple trigger threads
|
||||
var sending = len(s.Buffer)
|
||||
if sending > 0 {
|
||||
newError("Scheduler Trigger for ", sending, " buffer(s) with ", d, " ", trigger).AtDebug().WriteToLog(session.ExportIDToError(s.ctx))
|
||||
}
|
||||
for i := 0; i<sending; i++ {
|
||||
s.Error <- s.writer.WriteMultiBuffer(<-s.Buffer)
|
||||
}
|
||||
s.bufferReadLock.Unlock()
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func(s *Scheduler) exampleIndependentScheduler() {
|
||||
for {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
s.Trigger <- -1 // send all buffers
|
||||
}
|
||||
}
|
|
@ -127,6 +127,106 @@ func TestVless(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestVlessSeedWithIndependentScheduler(t *testing.T) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err := tcpServer.Start()
|
||||
common.Must(err)
|
||||
defer tcpServer.Close()
|
||||
|
||||
userID := protocol.NewID(uuid.New())
|
||||
serverPort := tcp.PickPort()
|
||||
serverConfig := &core.Config{
|
||||
App: []*serial.TypedMessage{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
ErrorLogLevel: clog.Severity_Debug,
|
||||
ErrorLogType: log.LogType_Console,
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&inbound.Config{
|
||||
Clients: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&vless.Account{
|
||||
Id: userID.String(),
|
||||
Seed: "1",
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
clientPort := tcp.PickPort()
|
||||
clientConfig := &core.Config{
|
||||
App: []*serial.TypedMessage{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
ErrorLogLevel: clog.Severity_Debug,
|
||||
ErrorLogType: log.LogType_Console,
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
Address: net.NewIPOrDomain(dest.Address),
|
||||
Port: uint32(dest.Port),
|
||||
NetworkList: &net.NetworkList{
|
||||
Network: []net.Network{net.Network_TCP},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||
Vnext: []*protocol.ServerEndpoint{
|
||||
{
|
||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||
Port: uint32(serverPort),
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&vless.Account{
|
||||
Id: userID.String(),
|
||||
Seed: "1",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||
common.Must(err)
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
var errg errgroup.Group
|
||||
for i := 0; i < 10; i++ {
|
||||
errg.Go(testTCPConn(clientPort, 1024*1024, time.Second*30))
|
||||
}
|
||||
if err := errg.Wait(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVlessTls(t *testing.T) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
|
@ -377,6 +477,134 @@ func TestVlessXtlsVision(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestVlessXtlsVisionWithSeed(t *testing.T) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err := tcpServer.Start()
|
||||
common.Must(err)
|
||||
defer tcpServer.Close()
|
||||
|
||||
userID := protocol.NewID(uuid.New())
|
||||
serverPort := tcp.PickPort()
|
||||
serverConfig := &core.Config{
|
||||
App: []*serial.TypedMessage{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
ErrorLogLevel: clog.Severity_Debug,
|
||||
ErrorLogType: log.LogType_Console,
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
Protocol: internet.TransportProtocol_TCP,
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*serial.TypedMessage{
|
||||
serial.ToTypedMessage(&tls.Config{
|
||||
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&inbound.Config{
|
||||
Clients: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&vless.Account{
|
||||
Id: userID.String(),
|
||||
Flow: vless.XRV,
|
||||
Seed: "1",
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
clientPort := tcp.PickPort()
|
||||
clientConfig := &core.Config{
|
||||
App: []*serial.TypedMessage{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
ErrorLogLevel: clog.Severity_Debug,
|
||||
ErrorLogType: log.LogType_Console,
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
Address: net.NewIPOrDomain(dest.Address),
|
||||
Port: uint32(dest.Port),
|
||||
NetworkList: &net.NetworkList{
|
||||
Network: []net.Network{net.Network_TCP},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||
Vnext: []*protocol.ServerEndpoint{
|
||||
{
|
||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||
Port: uint32(serverPort),
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&vless.Account{
|
||||
Id: userID.String(),
|
||||
Flow: vless.XRV,
|
||||
Seed: "1",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
Protocol: internet.TransportProtocol_TCP,
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
Protocol: internet.TransportProtocol_TCP,
|
||||
Settings: serial.ToTypedMessage(&transtcp.Config{}),
|
||||
},
|
||||
},
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*serial.TypedMessage{
|
||||
serial.ToTypedMessage(&tls.Config{
|
||||
AllowInsecure: true,
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||
common.Must(err)
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
var errg errgroup.Group
|
||||
for i := 0; i < 10; i++ {
|
||||
errg.Go(testTCPConn(clientPort, 1024*1024, time.Second*30))
|
||||
}
|
||||
if err := errg.Wait(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVlessXtlsVisionReality(t *testing.T) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
|
|
Loading…
Reference in New Issue