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:
1 parent
ea87941b77
commit
a204873d79
62 files changed
+3045
-1367
No files matched your search
@@ -0,0 +1,128 @@
|
||||
package fragment
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common/crypto"
|
||||
)
|
||||
|
||||
type fragmentConn struct {
|
||||
net.Conn
|
||||
config *Config
|
||||
count uint64
|
||||
|
||||
server bool
|
||||
}
|
||||
|
||||
func NewConnClient(c *Config, raw net.Conn, server bool) (net.Conn, error) {
|
||||
conn := &fragmentConn{
|
||||
Conn: raw,
|
||||
config: c,
|
||||
|
||||
server: server,
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func NewConnServer(c *Config, raw net.Conn, server bool) (net.Conn, error) {
|
||||
return NewConnClient(c, raw, server)
|
||||
}
|
||||
|
||||
func (c *fragmentConn) TcpMaskConn() {}
|
||||
|
||||
func (c *fragmentConn) RawConn() net.Conn {
|
||||
if c.server {
|
||||
return c
|
||||
}
|
||||
return c.Conn
|
||||
}
|
||||
|
||||
func (c *fragmentConn) Splice() bool {
|
||||
if c.server {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *fragmentConn) Write(p []byte) (n int, err error) {
|
||||
c.count++
|
||||
|
||||
if c.config.PacketsFrom == 0 && c.config.PacketsTo == 1 {
|
||||
if c.count != 1 || len(p) <= 5 || p[0] != 22 {
|
||||
return c.Conn.Write(p)
|
||||
}
|
||||
recordLen := 5 + ((int(p[3]) << 8) | int(p[4]))
|
||||
if len(p) < recordLen {
|
||||
return c.Conn.Write(p)
|
||||
}
|
||||
data := p[5:recordLen]
|
||||
buff := make([]byte, 2048)
|
||||
var hello []byte
|
||||
maxSplit := crypto.RandBetween(c.config.MaxSplitMin, c.config.MaxSplitMax)
|
||||
var splitNum int64
|
||||
for from := 0; ; {
|
||||
to := from + int(crypto.RandBetween(c.config.LengthMin, c.config.LengthMax))
|
||||
splitNum++
|
||||
if to > len(data) || (maxSplit > 0 && splitNum >= maxSplit) {
|
||||
to = len(data)
|
||||
}
|
||||
l := to - from
|
||||
if 5+l > len(buff) {
|
||||
buff = make([]byte, 5+l)
|
||||
}
|
||||
copy(buff[:3], p)
|
||||
copy(buff[5:], data[from:to])
|
||||
from = to
|
||||
buff[3] = byte(l >> 8)
|
||||
buff[4] = byte(l)
|
||||
if c.config.DelayMax == 0 {
|
||||
hello = append(hello, buff[:5+l]...)
|
||||
} else {
|
||||
_, err := c.Conn.Write(buff[:5+l])
|
||||
time.Sleep(time.Duration(crypto.RandBetween(c.config.DelayMin, c.config.DelayMax)) * time.Millisecond)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
if from == len(data) {
|
||||
if len(hello) > 0 {
|
||||
_, err := c.Conn.Write(hello)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
if len(p) > recordLen {
|
||||
n, err := c.Conn.Write(p[recordLen:])
|
||||
if err != nil {
|
||||
return recordLen + n, err
|
||||
}
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if c.config.PacketsFrom != 0 && (c.count < uint64(c.config.PacketsFrom) || c.count > uint64(c.config.PacketsTo)) {
|
||||
return c.Conn.Write(p)
|
||||
}
|
||||
maxSplit := crypto.RandBetween(c.config.MaxSplitMin, c.config.MaxSplitMax)
|
||||
var splitNum int64
|
||||
for from := 0; ; {
|
||||
to := from + int(crypto.RandBetween(c.config.LengthMin, c.config.LengthMax))
|
||||
splitNum++
|
||||
if to > len(p) || (maxSplit > 0 && splitNum >= maxSplit) {
|
||||
to = len(p)
|
||||
}
|
||||
n, err := c.Conn.Write(p[from:to])
|
||||
from += n
|
||||
if err != nil {
|
||||
return from, err
|
||||
}
|
||||
time.Sleep(time.Duration(crypto.RandBetween(c.config.DelayMin, c.config.DelayMax)) * time.Millisecond)
|
||||
if from >= len(p) {
|
||||
return from, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user