mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-05-08 14:13:22 +00:00
Finalmask: Add header-custom (TCP & UDP), fragment (TCP), noise (UDP); Support dialer-proxy, XHTTP/3; Fix XDNS, XICMP potential panic (#5657)
https://github.com/XTLS/Xray-core/pull/5657#issuecomment-4016609446
This commit is contained in:
@@ -10,8 +10,8 @@ import (
|
||||
v2net "github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
"github.com/xtls/xray-core/proxy/freedom"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type FreedomConfig struct {
|
||||
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/fragment"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/header/custom"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/header/dns"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/header/dtls"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/header/srtp"
|
||||
@@ -26,6 +28,7 @@ import (
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/header/wireguard"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/mkcp/aes128gcm"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/mkcp/original"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/noise"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/salamander"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/xdns"
|
||||
"github.com/xtls/xray-core/transport/internet/finalmask/xicmp"
|
||||
@@ -1273,8 +1276,48 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func PraseByteSlice(data json.RawMessage, typ string) ([]byte, error) {
|
||||
switch strings.ToLower(typ) {
|
||||
case "", "array":
|
||||
if len(data) == 0 {
|
||||
return data, nil
|
||||
}
|
||||
var packet []byte
|
||||
if err := json.Unmarshal(data, &packet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return packet, nil
|
||||
case "str":
|
||||
var str string
|
||||
if err := json.Unmarshal(data, &str); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(str), nil
|
||||
case "hex":
|
||||
var str string
|
||||
if err := json.Unmarshal(data, &str); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hex.DecodeString(str)
|
||||
case "base64":
|
||||
var str string
|
||||
if err := json.Unmarshal(data, &str); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return base64.StdEncoding.DecodeString(str)
|
||||
default:
|
||||
return nil, errors.New("unknown type")
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
tcpmaskLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
||||
"header-custom": func() interface{} { return new(HeaderCustomTCP) },
|
||||
"fragment": func() interface{} { return new(FragmentMask) },
|
||||
}, "type", "settings")
|
||||
|
||||
udpmaskLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
||||
"header-custom": func() interface{} { return new(HeaderCustomUDP) },
|
||||
"header-dns": func() interface{} { return new(Dns) },
|
||||
"header-dtls": func() interface{} { return new(Dtls) },
|
||||
"header-srtp": func() interface{} { return new(Srtp) },
|
||||
@@ -1283,12 +1326,245 @@ var (
|
||||
"header-wireguard": func() interface{} { return new(Wireguard) },
|
||||
"mkcp-original": func() interface{} { return new(Original) },
|
||||
"mkcp-aes128gcm": func() interface{} { return new(Aes128Gcm) },
|
||||
"noise": func() interface{} { return new(NoiseMask) },
|
||||
"salamander": func() interface{} { return new(Salamander) },
|
||||
"xdns": func() interface{} { return new(Xdns) },
|
||||
"xicmp": func() interface{} { return new(Xicmp) },
|
||||
}, "type", "settings")
|
||||
)
|
||||
|
||||
type TCPItem struct {
|
||||
Delay Int32Range `json:"delay"`
|
||||
Rand int32 `json:"rand"`
|
||||
Type string `json:"type"`
|
||||
Packet json.RawMessage `json:"packet"`
|
||||
}
|
||||
|
||||
type HeaderCustomTCP struct {
|
||||
Clients [][]TCPItem `json:"clients"`
|
||||
Servers [][]TCPItem `json:"servers"`
|
||||
Errors [][]TCPItem `json:"errors"`
|
||||
}
|
||||
|
||||
func (c *HeaderCustomTCP) Build() (proto.Message, error) {
|
||||
for _, value := range c.Clients {
|
||||
for _, item := range value {
|
||||
if len(item.Packet) > 0 && item.Rand > 0 {
|
||||
return nil, errors.New("len(item.Packet) > 0 && item.Rand > 0")
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, value := range c.Servers {
|
||||
for _, item := range value {
|
||||
if len(item.Packet) > 0 && item.Rand > 0 {
|
||||
return nil, errors.New("len(item.Packet) > 0 && item.Rand > 0")
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, value := range c.Errors {
|
||||
for _, item := range value {
|
||||
if len(item.Packet) > 0 && item.Rand > 0 {
|
||||
return nil, errors.New("len(item.Packet) > 0 && item.Rand > 0")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clients := make([]*custom.TCPSequence, len(c.Clients))
|
||||
for i, value := range c.Clients {
|
||||
clients[i] = &custom.TCPSequence{}
|
||||
for _, item := range value {
|
||||
var err error
|
||||
if item.Packet, err = PraseByteSlice(item.Packet, item.Type); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clients[i].Sequence = append(clients[i].Sequence, &custom.TCPItem{
|
||||
DelayMin: int64(item.Delay.From),
|
||||
DelayMax: int64(item.Delay.To),
|
||||
Rand: item.Rand,
|
||||
Packet: item.Packet,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
servers := make([]*custom.TCPSequence, len(c.Servers))
|
||||
for i, value := range c.Servers {
|
||||
servers[i] = &custom.TCPSequence{}
|
||||
for _, item := range value {
|
||||
var err error
|
||||
if item.Packet, err = PraseByteSlice(item.Packet, item.Type); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
servers[i].Sequence = append(servers[i].Sequence, &custom.TCPItem{
|
||||
DelayMin: int64(item.Delay.From),
|
||||
DelayMax: int64(item.Delay.To),
|
||||
Rand: item.Rand,
|
||||
Packet: item.Packet,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
errors := make([]*custom.TCPSequence, len(c.Errors))
|
||||
for i, value := range c.Errors {
|
||||
errors[i] = &custom.TCPSequence{}
|
||||
for _, item := range value {
|
||||
var err error
|
||||
if item.Packet, err = PraseByteSlice(item.Packet, item.Type); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
errors[i].Sequence = append(errors[i].Sequence, &custom.TCPItem{
|
||||
DelayMin: int64(item.Delay.From),
|
||||
DelayMax: int64(item.Delay.To),
|
||||
Rand: item.Rand,
|
||||
Packet: item.Packet,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &custom.TCPConfig{
|
||||
Clients: clients,
|
||||
Servers: servers,
|
||||
Errors: errors,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type FragmentMask struct {
|
||||
Packets string `json:"packets"`
|
||||
Length Int32Range `json:"length"`
|
||||
Delay Int32Range `json:"delay"`
|
||||
MaxSplit Int32Range `json:"maxSplit"`
|
||||
}
|
||||
|
||||
func (c *FragmentMask) Build() (proto.Message, error) {
|
||||
config := &fragment.Config{}
|
||||
|
||||
switch strings.ToLower(c.Packets) {
|
||||
case "tlshello":
|
||||
config.PacketsFrom = 0
|
||||
config.PacketsTo = 1
|
||||
case "":
|
||||
config.PacketsFrom = 0
|
||||
config.PacketsTo = 0
|
||||
default:
|
||||
from, to, err := ParseRangeString(c.Packets)
|
||||
if err != nil {
|
||||
return nil, errors.New("Invalid PacketsFrom").Base(err)
|
||||
}
|
||||
config.PacketsFrom = int64(from)
|
||||
config.PacketsTo = int64(to)
|
||||
if config.PacketsFrom == 0 {
|
||||
return nil, errors.New("PacketsFrom can't be 0")
|
||||
}
|
||||
}
|
||||
|
||||
config.LengthMin = int64(c.Length.From)
|
||||
config.LengthMax = int64(c.Length.To)
|
||||
if config.LengthMin == 0 {
|
||||
return nil, errors.New("LengthMin can't be 0")
|
||||
}
|
||||
|
||||
config.DelayMin = int64(c.Delay.From)
|
||||
config.DelayMax = int64(c.Delay.To)
|
||||
|
||||
config.MaxSplitMin = int64(c.MaxSplit.From)
|
||||
config.MaxSplitMax = int64(c.MaxSplit.To)
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type NoiseItem struct {
|
||||
Rand Int32Range `json:"rand"`
|
||||
Type string `json:"type"`
|
||||
Packet json.RawMessage `json:"packet"`
|
||||
Delay Int32Range `json:"delay"`
|
||||
}
|
||||
|
||||
type NoiseMask struct {
|
||||
Reset Int32Range `json:"reset"`
|
||||
Noise []NoiseItem `json:"noise"`
|
||||
}
|
||||
|
||||
func (c *NoiseMask) Build() (proto.Message, error) {
|
||||
for _, item := range c.Noise {
|
||||
if len(item.Packet) > 0 && item.Rand.To > 0 {
|
||||
return nil, errors.New("len(item.Packet) > 0 && item.Rand.To > 0")
|
||||
}
|
||||
}
|
||||
|
||||
noiseSlice := make([]*noise.Item, 0, len(c.Noise))
|
||||
for _, item := range c.Noise {
|
||||
var err error
|
||||
if item.Packet, err = PraseByteSlice(item.Packet, item.Type); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
noiseSlice = append(noiseSlice, &noise.Item{
|
||||
RandMin: int64(item.Rand.From),
|
||||
RandMax: int64(item.Rand.To),
|
||||
Packet: item.Packet,
|
||||
DelayMin: int64(item.Delay.From),
|
||||
DelayMax: int64(item.Delay.To),
|
||||
})
|
||||
}
|
||||
|
||||
return &noise.Config{
|
||||
ResetMin: int64(c.Reset.From),
|
||||
ResetMax: int64(c.Reset.To),
|
||||
Items: noiseSlice,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type UDPItem struct {
|
||||
Rand int32 `json:"rand"`
|
||||
Type string `json:"type"`
|
||||
Packet json.RawMessage `json:"packet"`
|
||||
}
|
||||
|
||||
type HeaderCustomUDP struct {
|
||||
Client []UDPItem `json:"client"`
|
||||
Server []UDPItem `json:"server"`
|
||||
}
|
||||
|
||||
func (c *HeaderCustomUDP) Build() (proto.Message, error) {
|
||||
for _, item := range c.Client {
|
||||
if len(item.Packet) > 0 && item.Rand > 0 {
|
||||
return nil, errors.New("len(item.Packet) > 0 && item.Rand > 0")
|
||||
}
|
||||
}
|
||||
for _, item := range c.Server {
|
||||
if len(item.Packet) > 0 && item.Rand > 0 {
|
||||
return nil, errors.New("len(item.Packet) > 0 && item.Rand > 0")
|
||||
}
|
||||
}
|
||||
|
||||
client := make([]*custom.UDPItem, 0, len(c.Client))
|
||||
for _, item := range c.Client {
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
server := make([]*custom.UDPItem, 0, len(c.Server))
|
||||
for _, item := range c.Server {
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
return &custom.UDPConfig{
|
||||
Client: client,
|
||||
Server: server,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Dns struct {
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
@@ -1400,7 +1676,7 @@ type Mask struct {
|
||||
func (c *Mask) Build(tcp bool) (proto.Message, error) {
|
||||
loader := udpmaskLoader
|
||||
if tcp {
|
||||
return nil, errors.New("")
|
||||
loader = tcpmaskLoader
|
||||
}
|
||||
|
||||
settings := []byte("{}")
|
||||
|
||||
Reference in New Issue
Block a user