Skip to content

Commit b33fde2

Browse files
committed
Add brutal
1 parent 65da3d9 commit b33fde2

8 files changed

Lines changed: 91 additions & 4 deletions

File tree

app/proxyman/config.pb.go

Lines changed: 11 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/proxyman/config.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,5 @@ message MultiplexingConfig {
6868
int32 xudpConcurrency = 3;
6969
// "reject" (default), "allow" or "skip".
7070
string xudpProxyUDP443 = 4;
71+
uint64 brutalBPS = 5;
7172
}

app/proxyman/outbound/handler.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
136136
Dialer: h,
137137
Strategy: mux.ClientStrategy{
138138
MaxConcurrency: uint32(config.Concurrency),
139-
MaxConnection: 128,
139+
MaxReuseTimes: 32768,
140+
BrutalBPS: config.BrutalBPS,
140141
},
141142
},
142143
},
@@ -157,7 +158,8 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
157158
Dialer: h,
158159
Strategy: mux.ClientStrategy{
159160
MaxConcurrency: uint32(config.XudpConcurrency),
160-
MaxConnection: 128,
161+
MaxReuseTimes: 32768,
162+
BrutalBPS: config.BrutalBPS,
161163
},
162164
},
163165
},

common/buf/multi_buffer.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ func (mb MultiBuffer) Copy(b []byte) int {
7575
return total
7676
}
7777

78+
func (mb MultiBuffer) Bytes() []byte {
79+
b := make([]byte, mb.Len())
80+
mb.Copy(b)
81+
return b
82+
}
83+
7884
// ReadFrom reads all content from reader until EOF.
7985
func ReadFrom(reader io.Reader) (MultiBuffer, error) {
8086
mb := make(MultiBuffer, 0, 16)

common/mux/client.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package mux
22

33
import (
44
"context"
5+
"encoding/binary"
56
goerrors "errors"
67
"io"
78
"sync"
89
"time"
910

1011
"github.com/xtls/xray-core/common"
1112
"github.com/xtls/xray-core/common/buf"
13+
"github.com/xtls/xray-core/common/dice"
1214
"github.com/xtls/xray-core/common/errors"
1315
"github.com/xtls/xray-core/common/net"
1416
"github.com/xtls/xray-core/common/protocol"
@@ -171,6 +173,7 @@ func (f *DialingWorkerFactory) Create() (*ClientWorker, error) {
171173
type ClientStrategy struct {
172174
MaxConcurrency uint32
173175
MaxReuseTimes uint32
176+
BrutalBPS uint64
174177
}
175178

176179
type ClientWorker struct {
@@ -198,6 +201,9 @@ func NewClientWorker(stream transport.Link, s ClientStrategy) (*ClientWorker, er
198201

199202
go c.fetchOutput()
200203
go c.monitor()
204+
if s.BrutalBPS > 0 {
205+
go c.sendSetBrutal(s.BrutalBPS)
206+
}
201207

202208
return c, nil
203209
}
@@ -417,3 +423,24 @@ func (m *ClientWorker) fetchOutput() {
417423
}
418424
}
419425
}
426+
427+
func (m *ClientWorker) sendSetBrutal(sendBPS uint64) {
428+
meta := FrameMetadata{
429+
SessionID: 91,
430+
SessionStatus: SessionStatusSetBrutal,
431+
}
432+
meta.Option.Set(OptionData)
433+
frame := buf.New()
434+
common.Must(meta.WriteTo(frame))
435+
lengthByte := frame.Extend(2)
436+
speedByte := frame.Extend(int32(200 + dice.Roll(200)))
437+
binary.BigEndian.PutUint64(speedByte, sendBPS)
438+
binary.BigEndian.PutUint16(lengthByte, uint16(len(speedByte)))
439+
errors.LogError(context.Background(), "Start sending SetBrutal frame with speed: ", sendBPS)
440+
err := m.link.Writer.WriteMultiBuffer(buf.MultiBuffer{frame})
441+
if err != nil {
442+
frame.Release()
443+
errors.LogError(context.Background(), "failed to send SetBrutal frame: ", err)
444+
}
445+
errors.LogInfo(context.Background(), "SetBrutal frame sent successfully")
446+
}

common/mux/frame.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ const (
2121
SessionStatusKeep SessionStatus = 0x02
2222
SessionStatusEnd SessionStatus = 0x03
2323
SessionStatusKeepAlive SessionStatus = 0x04
24+
25+
SessionStatusSetBrutal SessionStatus = 0x91
2426
)
2527

2628
const (

common/mux/server.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package mux
22

33
import (
44
"context"
5+
"encoding/binary"
56
"io"
67
"time"
78

@@ -16,6 +17,7 @@ import (
1617
"github.com/xtls/xray-core/core"
1718
"github.com/xtls/xray-core/features/routing"
1819
"github.com/xtls/xray-core/transport"
20+
"github.com/xtls/xray-core/transport/internet/brutal"
1921
"github.com/xtls/xray-core/transport/pipe"
2022
)
2123

@@ -333,6 +335,40 @@ func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.Buffered
333335
return nil
334336
}
335337

338+
// note: do not return error, just log it
339+
func (w *ServerWorker) HandleSetBrutal(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error {
340+
if meta.Option.Has(OptionData) == false {
341+
errors.LogError(ctx, "SetBrutal frame missing data")
342+
return nil
343+
}
344+
chunkReader := NewStreamReader(reader)
345+
data, err := chunkReader.ReadMultiBuffer()
346+
if err != nil {
347+
errors.LogError(ctx, "unexpected error when reading brutal data: ", err)
348+
}
349+
speed := binary.BigEndian.Uint64(data.Bytes())
350+
351+
inbound := session.InboundFromContext(ctx)
352+
if inbound == nil || inbound.Conn == nil {
353+
errors.LogError(ctx, "no inbound connection found for brutal set")
354+
return nil
355+
}
356+
conn := inbound.Conn
357+
tcpConn, ok := conn.(*net.TCPConn)
358+
if !ok {
359+
errors.LogError(ctx, "brutal can only be set on TCP connections")
360+
return nil
361+
}
362+
err = brutal.SetBrutal(tcpConn, speed)
363+
if err != nil {
364+
errors.LogError(ctx, "failed to set brutal: ", err)
365+
return nil
366+
} else {
367+
errors.LogInfo(ctx, "successfully set brutal speed: ", speed)
368+
}
369+
return nil
370+
}
371+
336372
func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedReader) error {
337373
var meta FrameMetadata
338374
err := meta.Unmarshal(reader, session.IsReverseMuxFromContext(ctx))
@@ -349,6 +385,8 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedRead
349385
err = w.handleStatusNew(session.ContextWithIsReverseMux(ctx, false), &meta, reader)
350386
case SessionStatusKeep:
351387
err = w.handleStatusKeep(&meta, reader)
388+
case SessionStatusSetBrutal:
389+
err = w.HandleSetBrutal(ctx, &meta, reader)
352390
default:
353391
status := meta.SessionStatus
354392
return errors.New("unknown status: ", status).AtError()

infra/conf/xray.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
102102
type MuxConfig struct {
103103
Enabled bool `json:"enabled"`
104104
Concurrency int16 `json:"concurrency"`
105+
BrutalBPS uint64 `json:"brutalBPS"`
105106
XudpConcurrency int16 `json:"xudpConcurrency"`
106107
XudpProxyUDP443 string `json:"xudpProxyUDP443"`
107108
}
@@ -118,6 +119,7 @@ func (m *MuxConfig) Build() (*proxyman.MultiplexingConfig, error) {
118119
return &proxyman.MultiplexingConfig{
119120
Enabled: m.Enabled,
120121
Concurrency: int32(m.Concurrency),
122+
BrutalBPS: m.BrutalBPS,
121123
XudpConcurrency: int32(m.XudpConcurrency),
122124
XudpProxyUDP443: m.XudpProxyUDP443,
123125
}, nil

0 commit comments

Comments
 (0)