Finalmask: Refactor header conns to avoid multiple-copy; Add randRange to "header-custom" (TCP & UDP) (#5812)

https://github.com/XTLS/Xray-core/pull/5657#issuecomment-4016760602
https://github.com/XTLS/Xray-core/pull/5657#issuecomment-4052921628
This commit is contained in:
LjhAUMEM
2026-03-21 17:04:22 +08:00
committed by GitHub
parent 35800e953e
commit 06dc4cf8bd
28 changed files with 388 additions and 558 deletions

View File

@@ -4,8 +4,11 @@ package crypto // import "github.com/xtls/xray-core/common/crypto"
import (
"crypto/rand"
"math/big"
"github.com/xtls/xray-core/common"
)
// [,)
func RandBetween(from int64, to int64) int64 {
if from == to {
return from
@@ -16,3 +19,20 @@ func RandBetween(from int64, to int64) int64 {
bigInt, _ := rand.Int(rand.Reader, big.NewInt(to-from))
return from + bigInt.Int64()
}
// [,]
func RandBytesBetween(b []byte, from, to byte) {
common.Must2(rand.Read(b))
if from > to {
from, to = to, from
}
if to-from == 255 {
return
}
for i := range b {
b[i] = from + b[i]%(to-from+1)
}
}

View File

@@ -1254,10 +1254,11 @@ var (
)
type TCPItem struct {
Delay Int32Range `json:"delay"`
Rand int32 `json:"rand"`
Type string `json:"type"`
Packet json.RawMessage `json:"packet"`
Delay Int32Range `json:"delay"`
Rand int32 `json:"rand"`
RandRange *Int32Range `json:"randRange"`
Type string `json:"type"`
Packet json.RawMessage `json:"packet"`
}
type HeaderCustomTCP struct {
@@ -1289,10 +1290,18 @@ func (c *HeaderCustomTCP) Build() (proto.Message, error) {
}
}
errInvalidRange := errors.New("invalid randRange")
clients := make([]*custom.TCPSequence, len(c.Clients))
for i, value := range c.Clients {
clients[i] = &custom.TCPSequence{}
for _, item := range value {
if item.RandRange == nil {
item.RandRange = &Int32Range{From: 0, To: 255}
}
if item.RandRange.From < 0 || item.RandRange.To > 255 {
return nil, errInvalidRange
}
var err error
if item.Packet, err = PraseByteSlice(item.Packet, item.Type); err != nil {
return nil, err
@@ -1301,6 +1310,8 @@ func (c *HeaderCustomTCP) Build() (proto.Message, error) {
DelayMin: int64(item.Delay.From),
DelayMax: int64(item.Delay.To),
Rand: item.Rand,
RandMin: item.RandRange.From,
RandMax: item.RandRange.To,
Packet: item.Packet,
})
}
@@ -1310,6 +1321,12 @@ func (c *HeaderCustomTCP) Build() (proto.Message, error) {
for i, value := range c.Servers {
servers[i] = &custom.TCPSequence{}
for _, item := range value {
if item.RandRange == nil {
item.RandRange = &Int32Range{From: 0, To: 255}
}
if item.RandRange.From < 0 || item.RandRange.To > 255 {
return nil, errInvalidRange
}
var err error
if item.Packet, err = PraseByteSlice(item.Packet, item.Type); err != nil {
return nil, err
@@ -1318,6 +1335,8 @@ func (c *HeaderCustomTCP) Build() (proto.Message, error) {
DelayMin: int64(item.Delay.From),
DelayMax: int64(item.Delay.To),
Rand: item.Rand,
RandMin: item.RandRange.From,
RandMax: item.RandRange.To,
Packet: item.Packet,
})
}
@@ -1327,6 +1346,12 @@ func (c *HeaderCustomTCP) Build() (proto.Message, error) {
for i, value := range c.Errors {
errors[i] = &custom.TCPSequence{}
for _, item := range value {
if item.RandRange == nil {
item.RandRange = &Int32Range{From: 0, To: 255}
}
if item.RandRange.From < 0 || item.RandRange.To > 255 {
return nil, errInvalidRange
}
var err error
if item.Packet, err = PraseByteSlice(item.Packet, item.Type); err != nil {
return nil, err
@@ -1335,6 +1360,8 @@ func (c *HeaderCustomTCP) Build() (proto.Message, error) {
DelayMin: int64(item.Delay.From),
DelayMax: int64(item.Delay.To),
Rand: item.Rand,
RandMin: item.RandRange.From,
RandMax: item.RandRange.To,
Packet: item.Packet,
})
}
@@ -1433,9 +1460,10 @@ func (c *NoiseMask) Build() (proto.Message, error) {
}
type UDPItem struct {
Rand int32 `json:"rand"`
Type string `json:"type"`
Packet json.RawMessage `json:"packet"`
Rand int32 `json:"rand"`
RandRange *Int32Range `json:"randRange"`
Type string `json:"type"`
Packet json.RawMessage `json:"packet"`
}
type HeaderCustomUDP struct {
@@ -1457,25 +1485,41 @@ func (c *HeaderCustomUDP) Build() (proto.Message, error) {
client := make([]*custom.UDPItem, 0, len(c.Client))
for _, item := range c.Client {
if item.RandRange == nil {
item.RandRange = &Int32Range{From: 0, To: 255}
}
if item.RandRange.From < 0 || item.RandRange.To > 255 {
return nil, errors.New("invalid randRange")
}
var err error
if item.Packet, err = PraseByteSlice(item.Packet, item.Type); err != nil {
return nil, err
}
client = append(client, &custom.UDPItem{
Rand: item.Rand,
Packet: item.Packet,
Rand: item.Rand,
RandMin: item.RandRange.From,
RandMax: item.RandRange.To,
Packet: item.Packet,
})
}
server := make([]*custom.UDPItem, 0, len(c.Server))
for _, item := range c.Server {
if item.RandRange == nil {
item.RandRange = &Int32Range{From: 0, To: 255}
}
if item.RandRange.From < 0 || item.RandRange.To > 255 {
return nil, errors.New("invalid randRange")
}
var err error
if item.Packet, err = PraseByteSlice(item.Packet, item.Type); err != nil {
return nil, err
}
server = append(server, &custom.UDPItem{
Rand: item.Rand,
Packet: item.Packet,
Rand: item.Rand,
RandMin: item.RandRange.From,
RandMax: item.RandRange.To,
Packet: item.Packet,
})
}

View File

@@ -3,14 +3,11 @@ package finalmask
import (
"context"
"net"
"sync"
"github.com/xtls/xray-core/common/errors"
)
const (
UDPSize = 4096 + 123
)
type Udpmask interface {
UDP()
@@ -29,27 +26,165 @@ func NewUdpmaskManager(udpmasks []Udpmask) *UdpmaskManager {
}
func (m *UdpmaskManager) WrapPacketConnClient(raw net.PacketConn) (net.PacketConn, error) {
var err error
var sizes []int
var conns []net.PacketConn
for i, mask := range m.udpmasks {
raw, err = mask.WrapPacketConnClient(raw, i, len(m.udpmasks)-1)
if err != nil {
return nil, err
if _, ok := mask.(headerConn); ok {
conn, err := mask.WrapPacketConnClient(nil, i, len(m.udpmasks)-1)
if err != nil {
return nil, err
}
sizes = append(sizes, conn.(headerSize).Size())
conns = append(conns, conn)
} else {
if len(conns) > 0 {
raw = &headerManagerConn{sizes: sizes, conns: conns, PacketConn: raw}
sizes = nil
conns = nil
}
var err error
raw, err = mask.WrapPacketConnClient(raw, i, len(m.udpmasks)-1)
if err != nil {
return nil, err
}
}
}
if len(conns) > 0 {
raw = &headerManagerConn{sizes: sizes, conns: conns, PacketConn: raw}
sizes = nil
conns = nil
}
return raw, nil
}
func (m *UdpmaskManager) WrapPacketConnServer(raw net.PacketConn) (net.PacketConn, error) {
var err error
var sizes []int
var conns []net.PacketConn
for i, mask := range m.udpmasks {
raw, err = mask.WrapPacketConnServer(raw, i, len(m.udpmasks)-1)
if err != nil {
return nil, err
if _, ok := mask.(headerConn); ok {
conn, err := mask.WrapPacketConnServer(nil, i, len(m.udpmasks)-1)
if err != nil {
return nil, err
}
sizes = append(sizes, conn.(headerSize).Size())
conns = append(conns, conn)
} else {
if len(conns) > 0 {
raw = &headerManagerConn{sizes: sizes, conns: conns, PacketConn: raw}
sizes = nil
conns = nil
}
var err error
raw, err = mask.WrapPacketConnServer(raw, i, len(m.udpmasks)-1)
if err != nil {
return nil, err
}
}
}
if len(conns) > 0 {
raw = &headerManagerConn{sizes: sizes, conns: conns, PacketConn: raw}
sizes = nil
conns = nil
}
return raw, nil
}
const (
UDPSize = 4096
)
type headerConn interface {
HeaderConn()
}
type headerSize interface {
Size() int
}
type headerManagerConn struct {
sizes []int
conns []net.PacketConn
net.PacketConn
m sync.Mutex
writeBuf [UDPSize]byte
}
func (c *headerManagerConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(buf) < UDPSize {
buf = make([]byte, UDPSize)
}
n, addr, err = c.PacketConn.ReadFrom(buf)
if n == 0 || err != nil {
return 0, addr, err
}
newBuf := buf[:n]
sum := 0
for _, size := range c.sizes {
sum += size
}
if n < sum {
errors.LogDebug(context.Background(), addr, " mask read err short length")
return 0, addr, nil
}
for i := range c.conns {
n, _, err = c.conns[i].ReadFrom(newBuf)
if n == 0 || err != nil {
errors.LogDebug(context.Background(), addr, " mask read err ", err)
return 0, addr, nil
}
newBuf = newBuf[c.sizes[i] : n+c.sizes[i]]
}
if len(p) < n {
errors.LogDebug(context.Background(), addr, " mask read err short buffer")
return 0, addr, nil
}
copy(p, buf[sum:sum+n])
return n, addr, nil
}
func (c *headerManagerConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
c.m.Lock()
defer c.m.Unlock()
sum := 0
for _, size := range c.sizes {
sum += size
}
if sum+len(p) > UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write")
return 0, nil
}
n = copy(c.writeBuf[sum:], p)
for i := len(c.conns) - 1; i >= 0; i-- {
n, err = c.conns[i].WriteTo(c.writeBuf[sum-c.sizes[i]:n+sum], nil)
if n == 0 || err != nil {
errors.LogDebug(context.Background(), addr, " mask write err ", err)
return 0, nil
}
sum -= c.sizes[i]
}
n, err = c.PacketConn.WriteTo(c.writeBuf[:n], addr)
if n == 0 || err != nil {
return n, err
}
return len(p), nil
}
type Tcpmask interface {
TCP()

View File

@@ -33,9 +33,6 @@ func NewConnServer(c *Config, raw net.Conn, server bool) (net.Conn, error) {
func (c *fragmentConn) TcpMaskConn() {}
func (c *fragmentConn) RawConn() net.Conn {
if c.server {
return c
}
return c.Conn
}

View File

@@ -25,3 +25,6 @@ func (c *UDPConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCou
func (c *UDPConfig) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnServerUDP(c, raw)
}
func (c *UDPConfig) HeaderConn() {
}

View File

@@ -26,7 +26,9 @@ type TCPItem struct {
DelayMin int64 `protobuf:"varint,1,opt,name=delay_min,json=delayMin,proto3" json:"delay_min,omitempty"`
DelayMax int64 `protobuf:"varint,2,opt,name=delay_max,json=delayMax,proto3" json:"delay_max,omitempty"`
Rand int32 `protobuf:"varint,3,opt,name=rand,proto3" json:"rand,omitempty"`
Packet []byte `protobuf:"bytes,4,opt,name=packet,proto3" json:"packet,omitempty"`
RandMin int32 `protobuf:"varint,4,opt,name=rand_min,json=randMin,proto3" json:"rand_min,omitempty"`
RandMax int32 `protobuf:"varint,5,opt,name=rand_max,json=randMax,proto3" json:"rand_max,omitempty"`
Packet []byte `protobuf:"bytes,6,opt,name=packet,proto3" json:"packet,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -82,6 +84,20 @@ func (x *TCPItem) GetRand() int32 {
return 0
}
func (x *TCPItem) GetRandMin() int32 {
if x != nil {
return x.RandMin
}
return 0
}
func (x *TCPItem) GetRandMax() int32 {
if x != nil {
return x.RandMax
}
return 0
}
func (x *TCPItem) GetPacket() []byte {
if x != nil {
return x.Packet
@@ -196,7 +212,9 @@ func (x *TCPConfig) GetErrors() []*TCPSequence {
type UDPItem struct {
state protoimpl.MessageState `protogen:"open.v1"`
Rand int32 `protobuf:"varint,1,opt,name=rand,proto3" json:"rand,omitempty"`
Packet []byte `protobuf:"bytes,2,opt,name=packet,proto3" json:"packet,omitempty"`
RandMin int32 `protobuf:"varint,2,opt,name=rand_min,json=randMin,proto3" json:"rand_min,omitempty"`
RandMax int32 `protobuf:"varint,3,opt,name=rand_max,json=randMax,proto3" json:"rand_max,omitempty"`
Packet []byte `protobuf:"bytes,4,opt,name=packet,proto3" json:"packet,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -238,6 +256,20 @@ func (x *UDPItem) GetRand() int32 {
return 0
}
func (x *UDPItem) GetRandMin() int32 {
if x != nil {
return x.RandMin
}
return 0
}
func (x *UDPItem) GetRandMax() int32 {
if x != nil {
return x.RandMax
}
return 0
}
func (x *UDPItem) GetPacket() []byte {
if x != nil {
return x.Packet
@@ -301,21 +333,25 @@ var File_transport_internet_finalmask_header_custom_config_proto protoreflect.Fi
const file_transport_internet_finalmask_header_custom_config_proto_rawDesc = "" +
"\n" +
"7transport/internet/finalmask/header/custom/config.proto\x12/xray.transport.internet.finalmask.header.custom\"o\n" +
"7transport/internet/finalmask/header/custom/config.proto\x12/xray.transport.internet.finalmask.header.custom\"\xa5\x01\n" +
"\aTCPItem\x12\x1b\n" +
"\tdelay_min\x18\x01 \x01(\x03R\bdelayMin\x12\x1b\n" +
"\tdelay_max\x18\x02 \x01(\x03R\bdelayMax\x12\x12\n" +
"\x04rand\x18\x03 \x01(\x05R\x04rand\x12\x16\n" +
"\x06packet\x18\x04 \x01(\fR\x06packet\"c\n" +
"\x04rand\x18\x03 \x01(\x05R\x04rand\x12\x19\n" +
"\brand_min\x18\x04 \x01(\x05R\arandMin\x12\x19\n" +
"\brand_max\x18\x05 \x01(\x05R\arandMax\x12\x16\n" +
"\x06packet\x18\x06 \x01(\fR\x06packet\"c\n" +
"\vTCPSequence\x12T\n" +
"\bsequence\x18\x01 \x03(\v28.xray.transport.internet.finalmask.header.custom.TCPItemR\bsequence\"\x91\x02\n" +
"\tTCPConfig\x12V\n" +
"\aclients\x18\x01 \x03(\v2<.xray.transport.internet.finalmask.header.custom.TCPSequenceR\aclients\x12V\n" +
"\aservers\x18\x02 \x03(\v2<.xray.transport.internet.finalmask.header.custom.TCPSequenceR\aservers\x12T\n" +
"\x06errors\x18\x03 \x03(\v2<.xray.transport.internet.finalmask.header.custom.TCPSequenceR\x06errors\"5\n" +
"\x06errors\x18\x03 \x03(\v2<.xray.transport.internet.finalmask.header.custom.TCPSequenceR\x06errors\"k\n" +
"\aUDPItem\x12\x12\n" +
"\x04rand\x18\x01 \x01(\x05R\x04rand\x12\x16\n" +
"\x06packet\x18\x02 \x01(\fR\x06packet\"\xaf\x01\n" +
"\x04rand\x18\x01 \x01(\x05R\x04rand\x12\x19\n" +
"\brand_min\x18\x02 \x01(\x05R\arandMin\x12\x19\n" +
"\brand_max\x18\x03 \x01(\x05R\arandMax\x12\x16\n" +
"\x06packet\x18\x04 \x01(\fR\x06packet\"\xaf\x01\n" +
"\tUDPConfig\x12P\n" +
"\x06client\x18\x01 \x03(\v28.xray.transport.internet.finalmask.header.custom.UDPItemR\x06client\x12P\n" +
"\x06server\x18\x02 \x03(\v28.xray.transport.internet.finalmask.header.custom.UDPItemR\x06serverB\xaf\x01\n" +

View File

@@ -10,7 +10,9 @@ message TCPItem {
int64 delay_min = 1;
int64 delay_max = 2;
int32 rand = 3;
bytes packet = 4;
int32 rand_min = 4;
int32 rand_max = 5;
bytes packet = 6;
}
message TCPSequence {
@@ -25,7 +27,9 @@ message TCPConfig {
message UDPItem {
int32 rand = 1;
bytes packet = 2;
int32 rand_min = 2;
int32 rand_max = 3;
bytes packet = 4;
}
message UDPConfig {

View File

@@ -2,13 +2,11 @@ package custom
import (
"bytes"
"crypto/rand"
"io"
"net"
"sync"
"time"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/errors"
)
@@ -231,7 +229,7 @@ func writeSequence(w io.Writer, sequence *TCPSequence) bool {
}
if item.Rand > 0 {
buf := make([]byte, item.Rand)
common.Must2(rand.Read(buf))
crypto.RandBytesBetween(buf, byte(item.RandMin), byte(item.RandMax))
merged = append(merged, buf...)
} else {
merged = append(merged, item.Packet...)

View File

@@ -2,13 +2,10 @@ package custom
import (
"bytes"
"context"
"crypto/rand"
"net"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
type udpCustomClient struct {
@@ -21,7 +18,7 @@ func (h *udpCustomClient) Serialize(b []byte) {
index := 0
for _, item := range h.client {
if item.Rand > 0 {
common.Must2(rand.Read(h.merged[index : index+int(item.Rand)]))
crypto.RandBytesBetween(h.merged[index:index+int(item.Rand)], byte(item.RandMin), byte(item.RandMax))
index += int(item.Rand)
} else {
index += len(item.Packet)
@@ -80,52 +77,20 @@ func NewConnClientUDP(c *UDPConfig, raw net.PacketConn) (net.PacketConn, error)
return conn, nil
}
func (c *udpCustomClientConn) Size() int {
return len(c.header.merged)
}
func (c *udpCustomClientConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(p) < finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
if !c.header.Match(p) {
return 0, addr, errors.New("header mismatch")
}
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if !c.header.Match(buf[:n]) {
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
return 0, addr, nil
}
if len(p) < n-len(c.header.merged) {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", n-len(c.header.merged))
return 0, addr, nil
}
copy(p, buf[len(c.header.merged):n])
return n - len(c.header.merged), addr, nil
return len(p) - len(c.header.merged), addr, nil
}
func (c *udpCustomClientConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if len(c.header.merged)+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", len(c.header.merged)+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:len(c.header.merged)+len(p)]
}
copy(buf[len(c.header.merged):], p)
c.header.Serialize(buf)
_, err = c.PacketConn.WriteTo(buf[:len(c.header.merged)+len(p)], addr)
if err != nil {
return 0, err
}
c.header.Serialize(p)
return len(p), nil
}
@@ -140,7 +105,7 @@ func (h *udpCustomServer) Serialize(b []byte) {
index := 0
for _, item := range h.server {
if item.Rand > 0 {
common.Must2(rand.Read(h.merged[index : index+int(item.Rand)]))
crypto.RandBytesBetween(h.merged[index:index+int(item.Rand)], byte(item.RandMin), byte(item.RandMax))
index += int(item.Rand)
} else {
index += len(item.Packet)
@@ -199,52 +164,20 @@ func NewConnServerUDP(c *UDPConfig, raw net.PacketConn) (net.PacketConn, error)
return conn, nil
}
func (c *udpCustomServerConn) Size() int {
return len(c.header.merged)
}
func (c *udpCustomServerConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(p) < finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
if !c.header.Match(p) {
return 0, addr, errors.New("header mismatch")
}
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if !c.header.Match(buf[:n]) {
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
return 0, addr, nil
}
if len(p) < n-len(c.header.merged) {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", n-len(c.header.merged))
return 0, addr, nil
}
copy(p, buf[len(c.header.merged):n])
return n - len(c.header.merged), addr, nil
return len(p) - len(c.header.merged), addr, nil
}
func (c *udpCustomServerConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if len(c.header.merged)+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", len(c.header.merged)+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:len(c.header.merged)+len(p)]
}
copy(buf[len(c.header.merged):], p)
c.header.Serialize(buf)
_, err = c.PacketConn.WriteTo(buf[:len(c.header.merged)+len(p)], addr)
if err != nil {
return 0, err
}
c.header.Serialize(p)
return len(p), nil
}

View File

@@ -14,3 +14,6 @@ func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnServer(c, raw)
}
func (c *Config) HeaderConn() {
}

View File

@@ -1,13 +1,11 @@
package dns
import (
"context"
"encoding/binary"
"net"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
func packDomainName(s string, msg []byte) (off1 int, err error) {
@@ -125,52 +123,16 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
return NewConnClient(c, raw)
}
func (c *dnsConn) Size() int {
return c.header.Size()
}
func (c *dnsConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(p) < finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
}
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if n < c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
return 0, addr, nil
}
if len(p) < n-c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", n-c.header.Size())
return 0, addr, nil
}
copy(p, buf[c.header.Size():n])
return n - c.header.Size(), addr, nil
return len(p) - c.header.Size(), addr, nil
}
func (c *dnsConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if c.header.Size()+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:c.header.Size()+len(p)]
}
copy(buf[c.header.Size():], p)
c.header.Serialize(buf)
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
if err != nil {
return 0, err
}
c.header.Serialize(p)
return len(p), nil
}

View File

@@ -14,3 +14,6 @@ func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnServer(c, raw)
}
func (c *Config) HeaderConn() {
}

View File

@@ -1,12 +1,9 @@
package dtls
import (
"context"
"net"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
type dtls struct {
@@ -62,52 +59,16 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
return NewConnClient(c, raw)
}
func (c *dtlsConn) Size() int {
return c.header.Size()
}
func (c *dtlsConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(p) < finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
}
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if n < c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
return 0, addr, nil
}
if len(p) < n-c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", n-c.header.Size())
return 0, addr, nil
}
copy(p, buf[c.header.Size():n])
return n - c.header.Size(), addr, nil
return len(p) - c.header.Size(), addr, nil
}
func (c *dtlsConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if c.header.Size()+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:c.header.Size()+len(p)]
}
copy(buf[c.header.Size():], p)
c.header.Serialize(buf)
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
if err != nil {
return 0, err
}
c.header.Serialize(p)
return len(p), nil
}

View File

@@ -14,3 +14,6 @@ func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnServer(c, raw)
}
func (c *Config) HeaderConn() {
}

View File

@@ -1,13 +1,10 @@
package srtp
import (
"context"
"encoding/binary"
"net"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
type srtp struct {
@@ -46,52 +43,16 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
return NewConnClient(c, raw)
}
func (c *srtpConn) Size() int {
return c.header.Size()
}
func (c *srtpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(p) < finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
}
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if n < c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
return 0, addr, nil
}
if len(p) < n-c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", n-c.header.Size())
return 0, addr, nil
}
copy(p, buf[c.header.Size():n])
return n - c.header.Size(), addr, nil
return len(p) - c.header.Size(), addr, nil
}
func (c *srtpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if c.header.Size()+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:c.header.Size()+len(p)]
}
copy(buf[c.header.Size():], p)
c.header.Serialize(buf)
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
if err != nil {
return 0, err
}
c.header.Serialize(p)
return len(p), nil
}

View File

@@ -14,3 +14,6 @@ func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnServer(c, raw)
}
func (c *Config) HeaderConn() {
}

View File

@@ -1,13 +1,10 @@
package utp
import (
"context"
"encoding/binary"
"net"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
type utp struct {
@@ -48,52 +45,16 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
return NewConnClient(c, raw)
}
func (c *utpConn) Size() int {
return c.header.Size()
}
func (c *utpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(p) < finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
}
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if n < c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
return 0, addr, nil
}
if len(p) < n-c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", n-c.header.Size())
return 0, addr, nil
}
copy(p, buf[c.header.Size():n])
return n - c.header.Size(), addr, nil
return len(p) - c.header.Size(), addr, nil
}
func (c *utpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if c.header.Size()+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:c.header.Size()+len(p)]
}
copy(buf[c.header.Size():], p)
c.header.Serialize(buf)
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
if err != nil {
return 0, err
}
c.header.Serialize(p)
return len(p), nil
}

View File

@@ -14,3 +14,6 @@ func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnServer(c, raw)
}
func (c *Config) HeaderConn() {
}

View File

@@ -1,13 +1,10 @@
package wechat
import (
"context"
"encoding/binary"
"net"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
type wechat struct {
@@ -52,52 +49,16 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
return NewConnClient(c, raw)
}
func (c *wechatConn) Size() int {
return c.header.Size()
}
func (c *wechatConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(p) < finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
}
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if n < c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
return 0, addr, nil
}
if len(p) < n-c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", n-c.header.Size())
return 0, addr, nil
}
copy(p, buf[c.header.Size():n])
return n - c.header.Size(), addr, nil
return len(p) - c.header.Size(), addr, nil
}
func (c *wechatConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if c.header.Size()+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:c.header.Size()+len(p)]
}
copy(buf[c.header.Size():], p)
c.header.Serialize(buf)
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
if err != nil {
return 0, err
}
c.header.Serialize(p)
return len(p), nil
}

View File

@@ -14,3 +14,6 @@ func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnServer(c, raw)
}
func (c *Config) HeaderConn() {
}

View File

@@ -1,11 +1,7 @@
package wireguard
import (
"context"
"net"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
type wireguare struct{}
@@ -39,52 +35,16 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
return NewConnClient(c, raw)
}
func (c *wireguareConn) Size() int {
return c.header.Size()
}
func (c *wireguareConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(p) < finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
}
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if n < c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
return 0, addr, nil
}
if len(p) < n-c.header.Size() {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", n-c.header.Size())
return 0, addr, nil
}
copy(p, buf[c.header.Size():n])
return n - c.header.Size(), addr, nil
return len(p) - c.header.Size(), addr, nil
}
func (c *wireguareConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if c.header.Size()+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:c.header.Size()+len(p)]
}
copy(buf[c.header.Size():], p)
c.header.Serialize(buf)
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
if err != nil {
return 0, err
}
c.header.Serialize(p)
return len(p), nil
}

View File

@@ -14,3 +14,6 @@ func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnServer(c, raw)
}
func (c *Config) HeaderConn() {
}

View File

@@ -1,7 +1,6 @@
package aes128gcm
import (
"context"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
@@ -33,86 +32,36 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
return NewConnClient(c, raw)
}
func (c *aes128gcmConn) Size() int {
return c.aead.NonceSize()
}
func (c *aes128gcmConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
if len(p) < finalmask.UDPSize {
buf := make([]byte, finalmask.UDPSize)
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if n < c.aead.NonceSize()+c.aead.Overhead() {
errors.LogDebug(context.Background(), addr, " mask read err aead short lenth ", n)
return 0, addr, nil
}
nonceSize := c.aead.NonceSize()
nonce := buf[:nonceSize]
ciphertext := buf[nonceSize:n]
plaintext, err := c.aead.Open(p[:0], nonce, ciphertext, nil)
if err != nil {
errors.LogDebug(context.Background(), addr, " mask read err aead open ", err)
return 0, addr, nil
}
if len(plaintext) > len(p) {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", len(plaintext))
return 0, addr, nil
}
return n - c.aead.NonceSize() - c.aead.Overhead(), addr, nil
}
n, addr, err = c.PacketConn.ReadFrom(p)
if err != nil || n == 0 {
return n, addr, err
}
if n < c.aead.NonceSize()+c.aead.Overhead() {
errors.LogDebug(context.Background(), addr, " mask read err aead short lenth ", n)
return 0, addr, nil
if len(p) < c.aead.NonceSize()+c.aead.Overhead() {
return 0, addr, errors.New("aead short lenth")
}
nonceSize := c.aead.NonceSize()
nonce := p[:nonceSize]
ciphertext := p[nonceSize:n]
ciphertext := p[nonceSize:]
_, err = c.aead.Open(ciphertext[:0], nonce, ciphertext, nil)
if err != nil {
errors.LogDebug(context.Background(), addr, " mask read err aead open ", err)
return 0, addr, nil
return 0, addr, errors.New("aead open").Base(err)
}
copy(p, p[nonceSize:n-c.aead.Overhead()])
return n - c.aead.NonceSize() - c.aead.Overhead(), addr, nil
return len(p) - c.aead.NonceSize() - c.aead.Overhead(), addr, nil
}
func (c *aes128gcmConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if c.aead.NonceSize()+c.aead.Overhead()+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.aead.NonceSize()+c.aead.Overhead()+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:c.aead.NonceSize()+c.aead.Overhead()+len(p)]
copy(buf[c.aead.NonceSize():], p)
p = buf[c.aead.NonceSize() : c.aead.NonceSize()+len(p)]
if c.aead.Overhead()+len(p) > finalmask.UDPSize {
return 0, errors.New("aead short write")
}
nonceSize := c.aead.NonceSize()
nonce := buf[:nonceSize]
nonce := p[:nonceSize]
common.Must2(rand.Read(nonce))
ciphertext := buf[nonceSize : c.aead.NonceSize()+c.aead.Overhead()+len(p)]
_ = c.aead.Seal(ciphertext[:0], nonce, p, nil)
plaintext := p[nonceSize:]
_ = c.aead.Seal(plaintext[:0], nonce, plaintext, nil)
_, err = c.PacketConn.WriteTo(buf[:c.aead.NonceSize()+c.aead.Overhead()+len(p)], addr)
if err != nil {
return 0, err
}
return len(p), nil
return len(p) + c.aead.Overhead(), nil
}

View File

@@ -14,3 +14,6 @@ func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnServer(c, raw)
}
func (c *Config) HeaderConn() {
}

View File

@@ -1,7 +1,6 @@
package original
import (
"context"
"crypto/cipher"
"encoding/binary"
"hash/fnv"
@@ -9,7 +8,6 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
type simple struct{}
@@ -91,60 +89,21 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
return NewConnClient(c, raw)
}
func (c *simpleConn) Size() int {
return c.aead.Overhead()
}
func (c *simpleConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(p) < finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
}
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if n < c.aead.Overhead() {
errors.LogDebug(context.Background(), addr, " mask read err aead short lenth ", n)
return 0, addr, nil
}
ciphertext := buf[:n]
opened, err := c.aead.Open(nil, nil, ciphertext, nil)
_, err = c.aead.Open(p[:0], nil, p, nil)
if err != nil {
errors.LogDebug(context.Background(), addr, " mask read err aead open ", err)
return 0, addr, nil
return 0, addr, errors.New("aead open").Base(err)
}
if len(opened) > len(p) {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", len(opened))
return 0, addr, nil
}
copy(p, opened)
return n - c.aead.Overhead(), addr, nil
return len(p) - c.aead.Overhead(), addr, nil
}
func (c *simpleConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if c.aead.Overhead()+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.aead.Overhead()+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:c.aead.Overhead()+len(p)]
copy(buf[c.aead.Overhead():], p)
p = buf[c.aead.Overhead() : c.aead.Overhead()+len(p)]
}
_ = c.aead.Seal(buf[:0], nil, p, nil)
_, err = c.PacketConn.WriteTo(buf[:c.aead.Overhead()+len(p)], addr)
if err != nil {
return 0, err
}
_ = c.aead.Seal(p[:0], nil, p[c.aead.Overhead():], nil)
return len(p), nil
}

View File

@@ -14,3 +14,6 @@ func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnServer(c, raw)
}
func (c *Config) HeaderConn() {
}

View File

@@ -1,11 +1,9 @@
package salamander
import (
"context"
"net"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
type salamanderConn struct {
@@ -31,53 +29,18 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
return NewConnClient(c, raw)
}
func (c *salamanderConn) Size() int {
return smSaltLen
}
func (c *salamanderConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
buf := p
if len(p) < finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
}
c.obfs.Deobfuscate(p, p[smSaltLen:])
n, addr, err = c.PacketConn.ReadFrom(buf)
if err != nil || n == 0 {
return n, addr, err
}
if n < smSaltLen {
errors.LogDebug(context.Background(), addr, " mask read err short lenth ", n)
return 0, addr, nil
}
if len(p) < n-smSaltLen {
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", n-smSaltLen)
return 0, addr, nil
}
c.obfs.Deobfuscate(buf[:n], p)
return n - smSaltLen, addr, nil
return len(p) - smSaltLen, addr, nil
}
func (c *salamanderConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
if smSaltLen+len(p) > finalmask.UDPSize {
errors.LogDebug(context.Background(), addr, " mask write err short write ", smSaltLen+len(p), " ", finalmask.UDPSize)
return 0, nil
}
var buf []byte
if cap(p) != finalmask.UDPSize {
buf = make([]byte, finalmask.UDPSize)
} else {
buf = p[:smSaltLen+len(p)]
copy(buf[smSaltLen:], p)
p = buf[smSaltLen:]
}
c.obfs.Obfuscate(p, buf)
_, err = c.PacketConn.WriteTo(buf[:smSaltLen+len(p)], addr)
if err != nil {
return 0, err
}
c.obfs.Obfuscate(p[smSaltLen:], p)
return len(p), nil
}

View File

@@ -35,10 +35,6 @@ func NewUDPConn(raw net.PacketConn, config *Config) (net.PacketConn, error) {
}, nil
}
func (c *udpConn) Size() int32 {
return 0
}
func (c *udpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
c.readMu.Lock()
defer c.readMu.Unlock()