mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-22 22:58:03 +03: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,46 +10,46 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConnectionOption func(*connection)
|
type ConnectionOption func(*Connection)
|
||||||
|
|
||||||
func ConnectionLocalAddr(a net.Addr) ConnectionOption {
|
func ConnectionLocalAddr(a net.Addr) ConnectionOption {
|
||||||
return func(c *connection) {
|
return func(c *Connection) {
|
||||||
c.local = a
|
c.local = a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectionRemoteAddr(a net.Addr) ConnectionOption {
|
func ConnectionRemoteAddr(a net.Addr) ConnectionOption {
|
||||||
return func(c *connection) {
|
return func(c *Connection) {
|
||||||
c.remote = a
|
c.remote = a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectionInput(writer io.Writer) ConnectionOption {
|
func ConnectionInput(writer io.Writer) ConnectionOption {
|
||||||
return func(c *connection) {
|
return func(c *Connection) {
|
||||||
c.writer = buf.NewWriter(writer)
|
c.writer = buf.NewWriter(writer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectionInputMulti(writer buf.Writer) ConnectionOption {
|
func ConnectionInputMulti(writer buf.Writer) ConnectionOption {
|
||||||
return func(c *connection) {
|
return func(c *Connection) {
|
||||||
c.writer = writer
|
c.writer = writer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectionOutput(reader io.Reader) ConnectionOption {
|
func ConnectionOutput(reader io.Reader) ConnectionOption {
|
||||||
return func(c *connection) {
|
return func(c *Connection) {
|
||||||
c.reader = &buf.BufferedReader{Reader: buf.NewReader(reader)}
|
c.reader = &buf.BufferedReader{Reader: buf.NewReader(reader)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectionOutputMulti(reader buf.Reader) ConnectionOption {
|
func ConnectionOutputMulti(reader buf.Reader) ConnectionOption {
|
||||||
return func(c *connection) {
|
return func(c *Connection) {
|
||||||
c.reader = &buf.BufferedReader{Reader: reader}
|
c.reader = &buf.BufferedReader{Reader: reader}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectionOutputMultiUDP(reader buf.Reader) ConnectionOption {
|
func ConnectionOutputMultiUDP(reader buf.Reader) ConnectionOption {
|
||||||
return func(c *connection) {
|
return func(c *Connection) {
|
||||||
c.reader = &buf.BufferedReader{
|
c.reader = &buf.BufferedReader{
|
||||||
Reader: reader,
|
Reader: reader,
|
||||||
Splitter: buf.SplitFirstBytes,
|
Splitter: buf.SplitFirstBytes,
|
||||||
@@ -58,13 +58,13 @@ func ConnectionOutputMultiUDP(reader buf.Reader) ConnectionOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ConnectionOnClose(n io.Closer) ConnectionOption {
|
func ConnectionOnClose(n io.Closer) ConnectionOption {
|
||||||
return func(c *connection) {
|
return func(c *Connection) {
|
||||||
c.onClose = n
|
c.onClose = n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnection(opts ...ConnectionOption) net.Conn {
|
func NewConnection(opts ...ConnectionOption) net.Conn {
|
||||||
c := &connection{
|
c := &Connection{
|
||||||
done: done.New(),
|
done: done.New(),
|
||||||
local: &net.TCPAddr{
|
local: &net.TCPAddr{
|
||||||
IP: []byte{0, 0, 0, 0},
|
IP: []byte{0, 0, 0, 0},
|
||||||
@@ -83,7 +83,7 @@ func NewConnection(opts ...ConnectionOption) net.Conn {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
type connection struct {
|
type Connection struct {
|
||||||
reader *buf.BufferedReader
|
reader *buf.BufferedReader
|
||||||
writer buf.Writer
|
writer buf.Writer
|
||||||
done *done.Instance
|
done *done.Instance
|
||||||
@@ -92,17 +92,17 @@ type connection struct {
|
|||||||
remote net.Addr
|
remote net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connection) Read(b []byte) (int, error) {
|
func (c *Connection) Read(b []byte) (int, error) {
|
||||||
return c.reader.Read(b)
|
return c.reader.Read(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadMultiBuffer implements buf.Reader.
|
// ReadMultiBuffer implements buf.Reader.
|
||||||
func (c *connection) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
func (c *Connection) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||||
return c.reader.ReadMultiBuffer()
|
return c.reader.ReadMultiBuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write implements net.Conn.Write().
|
// Write implements net.Conn.Write().
|
||||||
func (c *connection) Write(b []byte) (int, error) {
|
func (c *Connection) Write(b []byte) (int, error) {
|
||||||
if c.done.Done() {
|
if c.done.Done() {
|
||||||
return 0, io.ErrClosedPipe
|
return 0, io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ func (c *connection) Write(b []byte) (int, error) {
|
|||||||
return l, c.writer.WriteMultiBuffer(mb)
|
return l, c.writer.WriteMultiBuffer(mb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *connection) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
func (c *Connection) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||||
if c.done.Done() {
|
if c.done.Done() {
|
||||||
buf.ReleaseMulti(mb)
|
buf.ReleaseMulti(mb)
|
||||||
return io.ErrClosedPipe
|
return io.ErrClosedPipe
|
||||||
@@ -123,7 +123,7 @@ func (c *connection) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Close implements net.Conn.Close().
|
// Close implements net.Conn.Close().
|
||||||
func (c *connection) Close() error {
|
func (c *Connection) Close() error {
|
||||||
common.Must(c.done.Close())
|
common.Must(c.done.Close())
|
||||||
common.Interrupt(c.reader)
|
common.Interrupt(c.reader)
|
||||||
common.Close(c.writer)
|
common.Close(c.writer)
|
||||||
@@ -135,26 +135,26 @@ func (c *connection) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LocalAddr implements net.Conn.LocalAddr().
|
// LocalAddr implements net.Conn.LocalAddr().
|
||||||
func (c *connection) LocalAddr() net.Addr {
|
func (c *Connection) LocalAddr() net.Addr {
|
||||||
return c.local
|
return c.local
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteAddr implements net.Conn.RemoteAddr().
|
// RemoteAddr implements net.Conn.RemoteAddr().
|
||||||
func (c *connection) RemoteAddr() net.Addr {
|
func (c *Connection) RemoteAddr() net.Addr {
|
||||||
return c.remote
|
return c.remote
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeadline implements net.Conn.SetDeadline().
|
// SetDeadline implements net.Conn.SetDeadline().
|
||||||
func (c *connection) SetDeadline(t time.Time) error {
|
func (c *Connection) SetDeadline(t time.Time) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetReadDeadline implements net.Conn.SetReadDeadline().
|
// SetReadDeadline implements net.Conn.SetReadDeadline().
|
||||||
func (c *connection) SetReadDeadline(t time.Time) error {
|
func (c *Connection) SetReadDeadline(t time.Time) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetWriteDeadline implements net.Conn.SetWriteDeadline().
|
// SetWriteDeadline implements net.Conn.SetWriteDeadline().
|
||||||
func (c *connection) SetWriteDeadline(t time.Time) error {
|
func (c *Connection) SetWriteDeadline(t time.Time) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
v2net "github.com/xtls/xray-core/common/net"
|
v2net "github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/proxy/freedom"
|
"github.com/xtls/xray-core/proxy/freedom"
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FreedomConfig struct {
|
type FreedomConfig struct {
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"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/dns"
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask/header/dtls"
|
"github.com/xtls/xray-core/transport/internet/finalmask/header/dtls"
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask/header/srtp"
|
"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/header/wireguard"
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask/mkcp/aes128gcm"
|
"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/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/salamander"
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask/xdns"
|
"github.com/xtls/xray-core/transport/internet/finalmask/xdns"
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask/xicmp"
|
"github.com/xtls/xray-core/transport/internet/finalmask/xicmp"
|
||||||
@@ -1273,8 +1276,48 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|||||||
}, nil
|
}, 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 (
|
var (
|
||||||
|
tcpmaskLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
||||||
|
"header-custom": func() interface{} { return new(HeaderCustomTCP) },
|
||||||
|
"fragment": func() interface{} { return new(FragmentMask) },
|
||||||
|
}, "type", "settings")
|
||||||
|
|
||||||
udpmaskLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
udpmaskLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
||||||
|
"header-custom": func() interface{} { return new(HeaderCustomUDP) },
|
||||||
"header-dns": func() interface{} { return new(Dns) },
|
"header-dns": func() interface{} { return new(Dns) },
|
||||||
"header-dtls": func() interface{} { return new(Dtls) },
|
"header-dtls": func() interface{} { return new(Dtls) },
|
||||||
"header-srtp": func() interface{} { return new(Srtp) },
|
"header-srtp": func() interface{} { return new(Srtp) },
|
||||||
@@ -1283,12 +1326,245 @@ var (
|
|||||||
"header-wireguard": func() interface{} { return new(Wireguard) },
|
"header-wireguard": func() interface{} { return new(Wireguard) },
|
||||||
"mkcp-original": func() interface{} { return new(Original) },
|
"mkcp-original": func() interface{} { return new(Original) },
|
||||||
"mkcp-aes128gcm": func() interface{} { return new(Aes128Gcm) },
|
"mkcp-aes128gcm": func() interface{} { return new(Aes128Gcm) },
|
||||||
|
"noise": func() interface{} { return new(NoiseMask) },
|
||||||
"salamander": func() interface{} { return new(Salamander) },
|
"salamander": func() interface{} { return new(Salamander) },
|
||||||
"xdns": func() interface{} { return new(Xdns) },
|
"xdns": func() interface{} { return new(Xdns) },
|
||||||
"xicmp": func() interface{} { return new(Xicmp) },
|
"xicmp": func() interface{} { return new(Xicmp) },
|
||||||
}, "type", "settings")
|
}, "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 {
|
type Dns struct {
|
||||||
Domain string `json:"domain"`
|
Domain string `json:"domain"`
|
||||||
}
|
}
|
||||||
@@ -1400,7 +1676,7 @@ type Mask struct {
|
|||||||
func (c *Mask) Build(tcp bool) (proto.Message, error) {
|
func (c *Mask) Build(tcp bool) (proto.Message, error) {
|
||||||
loader := udpmaskLoader
|
loader := udpmaskLoader
|
||||||
if tcp {
|
if tcp {
|
||||||
return nil, errors.New("")
|
loader = tcpmaskLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
settings := []byte("{}")
|
settings := []byte("{}")
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/proxy/vless/encryption"
|
"github.com/xtls/xray-core/proxy/vless/encryption"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
"github.com/xtls/xray-core/transport/internet/reality"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
@@ -687,6 +688,9 @@ func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
|
|||||||
conn = realityUConn.NetConn()
|
conn = realityUConn.NetConn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conn = finalmask.UnwrapTcpMask(conn)
|
||||||
|
|
||||||
if pc, ok := conn.(*proxyproto.Conn); ok {
|
if pc, ok := conn.(*proxyproto.Conn); ok {
|
||||||
conn = pc.Raw()
|
conn = pc.Raw()
|
||||||
// 8192 > 4096, there is no need to process pc's bufReader
|
// 8192 > 4096, there is no need to process pc's bufReader
|
||||||
@@ -788,6 +792,7 @@ func readV(ctx context.Context, reader buf.Reader, writer buf.Writer, timer sign
|
|||||||
|
|
||||||
func IsRAWTransportWithoutSecurity(conn stat.Connection) bool {
|
func IsRAWTransportWithoutSecurity(conn stat.Connection) bool {
|
||||||
iConn := stat.TryUnwrapStatsConn(conn)
|
iConn := stat.TryUnwrapStatsConn(conn)
|
||||||
|
iConn = finalmask.UnwrapTcpMask(iConn)
|
||||||
_, ok1 := iConn.(*proxyproto.Conn)
|
_, ok1 := iConn.(*proxyproto.Conn)
|
||||||
_, ok2 := iConn.(*net.TCPConn)
|
_, ok2 := iConn.(*net.TCPConn)
|
||||||
_, ok3 := iConn.(*internet.UnixConnWrapper)
|
_, ok3 := iConn.(*internet.UnixConnWrapper)
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
package finalmask
|
package finalmask
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConnSize interface {
|
const (
|
||||||
Size() int32
|
UDPSize = 4096 + 123
|
||||||
}
|
)
|
||||||
|
|
||||||
type Udpmask interface {
|
type Udpmask interface {
|
||||||
UDP()
|
UDP()
|
||||||
|
|
||||||
WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error)
|
WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error)
|
||||||
WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error)
|
WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UdpmaskManager struct {
|
type UdpmaskManager struct {
|
||||||
@@ -26,27 +29,23 @@ func NewUdpmaskManager(udpmasks []Udpmask) *UdpmaskManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *UdpmaskManager) WrapPacketConnClient(raw net.PacketConn) (net.PacketConn, error) {
|
func (m *UdpmaskManager) WrapPacketConnClient(raw net.PacketConn) (net.PacketConn, error) {
|
||||||
leaveSize := int32(0)
|
|
||||||
var err error
|
var err error
|
||||||
for i, mask := range m.udpmasks {
|
for i, mask := range m.udpmasks {
|
||||||
raw, err = mask.WrapPacketConnClient(raw, i == len(m.udpmasks)-1, leaveSize, i == 0)
|
raw, err = mask.WrapPacketConnClient(raw, i, len(m.udpmasks)-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
leaveSize += raw.(ConnSize).Size()
|
|
||||||
}
|
}
|
||||||
return raw, nil
|
return raw, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UdpmaskManager) WrapPacketConnServer(raw net.PacketConn) (net.PacketConn, error) {
|
func (m *UdpmaskManager) WrapPacketConnServer(raw net.PacketConn) (net.PacketConn, error) {
|
||||||
leaveSize := int32(0)
|
|
||||||
var err error
|
var err error
|
||||||
for i, mask := range m.udpmasks {
|
for i, mask := range m.udpmasks {
|
||||||
raw, err = mask.WrapPacketConnServer(raw, i == len(m.udpmasks)-1, leaveSize, i == 0)
|
raw, err = mask.WrapPacketConnServer(raw, i, len(m.udpmasks)-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
leaveSize += raw.(ConnSize).Size()
|
|
||||||
}
|
}
|
||||||
return raw, nil
|
return raw, nil
|
||||||
}
|
}
|
||||||
@@ -89,3 +88,54 @@ func (m *TcpmaskManager) WrapConnServer(raw net.Conn) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
return raw, nil
|
return raw, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *TcpmaskManager) WrapListener(l net.Listener) (net.Listener, error) {
|
||||||
|
return NewTcpListener(m, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
type tcpListener struct {
|
||||||
|
m *TcpmaskManager
|
||||||
|
net.Listener
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTcpListener(m *TcpmaskManager, l net.Listener) (net.Listener, error) {
|
||||||
|
return &tcpListener{
|
||||||
|
m: m,
|
||||||
|
Listener: l,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tcpListener) Accept() (net.Conn, error) {
|
||||||
|
conn, err := l.Listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return conn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newConn, err := l.m.WrapConnServer(conn)
|
||||||
|
if err != nil {
|
||||||
|
errors.LogDebugInner(context.Background(), err, "mask err")
|
||||||
|
// conn.Close()
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return newConn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TcpMaskConn interface {
|
||||||
|
TcpMaskConn()
|
||||||
|
RawConn() net.Conn
|
||||||
|
Splice() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnwrapTcpMask(conn net.Conn) net.Conn {
|
||||||
|
for {
|
||||||
|
if v, ok := conn.(TcpMaskConn); ok {
|
||||||
|
if !v.Splice() {
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
conn = v.RawConn()
|
||||||
|
} else {
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package fragment
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func (c *Config) TCP() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) WrapConnClient(raw net.Conn) (net.Conn, error) {
|
||||||
|
return NewConnClient(c, raw, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) WrapConnServer(raw net.Conn) (net.Conn, error) {
|
||||||
|
return NewConnServer(c, raw, true)
|
||||||
|
}
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.36.11
|
||||||
|
// protoc v6.33.5
|
||||||
|
// source: transport/internet/finalmask/fragment/config.proto
|
||||||
|
|
||||||
|
package fragment
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
PacketsFrom int64 `protobuf:"varint,1,opt,name=packets_from,json=packetsFrom,proto3" json:"packets_from,omitempty"`
|
||||||
|
PacketsTo int64 `protobuf:"varint,2,opt,name=packets_to,json=packetsTo,proto3" json:"packets_to,omitempty"`
|
||||||
|
LengthMin int64 `protobuf:"varint,3,opt,name=length_min,json=lengthMin,proto3" json:"length_min,omitempty"`
|
||||||
|
LengthMax int64 `protobuf:"varint,4,opt,name=length_max,json=lengthMax,proto3" json:"length_max,omitempty"`
|
||||||
|
DelayMin int64 `protobuf:"varint,5,opt,name=delay_min,json=delayMin,proto3" json:"delay_min,omitempty"`
|
||||||
|
DelayMax int64 `protobuf:"varint,6,opt,name=delay_max,json=delayMax,proto3" json:"delay_max,omitempty"`
|
||||||
|
MaxSplitMin int64 `protobuf:"varint,7,opt,name=max_split_min,json=maxSplitMin,proto3" json:"max_split_min,omitempty"`
|
||||||
|
MaxSplitMax int64 `protobuf:"varint,8,opt,name=max_split_max,json=maxSplitMax,proto3" json:"max_split_max,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) Reset() {
|
||||||
|
*x = Config{}
|
||||||
|
mi := &file_transport_internet_finalmask_fragment_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_transport_internet_finalmask_fragment_config_proto_msgTypes[0]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
|
return file_transport_internet_finalmask_fragment_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetPacketsFrom() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.PacketsFrom
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetPacketsTo() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.PacketsTo
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetLengthMin() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.LengthMin
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetLengthMax() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.LengthMax
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetDelayMin() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.DelayMin
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetDelayMax() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.DelayMax
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetMaxSplitMin() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.MaxSplitMin
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetMaxSplitMax() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.MaxSplitMax
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_transport_internet_finalmask_fragment_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
const file_transport_internet_finalmask_fragment_config_proto_rawDesc = "" +
|
||||||
|
"\n" +
|
||||||
|
"2transport/internet/finalmask/fragment/config.proto\x12*xray.transport.internet.finalmask.fragment\"\x8a\x02\n" +
|
||||||
|
"\x06Config\x12!\n" +
|
||||||
|
"\fpackets_from\x18\x01 \x01(\x03R\vpacketsFrom\x12\x1d\n" +
|
||||||
|
"\n" +
|
||||||
|
"packets_to\x18\x02 \x01(\x03R\tpacketsTo\x12\x1d\n" +
|
||||||
|
"\n" +
|
||||||
|
"length_min\x18\x03 \x01(\x03R\tlengthMin\x12\x1d\n" +
|
||||||
|
"\n" +
|
||||||
|
"length_max\x18\x04 \x01(\x03R\tlengthMax\x12\x1b\n" +
|
||||||
|
"\tdelay_min\x18\x05 \x01(\x03R\bdelayMin\x12\x1b\n" +
|
||||||
|
"\tdelay_max\x18\x06 \x01(\x03R\bdelayMax\x12\"\n" +
|
||||||
|
"\rmax_split_min\x18\a \x01(\x03R\vmaxSplitMin\x12\"\n" +
|
||||||
|
"\rmax_split_max\x18\b \x01(\x03R\vmaxSplitMaxB\xa0\x01\n" +
|
||||||
|
".com.xray.transport.internet.finalmask.fragmentP\x01Z?github.com/xtls/xray-core/transport/internet/finalmask/fragment\xaa\x02*Xray.Transport.Internet.Finalmask.Fragmentb\x06proto3"
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_transport_internet_finalmask_fragment_config_proto_rawDescOnce sync.Once
|
||||||
|
file_transport_internet_finalmask_fragment_config_proto_rawDescData []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_transport_internet_finalmask_fragment_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_transport_internet_finalmask_fragment_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_transport_internet_finalmask_fragment_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_transport_internet_finalmask_fragment_config_proto_rawDesc), len(file_transport_internet_finalmask_fragment_config_proto_rawDesc)))
|
||||||
|
})
|
||||||
|
return file_transport_internet_finalmask_fragment_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_transport_internet_finalmask_fragment_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||||
|
var file_transport_internet_finalmask_fragment_config_proto_goTypes = []any{
|
||||||
|
(*Config)(nil), // 0: xray.transport.internet.finalmask.fragment.Config
|
||||||
|
}
|
||||||
|
var file_transport_internet_finalmask_fragment_config_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_transport_internet_finalmask_fragment_config_proto_init() }
|
||||||
|
func file_transport_internet_finalmask_fragment_config_proto_init() {
|
||||||
|
if File_transport_internet_finalmask_fragment_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_transport_internet_finalmask_fragment_config_proto_rawDesc), len(file_transport_internet_finalmask_fragment_config_proto_rawDesc)),
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 1,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_transport_internet_finalmask_fragment_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_transport_internet_finalmask_fragment_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_transport_internet_finalmask_fragment_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_transport_internet_finalmask_fragment_config_proto = out.File
|
||||||
|
file_transport_internet_finalmask_fragment_config_proto_goTypes = nil
|
||||||
|
file_transport_internet_finalmask_fragment_config_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.transport.internet.finalmask.fragment;
|
||||||
|
option csharp_namespace = "Xray.Transport.Internet.Finalmask.Fragment";
|
||||||
|
option go_package = "github.com/xtls/xray-core/transport/internet/finalmask/fragment";
|
||||||
|
option java_package = "com.xray.transport.internet.finalmask.fragment";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
message Config {
|
||||||
|
int64 packets_from = 1;
|
||||||
|
int64 packets_to = 2;
|
||||||
|
int64 length_min = 3;
|
||||||
|
int64 length_max = 4;
|
||||||
|
int64 delay_min = 5;
|
||||||
|
int64 delay_max = 6;
|
||||||
|
int64 max_split_min = 7;
|
||||||
|
int64 max_split_max = 8;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package custom
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *TCPConfig) TCP() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TCPConfig) WrapConnClient(raw net.Conn) (net.Conn, error) {
|
||||||
|
return NewConnClientTCP(c, raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TCPConfig) WrapConnServer(raw net.Conn) (net.Conn, error) {
|
||||||
|
return NewConnServerTCP(c, raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConfig) UDP() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
|
return NewConnClientUDP(c, raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *UDPConfig) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
|
return NewConnServerUDP(c, raw)
|
||||||
|
}
|
||||||
@@ -0,0 +1,380 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.36.11
|
||||||
|
// protoc v6.33.5
|
||||||
|
// source: transport/internet/finalmask/header/custom/config.proto
|
||||||
|
|
||||||
|
package custom
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type TCPItem struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
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"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPItem) Reset() {
|
||||||
|
*x = TCPItem{}
|
||||||
|
mi := &file_transport_internet_finalmask_header_custom_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPItem) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*TCPItem) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *TCPItem) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_transport_internet_finalmask_header_custom_config_proto_msgTypes[0]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use TCPItem.ProtoReflect.Descriptor instead.
|
||||||
|
func (*TCPItem) Descriptor() ([]byte, []int) {
|
||||||
|
return file_transport_internet_finalmask_header_custom_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPItem) GetDelayMin() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.DelayMin
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPItem) GetDelayMax() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.DelayMax
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPItem) GetRand() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Rand
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPItem) GetPacket() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Packet
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TCPSequence struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Sequence []*TCPItem `protobuf:"bytes,1,rep,name=sequence,proto3" json:"sequence,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPSequence) Reset() {
|
||||||
|
*x = TCPSequence{}
|
||||||
|
mi := &file_transport_internet_finalmask_header_custom_config_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPSequence) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*TCPSequence) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *TCPSequence) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_transport_internet_finalmask_header_custom_config_proto_msgTypes[1]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use TCPSequence.ProtoReflect.Descriptor instead.
|
||||||
|
func (*TCPSequence) Descriptor() ([]byte, []int) {
|
||||||
|
return file_transport_internet_finalmask_header_custom_config_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPSequence) GetSequence() []*TCPItem {
|
||||||
|
if x != nil {
|
||||||
|
return x.Sequence
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TCPConfig struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Clients []*TCPSequence `protobuf:"bytes,1,rep,name=clients,proto3" json:"clients,omitempty"`
|
||||||
|
Servers []*TCPSequence `protobuf:"bytes,2,rep,name=servers,proto3" json:"servers,omitempty"`
|
||||||
|
Errors []*TCPSequence `protobuf:"bytes,3,rep,name=errors,proto3" json:"errors,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPConfig) Reset() {
|
||||||
|
*x = TCPConfig{}
|
||||||
|
mi := &file_transport_internet_finalmask_header_custom_config_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPConfig) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*TCPConfig) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *TCPConfig) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_transport_internet_finalmask_header_custom_config_proto_msgTypes[2]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use TCPConfig.ProtoReflect.Descriptor instead.
|
||||||
|
func (*TCPConfig) Descriptor() ([]byte, []int) {
|
||||||
|
return file_transport_internet_finalmask_header_custom_config_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPConfig) GetClients() []*TCPSequence {
|
||||||
|
if x != nil {
|
||||||
|
return x.Clients
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPConfig) GetServers() []*TCPSequence {
|
||||||
|
if x != nil {
|
||||||
|
return x.Servers
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TCPConfig) GetErrors() []*TCPSequence {
|
||||||
|
if x != nil {
|
||||||
|
return x.Errors
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UDPItem) Reset() {
|
||||||
|
*x = UDPItem{}
|
||||||
|
mi := &file_transport_internet_finalmask_header_custom_config_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UDPItem) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UDPItem) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *UDPItem) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_transport_internet_finalmask_header_custom_config_proto_msgTypes[3]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use UDPItem.ProtoReflect.Descriptor instead.
|
||||||
|
func (*UDPItem) Descriptor() ([]byte, []int) {
|
||||||
|
return file_transport_internet_finalmask_header_custom_config_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UDPItem) GetRand() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Rand
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UDPItem) GetPacket() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Packet
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type UDPConfig struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Client []*UDPItem `protobuf:"bytes,1,rep,name=client,proto3" json:"client,omitempty"`
|
||||||
|
Server []*UDPItem `protobuf:"bytes,2,rep,name=server,proto3" json:"server,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UDPConfig) Reset() {
|
||||||
|
*x = UDPConfig{}
|
||||||
|
mi := &file_transport_internet_finalmask_header_custom_config_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UDPConfig) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UDPConfig) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *UDPConfig) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_transport_internet_finalmask_header_custom_config_proto_msgTypes[4]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use UDPConfig.ProtoReflect.Descriptor instead.
|
||||||
|
func (*UDPConfig) Descriptor() ([]byte, []int) {
|
||||||
|
return file_transport_internet_finalmask_header_custom_config_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UDPConfig) GetClient() []*UDPItem {
|
||||||
|
if x != nil {
|
||||||
|
return x.Client
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UDPConfig) GetServer() []*UDPItem {
|
||||||
|
if x != nil {
|
||||||
|
return x.Server
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_transport_internet_finalmask_header_custom_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
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" +
|
||||||
|
"\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" +
|
||||||
|
"\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" +
|
||||||
|
"\aUDPItem\x12\x12\n" +
|
||||||
|
"\x04rand\x18\x01 \x01(\x05R\x04rand\x12\x16\n" +
|
||||||
|
"\x06packet\x18\x02 \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" +
|
||||||
|
"3com.xray.transport.internet.finalmask.header.customP\x01ZDgithub.com/xtls/xray-core/transport/internet/finalmask/header/custom\xaa\x02/Xray.Transport.Internet.Finalmask.Header.Customb\x06proto3"
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_transport_internet_finalmask_header_custom_config_proto_rawDescOnce sync.Once
|
||||||
|
file_transport_internet_finalmask_header_custom_config_proto_rawDescData []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_transport_internet_finalmask_header_custom_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_transport_internet_finalmask_header_custom_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_transport_internet_finalmask_header_custom_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_transport_internet_finalmask_header_custom_config_proto_rawDesc), len(file_transport_internet_finalmask_header_custom_config_proto_rawDesc)))
|
||||||
|
})
|
||||||
|
return file_transport_internet_finalmask_header_custom_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_transport_internet_finalmask_header_custom_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
|
var file_transport_internet_finalmask_header_custom_config_proto_goTypes = []any{
|
||||||
|
(*TCPItem)(nil), // 0: xray.transport.internet.finalmask.header.custom.TCPItem
|
||||||
|
(*TCPSequence)(nil), // 1: xray.transport.internet.finalmask.header.custom.TCPSequence
|
||||||
|
(*TCPConfig)(nil), // 2: xray.transport.internet.finalmask.header.custom.TCPConfig
|
||||||
|
(*UDPItem)(nil), // 3: xray.transport.internet.finalmask.header.custom.UDPItem
|
||||||
|
(*UDPConfig)(nil), // 4: xray.transport.internet.finalmask.header.custom.UDPConfig
|
||||||
|
}
|
||||||
|
var file_transport_internet_finalmask_header_custom_config_proto_depIdxs = []int32{
|
||||||
|
0, // 0: xray.transport.internet.finalmask.header.custom.TCPSequence.sequence:type_name -> xray.transport.internet.finalmask.header.custom.TCPItem
|
||||||
|
1, // 1: xray.transport.internet.finalmask.header.custom.TCPConfig.clients:type_name -> xray.transport.internet.finalmask.header.custom.TCPSequence
|
||||||
|
1, // 2: xray.transport.internet.finalmask.header.custom.TCPConfig.servers:type_name -> xray.transport.internet.finalmask.header.custom.TCPSequence
|
||||||
|
1, // 3: xray.transport.internet.finalmask.header.custom.TCPConfig.errors:type_name -> xray.transport.internet.finalmask.header.custom.TCPSequence
|
||||||
|
3, // 4: xray.transport.internet.finalmask.header.custom.UDPConfig.client:type_name -> xray.transport.internet.finalmask.header.custom.UDPItem
|
||||||
|
3, // 5: xray.transport.internet.finalmask.header.custom.UDPConfig.server:type_name -> xray.transport.internet.finalmask.header.custom.UDPItem
|
||||||
|
6, // [6:6] is the sub-list for method output_type
|
||||||
|
6, // [6:6] is the sub-list for method input_type
|
||||||
|
6, // [6:6] is the sub-list for extension type_name
|
||||||
|
6, // [6:6] is the sub-list for extension extendee
|
||||||
|
0, // [0:6] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_transport_internet_finalmask_header_custom_config_proto_init() }
|
||||||
|
func file_transport_internet_finalmask_header_custom_config_proto_init() {
|
||||||
|
if File_transport_internet_finalmask_header_custom_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_transport_internet_finalmask_header_custom_config_proto_rawDesc), len(file_transport_internet_finalmask_header_custom_config_proto_rawDesc)),
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 5,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_transport_internet_finalmask_header_custom_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_transport_internet_finalmask_header_custom_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_transport_internet_finalmask_header_custom_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_transport_internet_finalmask_header_custom_config_proto = out.File
|
||||||
|
file_transport_internet_finalmask_header_custom_config_proto_goTypes = nil
|
||||||
|
file_transport_internet_finalmask_header_custom_config_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.transport.internet.finalmask.header.custom;
|
||||||
|
option csharp_namespace = "Xray.Transport.Internet.Finalmask.Header.Custom";
|
||||||
|
option go_package = "github.com/xtls/xray-core/transport/internet/finalmask/header/custom";
|
||||||
|
option java_package = "com.xray.transport.internet.finalmask.header.custom";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
message TCPItem {
|
||||||
|
int64 delay_min = 1;
|
||||||
|
int64 delay_max = 2;
|
||||||
|
int32 rand = 3;
|
||||||
|
bytes packet = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TCPSequence {
|
||||||
|
repeated TCPItem sequence = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TCPConfig {
|
||||||
|
repeated TCPSequence clients = 1;
|
||||||
|
repeated TCPSequence servers = 2;
|
||||||
|
repeated TCPSequence errors = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UDPItem {
|
||||||
|
int32 rand = 1;
|
||||||
|
bytes packet = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UDPConfig {
|
||||||
|
repeated UDPItem client = 1;
|
||||||
|
repeated UDPItem server = 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tcpCustomClient struct {
|
||||||
|
clients []*TCPSequence
|
||||||
|
servers []*TCPSequence
|
||||||
|
}
|
||||||
|
|
||||||
|
type tcpCustomClientConn struct {
|
||||||
|
net.Conn
|
||||||
|
header *tcpCustomClient
|
||||||
|
|
||||||
|
auth bool
|
||||||
|
wg sync.WaitGroup
|
||||||
|
once sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConnClientTCP(c *TCPConfig, raw net.Conn) (net.Conn, error) {
|
||||||
|
conn := &tcpCustomClientConn{
|
||||||
|
Conn: raw,
|
||||||
|
header: &tcpCustomClient{
|
||||||
|
clients: c.Clients,
|
||||||
|
servers: c.Servers,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.wg.Add(1)
|
||||||
|
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tcpCustomClientConn) TcpMaskConn() {}
|
||||||
|
|
||||||
|
func (c *tcpCustomClientConn) RawConn() net.Conn {
|
||||||
|
// c.wg.Wait()
|
||||||
|
|
||||||
|
return c.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tcpCustomClientConn) Splice() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tcpCustomClientConn) Read(p []byte) (n int, err error) {
|
||||||
|
c.wg.Wait()
|
||||||
|
|
||||||
|
if !c.auth {
|
||||||
|
return 0, errors.New("header auth failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Conn.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tcpCustomClientConn) Write(p []byte) (n int, err error) {
|
||||||
|
c.once.Do(func() {
|
||||||
|
i := 0
|
||||||
|
j := 0
|
||||||
|
for i = range c.header.clients {
|
||||||
|
if !writeSequence(c.Conn, c.header.clients[i]) {
|
||||||
|
c.wg.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if j < len(c.header.servers) {
|
||||||
|
if !readSequence(c.Conn, c.header.servers[j]) {
|
||||||
|
c.wg.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for j < len(c.header.servers) {
|
||||||
|
if !readSequence(c.Conn, c.header.servers[j]) {
|
||||||
|
c.wg.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
|
||||||
|
c.auth = true
|
||||||
|
c.wg.Done()
|
||||||
|
})
|
||||||
|
|
||||||
|
c.wg.Wait()
|
||||||
|
|
||||||
|
if !c.auth {
|
||||||
|
return 0, errors.New("header auth failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Conn.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
type tcpCustomServer struct {
|
||||||
|
clients []*TCPSequence
|
||||||
|
servers []*TCPSequence
|
||||||
|
errors []*TCPSequence
|
||||||
|
}
|
||||||
|
|
||||||
|
type tcpCustomServerConn struct {
|
||||||
|
net.Conn
|
||||||
|
header *tcpCustomServer
|
||||||
|
|
||||||
|
auth bool
|
||||||
|
wg sync.WaitGroup
|
||||||
|
once sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConnServerTCP(c *TCPConfig, raw net.Conn) (net.Conn, error) {
|
||||||
|
conn := &tcpCustomServerConn{
|
||||||
|
Conn: raw,
|
||||||
|
header: &tcpCustomServer{
|
||||||
|
clients: c.Clients,
|
||||||
|
servers: c.Servers,
|
||||||
|
errors: c.Errors,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.wg.Add(1)
|
||||||
|
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tcpCustomServerConn) TcpMaskConn() {}
|
||||||
|
|
||||||
|
func (c *tcpCustomServerConn) RawConn() net.Conn {
|
||||||
|
// c.wg.Wait()
|
||||||
|
|
||||||
|
return c.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tcpCustomServerConn) Splice() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tcpCustomServerConn) Read(p []byte) (n int, err error) {
|
||||||
|
c.once.Do(func() {
|
||||||
|
i := 0
|
||||||
|
j := 0
|
||||||
|
for i = range c.header.clients {
|
||||||
|
if !readSequence(c.Conn, c.header.clients[i]) {
|
||||||
|
if i < len(c.header.errors) {
|
||||||
|
writeSequence(c.Conn, c.header.errors[i])
|
||||||
|
}
|
||||||
|
c.wg.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if j < len(c.header.servers) {
|
||||||
|
if !writeSequence(c.Conn, c.header.servers[j]) {
|
||||||
|
c.wg.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for j < len(c.header.servers) {
|
||||||
|
if !writeSequence(c.Conn, c.header.servers[j]) {
|
||||||
|
c.wg.Done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
|
||||||
|
c.auth = true
|
||||||
|
c.wg.Done()
|
||||||
|
})
|
||||||
|
|
||||||
|
c.wg.Wait()
|
||||||
|
|
||||||
|
if !c.auth {
|
||||||
|
return 0, errors.New("header auth failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Conn.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *tcpCustomServerConn) Write(p []byte) (n int, err error) {
|
||||||
|
c.wg.Wait()
|
||||||
|
|
||||||
|
if !c.auth {
|
||||||
|
return 0, errors.New("header auth failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Conn.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readSequence(r io.Reader, sequence *TCPSequence) bool {
|
||||||
|
for _, item := range sequence.Sequence {
|
||||||
|
length := max(int(item.Rand), len(item.Packet))
|
||||||
|
buf := make([]byte, length)
|
||||||
|
n, err := io.ReadFull(r, buf)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if item.Rand > 0 && n != length {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(item.Packet) > 0 && !bytes.Equal(item.Packet, buf[:n]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeSequence(w io.Writer, sequence *TCPSequence) bool {
|
||||||
|
var merged []byte
|
||||||
|
for _, item := range sequence.Sequence {
|
||||||
|
if item.DelayMax > 0 {
|
||||||
|
if len(merged) > 0 {
|
||||||
|
_, err := w.Write(merged)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
merged = nil
|
||||||
|
}
|
||||||
|
time.Sleep(time.Duration(crypto.RandBetween(item.DelayMin, item.DelayMax)) * time.Millisecond)
|
||||||
|
}
|
||||||
|
if item.Rand > 0 {
|
||||||
|
buf := make([]byte, item.Rand)
|
||||||
|
common.Must2(rand.Read(buf))
|
||||||
|
merged = append(merged, buf...)
|
||||||
|
} else {
|
||||||
|
merged = append(merged, item.Packet...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(merged) > 0 {
|
||||||
|
_, err := w.Write(merged)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
merged = nil
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
package custom
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
|
)
|
||||||
|
|
||||||
|
type udpCustomClient struct {
|
||||||
|
client []*UDPItem
|
||||||
|
server []*UDPItem
|
||||||
|
merged []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
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)]))
|
||||||
|
index += int(item.Rand)
|
||||||
|
} else {
|
||||||
|
index += len(item.Packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copy(b, h.merged)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *udpCustomClient) Match(b []byte) bool {
|
||||||
|
if len(b) < len(h.merged) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
data := b
|
||||||
|
match := true
|
||||||
|
|
||||||
|
for _, item := range h.server {
|
||||||
|
length := max(int(item.Rand), len(item.Packet))
|
||||||
|
|
||||||
|
if len(item.Packet) > 0 && !bytes.Equal(item.Packet, data[:length]) {
|
||||||
|
match = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
data = data[length:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
|
||||||
|
type udpCustomClientConn struct {
|
||||||
|
net.PacketConn
|
||||||
|
header *udpCustomClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConnClientUDP(c *UDPConfig, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
|
conn := &udpCustomClientConn{
|
||||||
|
PacketConn: raw,
|
||||||
|
header: &udpCustomClient{
|
||||||
|
client: c.Client,
|
||||||
|
server: c.Server,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
index := 0
|
||||||
|
for _, item := range conn.header.client {
|
||||||
|
if item.Rand > 0 {
|
||||||
|
conn.header.merged = append(conn.header.merged, make([]byte, item.Rand)...)
|
||||||
|
index += int(item.Rand)
|
||||||
|
} else {
|
||||||
|
conn.header.merged = append(conn.header.merged, item.Packet...)
|
||||||
|
index += len(item.Packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type udpCustomServer struct {
|
||||||
|
client []*UDPItem
|
||||||
|
server []*UDPItem
|
||||||
|
merged []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
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)]))
|
||||||
|
index += int(item.Rand)
|
||||||
|
} else {
|
||||||
|
index += len(item.Packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copy(b, h.merged)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *udpCustomServer) Match(b []byte) bool {
|
||||||
|
if len(b) < len(h.merged) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
data := b
|
||||||
|
match := true
|
||||||
|
|
||||||
|
for _, item := range h.client {
|
||||||
|
length := max(int(item.Rand), len(item.Packet))
|
||||||
|
|
||||||
|
if len(item.Packet) > 0 && !bytes.Equal(item.Packet, data[:length]) {
|
||||||
|
match = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
data = data[length:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
|
||||||
|
type udpCustomServerConn struct {
|
||||||
|
net.PacketConn
|
||||||
|
header *udpCustomServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConnServerUDP(c *UDPConfig, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
|
conn := &udpCustomServerConn{
|
||||||
|
PacketConn: raw,
|
||||||
|
header: &udpCustomServer{
|
||||||
|
client: c.Client,
|
||||||
|
server: c.Server,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
index := 0
|
||||||
|
for _, item := range conn.header.server {
|
||||||
|
if item.Rand > 0 {
|
||||||
|
conn.header.merged = append(conn.header.merged, make([]byte, item.Rand)...)
|
||||||
|
index += int(item.Rand)
|
||||||
|
} else {
|
||||||
|
conn.header.merged = append(conn.header.merged, item.Packet...)
|
||||||
|
index += len(item.Packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, first, leaveSize)
|
return NewConnServer(c, raw)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
sync "sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"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) {
|
func packDomainName(s string, msg []byte) (off1 int, err error) {
|
||||||
@@ -81,8 +80,8 @@ type dns struct {
|
|||||||
header []byte
|
header []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *dns) Size() int32 {
|
func (h *dns) Size() int {
|
||||||
return int32(len(h.header))
|
return len(h.header)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *dns) Serialize(b []byte) {
|
func (h *dns) Serialize(b []byte) {
|
||||||
@@ -91,19 +90,11 @@ func (h *dns) Serialize(b []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type dnsConn struct {
|
type dnsConn struct {
|
||||||
first bool
|
net.PacketConn
|
||||||
leaveSize int32
|
|
||||||
|
|
||||||
conn net.PacketConn
|
|
||||||
header *dns
|
header *dns
|
||||||
|
|
||||||
readBuf []byte
|
|
||||||
readMutex sync.Mutex
|
|
||||||
writeBuf []byte
|
|
||||||
writeMutex sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
var header []byte
|
var header []byte
|
||||||
header = binary.BigEndian.AppendUint16(header, 0x0000) // Transaction ID
|
header = binary.BigEndian.AppendUint16(header, 0x0000) // Transaction ID
|
||||||
header = binary.BigEndian.AppendUint16(header, 0x0100) // Flags: Standard query
|
header = binary.BigEndian.AppendUint16(header, 0x0100) // Flags: Standard query
|
||||||
@@ -121,121 +112,65 @@ func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (
|
|||||||
header = binary.BigEndian.AppendUint16(header, 0x0001) // Class: IN
|
header = binary.BigEndian.AppendUint16(header, 0x0001) // Class: IN
|
||||||
|
|
||||||
conn := &dnsConn{
|
conn := &dnsConn{
|
||||||
first: first,
|
PacketConn: raw,
|
||||||
leaveSize: leaveSize,
|
|
||||||
|
|
||||||
conn: raw,
|
|
||||||
header: &dns{
|
header: &dns{
|
||||||
header: header,
|
header: header,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if first {
|
|
||||||
conn.readBuf = make([]byte, 8192)
|
|
||||||
conn.writeBuf = make([]byte, 8192)
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dnsConn) Size() int32 {
|
|
||||||
return c.header.Size()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dnsConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *dnsConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
if c.first {
|
buf := p
|
||||||
c.readMutex.Lock()
|
if len(p) < finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
n, addr, err = c.conn.ReadFrom(c.readBuf)
|
|
||||||
if err != nil {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n, addr, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) < n-int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(p, c.readBuf[c.Size():n])
|
|
||||||
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n - int(c.Size()), addr, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n, addr, err = c.conn.ReadFrom(p)
|
n, addr, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil || n == 0 {
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
if n < c.header.Size() {
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
|
||||||
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(p, p[c.Size():n])
|
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
|
||||||
|
}
|
||||||
|
|
||||||
return n - int(c.Size()), addr, err
|
copy(p, buf[c.header.Size():n])
|
||||||
|
|
||||||
|
return n - c.header.Size(), addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dnsConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *dnsConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
if c.first {
|
if c.header.Size()+len(p) > finalmask.UDPSize {
|
||||||
if c.leaveSize+c.Size()+int32(len(p)) > 8192 {
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
|
||||||
return 0, errors.New("too many masks")
|
return 0, nil
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Lock()
|
|
||||||
|
|
||||||
n = copy(c.writeBuf[c.leaveSize+c.Size():], p)
|
|
||||||
n += int(c.leaveSize) + int(c.Size())
|
|
||||||
|
|
||||||
c.header.Serialize(c.writeBuf[c.leaveSize : c.leaveSize+c.Size()])
|
|
||||||
|
|
||||||
nn, err := c.conn.WriteTo(c.writeBuf[:n], addr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nn != n {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, errors.New("nn != n")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.header.Serialize(p[c.leaveSize : c.leaveSize+c.Size()])
|
var buf []byte
|
||||||
|
if cap(p) != finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
|
} else {
|
||||||
|
buf = p[:c.header.Size()+len(p)]
|
||||||
|
}
|
||||||
|
|
||||||
return c.conn.WriteTo(p, addr)
|
copy(buf[c.header.Size():], p)
|
||||||
}
|
c.header.Serialize(buf)
|
||||||
|
|
||||||
func (c *dnsConn) Close() error {
|
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
|
||||||
return c.conn.Close()
|
if err != nil {
|
||||||
}
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *dnsConn) LocalAddr() net.Addr {
|
return len(p), nil
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dnsConn) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dnsConn) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dnsConn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, first, leaveSize)
|
return NewConnServer(c, raw)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package dtls
|
package dtls
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
sync "sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
type dtls struct {
|
type dtls struct {
|
||||||
@@ -16,7 +15,7 @@ type dtls struct {
|
|||||||
sequence uint32
|
sequence uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*dtls) Size() int32 {
|
func (*dtls) Size() int {
|
||||||
return 1 + 2 + 2 + 6 + 2
|
return 1 + 2 + 2 + 6 + 2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,24 +41,13 @@ func (h *dtls) Serialize(b []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type dtlsConn struct {
|
type dtlsConn struct {
|
||||||
first bool
|
net.PacketConn
|
||||||
leaveSize int32
|
|
||||||
|
|
||||||
conn net.PacketConn
|
|
||||||
header *dtls
|
header *dtls
|
||||||
|
|
||||||
readBuf []byte
|
|
||||||
readMutex sync.Mutex
|
|
||||||
writeBuf []byte
|
|
||||||
writeMutex sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
conn := &dtlsConn{
|
conn := &dtlsConn{
|
||||||
first: first,
|
PacketConn: raw,
|
||||||
leaveSize: leaveSize,
|
|
||||||
|
|
||||||
conn: raw,
|
|
||||||
header: &dtls{
|
header: &dtls{
|
||||||
epoch: dice.RollUint16(),
|
epoch: dice.RollUint16(),
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
@@ -67,112 +55,59 @@ func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if first {
|
|
||||||
conn.readBuf = make([]byte, 8192)
|
|
||||||
conn.writeBuf = make([]byte, 8192)
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dtlsConn) Size() int32 {
|
|
||||||
return c.header.Size()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dtlsConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *dtlsConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
if c.first {
|
buf := p
|
||||||
c.readMutex.Lock()
|
if len(p) < finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
n, addr, err = c.conn.ReadFrom(c.readBuf)
|
|
||||||
if err != nil {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n, addr, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) < n-int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(p, c.readBuf[c.Size():n])
|
|
||||||
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n - int(c.Size()), addr, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n, addr, err = c.conn.ReadFrom(p)
|
n, addr, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil || n == 0 {
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
if n < c.header.Size() {
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
|
||||||
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(p, p[c.Size():n])
|
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
|
||||||
|
}
|
||||||
|
|
||||||
return n - int(c.Size()), addr, err
|
copy(p, buf[c.header.Size():n])
|
||||||
|
|
||||||
|
return n - c.header.Size(), addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dtlsConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *dtlsConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
if c.first {
|
if c.header.Size()+len(p) > finalmask.UDPSize {
|
||||||
if c.leaveSize+c.Size()+int32(len(p)) > 8192 {
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
|
||||||
return 0, errors.New("too many masks")
|
return 0, nil
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Lock()
|
|
||||||
|
|
||||||
n = copy(c.writeBuf[c.leaveSize+c.Size():], p)
|
|
||||||
n += int(c.leaveSize) + int(c.Size())
|
|
||||||
|
|
||||||
c.header.Serialize(c.writeBuf[c.leaveSize : c.leaveSize+c.Size()])
|
|
||||||
|
|
||||||
nn, err := c.conn.WriteTo(c.writeBuf[:n], addr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nn != n {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, errors.New("nn != n")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.header.Serialize(p[c.leaveSize : c.leaveSize+c.Size()])
|
var buf []byte
|
||||||
|
if cap(p) != finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
|
} else {
|
||||||
|
buf = p[:c.header.Size()+len(p)]
|
||||||
|
}
|
||||||
|
|
||||||
return c.conn.WriteTo(p, addr)
|
copy(buf[c.header.Size():], p)
|
||||||
}
|
c.header.Serialize(buf)
|
||||||
|
|
||||||
func (c *dtlsConn) Close() error {
|
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
|
||||||
return c.conn.Close()
|
if err != nil {
|
||||||
}
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *dtlsConn) LocalAddr() net.Addr {
|
return len(p), nil
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dtlsConn) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dtlsConn) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dtlsConn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, first, leaveSize)
|
return NewConnServer(c, raw)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package srtp
|
package srtp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
sync "sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
type srtp struct {
|
type srtp struct {
|
||||||
@@ -16,7 +15,7 @@ type srtp struct {
|
|||||||
number uint16
|
number uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*srtp) Size() int32 {
|
func (*srtp) Size() int {
|
||||||
return 4
|
return 4
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,136 +26,72 @@ func (h *srtp) Serialize(b []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type srtpConn struct {
|
type srtpConn struct {
|
||||||
first bool
|
net.PacketConn
|
||||||
leaveSize int32
|
|
||||||
|
|
||||||
conn net.PacketConn
|
|
||||||
header *srtp
|
header *srtp
|
||||||
|
|
||||||
readBuf []byte
|
|
||||||
readMutex sync.Mutex
|
|
||||||
writeBuf []byte
|
|
||||||
writeMutex sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
conn := &srtpConn{
|
conn := &srtpConn{
|
||||||
first: first,
|
PacketConn: raw,
|
||||||
leaveSize: leaveSize,
|
|
||||||
|
|
||||||
conn: raw,
|
|
||||||
header: &srtp{
|
header: &srtp{
|
||||||
header: 0xB5E8,
|
header: 0xB5E8,
|
||||||
number: dice.RollUint16(),
|
number: dice.RollUint16(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if first {
|
|
||||||
conn.readBuf = make([]byte, 8192)
|
|
||||||
conn.writeBuf = make([]byte, 8192)
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *srtpConn) Size() int32 {
|
|
||||||
return c.header.Size()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *srtpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *srtpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
if c.first {
|
buf := p
|
||||||
c.readMutex.Lock()
|
if len(p) < finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
n, addr, err = c.conn.ReadFrom(c.readBuf)
|
|
||||||
if err != nil {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n, addr, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) < n-int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(p, c.readBuf[c.Size():n])
|
|
||||||
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n - int(c.Size()), addr, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n, addr, err = c.conn.ReadFrom(p)
|
n, addr, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil || n == 0 {
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
if n < c.header.Size() {
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
|
||||||
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(p, p[c.Size():n])
|
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
|
||||||
|
}
|
||||||
|
|
||||||
return n - int(c.Size()), addr, err
|
copy(p, buf[c.header.Size():n])
|
||||||
|
|
||||||
|
return n - c.header.Size(), addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *srtpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *srtpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
if c.first {
|
if c.header.Size()+len(p) > finalmask.UDPSize {
|
||||||
if c.leaveSize+c.Size()+int32(len(p)) > 8192 {
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
|
||||||
return 0, errors.New("too many masks")
|
return 0, nil
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Lock()
|
|
||||||
|
|
||||||
n = copy(c.writeBuf[c.leaveSize+c.Size():], p)
|
|
||||||
n += int(c.leaveSize) + int(c.Size())
|
|
||||||
|
|
||||||
c.header.Serialize(c.writeBuf[c.leaveSize : c.leaveSize+c.Size()])
|
|
||||||
|
|
||||||
nn, err := c.conn.WriteTo(c.writeBuf[:n], addr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nn != n {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, errors.New("nn != n")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.header.Serialize(p[c.leaveSize : c.leaveSize+c.Size()])
|
var buf []byte
|
||||||
|
if cap(p) != finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
|
} else {
|
||||||
|
buf = p[:c.header.Size()+len(p)]
|
||||||
|
}
|
||||||
|
|
||||||
return c.conn.WriteTo(p, addr)
|
copy(buf[c.header.Size():], p)
|
||||||
}
|
c.header.Serialize(buf)
|
||||||
|
|
||||||
func (c *srtpConn) Close() error {
|
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
|
||||||
return c.conn.Close()
|
if err != nil {
|
||||||
}
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *srtpConn) LocalAddr() net.Addr {
|
return len(p), nil
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *srtpConn) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *srtpConn) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *srtpConn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, first, leaveSize)
|
return NewConnServer(c, raw)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package utp
|
package utp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
sync "sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
type utp struct {
|
type utp struct {
|
||||||
@@ -17,7 +16,7 @@ type utp struct {
|
|||||||
connectionID uint16
|
connectionID uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*utp) Size() int32 {
|
func (*utp) Size() int {
|
||||||
return 4
|
return 4
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,24 +27,13 @@ func (h *utp) Serialize(b []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type utpConn struct {
|
type utpConn struct {
|
||||||
first bool
|
net.PacketConn
|
||||||
leaveSize int32
|
|
||||||
|
|
||||||
conn net.PacketConn
|
|
||||||
header *utp
|
header *utp
|
||||||
|
|
||||||
readBuf []byte
|
|
||||||
readMutex sync.Mutex
|
|
||||||
writeBuf []byte
|
|
||||||
writeMutex sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
conn := &utpConn{
|
conn := &utpConn{
|
||||||
first: first,
|
PacketConn: raw,
|
||||||
leaveSize: leaveSize,
|
|
||||||
|
|
||||||
conn: raw,
|
|
||||||
header: &utp{
|
header: &utp{
|
||||||
header: 1,
|
header: 1,
|
||||||
extension: 0,
|
extension: 0,
|
||||||
@@ -53,112 +41,59 @@ func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if first {
|
|
||||||
conn.readBuf = make([]byte, 8192)
|
|
||||||
conn.writeBuf = make([]byte, 8192)
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *utpConn) Size() int32 {
|
|
||||||
return c.header.Size()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *utpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *utpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
if c.first {
|
buf := p
|
||||||
c.readMutex.Lock()
|
if len(p) < finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
n, addr, err = c.conn.ReadFrom(c.readBuf)
|
|
||||||
if err != nil {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n, addr, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) < n-int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(p, c.readBuf[c.Size():n])
|
|
||||||
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n - int(c.Size()), addr, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n, addr, err = c.conn.ReadFrom(p)
|
n, addr, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil || n == 0 {
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
if n < c.header.Size() {
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
|
||||||
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(p, p[c.Size():n])
|
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
|
||||||
|
}
|
||||||
|
|
||||||
return n - int(c.Size()), addr, err
|
copy(p, buf[c.header.Size():n])
|
||||||
|
|
||||||
|
return n - c.header.Size(), addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *utpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *utpConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
if c.first {
|
if c.header.Size()+len(p) > finalmask.UDPSize {
|
||||||
if c.leaveSize+c.Size()+int32(len(p)) > 8192 {
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
|
||||||
return 0, errors.New("too many masks")
|
return 0, nil
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Lock()
|
|
||||||
|
|
||||||
n = copy(c.writeBuf[c.leaveSize+c.Size():], p)
|
|
||||||
n += int(c.leaveSize) + int(c.Size())
|
|
||||||
|
|
||||||
c.header.Serialize(c.writeBuf[c.leaveSize : c.leaveSize+c.Size()])
|
|
||||||
|
|
||||||
nn, err := c.conn.WriteTo(c.writeBuf[:n], addr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nn != n {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, errors.New("nn != n")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.header.Serialize(p[c.leaveSize : c.leaveSize+c.Size()])
|
var buf []byte
|
||||||
|
if cap(p) != finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
|
} else {
|
||||||
|
buf = p[:c.header.Size()+len(p)]
|
||||||
|
}
|
||||||
|
|
||||||
return c.conn.WriteTo(p, addr)
|
copy(buf[c.header.Size():], p)
|
||||||
}
|
c.header.Serialize(buf)
|
||||||
|
|
||||||
func (c *utpConn) Close() error {
|
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
|
||||||
return c.conn.Close()
|
if err != nil {
|
||||||
}
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *utpConn) LocalAddr() net.Addr {
|
return len(p), nil
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *utpConn) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *utpConn) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *utpConn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, first, leaveSize)
|
return NewConnServer(c, raw)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
package wechat
|
package wechat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
sync "sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wechat struct {
|
type wechat struct {
|
||||||
sn uint32
|
sn uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*wechat) Size() int32 {
|
func (*wechat) Size() int {
|
||||||
return 13
|
return 13
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,135 +33,71 @@ func (h *wechat) Serialize(b []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type wechatConn struct {
|
type wechatConn struct {
|
||||||
first bool
|
net.PacketConn
|
||||||
leaveSize int32
|
|
||||||
|
|
||||||
conn net.PacketConn
|
|
||||||
header *wechat
|
header *wechat
|
||||||
|
|
||||||
readBuf []byte
|
|
||||||
readMutex sync.Mutex
|
|
||||||
writeBuf []byte
|
|
||||||
writeMutex sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
conn := &wechatConn{
|
conn := &wechatConn{
|
||||||
first: first,
|
PacketConn: raw,
|
||||||
leaveSize: leaveSize,
|
|
||||||
|
|
||||||
conn: raw,
|
|
||||||
header: &wechat{
|
header: &wechat{
|
||||||
sn: uint32(dice.RollUint16()),
|
sn: uint32(dice.RollUint16()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if first {
|
|
||||||
conn.readBuf = make([]byte, 8192)
|
|
||||||
conn.writeBuf = make([]byte, 8192)
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *wechatConn) Size() int32 {
|
|
||||||
return c.header.Size()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *wechatConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *wechatConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
if c.first {
|
buf := p
|
||||||
c.readMutex.Lock()
|
if len(p) < finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
n, addr, err = c.conn.ReadFrom(c.readBuf)
|
|
||||||
if err != nil {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n, addr, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) < n-int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(p, c.readBuf[c.Size():n])
|
|
||||||
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n - int(c.Size()), addr, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n, addr, err = c.conn.ReadFrom(p)
|
n, addr, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil || n == 0 {
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
if n < c.header.Size() {
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
|
||||||
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(p, p[c.Size():n])
|
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
|
||||||
|
}
|
||||||
|
|
||||||
return n - int(c.Size()), addr, err
|
copy(p, buf[c.header.Size():n])
|
||||||
|
|
||||||
|
return n - c.header.Size(), addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *wechatConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *wechatConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
if c.first {
|
if c.header.Size()+len(p) > finalmask.UDPSize {
|
||||||
if c.leaveSize+c.Size()+int32(len(p)) > 8192 {
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
|
||||||
return 0, errors.New("too many masks")
|
return 0, nil
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Lock()
|
|
||||||
|
|
||||||
n = copy(c.writeBuf[c.leaveSize+c.Size():], p)
|
|
||||||
n += int(c.leaveSize) + int(c.Size())
|
|
||||||
|
|
||||||
c.header.Serialize(c.writeBuf[c.leaveSize : c.leaveSize+c.Size()])
|
|
||||||
|
|
||||||
nn, err := c.conn.WriteTo(c.writeBuf[:n], addr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nn != n {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, errors.New("nn != n")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.header.Serialize(p[c.leaveSize : c.leaveSize+c.Size()])
|
var buf []byte
|
||||||
|
if cap(p) != finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
|
} else {
|
||||||
|
buf = p[:c.header.Size()+len(p)]
|
||||||
|
}
|
||||||
|
|
||||||
return c.conn.WriteTo(p, addr)
|
copy(buf[c.header.Size():], p)
|
||||||
}
|
c.header.Serialize(buf)
|
||||||
|
|
||||||
func (c *wechatConn) Close() error {
|
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
|
||||||
return c.conn.Close()
|
if err != nil {
|
||||||
}
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *wechatConn) LocalAddr() net.Addr {
|
return len(p), nil
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *wechatConn) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *wechatConn) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *wechatConn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, first, leaveSize)
|
return NewConnServer(c, raw)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
package wireguard
|
package wireguard
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
sync "sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wireguare struct{}
|
type wireguare struct{}
|
||||||
|
|
||||||
func (*wireguare) Size() int32 {
|
func (*wireguare) Size() int {
|
||||||
return 4
|
return 4
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,133 +22,69 @@ func (h *wireguare) Serialize(b []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type wireguareConn struct {
|
type wireguareConn struct {
|
||||||
first bool
|
net.PacketConn
|
||||||
leaveSize int32
|
|
||||||
|
|
||||||
conn net.PacketConn
|
|
||||||
header *wireguare
|
header *wireguare
|
||||||
|
|
||||||
readBuf []byte
|
|
||||||
readMutex sync.Mutex
|
|
||||||
writeBuf []byte
|
|
||||||
writeMutex sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
conn := &wireguareConn{
|
conn := &wireguareConn{
|
||||||
first: first,
|
PacketConn: raw,
|
||||||
leaveSize: leaveSize,
|
header: &wireguare{},
|
||||||
|
|
||||||
conn: raw,
|
|
||||||
header: &wireguare{},
|
|
||||||
}
|
|
||||||
|
|
||||||
if first {
|
|
||||||
conn.readBuf = make([]byte, 8192)
|
|
||||||
conn.writeBuf = make([]byte, 8192)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *wireguareConn) Size() int32 {
|
|
||||||
return c.header.Size()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *wireguareConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *wireguareConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
if c.first {
|
buf := p
|
||||||
c.readMutex.Lock()
|
if len(p) < finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
n, addr, err = c.conn.ReadFrom(c.readBuf)
|
|
||||||
if err != nil {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n, addr, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) < n-int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(p, c.readBuf[c.Size():n])
|
|
||||||
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n - int(c.Size()), addr, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n, addr, err = c.conn.ReadFrom(p)
|
n, addr, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil || n == 0 {
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
if n < c.header.Size() {
|
||||||
return 0, addr, errors.New("header").Base(io.ErrShortBuffer)
|
errors.LogDebug(context.Background(), addr, " mask read err header mismatch")
|
||||||
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(p, p[c.Size():n])
|
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
|
||||||
|
}
|
||||||
|
|
||||||
return n - int(c.Size()), addr, err
|
copy(p, buf[c.header.Size():n])
|
||||||
|
|
||||||
|
return n - c.header.Size(), addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *wireguareConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *wireguareConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
if c.first {
|
if c.header.Size()+len(p) > finalmask.UDPSize {
|
||||||
if c.leaveSize+c.Size()+int32(len(p)) > 8192 {
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.header.Size()+len(p), " ", finalmask.UDPSize)
|
||||||
return 0, errors.New("too many masks")
|
return 0, nil
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Lock()
|
|
||||||
|
|
||||||
n = copy(c.writeBuf[c.leaveSize+c.Size():], p)
|
|
||||||
n += int(c.leaveSize) + int(c.Size())
|
|
||||||
|
|
||||||
c.header.Serialize(c.writeBuf[c.leaveSize : c.leaveSize+c.Size()])
|
|
||||||
|
|
||||||
nn, err := c.conn.WriteTo(c.writeBuf[:n], addr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nn != n {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, errors.New("nn != n")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.header.Serialize(p[c.leaveSize : c.leaveSize+c.Size()])
|
var buf []byte
|
||||||
|
if cap(p) != finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
|
} else {
|
||||||
|
buf = p[:c.header.Size()+len(p)]
|
||||||
|
}
|
||||||
|
|
||||||
return c.conn.WriteTo(p, addr)
|
copy(buf[c.header.Size():], p)
|
||||||
}
|
c.header.Serialize(buf)
|
||||||
|
|
||||||
func (c *wireguareConn) Close() error {
|
_, err = c.PacketConn.WriteTo(buf[:c.header.Size()+len(p)], addr)
|
||||||
return c.conn.Close()
|
if err != nil {
|
||||||
}
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *wireguareConn) LocalAddr() net.Addr {
|
return len(p), nil
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *wireguareConn) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *wireguareConn) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *wireguareConn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, first, leaveSize)
|
return NewConnServer(c, raw)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,99 +1,77 @@
|
|||||||
package aes128gcm
|
package aes128gcm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
sync "sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/crypto"
|
"github.com/xtls/xray-core/common/crypto"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
type aes128gcmConn struct {
|
type aes128gcmConn struct {
|
||||||
first bool
|
net.PacketConn
|
||||||
leaveSize int32
|
|
||||||
|
|
||||||
conn net.PacketConn
|
|
||||||
aead cipher.AEAD
|
aead cipher.AEAD
|
||||||
|
|
||||||
readBuf []byte
|
|
||||||
readMutex sync.Mutex
|
|
||||||
writeBuf []byte
|
|
||||||
writeMutex sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
hashedPsk := sha256.Sum256([]byte(c.Password))
|
hashedPsk := sha256.Sum256([]byte(c.Password))
|
||||||
|
|
||||||
conn := &aes128gcmConn{
|
conn := &aes128gcmConn{
|
||||||
first: first,
|
PacketConn: raw,
|
||||||
leaveSize: leaveSize,
|
aead: crypto.NewAesGcm(hashedPsk[:16]),
|
||||||
|
|
||||||
conn: raw,
|
|
||||||
aead: crypto.NewAesGcm(hashedPsk[:16]),
|
|
||||||
}
|
|
||||||
|
|
||||||
if first {
|
|
||||||
conn.readBuf = make([]byte, 8192)
|
|
||||||
conn.writeBuf = make([]byte, 8192)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *aes128gcmConn) Size() int32 {
|
|
||||||
return int32(c.aead.NonceSize()) + int32(c.aead.Overhead())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *aes128gcmConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *aes128gcmConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
if c.first {
|
if len(p) < finalmask.UDPSize {
|
||||||
c.readMutex.Lock()
|
buf := make([]byte, finalmask.UDPSize)
|
||||||
|
|
||||||
n, addr, err = c.conn.ReadFrom(c.readBuf)
|
n, addr, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil || n == 0 {
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
if n < c.aead.NonceSize()+c.aead.Overhead() {
|
||||||
c.readMutex.Unlock()
|
errors.LogDebug(context.Background(), addr, " mask read err aead short lenth ", n)
|
||||||
return 0, addr, errors.New("aead").Base(io.ErrShortBuffer)
|
return 0, addr, nil
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) < n-int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("aead").Base(io.ErrShortBuffer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nonceSize := c.aead.NonceSize()
|
nonceSize := c.aead.NonceSize()
|
||||||
nonce := c.readBuf[:nonceSize]
|
nonce := buf[:nonceSize]
|
||||||
ciphertext := c.readBuf[nonceSize:n]
|
ciphertext := buf[nonceSize:n]
|
||||||
_, err = c.aead.Open(p[:0], nonce, ciphertext, nil)
|
plaintext, err := c.aead.Open(p[:0], nonce, ciphertext, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.readMutex.Unlock()
|
errors.LogDebug(context.Background(), addr, " mask read err aead open ", err)
|
||||||
return 0, addr, errors.New("aead open").Base(err)
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.readMutex.Unlock()
|
if len(plaintext) > len(p) {
|
||||||
return n - int(c.Size()), addr, nil
|
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.conn.ReadFrom(p)
|
n, addr, err = c.PacketConn.ReadFrom(p)
|
||||||
if err != nil {
|
if err != nil || n == 0 {
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
if n < c.aead.NonceSize()+c.aead.Overhead() {
|
||||||
return 0, addr, errors.New("aead").Base(io.ErrShortBuffer)
|
errors.LogDebug(context.Background(), addr, " mask read err aead short lenth ", n)
|
||||||
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
nonceSize := c.aead.NonceSize()
|
nonceSize := c.aead.NonceSize()
|
||||||
@@ -101,74 +79,40 @@ func (c *aes128gcmConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
|||||||
ciphertext := p[nonceSize:n]
|
ciphertext := p[nonceSize:n]
|
||||||
_, err = c.aead.Open(ciphertext[:0], nonce, ciphertext, nil)
|
_, err = c.aead.Open(ciphertext[:0], nonce, ciphertext, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, addr, errors.New("aead open").Base(err)
|
errors.LogDebug(context.Background(), addr, " mask read err aead open ", err)
|
||||||
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(p, p[nonceSize:n-c.aead.Overhead()])
|
copy(p, p[nonceSize:n-c.aead.Overhead()])
|
||||||
|
|
||||||
return n - int(c.Size()), addr, nil
|
return n - c.aead.NonceSize() - c.aead.Overhead(), addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *aes128gcmConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *aes128gcmConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
if c.first {
|
if c.aead.NonceSize()+c.aead.Overhead()+len(p) > finalmask.UDPSize {
|
||||||
if c.leaveSize+c.Size()+int32(len(p)) > 8192 {
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.aead.NonceSize()+c.aead.Overhead()+len(p), " ", finalmask.UDPSize)
|
||||||
return 0, errors.New("too many masks")
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.writeMutex.Lock()
|
var buf []byte
|
||||||
|
if cap(p) != finalmask.UDPSize {
|
||||||
n = copy(c.writeBuf[c.leaveSize+int32(c.aead.NonceSize()):], p)
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
// n = copy(c.writeBuf[c.leaveSize+c.Size():], p)
|
} else {
|
||||||
n += int(c.leaveSize) + int(c.Size())
|
buf = p[:c.aead.NonceSize()+c.aead.Overhead()+len(p)]
|
||||||
|
copy(buf[c.aead.NonceSize():], p)
|
||||||
nonceSize := c.aead.NonceSize()
|
p = buf[c.aead.NonceSize() : c.aead.NonceSize()+len(p)]
|
||||||
nonce := c.writeBuf[c.leaveSize : c.leaveSize+int32(nonceSize)]
|
|
||||||
common.Must2(rand.Read(nonce))
|
|
||||||
// copy(c.writeBuf[c.leaveSize+int32(nonceSize):], c.writeBuf[c.leaveSize+c.Size():n])
|
|
||||||
plaintext := c.writeBuf[c.leaveSize+int32(nonceSize) : n-c.aead.Overhead()]
|
|
||||||
_ = c.aead.Seal(plaintext[:0], nonce, plaintext, nil)
|
|
||||||
|
|
||||||
nn, err := c.conn.WriteTo(c.writeBuf[:n], addr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nn != n {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, errors.New("nn != n")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nonceSize := c.aead.NonceSize()
|
nonceSize := c.aead.NonceSize()
|
||||||
nonce := p[c.leaveSize : c.leaveSize+int32(nonceSize)]
|
nonce := buf[:nonceSize]
|
||||||
common.Must2(rand.Read(nonce))
|
common.Must2(rand.Read(nonce))
|
||||||
copy(p[c.leaveSize+int32(nonceSize):], p[c.leaveSize+c.Size():])
|
ciphertext := buf[nonceSize : c.aead.NonceSize()+c.aead.Overhead()+len(p)]
|
||||||
plaintext := p[c.leaveSize+int32(nonceSize) : len(p)-c.aead.Overhead()]
|
_ = c.aead.Seal(ciphertext[:0], nonce, p, nil)
|
||||||
_ = c.aead.Seal(plaintext[:0], nonce, plaintext, nil)
|
|
||||||
|
|
||||||
return c.conn.WriteTo(p, addr)
|
_, err = c.PacketConn.WriteTo(buf[:c.aead.NonceSize()+c.aead.Overhead()+len(p)], addr)
|
||||||
}
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *aes128gcmConn) Close() error {
|
return len(p), nil
|
||||||
return c.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *aes128gcmConn) LocalAddr() net.Addr {
|
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *aes128gcmConn) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *aes128gcmConn) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *aes128gcmConn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, first, leaveSize)
|
return NewConnServer(c, raw)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
package original
|
package original
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
sync "sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
type simple struct{}
|
type simple struct{}
|
||||||
@@ -75,151 +74,77 @@ func (a *simple) Open(dst, nonce, cipherText, extra []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type simpleConn struct {
|
type simpleConn struct {
|
||||||
first bool
|
net.PacketConn
|
||||||
leaveSize int32
|
|
||||||
|
|
||||||
conn net.PacketConn
|
|
||||||
aead cipher.AEAD
|
aead cipher.AEAD
|
||||||
|
|
||||||
readBuf []byte
|
|
||||||
readMutex sync.Mutex
|
|
||||||
writeBuf []byte
|
|
||||||
writeMutex sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
conn := &simpleConn{
|
conn := &simpleConn{
|
||||||
first: first,
|
PacketConn: raw,
|
||||||
leaveSize: leaveSize,
|
aead: &simple{},
|
||||||
|
|
||||||
conn: raw,
|
|
||||||
aead: &simple{},
|
|
||||||
}
|
|
||||||
|
|
||||||
if first {
|
|
||||||
conn.readBuf = make([]byte, 8192)
|
|
||||||
conn.writeBuf = make([]byte, 8192)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *simpleConn) Size() int32 {
|
|
||||||
return int32(c.aead.NonceSize()) + int32(c.aead.Overhead())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *simpleConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *simpleConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
if c.first {
|
buf := p
|
||||||
c.readMutex.Lock()
|
if len(p) < finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
n, addr, err = c.conn.ReadFrom(c.readBuf)
|
|
||||||
if err != nil {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n, addr, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("aead").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) < n-int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("aead").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
ciphertext := c.readBuf[:n]
|
|
||||||
opened, err := c.aead.Open(nil, nil, ciphertext, nil)
|
|
||||||
if err != nil {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("aead open").Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(p, opened)
|
|
||||||
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n - int(c.Size()), addr, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n, addr, err = c.conn.ReadFrom(p)
|
n, addr, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil || n == 0 {
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
if n < c.aead.Overhead() {
|
||||||
return 0, addr, errors.New("aead").Base(io.ErrShortBuffer)
|
errors.LogDebug(context.Background(), addr, " mask read err aead short lenth ", n)
|
||||||
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ciphertext := p[:n]
|
ciphertext := buf[:n]
|
||||||
opened, err := c.aead.Open(nil, nil, ciphertext, nil)
|
opened, err := c.aead.Open(nil, nil, ciphertext, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.readMutex.Unlock()
|
errors.LogDebug(context.Background(), addr, " mask read err aead open ", err)
|
||||||
return 0, addr, errors.New("aead open").Base(err)
|
return 0, addr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
copy(p, opened)
|
||||||
|
|
||||||
return n - int(c.Size()), addr, nil
|
return n - c.aead.Overhead(), addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *simpleConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *simpleConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
if c.first {
|
if c.aead.Overhead()+len(p) > finalmask.UDPSize {
|
||||||
if c.leaveSize+c.Size()+int32(len(p)) > 8192 {
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", c.aead.Overhead()+len(p), " ", finalmask.UDPSize)
|
||||||
return 0, errors.New("too many masks")
|
return 0, nil
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Lock()
|
|
||||||
|
|
||||||
n = copy(c.writeBuf[c.leaveSize+c.Size():], p)
|
|
||||||
n += int(c.leaveSize) + int(c.Size())
|
|
||||||
|
|
||||||
plaintext := c.writeBuf[c.leaveSize+c.Size() : n]
|
|
||||||
sealed := c.aead.Seal(nil, nil, plaintext, nil)
|
|
||||||
copy(c.writeBuf[c.leaveSize:], sealed)
|
|
||||||
|
|
||||||
nn, err := c.conn.WriteTo(c.writeBuf[:n], addr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nn != n {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, errors.New("nn != n")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plaintext := p[c.leaveSize+c.Size():]
|
var buf []byte
|
||||||
sealed := c.aead.Seal(nil, nil, plaintext, nil)
|
if cap(p) != finalmask.UDPSize {
|
||||||
copy(p[c.leaveSize:], sealed)
|
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)]
|
||||||
|
}
|
||||||
|
|
||||||
return c.conn.WriteTo(p, addr)
|
_ = c.aead.Seal(buf[:0], nil, p, nil)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *simpleConn) Close() error {
|
_, err = c.PacketConn.WriteTo(buf[:c.aead.Overhead()+len(p)], addr)
|
||||||
return c.conn.Close()
|
if err != nil {
|
||||||
}
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *simpleConn) LocalAddr() net.Addr {
|
return len(p), nil
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *simpleConn) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *simpleConn) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *simpleConn) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,22 @@ import (
|
|||||||
"github.com/xtls/xray-core/transport/internet/finalmask/mkcp/original"
|
"github.com/xtls/xray-core/transport/internet/finalmask/mkcp/original"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestSimpleSealInPlace(t *testing.T) {
|
||||||
|
aead := original.NewSimple()
|
||||||
|
|
||||||
|
text := []byte("0123456789012")
|
||||||
|
buf := make([]byte, 8192)
|
||||||
|
|
||||||
|
copy(buf[aead.Overhead():], text)
|
||||||
|
plaintext := buf[aead.Overhead() : aead.Overhead()+len(text)]
|
||||||
|
|
||||||
|
sealed := aead.Seal(nil, nil, plaintext, nil)
|
||||||
|
|
||||||
|
_ = aead.Seal(buf[:0], nil, plaintext, nil)
|
||||||
|
|
||||||
|
assert.Equal(t, sealed, buf[:aead.Overhead()+len(text)])
|
||||||
|
}
|
||||||
|
|
||||||
func TestOriginalBounce(t *testing.T) {
|
func TestOriginalBounce(t *testing.T) {
|
||||||
aead := original.NewSimple()
|
aead := original.NewSimple()
|
||||||
buf := make([]byte, aead.NonceSize()+aead.Overhead())
|
buf := make([]byte, aead.NonceSize()+aead.Overhead())
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package noise
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
func (c *Config) UDP() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
|
return NewConnClient(c, raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
|
return NewConnServer(c, raw)
|
||||||
|
}
|
||||||
@@ -0,0 +1,225 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.36.11
|
||||||
|
// protoc v6.33.5
|
||||||
|
// source: transport/internet/finalmask/noise/config.proto
|
||||||
|
|
||||||
|
package noise
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Item struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
RandMin int64 `protobuf:"varint,1,opt,name=rand_min,json=randMin,proto3" json:"rand_min,omitempty"`
|
||||||
|
RandMax int64 `protobuf:"varint,2,opt,name=rand_max,json=randMax,proto3" json:"rand_max,omitempty"`
|
||||||
|
Packet []byte `protobuf:"bytes,3,opt,name=packet,proto3" json:"packet,omitempty"`
|
||||||
|
DelayMin int64 `protobuf:"varint,4,opt,name=delay_min,json=delayMin,proto3" json:"delay_min,omitempty"`
|
||||||
|
DelayMax int64 `protobuf:"varint,5,opt,name=delay_max,json=delayMax,proto3" json:"delay_max,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Item) Reset() {
|
||||||
|
*x = Item{}
|
||||||
|
mi := &file_transport_internet_finalmask_noise_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Item) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Item) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Item) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_transport_internet_finalmask_noise_config_proto_msgTypes[0]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Item.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Item) Descriptor() ([]byte, []int) {
|
||||||
|
return file_transport_internet_finalmask_noise_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Item) GetRandMin() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.RandMin
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Item) GetRandMax() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.RandMax
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Item) GetPacket() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Packet
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Item) GetDelayMin() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.DelayMin
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Item) GetDelayMax() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.DelayMax
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
ResetMin int64 `protobuf:"varint,1,opt,name=reset_min,json=resetMin,proto3" json:"reset_min,omitempty"`
|
||||||
|
ResetMax int64 `protobuf:"varint,2,opt,name=reset_max,json=resetMax,proto3" json:"reset_max,omitempty"`
|
||||||
|
Items []*Item `protobuf:"bytes,3,rep,name=items,proto3" json:"items,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) Reset() {
|
||||||
|
*x = Config{}
|
||||||
|
mi := &file_transport_internet_finalmask_noise_config_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_transport_internet_finalmask_noise_config_proto_msgTypes[1]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
|
return file_transport_internet_finalmask_noise_config_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetResetMin() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.ResetMin
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetResetMax() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.ResetMax
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetItems() []*Item {
|
||||||
|
if x != nil {
|
||||||
|
return x.Items
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_transport_internet_finalmask_noise_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
const file_transport_internet_finalmask_noise_config_proto_rawDesc = "" +
|
||||||
|
"\n" +
|
||||||
|
"/transport/internet/finalmask/noise/config.proto\x12'xray.transport.internet.finalmask.noise\"\x8e\x01\n" +
|
||||||
|
"\x04Item\x12\x19\n" +
|
||||||
|
"\brand_min\x18\x01 \x01(\x03R\arandMin\x12\x19\n" +
|
||||||
|
"\brand_max\x18\x02 \x01(\x03R\arandMax\x12\x16\n" +
|
||||||
|
"\x06packet\x18\x03 \x01(\fR\x06packet\x12\x1b\n" +
|
||||||
|
"\tdelay_min\x18\x04 \x01(\x03R\bdelayMin\x12\x1b\n" +
|
||||||
|
"\tdelay_max\x18\x05 \x01(\x03R\bdelayMax\"\x87\x01\n" +
|
||||||
|
"\x06Config\x12\x1b\n" +
|
||||||
|
"\treset_min\x18\x01 \x01(\x03R\bresetMin\x12\x1b\n" +
|
||||||
|
"\treset_max\x18\x02 \x01(\x03R\bresetMax\x12C\n" +
|
||||||
|
"\x05items\x18\x03 \x03(\v2-.xray.transport.internet.finalmask.noise.ItemR\x05itemsB\x97\x01\n" +
|
||||||
|
"+com.xray.transport.internet.finalmask.noiseP\x01Z<github.com/xtls/xray-core/transport/internet/finalmask/noise\xaa\x02'Xray.Transport.Internet.Finalmask.Noiseb\x06proto3"
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_transport_internet_finalmask_noise_config_proto_rawDescOnce sync.Once
|
||||||
|
file_transport_internet_finalmask_noise_config_proto_rawDescData []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_transport_internet_finalmask_noise_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_transport_internet_finalmask_noise_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_transport_internet_finalmask_noise_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_transport_internet_finalmask_noise_config_proto_rawDesc), len(file_transport_internet_finalmask_noise_config_proto_rawDesc)))
|
||||||
|
})
|
||||||
|
return file_transport_internet_finalmask_noise_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_transport_internet_finalmask_noise_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||||
|
var file_transport_internet_finalmask_noise_config_proto_goTypes = []any{
|
||||||
|
(*Item)(nil), // 0: xray.transport.internet.finalmask.noise.Item
|
||||||
|
(*Config)(nil), // 1: xray.transport.internet.finalmask.noise.Config
|
||||||
|
}
|
||||||
|
var file_transport_internet_finalmask_noise_config_proto_depIdxs = []int32{
|
||||||
|
0, // 0: xray.transport.internet.finalmask.noise.Config.items:type_name -> xray.transport.internet.finalmask.noise.Item
|
||||||
|
1, // [1:1] is the sub-list for method output_type
|
||||||
|
1, // [1:1] is the sub-list for method input_type
|
||||||
|
1, // [1:1] is the sub-list for extension type_name
|
||||||
|
1, // [1:1] is the sub-list for extension extendee
|
||||||
|
0, // [0:1] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_transport_internet_finalmask_noise_config_proto_init() }
|
||||||
|
func file_transport_internet_finalmask_noise_config_proto_init() {
|
||||||
|
if File_transport_internet_finalmask_noise_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_transport_internet_finalmask_noise_config_proto_rawDesc), len(file_transport_internet_finalmask_noise_config_proto_rawDesc)),
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 2,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_transport_internet_finalmask_noise_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_transport_internet_finalmask_noise_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_transport_internet_finalmask_noise_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_transport_internet_finalmask_noise_config_proto = out.File
|
||||||
|
file_transport_internet_finalmask_noise_config_proto_goTypes = nil
|
||||||
|
file_transport_internet_finalmask_noise_config_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.transport.internet.finalmask.noise;
|
||||||
|
option csharp_namespace = "Xray.Transport.Internet.Finalmask.Noise";
|
||||||
|
option go_package = "github.com/xtls/xray-core/transport/internet/finalmask/noise";
|
||||||
|
option java_package = "com.xray.transport.internet.finalmask.noise";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
message Item {
|
||||||
|
int64 rand_min = 1;
|
||||||
|
int64 rand_max = 2;
|
||||||
|
bytes packet = 3;
|
||||||
|
int64 delay_min = 4;
|
||||||
|
int64 delay_max = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Config {
|
||||||
|
int64 reset_min = 1;
|
||||||
|
int64 reset_max = 2;
|
||||||
|
repeated Item items = 3;
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package noise
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type noiseConn struct {
|
||||||
|
net.PacketConn
|
||||||
|
config *Config
|
||||||
|
m map[string]time.Time
|
||||||
|
stop chan struct{}
|
||||||
|
once sync.Once
|
||||||
|
mutex sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
|
conn := &noiseConn{
|
||||||
|
PacketConn: raw,
|
||||||
|
config: c,
|
||||||
|
m: make(map[string]time.Time),
|
||||||
|
stop: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if conn.config.ResetMax > 0 {
|
||||||
|
go conn.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
|
return NewConnClient(c, raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *noiseConn) reset() {
|
||||||
|
ticker := time.NewTicker(1 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
c.mutex.RLock()
|
||||||
|
now := time.Now()
|
||||||
|
timeOut := make([]string, 0, len(c.m))
|
||||||
|
for key, last := range c.m {
|
||||||
|
if now.After(last) {
|
||||||
|
timeOut = append(timeOut, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
|
||||||
|
for _, key := range timeOut {
|
||||||
|
c.mutex.Lock()
|
||||||
|
delete(c.m, key)
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
case <-c.stop:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *noiseConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
_, ready := c.m[addr.String()]
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
|
||||||
|
if !ready {
|
||||||
|
c.mutex.Lock()
|
||||||
|
_, ready = c.m[addr.String()]
|
||||||
|
if !ready {
|
||||||
|
for _, item := range c.config.Items {
|
||||||
|
if item.RandMax > 0 {
|
||||||
|
item.Packet = make([]byte, crypto.RandBetween(item.RandMin, item.RandMax))
|
||||||
|
common.Must2(rand.Read(item.Packet))
|
||||||
|
}
|
||||||
|
c.PacketConn.WriteTo(item.Packet, addr)
|
||||||
|
time.Sleep(time.Duration(crypto.RandBetween(item.DelayMin, item.DelayMax)) * time.Millisecond)
|
||||||
|
}
|
||||||
|
c.m[addr.String()] = time.Now().Add(time.Duration(crypto.RandBetween(c.config.ResetMin, c.config.ResetMax)) * time.Second)
|
||||||
|
}
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.PacketConn.WriteTo(p, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *noiseConn) Close() error {
|
||||||
|
c.once.Do(func() {
|
||||||
|
close(c.stop)
|
||||||
|
})
|
||||||
|
return c.PacketConn.Close()
|
||||||
|
}
|
||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, first, leaveSize)
|
return NewConnServer(c, raw)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,147 +1,83 @@
|
|||||||
package salamander
|
package salamander
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
type obfsPacketConn struct {
|
type salamanderConn struct {
|
||||||
first bool
|
net.PacketConn
|
||||||
leaveSize int32
|
|
||||||
|
|
||||||
conn net.PacketConn
|
|
||||||
obfs *SalamanderObfuscator
|
obfs *SalamanderObfuscator
|
||||||
|
|
||||||
readBuf []byte
|
|
||||||
readMutex sync.Mutex
|
|
||||||
writeBuf []byte
|
|
||||||
writeMutex sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
ob, err := NewSalamanderObfuscator([]byte(c.Password))
|
ob, err := NewSalamanderObfuscator([]byte(c.Password))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("salamander err").Base(err)
|
return nil, errors.New("salamander err").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
conn := &obfsPacketConn{
|
conn := &salamanderConn{
|
||||||
first: first,
|
PacketConn: raw,
|
||||||
leaveSize: leaveSize,
|
obfs: ob,
|
||||||
|
|
||||||
conn: raw,
|
|
||||||
obfs: ob,
|
|
||||||
}
|
|
||||||
|
|
||||||
if first {
|
|
||||||
conn.readBuf = make([]byte, 8192)
|
|
||||||
conn.writeBuf = make([]byte, 8192)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, first bool, leaveSize int32) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, first, leaveSize)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *obfsPacketConn) Size() int32 {
|
func (c *salamanderConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
return smSaltLen
|
buf := p
|
||||||
}
|
if len(p) < finalmask.UDPSize {
|
||||||
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
func (c *obfsPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
|
||||||
if c.first {
|
|
||||||
c.readMutex.Lock()
|
|
||||||
|
|
||||||
n, addr, err = c.conn.ReadFrom(c.readBuf)
|
|
||||||
if err != nil {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n, addr, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("salamander").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) < n-int(c.Size()) {
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return 0, addr, errors.New("salamander").Base(io.ErrShortBuffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.obfs.Deobfuscate(c.readBuf[:n], p)
|
|
||||||
|
|
||||||
c.readMutex.Unlock()
|
|
||||||
return n - int(c.Size()), addr, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n, addr, err = c.conn.ReadFrom(p)
|
n, addr, err = c.PacketConn.ReadFrom(buf)
|
||||||
if err != nil {
|
if err != nil || n == 0 {
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < int(c.Size()) {
|
if n < smSaltLen {
|
||||||
return 0, addr, errors.New("salamander").Base(io.ErrShortBuffer)
|
errors.LogDebug(context.Background(), addr, " mask read err short lenth ", n)
|
||||||
|
return 0, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.obfs.Deobfuscate(p[:n], p)
|
if len(p) < n-smSaltLen {
|
||||||
|
errors.LogDebug(context.Background(), addr, " mask read err short buffer ", len(p), " ", n-smSaltLen)
|
||||||
return n - int(c.Size()), addr, err
|
return 0, addr, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (c *obfsPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|
||||||
if c.first {
|
|
||||||
if c.leaveSize+c.Size()+int32(len(p)) > 8192 {
|
|
||||||
return 0, errors.New("too many masks")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Lock()
|
|
||||||
|
|
||||||
n = copy(c.writeBuf[c.leaveSize+c.Size():], p)
|
|
||||||
n += int(c.leaveSize) + int(c.Size())
|
|
||||||
|
|
||||||
c.obfs.Obfuscate(c.writeBuf[c.leaveSize+c.Size():n], c.writeBuf[c.leaveSize:n])
|
|
||||||
|
|
||||||
nn, err := c.conn.WriteTo(c.writeBuf[:n], addr)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nn != n {
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return 0, errors.New("nn != n")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.writeMutex.Unlock()
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.obfs.Obfuscate(p[c.leaveSize+c.Size():], p[c.leaveSize:])
|
c.obfs.Deobfuscate(buf[:n], p)
|
||||||
|
|
||||||
return c.conn.WriteTo(p, addr)
|
return n - smSaltLen, addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *obfsPacketConn) Close() error {
|
func (c *salamanderConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
return c.conn.Close()
|
if smSaltLen+len(p) > finalmask.UDPSize {
|
||||||
}
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", smSaltLen+len(p), " ", finalmask.UDPSize)
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *obfsPacketConn) LocalAddr() net.Addr {
|
var buf []byte
|
||||||
return c.conn.LocalAddr()
|
if cap(p) != finalmask.UDPSize {
|
||||||
}
|
buf = make([]byte, finalmask.UDPSize)
|
||||||
|
} else {
|
||||||
|
buf = p[:smSaltLen+len(p)]
|
||||||
|
copy(buf[smSaltLen:], p)
|
||||||
|
p = buf[smSaltLen:]
|
||||||
|
}
|
||||||
|
|
||||||
func (c *obfsPacketConn) SetDeadline(t time.Time) error {
|
c.obfs.Obfuscate(p, buf)
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *obfsPacketConn) SetReadDeadline(t time.Time) error {
|
_, err = c.PacketConn.WriteTo(buf[:smSaltLen+len(p)], addr)
|
||||||
return c.conn.SetReadDeadline(t)
|
if err != nil {
|
||||||
}
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *obfsPacketConn) SetWriteDeadline(t time.Time) error {
|
return len(p), nil
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package finalmask_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask/header/custom"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mustSendRecvTcp(
|
||||||
|
t *testing.T,
|
||||||
|
from net.Conn,
|
||||||
|
to net.Conn,
|
||||||
|
msg []byte,
|
||||||
|
) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
_, err := from.Write(msg)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
n, err := io.ReadFull(to, buf[:len(msg)])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != len(msg) {
|
||||||
|
t.Fatalf("unexpected size: %d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(buf[:n], msg) {
|
||||||
|
t.Fatalf("unexpected data %q", buf[:n])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type layerMaskTcp struct {
|
||||||
|
name string
|
||||||
|
mask finalmask.Tcpmask
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConnReadWrite(t *testing.T) {
|
||||||
|
cases := []layerMaskTcp{
|
||||||
|
{
|
||||||
|
name: "custom",
|
||||||
|
mask: &custom.TCPConfig{
|
||||||
|
Clients: []*custom.TCPSequence{
|
||||||
|
{
|
||||||
|
Sequence: []*custom.TCPItem{
|
||||||
|
{
|
||||||
|
Packet: []byte{1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Rand: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Servers: []*custom.TCPSequence{
|
||||||
|
{
|
||||||
|
Sequence: []*custom.TCPItem{
|
||||||
|
{
|
||||||
|
Packet: []byte{2},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Rand: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
mask := c.mask
|
||||||
|
|
||||||
|
maskManager := finalmask.NewTcpmaskManager([]finalmask.Tcpmask{mask})
|
||||||
|
|
||||||
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := net.Dial("tcp", ln.Addr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err = maskManager.WrapConnClient(client)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server, err := ln.Accept()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server, err = maskManager.WrapConnServer(server)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = client.SetDeadline(time.Now().Add(time.Second))
|
||||||
|
_ = server.SetDeadline(time.Now().Add(time.Second))
|
||||||
|
|
||||||
|
mustSendRecvTcp(t, client, server, []byte("client -> server"))
|
||||||
|
mustSendRecvTcp(t, server, client, []byte("server -> client"))
|
||||||
|
|
||||||
|
mustSendRecvTcp(t, client, server, []byte{})
|
||||||
|
mustSendRecvTcp(t, server, client, []byte{})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask"
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
|
"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/dns"
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask/header/srtp"
|
"github.com/xtls/xray-core/transport/internet/finalmask/header/srtp"
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask/header/utp"
|
"github.com/xtls/xray-core/transport/internet/finalmask/header/utp"
|
||||||
@@ -82,6 +83,27 @@ func TestPacketConnReadWrite(t *testing.T) {
|
|||||||
name: "wireguard",
|
name: "wireguard",
|
||||||
mask: &wireguard.Config{},
|
mask: &wireguard.Config{},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "custom",
|
||||||
|
mask: &custom.UDPConfig{
|
||||||
|
Client: []*custom.UDPItem{
|
||||||
|
{
|
||||||
|
Packet: []byte{1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Rand: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Server: []*custom.UDPItem{
|
||||||
|
{
|
||||||
|
Packet: []byte{1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Rand: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "salamander",
|
name: "salamander",
|
||||||
mask: &salamander.Config{Password: "1234"},
|
mask: &salamander.Config{Password: "1234"},
|
||||||
@@ -98,7 +120,6 @@ func TestPacketConnReadWrite(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer client.Close()
|
|
||||||
|
|
||||||
client, err = maskManager.WrapPacketConnClient(client)
|
client, err = maskManager.WrapPacketConnClient(client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -109,7 +130,6 @@ func TestPacketConnReadWrite(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
server, err = maskManager.WrapPacketConnServer(server)
|
server, err = maskManager.WrapPacketConnServer(server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -6,12 +6,15 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
go_errors "errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -31,7 +34,7 @@ type packet struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type xdnsConnClient struct {
|
type xdnsConnClient struct {
|
||||||
conn net.PacketConn
|
net.PacketConn
|
||||||
|
|
||||||
clientID []byte
|
clientID []byte
|
||||||
domain Name
|
domain Name
|
||||||
@@ -44,28 +47,24 @@ type xdnsConnClient struct {
|
|||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, end bool) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
if !end {
|
|
||||||
return nil, errors.New("xdns requires being at the outermost level")
|
|
||||||
}
|
|
||||||
|
|
||||||
domain, err := ParseName(c.Domain)
|
domain, err := ParseName(c.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
conn := &xdnsConnClient{
|
conn := &xdnsConnClient{
|
||||||
conn: raw,
|
PacketConn: raw,
|
||||||
|
|
||||||
clientID: make([]byte, 8),
|
clientID: make([]byte, 8),
|
||||||
domain: domain,
|
domain: domain,
|
||||||
|
|
||||||
pollChan: make(chan struct{}, pollLimit),
|
pollChan: make(chan struct{}, pollLimit),
|
||||||
readQueue: make(chan *packet, 128),
|
readQueue: make(chan *packet, 256),
|
||||||
writeQueue: make(chan *packet, 128),
|
writeQueue: make(chan *packet, 256),
|
||||||
}
|
}
|
||||||
|
|
||||||
rand.Read(conn.clientID)
|
common.Must2(rand.Read(conn.clientID))
|
||||||
|
|
||||||
go conn.recvLoop()
|
go conn.recvLoop()
|
||||||
go conn.sendLoop()
|
go conn.sendLoop()
|
||||||
@@ -74,20 +73,24 @@ func NewConnClient(c *Config, raw net.PacketConn, end bool) (net.PacketConn, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnClient) recvLoop() {
|
func (c *xdnsConnClient) recvLoop() {
|
||||||
|
var buf [finalmask.UDPSize]byte
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if c.closed {
|
if c.closed {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf [4096]byte
|
n, addr, err := c.PacketConn.ReadFrom(buf[:])
|
||||||
|
if err != nil || n == 0 {
|
||||||
n, addr, err := c.conn.ReadFrom(buf[:])
|
if go_errors.Is(err, net.ErrClosed) || go_errors.Is(err, io.EOF) {
|
||||||
if err != nil {
|
break
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := MessageFromWireFormat(buf[:n])
|
resp, err := MessageFromWireFormat(buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errors.LogDebug(context.Background(), addr, " xdns from wireformat err ", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +113,7 @@ func (c *xdnsConnClient) recvLoop() {
|
|||||||
addr: addr,
|
addr: addr,
|
||||||
}:
|
}:
|
||||||
default:
|
default:
|
||||||
|
errors.LogDebug(context.Background(), addr, " mask read err queue full")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,8 +125,16 @@ func (c *xdnsConnClient) recvLoop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors.LogDebug(context.Background(), "xdns closed")
|
||||||
|
|
||||||
close(c.pollChan)
|
close(c.pollChan)
|
||||||
close(c.readQueue)
|
close(c.readQueue)
|
||||||
|
|
||||||
|
c.mutex.Lock()
|
||||||
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
|
c.closed = true
|
||||||
|
close(c.writeQueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnClient) sendLoop() {
|
func (c *xdnsConnClient) sendLoop() {
|
||||||
@@ -178,25 +190,26 @@ func (c *xdnsConnClient) sendLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if p != nil {
|
if p != nil {
|
||||||
_, _ = c.conn.WriteTo(p.p, p.addr)
|
_, err := c.PacketConn.WriteTo(p.p, p.addr)
|
||||||
|
if go_errors.Is(err, net.ErrClosed) || go_errors.Is(err, io.ErrClosedPipe) {
|
||||||
|
c.closed = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnClient) Size() int32 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xdnsConnClient) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *xdnsConnClient) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
packet, ok := <-c.readQueue
|
packet, ok := <-c.readQueue
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, nil, io.EOF
|
return 0, nil, net.ErrClosed
|
||||||
}
|
}
|
||||||
n = copy(p, packet.p)
|
if len(p) < len(packet.p) {
|
||||||
if n != len(packet.p) {
|
errors.LogDebug(context.Background(), packet.addr, " mask read err short buffer ", len(p), " ", len(packet.p))
|
||||||
return 0, nil, io.ErrShortBuffer
|
return 0, packet.addr, nil
|
||||||
}
|
}
|
||||||
return n, packet.addr, nil
|
copy(p, packet.p)
|
||||||
|
return len(packet.p), packet.addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *xdnsConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
@@ -204,13 +217,13 @@ func (c *xdnsConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
if c.closed {
|
if c.closed {
|
||||||
return 0, errors.New("xdns closed")
|
return 0, io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
|
|
||||||
encoded, err := encode(p, c.clientID, c.domain)
|
encoded, err := encode(p, c.clientID, c.domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogDebug(context.Background(), "xdns encode err ", err)
|
errors.LogDebug(context.Background(), addr, " xdns wireformat err ", err, " ", len(p))
|
||||||
return 0, errors.New("xdns encode").Base(err)
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@@ -220,38 +233,14 @@ func (c *xdnsConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|||||||
}:
|
}:
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
default:
|
default:
|
||||||
return 0, errors.New("xdns queue full")
|
errors.LogDebug(context.Background(), addr, " mask write err queue full")
|
||||||
|
return 0, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnClient) Close() error {
|
func (c *xdnsConnClient) Close() error {
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
|
|
||||||
if c.closed {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
c.closed = true
|
c.closed = true
|
||||||
close(c.writeQueue)
|
return c.PacketConn.Close()
|
||||||
|
|
||||||
return c.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xdnsConnClient) LocalAddr() net.Addr {
|
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xdnsConnClient) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xdnsConnClient) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xdnsConnClient) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(p []byte, clientID []byte, domain Name) ([]byte, error) {
|
func encode(p []byte, clientID []byte, domain Name) ([]byte, error) {
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, end)
|
return NewConnClient(c, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, end)
|
return NewConnServer(c, raw)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -557,6 +557,8 @@ func TestEncodeRDataTXT(t *testing.T) {
|
|||||||
if len(encoded) > 256 {
|
if len(encoded) > 256 {
|
||||||
t.Errorf("EncodeRDataTXT(%d bytes) returned %d bytes", len(p), len(encoded))
|
t.Errorf("EncodeRDataTXT(%d bytes) returned %d bytes", len(p), len(encoded))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println(EncodeRDataTXT(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRDataTXTRoundTrip(t *testing.T) {
|
func TestRDataTXTRoundTrip(t *testing.T) {
|
||||||
|
|||||||
@@ -4,16 +4,18 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
go_errors "errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
idleTimeout = 2 * time.Minute
|
idleTimeout = 10 * time.Second
|
||||||
responseTTL = 60
|
responseTTL = 60
|
||||||
maxResponseDelay = 1 * time.Second
|
maxResponseDelay = 1 * time.Second
|
||||||
)
|
)
|
||||||
@@ -42,13 +44,13 @@ type record struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type queue struct {
|
type queue struct {
|
||||||
lash time.Time
|
last time.Time
|
||||||
queue chan []byte
|
queue chan []byte
|
||||||
stash chan []byte
|
stash chan []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type xdnsConnServer struct {
|
type xdnsConnServer struct {
|
||||||
conn net.PacketConn
|
net.PacketConn
|
||||||
|
|
||||||
domain Name
|
domain Name
|
||||||
|
|
||||||
@@ -60,23 +62,19 @@ type xdnsConnServer struct {
|
|||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, end bool) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
||||||
if !end {
|
|
||||||
return nil, errors.New("xdns requires being at the outermost level")
|
|
||||||
}
|
|
||||||
|
|
||||||
domain, err := ParseName(c.Domain)
|
domain, err := ParseName(c.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
conn := &xdnsConnServer{
|
conn := &xdnsConnServer{
|
||||||
conn: raw,
|
PacketConn: raw,
|
||||||
|
|
||||||
domain: domain,
|
domain: domain,
|
||||||
|
|
||||||
ch: make(chan *record, 100),
|
ch: make(chan *record, 500),
|
||||||
readQueue: make(chan *packet, 128),
|
readQueue: make(chan *packet, 512),
|
||||||
writeQueueMap: make(map[string]*queue),
|
writeQueueMap: make(map[string]*queue),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +97,7 @@ func (c *xdnsConnServer) clean() {
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
for key, q := range c.writeQueueMap {
|
for key, q := range c.writeQueueMap {
|
||||||
if now.Sub(q.lash) >= idleTimeout {
|
if now.Sub(q.last) >= idleTimeout {
|
||||||
close(q.queue)
|
close(q.queue)
|
||||||
close(q.stash)
|
close(q.stash)
|
||||||
delete(c.writeQueueMap, key)
|
delete(c.writeQueueMap, key)
|
||||||
@@ -118,9 +116,6 @@ func (c *xdnsConnServer) clean() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnServer) ensureQueue(addr net.Addr) *queue {
|
func (c *xdnsConnServer) ensureQueue(addr net.Addr) *queue {
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
|
|
||||||
if c.closed {
|
if c.closed {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -128,12 +123,12 @@ func (c *xdnsConnServer) ensureQueue(addr net.Addr) *queue {
|
|||||||
q, ok := c.writeQueueMap[addr.String()]
|
q, ok := c.writeQueueMap[addr.String()]
|
||||||
if !ok {
|
if !ok {
|
||||||
q = &queue{
|
q = &queue{
|
||||||
queue: make(chan []byte, 128),
|
queue: make(chan []byte, 512),
|
||||||
stash: make(chan []byte, 1),
|
stash: make(chan []byte, 1),
|
||||||
}
|
}
|
||||||
c.writeQueueMap[addr.String()] = q
|
c.writeQueueMap[addr.String()] = q
|
||||||
}
|
}
|
||||||
q.lash = time.Now()
|
q.last = time.Now()
|
||||||
|
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
@@ -153,19 +148,24 @@ func (c *xdnsConnServer) stash(queue *queue, p []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnServer) recvLoop() {
|
func (c *xdnsConnServer) recvLoop() {
|
||||||
|
var buf [finalmask.UDPSize]byte
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if c.closed {
|
if c.closed {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf [4096]byte
|
n, addr, err := c.PacketConn.ReadFrom(buf[:])
|
||||||
n, addr, err := c.conn.ReadFrom(buf[:])
|
if err != nil || n == 0 {
|
||||||
if err != nil {
|
if go_errors.Is(err, net.ErrClosed) || go_errors.Is(err, io.EOF) {
|
||||||
|
break
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
query, err := MessageFromWireFormat(buf[:n])
|
query, err := MessageFromWireFormat(buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errors.LogDebug(context.Background(), addr, " xdns from wireformat err ", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +190,7 @@ func (c *xdnsConnServer) recvLoop() {
|
|||||||
addr: clientIDToAddr(clientID),
|
addr: clientIDToAddr(clientID),
|
||||||
}:
|
}:
|
||||||
default:
|
default:
|
||||||
|
errors.LogDebug(context.Background(), addr, " ", clientID, " mask read err queue full")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -202,12 +203,25 @@ func (c *xdnsConnServer) recvLoop() {
|
|||||||
select {
|
select {
|
||||||
case c.ch <- &record{resp, addr, clientIDToAddr(clientID)}:
|
case c.ch <- &record{resp, addr, clientIDToAddr(clientID)}:
|
||||||
default:
|
default:
|
||||||
|
errors.LogDebug(context.Background(), addr, " ", clientID, " mask read err record queue full")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors.LogDebug(context.Background(), "xdns closed")
|
||||||
|
|
||||||
close(c.ch)
|
close(c.ch)
|
||||||
close(c.readQueue)
|
close(c.readQueue)
|
||||||
|
|
||||||
|
c.mutex.Lock()
|
||||||
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
|
c.closed = true
|
||||||
|
for key, q := range c.writeQueueMap {
|
||||||
|
close(q.queue)
|
||||||
|
close(q.stash)
|
||||||
|
delete(c.writeQueueMap, key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnServer) sendLoop() {
|
func (c *xdnsConnServer) sendLoop() {
|
||||||
@@ -238,24 +252,28 @@ func (c *xdnsConnServer) sendLoop() {
|
|||||||
var payload bytes.Buffer
|
var payload bytes.Buffer
|
||||||
limit := maxEncodedPayload
|
limit := maxEncodedPayload
|
||||||
timer := time.NewTimer(maxResponseDelay)
|
timer := time.NewTimer(maxResponseDelay)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
queue := c.ensureQueue(rec.ClientAddr)
|
c.mutex.Lock()
|
||||||
if queue == nil {
|
q := c.ensureQueue(rec.ClientAddr)
|
||||||
|
if q == nil {
|
||||||
|
c.mutex.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
c.mutex.Unlock()
|
||||||
|
|
||||||
var p []byte
|
var p []byte
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case p = <-queue.stash:
|
case p = <-q.stash:
|
||||||
default:
|
default:
|
||||||
select {
|
select {
|
||||||
case p = <-queue.stash:
|
case p = <-q.stash:
|
||||||
case p = <-queue.queue:
|
case p = <-q.queue:
|
||||||
default:
|
default:
|
||||||
select {
|
select {
|
||||||
case p = <-queue.stash:
|
case p = <-q.stash:
|
||||||
case p = <-queue.queue:
|
case p = <-q.queue:
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
case nextRec = <-c.ch:
|
case nextRec = <-c.ch:
|
||||||
}
|
}
|
||||||
@@ -269,33 +287,31 @@ func (c *xdnsConnServer) sendLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
limit -= 2 + len(p)
|
limit -= 2 + len(p)
|
||||||
if payload.Len() == 0 {
|
if payload.Len() > 0 && limit < 0 {
|
||||||
|
c.stash(q, p)
|
||||||
} else if limit < 0 {
|
|
||||||
c.stash(queue, p)
|
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if int(uint16(len(p))) != len(p) {
|
// if len(p) > 65535 {
|
||||||
panic(len(p))
|
// panic(len(p))
|
||||||
}
|
// }
|
||||||
|
|
||||||
_ = binary.Write(&payload, binary.BigEndian, uint16(len(p)))
|
_ = binary.Write(&payload, binary.BigEndian, uint16(len(p)))
|
||||||
payload.Write(p)
|
payload.Write(p)
|
||||||
}
|
}
|
||||||
timer.Stop()
|
|
||||||
|
|
||||||
|
timer.Stop()
|
||||||
rec.Resp.Answer[0].Data = EncodeRDataTXT(payload.Bytes())
|
rec.Resp.Answer[0].Data = EncodeRDataTXT(payload.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err := rec.Resp.WireFormat()
|
buf, err := rec.Resp.WireFormat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errors.LogDebug(context.Background(), rec.Addr, " ", rec.ClientAddr, " xdns wireformat err ", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(buf) > maxUDPPayload {
|
if len(buf) > maxUDPPayload {
|
||||||
errors.LogDebug(context.Background(), "xdns server truncate ", len(buf))
|
errors.LogDebug(context.Background(), rec.Addr, " ", rec.ClientAddr, " xdns truncate ", len(buf))
|
||||||
buf = buf[:maxUDPPayload]
|
buf = buf[:maxUDPPayload]
|
||||||
buf[2] |= 0x02
|
buf[2] |= 0x02
|
||||||
}
|
}
|
||||||
@@ -304,37 +320,39 @@ func (c *xdnsConnServer) sendLoop() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = c.conn.WriteTo(buf, rec.Addr)
|
_, err = c.PacketConn.WriteTo(buf, rec.Addr)
|
||||||
|
if go_errors.Is(err, net.ErrClosed) || go_errors.Is(err, io.ErrClosedPipe) {
|
||||||
|
c.closed = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnServer) Size() int32 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xdnsConnServer) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *xdnsConnServer) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
packet, ok := <-c.readQueue
|
packet, ok := <-c.readQueue
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, nil, io.EOF
|
return 0, nil, net.ErrClosed
|
||||||
}
|
}
|
||||||
n = copy(p, packet.p)
|
if len(p) < len(packet.p) {
|
||||||
if n != len(packet.p) {
|
errors.LogDebug(context.Background(), packet.addr, " mask read err short buffer ", len(p), " ", len(packet.p))
|
||||||
return 0, nil, io.ErrShortBuffer
|
return 0, packet.addr, nil
|
||||||
}
|
}
|
||||||
return n, packet.addr, nil
|
copy(p, packet.p)
|
||||||
|
return len(packet.p), packet.addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *xdnsConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
q := c.ensureQueue(addr)
|
if len(p)+2 > maxEncodedPayload {
|
||||||
if q == nil {
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", len(p), "+2 > ", maxEncodedPayload)
|
||||||
return 0, errors.New("xdns closed")
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
if c.closed {
|
q := c.ensureQueue(addr)
|
||||||
return 0, errors.New("xdns closed")
|
if q == nil {
|
||||||
|
return 0, io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, len(p))
|
buf := make([]byte, len(p))
|
||||||
@@ -344,42 +362,14 @@ func (c *xdnsConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|||||||
case q.queue <- buf:
|
case q.queue <- buf:
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
default:
|
default:
|
||||||
return 0, errors.New("xdns queue full")
|
// errors.LogDebug(context.Background(), addr, " mask write err queue full")
|
||||||
|
return 0, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xdnsConnServer) Close() error {
|
func (c *xdnsConnServer) Close() error {
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
|
|
||||||
if c.closed {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
c.closed = true
|
c.closed = true
|
||||||
for key, q := range c.writeQueueMap {
|
return c.PacketConn.Close()
|
||||||
close(q.queue)
|
|
||||||
close(q.stash)
|
|
||||||
delete(c.writeQueueMap, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xdnsConnServer) LocalAddr() net.Addr {
|
|
||||||
return c.conn.LocalAddr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xdnsConnServer) SetDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xdnsConnServer) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xdnsConnServer) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.conn.SetWriteDeadline(t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func nextPacketServer(r *bytes.Reader) ([]byte, error) {
|
func nextPacketServer(r *bytes.Reader) ([]byte, error) {
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common/crypto"
|
"github.com/xtls/xray-core/common/crypto"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/hysteria/udphop"
|
||||||
"golang.org/x/net/icmp"
|
"golang.org/x/net/icmp"
|
||||||
"golang.org/x/net/ipv4"
|
"golang.org/x/net/ipv4"
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
@@ -51,8 +54,10 @@ type xicmpConnClient struct {
|
|||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn, end bool) (net.PacketConn, error) {
|
func NewConnClient(c *Config, raw net.PacketConn, level int) (net.PacketConn, error) {
|
||||||
if !end {
|
_, ok1 := raw.(*internet.FakePacketConn)
|
||||||
|
_, ok2 := raw.(*udphop.UdpHopPacketConn)
|
||||||
|
if level != 0 || ok1 || ok2 {
|
||||||
return nil, errors.New("xicmp requires being at the outermost level")
|
return nil, errors.New("xicmp requires being at the outermost level")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +90,8 @@ func NewConnClient(c *Config, raw net.PacketConn, end bool) (net.PacketConn, err
|
|||||||
seqStatus: make(map[int]*seqStatus),
|
seqStatus: make(map[int]*seqStatus),
|
||||||
|
|
||||||
pollChan: make(chan struct{}, pollLimit),
|
pollChan: make(chan struct{}, pollLimit),
|
||||||
readQueue: make(chan *packet, 128),
|
readQueue: make(chan *packet, 256),
|
||||||
writeQueue: make(chan *packet, 128),
|
writeQueue: make(chan *packet, 256),
|
||||||
}
|
}
|
||||||
|
|
||||||
go conn.recvLoop()
|
go conn.recvLoop()
|
||||||
@@ -122,8 +127,8 @@ func (c *xicmpConnClient) encode(p []byte) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(buf) > 8192 {
|
if len(buf) > finalmask.UDPSize {
|
||||||
return nil, errors.New("xicmp len(buf) > 8192")
|
return nil, errors.New("xicmp len(buf) > finalmask.UDPSize")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.seqStatus[c.seq] = &seqStatus{
|
c.seqStatus[c.seq] = &seqStatus{
|
||||||
@@ -144,13 +149,13 @@ func (c *xicmpConnClient) encode(p []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnClient) recvLoop() {
|
func (c *xicmpConnClient) recvLoop() {
|
||||||
|
var buf [finalmask.UDPSize]byte
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if c.closed {
|
if c.closed {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf [8192]byte
|
|
||||||
|
|
||||||
n, addr, err := c.icmpConn.ReadFrom(buf[:])
|
n, addr, err := c.icmpConn.ReadFrom(buf[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
@@ -201,6 +206,7 @@ func (c *xicmpConnClient) recvLoop() {
|
|||||||
addr: &net.UDPAddr{IP: addr.(*net.IPAddr).IP},
|
addr: &net.UDPAddr{IP: addr.(*net.IPAddr).IP},
|
||||||
}:
|
}:
|
||||||
default:
|
default:
|
||||||
|
errors.LogDebug(context.Background(), addr, " ", echo.Seq, " ", echo.ID, " mask read err queue full")
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@@ -210,8 +216,16 @@ func (c *xicmpConnClient) recvLoop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors.LogDebug(context.Background(), "xicmp closed")
|
||||||
|
|
||||||
close(c.pollChan)
|
close(c.pollChan)
|
||||||
close(c.readQueue)
|
close(c.readQueue)
|
||||||
|
|
||||||
|
c.mutex.Lock()
|
||||||
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
|
c.closed = true
|
||||||
|
close(c.writeQueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnClient) sendLoop() {
|
func (c *xicmpConnClient) sendLoop() {
|
||||||
@@ -269,39 +283,37 @@ func (c *xicmpConnClient) sendLoop() {
|
|||||||
if p != nil {
|
if p != nil {
|
||||||
_, err := c.icmpConn.WriteTo(p.p, p.addr)
|
_, err := c.icmpConn.WriteTo(p.p, p.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogDebug(context.Background(), "xicmp writeto err ", err)
|
errors.LogDebug(context.Background(), p.addr, " xicmp writeto err ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnClient) Size() int32 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xicmpConnClient) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *xicmpConnClient) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
packet, ok := <-c.readQueue
|
packet, ok := <-c.readQueue
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, nil, io.EOF
|
return 0, nil, net.ErrClosed
|
||||||
}
|
}
|
||||||
n = copy(p, packet.p)
|
if len(p) < len(packet.p) {
|
||||||
if n != len(packet.p) {
|
errors.LogDebug(context.Background(), packet.addr, " mask read err short buffer ", len(p), " ", len(packet.p))
|
||||||
return 0, nil, io.ErrShortBuffer
|
return 0, packet.addr, nil
|
||||||
}
|
}
|
||||||
return n, packet.addr, nil
|
copy(p, packet.p)
|
||||||
|
return len(packet.p), packet.addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *xicmpConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
encoded, err := c.encode(p)
|
encoded, err := c.encode(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.New("xicmp encode").Base(err)
|
errors.LogDebug(context.Background(), addr, " xicmp wireformat err ", err)
|
||||||
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
if c.closed {
|
if c.closed {
|
||||||
return 0, errors.New("xicmp closed")
|
return 0, io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@@ -311,21 +323,13 @@ func (c *xicmpConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|||||||
}:
|
}:
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
default:
|
default:
|
||||||
return 0, errors.New("xicmp queue full")
|
errors.LogDebug(context.Background(), addr, " mask write err queue full")
|
||||||
|
return 0, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnClient) Close() error {
|
func (c *xicmpConnClient) Close() error {
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
|
|
||||||
if c.closed {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
c.closed = true
|
c.closed = true
|
||||||
close(c.writeQueue)
|
|
||||||
|
|
||||||
_ = c.icmpConn.Close()
|
_ = c.icmpConn.Close()
|
||||||
return c.conn.Close()
|
return c.conn.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
func (c *Config) UDP() {
|
func (c *Config) UDP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw, end)
|
return NewConnClient(c, raw, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, first bool, leaveSize int32, end bool) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw, end)
|
return NewConnServer(c, raw, level)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,14 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common/crypto"
|
"github.com/xtls/xray-core/common/crypto"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
"golang.org/x/net/icmp"
|
"golang.org/x/net/icmp"
|
||||||
"golang.org/x/net/ipv4"
|
"golang.org/x/net/ipv4"
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
idleTimeout = 2 * time.Minute
|
idleTimeout = 10 * time.Second
|
||||||
maxResponseDelay = 1 * time.Second
|
maxResponseDelay = 1 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ type record struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type queue struct {
|
type queue struct {
|
||||||
lash time.Time
|
last time.Time
|
||||||
queue chan []byte
|
queue chan []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,8 +50,8 @@ type xicmpConnServer struct {
|
|||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn, end bool) (net.PacketConn, error) {
|
func NewConnServer(c *Config, raw net.PacketConn, level int) (net.PacketConn, error) {
|
||||||
if !end {
|
if level != 0 {
|
||||||
return nil, errors.New("xicmp requires being at the outermost level")
|
return nil, errors.New("xicmp requires being at the outermost level")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,8 +77,8 @@ func NewConnServer(c *Config, raw net.PacketConn, end bool) (net.PacketConn, err
|
|||||||
proto: proto,
|
proto: proto,
|
||||||
config: c,
|
config: c,
|
||||||
|
|
||||||
ch: make(chan *record, 100),
|
ch: make(chan *record, 500),
|
||||||
readQueue: make(chan *packet, 128),
|
readQueue: make(chan *packet, 512),
|
||||||
writeQueueMap: make(map[string]*queue),
|
writeQueueMap: make(map[string]*queue),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +101,7 @@ func (c *xicmpConnServer) clean() {
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
for key, q := range c.writeQueueMap {
|
for key, q := range c.writeQueueMap {
|
||||||
if now.Sub(q.lash) >= idleTimeout {
|
if now.Sub(q.last) >= idleTimeout {
|
||||||
close(q.queue)
|
close(q.queue)
|
||||||
delete(c.writeQueueMap, key)
|
delete(c.writeQueueMap, key)
|
||||||
}
|
}
|
||||||
@@ -118,9 +119,6 @@ func (c *xicmpConnServer) clean() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnServer) ensureQueue(addr net.Addr) *queue {
|
func (c *xicmpConnServer) ensureQueue(addr net.Addr) *queue {
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
|
|
||||||
if c.closed {
|
if c.closed {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -128,11 +126,11 @@ func (c *xicmpConnServer) ensureQueue(addr net.Addr) *queue {
|
|||||||
q, ok := c.writeQueueMap[addr.String()]
|
q, ok := c.writeQueueMap[addr.String()]
|
||||||
if !ok {
|
if !ok {
|
||||||
q = &queue{
|
q = &queue{
|
||||||
queue: make(chan []byte, 128),
|
queue: make(chan []byte, 512),
|
||||||
}
|
}
|
||||||
c.writeQueueMap[addr.String()] = q
|
c.writeQueueMap[addr.String()] = q
|
||||||
}
|
}
|
||||||
q.lash = time.Now()
|
q.last = time.Now()
|
||||||
|
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
@@ -159,8 +157,8 @@ func (c *xicmpConnServer) encode(p []byte, id int, seq int, needSeqByte bool, se
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(buf) > 8192 {
|
if len(buf) > finalmask.UDPSize {
|
||||||
return nil, errors.New("xicmp len(buf) > 8192")
|
return nil, errors.New("xicmp len(buf) > finalmask.UDPSize")
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf, nil
|
return buf, nil
|
||||||
@@ -177,13 +175,13 @@ func (c *xicmpConnServer) randUntil(b1 byte) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnServer) recvLoop() {
|
func (c *xicmpConnServer) recvLoop() {
|
||||||
|
var buf [finalmask.UDPSize]byte
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if c.closed {
|
if c.closed {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf [8192]byte
|
|
||||||
|
|
||||||
n, addr, err := c.icmpConn.ReadFrom(buf[:])
|
n, addr, err := c.icmpConn.ReadFrom(buf[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
@@ -225,6 +223,7 @@ func (c *xicmpConnServer) recvLoop() {
|
|||||||
},
|
},
|
||||||
}:
|
}:
|
||||||
default:
|
default:
|
||||||
|
errors.LogDebug(context.Background(), addr, " ", echo.ID, " ", echo.Seq, " mask read err queue full")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,11 +239,23 @@ func (c *xicmpConnServer) recvLoop() {
|
|||||||
},
|
},
|
||||||
}:
|
}:
|
||||||
default:
|
default:
|
||||||
|
errors.LogDebug(context.Background(), addr, " ", echo.ID, " ", echo.Seq, " mask read err record queue full")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors.LogDebug(context.Background(), "xicmp closed")
|
||||||
|
|
||||||
close(c.ch)
|
close(c.ch)
|
||||||
close(c.readQueue)
|
close(c.readQueue)
|
||||||
|
|
||||||
|
c.mutex.Lock()
|
||||||
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
|
c.closed = true
|
||||||
|
for key, q := range c.writeQueueMap {
|
||||||
|
close(q.queue)
|
||||||
|
delete(c.writeQueueMap, key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnServer) sendLoop() {
|
func (c *xicmpConnServer) sendLoop() {
|
||||||
@@ -261,20 +272,23 @@ func (c *xicmpConnServer) sendLoop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
queue := c.ensureQueue(rec.addr)
|
c.mutex.Lock()
|
||||||
if queue == nil {
|
q := c.ensureQueue(rec.addr)
|
||||||
|
if q == nil {
|
||||||
|
c.mutex.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
c.mutex.Unlock()
|
||||||
|
|
||||||
var p []byte
|
var p []byte
|
||||||
|
|
||||||
timer := time.NewTimer(maxResponseDelay)
|
timer := time.NewTimer(maxResponseDelay)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case p = <-queue.queue:
|
case p = <-q.queue:
|
||||||
default:
|
default:
|
||||||
select {
|
select {
|
||||||
case p = <-queue.queue:
|
case p = <-q.queue:
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
case nextRec = <-c.ch:
|
case nextRec = <-c.ch:
|
||||||
}
|
}
|
||||||
@@ -288,6 +302,7 @@ func (c *xicmpConnServer) sendLoop() {
|
|||||||
|
|
||||||
buf, err := c.encode(p, rec.id, rec.seq, rec.needSeqByte, rec.seqByte)
|
buf, err := c.encode(p, rec.id, rec.seq, rec.needSeqByte, rec.seqByte)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errors.LogDebug(context.Background(), rec.addr, " ", rec.id, " ", rec.seq, " xicmp wireformat err ", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,38 +312,36 @@ func (c *xicmpConnServer) sendLoop() {
|
|||||||
|
|
||||||
_, err = c.icmpConn.WriteTo(buf, &net.IPAddr{IP: rec.addr.(*net.UDPAddr).IP})
|
_, err = c.icmpConn.WriteTo(buf, &net.IPAddr{IP: rec.addr.(*net.UDPAddr).IP})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogDebug(context.Background(), "xicmp writeto err ", err)
|
errors.LogDebug(context.Background(), rec.addr, " ", rec.id, " ", rec.seq, " xicmp writeto err ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnServer) Size() int32 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xicmpConnServer) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *xicmpConnServer) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
packet, ok := <-c.readQueue
|
packet, ok := <-c.readQueue
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, nil, io.EOF
|
return 0, nil, net.ErrClosed
|
||||||
}
|
}
|
||||||
n = copy(p, packet.p)
|
if len(p) < len(packet.p) {
|
||||||
if n != len(packet.p) {
|
errors.LogDebug(context.Background(), packet.addr, " mask read err short buffer ", len(p), " ", len(packet.p))
|
||||||
return 0, nil, io.ErrShortBuffer
|
return 0, packet.addr, nil
|
||||||
}
|
}
|
||||||
return n, packet.addr, nil
|
copy(p, packet.p)
|
||||||
|
return len(packet.p), packet.addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *xicmpConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
q := c.ensureQueue(addr)
|
if len(p)+8+1 > finalmask.UDPSize {
|
||||||
if q == nil {
|
errors.LogDebug(context.Background(), addr, " mask write err short write ", len(p), "+8+1 > ", finalmask.UDPSize)
|
||||||
return 0, errors.New("xicmp closed")
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
if c.closed {
|
q := c.ensureQueue(addr)
|
||||||
return 0, errors.New("xicmp closed")
|
if q == nil {
|
||||||
|
return 0, io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, len(p))
|
buf := make([]byte, len(p))
|
||||||
@@ -338,24 +351,13 @@ func (c *xicmpConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|||||||
case q.queue <- buf:
|
case q.queue <- buf:
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
default:
|
default:
|
||||||
return 0, errors.New("xicmp queue full")
|
// errors.LogDebug(context.Background(), addr, " mask write err queue full")
|
||||||
|
return 0, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnServer) Close() error {
|
func (c *xicmpConnServer) Close() error {
|
||||||
c.mutex.Lock()
|
|
||||||
defer c.mutex.Unlock()
|
|
||||||
|
|
||||||
if c.closed {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
c.closed = true
|
c.closed = true
|
||||||
for key, q := range c.writeQueueMap {
|
|
||||||
close(q.queue)
|
|
||||||
delete(c.writeQueueMap, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = c.icmpConn.Close()
|
_ = c.icmpConn.Close()
|
||||||
return c.conn.Close()
|
return c.conn.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,15 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
|
|
||||||
c, err := internet.DialSystem(gctx, net.TCPDestination(address, port), sockopt)
|
c, err := internet.DialSystem(gctx, net.TCPDestination(address, port), sockopt)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
if streamSettings.TcpmaskManager != nil {
|
||||||
|
newConn, err := streamSettings.TcpmaskManager.WrapConnClient(c)
|
||||||
|
if err != nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
c = newConn
|
||||||
|
}
|
||||||
|
|
||||||
if tlsConfig != nil {
|
if tlsConfig != nil {
|
||||||
config := tlsConfig.GetTLSConfig()
|
config := tlsConfig.GetTLSConfig()
|
||||||
if config.ServerName == "" && address.Family().IsDomain() {
|
if config.ServerName == "" && address.Family().IsDomain() {
|
||||||
|
|||||||
@@ -120,6 +120,10 @@ func Listen(ctx context.Context, address net.Address, port net.Port, settings *i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if settings.TcpmaskManager != nil {
|
||||||
|
streamListener, _ = settings.TcpmaskManager.WrapListener(streamListener)
|
||||||
|
}
|
||||||
|
|
||||||
errors.LogDebug(ctx, "gRPC listen for service name `"+grpcSettings.getServiceName()+"` tun `"+grpcSettings.getTunStreamName()+"` multi tun `"+grpcSettings.getTunMultiStreamName()+"`")
|
errors.LogDebug(ctx, "gRPC listen for service name `"+grpcSettings.getServiceName()+"` tun `"+grpcSettings.getTunStreamName()+"` multi tun `"+grpcSettings.getTunMultiStreamName()+"`")
|
||||||
encoding.RegisterGRPCServiceServerX(s, listener, grpcSettings.getServiceName(), grpcSettings.getTunStreamName(), grpcSettings.getTunMultiStreamName())
|
encoding.RegisterGRPCServiceServerX(s, listener, grpcSettings.getServiceName(), grpcSettings.getTunStreamName(), grpcSettings.getTunMultiStreamName())
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,15 @@ func dialhttpUpgrade(ctx context.Context, dest net.Destination, streamSettings *
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamSettings.TcpmaskManager != nil {
|
||||||
|
newConn, err := streamSettings.TcpmaskManager.WrapConnClient(pconn)
|
||||||
|
if err != nil {
|
||||||
|
pconn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
pconn = newConn
|
||||||
|
}
|
||||||
|
|
||||||
var conn net.Conn
|
var conn net.Conn
|
||||||
var requestURL url.URL
|
var requestURL url.URL
|
||||||
tConfig := tls.ConfigFromStreamSettings(streamSettings)
|
tConfig := tls.ConfigFromStreamSettings(streamSettings)
|
||||||
|
|||||||
@@ -142,6 +142,10 @@ func ListenHTTPUpgrade(ctx context.Context, address net.Address, port net.Port,
|
|||||||
errors.LogInfo(ctx, "listening TCP(for HttpUpgrade) on ", address, ":", port)
|
errors.LogInfo(ctx, "listening TCP(for HttpUpgrade) on ", address, ":", port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamSettings.TcpmaskManager != nil {
|
||||||
|
listener, _ = streamSettings.TcpmaskManager.WrapListener(listener)
|
||||||
|
}
|
||||||
|
|
||||||
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
|
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
|
||||||
errors.LogWarning(ctx, "accepting PROXY protocol")
|
errors.LogWarning(ctx, "accepting PROXY protocol")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ func (i *interConn) Read(b []byte) (int, error) {
|
|||||||
func (i *interConn) Write(b []byte) (int, error) {
|
func (i *interConn) Write(b []byte) (int, error) {
|
||||||
if i.client {
|
if i.client {
|
||||||
i.mutex.Lock()
|
i.mutex.Lock()
|
||||||
|
defer i.mutex.Unlock()
|
||||||
if i.client {
|
if i.client {
|
||||||
buf := make([]byte, 0, quicvarint.Len(FrameTypeTCPRequest)+len(b))
|
buf := make([]byte, 0, quicvarint.Len(FrameTypeTCPRequest)+len(b))
|
||||||
buf = quicvarint.Append(buf, FrameTypeTCPRequest)
|
buf = quicvarint.Append(buf, FrameTypeTCPRequest)
|
||||||
@@ -45,7 +46,6 @@ func (i *interConn) Write(b []byte) (int, error) {
|
|||||||
i.client = false
|
i.client = false
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
i.mutex.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return i.stream.Write(b)
|
return i.stream.Write(b)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -16,6 +17,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
hyCtx "github.com/xtls/xray-core/proxy/hysteria/ctx"
|
hyCtx "github.com/xtls/xray-core/proxy/hysteria/ctx"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
@@ -162,17 +164,33 @@ func (c *client) dial() error {
|
|||||||
return errors.New("failed to dial to dest").Base(err)
|
return errors.New("failed to dial to dest").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
remote := raw.RemoteAddr()
|
var pktConn net.PacketConn
|
||||||
|
var remote *net.UDPAddr
|
||||||
|
|
||||||
pktConn, ok := raw.(net.PacketConn)
|
switch conn := raw.(type) {
|
||||||
if !ok {
|
case *internet.PacketConnWrapper:
|
||||||
|
pktConn = conn.PacketConn
|
||||||
|
remote = conn.RemoteAddr().(*net.UDPAddr)
|
||||||
|
case *net.UDPConn:
|
||||||
|
pktConn = conn
|
||||||
|
remote = conn.RemoteAddr().(*net.UDPAddr)
|
||||||
|
case *cnc.Connection:
|
||||||
|
fakeConn := &internet.FakePacketConn{Conn: conn}
|
||||||
|
pktConn = fakeConn
|
||||||
|
remote = fakeConn.RemoteAddr().(*net.UDPAddr)
|
||||||
|
|
||||||
|
if len(c.config.Ports) > 0 {
|
||||||
|
raw.Close()
|
||||||
|
return errors.New("udphop requires being at the outermost level")
|
||||||
|
}
|
||||||
|
default:
|
||||||
raw.Close()
|
raw.Close()
|
||||||
return errors.New("raw is not PacketConn")
|
return errors.New("unknown conn ", reflect.TypeOf(conn))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.config.Ports) > 0 {
|
if len(c.config.Ports) > 0 {
|
||||||
addr := &udphop.UDPHopAddr{
|
addr := &udphop.UDPHopAddr{
|
||||||
IP: remote.(*net.UDPAddr).IP,
|
IP: remote.IP,
|
||||||
Ports: c.config.Ports,
|
Ports: c.config.Ports,
|
||||||
}
|
}
|
||||||
pktConn, err = udphop.NewUDPHopPacketConn(addr, c.config.IntervalMin, c.config.IntervalMax, c.udphopDialer, pktConn, index)
|
pktConn, err = udphop.NewUDPHopPacketConn(addr, c.config.IntervalMin, c.config.IntervalMax, c.udphopDialer, pktConn, index)
|
||||||
@@ -341,20 +359,28 @@ func (c *client) udphopDialer(addr *net.UDPAddr) (net.PacketConn, error) {
|
|||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
|
|
||||||
if c.status() != StatusActive {
|
if c.status() != StatusActive {
|
||||||
errors.LogDebug(c.ctx, "stop hop on disconnected QUIC waiting to be closed")
|
errors.LogDebug(c.ctx, "skip hop: disconnected QUIC")
|
||||||
return nil, errors.New()
|
return nil, errors.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
raw, err := internet.DialSystem(c.ctx, net.DestinationFromAddr(addr), c.socketConfig)
|
raw, err := internet.DialSystem(c.ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), c.socketConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogDebug(c.ctx, "failed to dial to dest skip hop")
|
errors.LogDebug(c.ctx, "skip hop: failed to dial to dest")
|
||||||
return nil, errors.New()
|
return nil, errors.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
pktConn, ok := raw.(net.PacketConn)
|
var pktConn net.PacketConn
|
||||||
if !ok {
|
|
||||||
errors.LogDebug(c.ctx, "raw is not PacketConn skip hop")
|
switch conn := raw.(type) {
|
||||||
raw.Close()
|
case *internet.PacketConnWrapper:
|
||||||
|
pktConn = conn.PacketConn
|
||||||
|
case *net.UDPConn:
|
||||||
|
pktConn = conn
|
||||||
|
case *cnc.Connection:
|
||||||
|
errors.LogDebug(c.ctx, "skip hop: udphop requires being at the outermost level")
|
||||||
|
return nil, errors.New()
|
||||||
|
default:
|
||||||
|
errors.LogDebug(c.ctx, "skip hop: unknown conn ", reflect.TypeOf(conn))
|
||||||
return nil, errors.New()
|
return nil, errors.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const (
|
|||||||
defaultHopInterval = 30 * time.Second
|
defaultHopInterval = 30 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
type udpHopPacketConn struct {
|
type UdpHopPacketConn struct {
|
||||||
Addr net.Addr
|
Addr net.Addr
|
||||||
Addrs []net.Addr
|
Addrs []net.Addr
|
||||||
HopIntervalMin int64
|
HopIntervalMin int64
|
||||||
@@ -73,7 +73,7 @@ func NewUDPHopPacketConn(addr *UDPHopAddr, intervalMin int64, intervalMax int64,
|
|||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return nil, err
|
// return nil, err
|
||||||
// }
|
// }
|
||||||
hConn := &udpHopPacketConn{
|
hConn := &UdpHopPacketConn{
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
Addrs: addrs,
|
Addrs: addrs,
|
||||||
HopIntervalMin: intervalMin,
|
HopIntervalMin: intervalMin,
|
||||||
@@ -95,7 +95,7 @@ func NewUDPHopPacketConn(addr *UDPHopAddr, intervalMin int64, intervalMax int64,
|
|||||||
return hConn, nil
|
return hConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) recvLoop(conn net.PacketConn) {
|
func (u *UdpHopPacketConn) recvLoop(conn net.PacketConn) {
|
||||||
for {
|
for {
|
||||||
buf := u.bufPool.Get().([]byte)
|
buf := u.bufPool.Get().([]byte)
|
||||||
n, addr, err := conn.ReadFrom(buf)
|
n, addr, err := conn.ReadFrom(buf)
|
||||||
@@ -120,7 +120,7 @@ func (u *udpHopPacketConn) recvLoop(conn net.PacketConn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) hopLoop() {
|
func (u *UdpHopPacketConn) hopLoop() {
|
||||||
ticker := time.NewTicker(time.Duration(crypto.RandBetween(u.HopIntervalMin, u.HopIntervalMax)) * time.Second)
|
ticker := time.NewTicker(time.Duration(crypto.RandBetween(u.HopIntervalMin, u.HopIntervalMax)) * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for {
|
for {
|
||||||
@@ -134,7 +134,7 @@ func (u *udpHopPacketConn) hopLoop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) hop() {
|
func (u *UdpHopPacketConn) hop() {
|
||||||
u.connMutex.Lock()
|
u.connMutex.Lock()
|
||||||
defer u.connMutex.Unlock()
|
defer u.connMutex.Unlock()
|
||||||
if u.closed {
|
if u.closed {
|
||||||
@@ -170,7 +170,7 @@ func (u *udpHopPacketConn) hop() {
|
|||||||
go u.recvLoop(newConn)
|
go u.recvLoop(newConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
func (u *UdpHopPacketConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case p := <-u.recvQueue:
|
case p := <-u.recvQueue:
|
||||||
@@ -188,7 +188,7 @@ func (u *udpHopPacketConn) ReadFrom(b []byte) (n int, addr net.Addr, err error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
func (u *UdpHopPacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
||||||
u.connMutex.RLock()
|
u.connMutex.RLock()
|
||||||
defer u.connMutex.RUnlock()
|
defer u.connMutex.RUnlock()
|
||||||
if u.closed {
|
if u.closed {
|
||||||
@@ -199,7 +199,7 @@ func (u *udpHopPacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
|
|||||||
return u.currentConn.WriteTo(b, u.Addrs[u.addrIndex])
|
return u.currentConn.WriteTo(b, u.Addrs[u.addrIndex])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) Close() error {
|
func (u *UdpHopPacketConn) Close() error {
|
||||||
u.connMutex.Lock()
|
u.connMutex.Lock()
|
||||||
defer u.connMutex.Unlock()
|
defer u.connMutex.Unlock()
|
||||||
if u.closed {
|
if u.closed {
|
||||||
@@ -218,13 +218,13 @@ func (u *udpHopPacketConn) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) LocalAddr() net.Addr {
|
func (u *UdpHopPacketConn) LocalAddr() net.Addr {
|
||||||
u.connMutex.RLock()
|
u.connMutex.RLock()
|
||||||
defer u.connMutex.RUnlock()
|
defer u.connMutex.RUnlock()
|
||||||
return u.currentConn.LocalAddr()
|
return u.currentConn.LocalAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) SetDeadline(t time.Time) error {
|
func (u *UdpHopPacketConn) SetDeadline(t time.Time) error {
|
||||||
u.connMutex.RLock()
|
u.connMutex.RLock()
|
||||||
defer u.connMutex.RUnlock()
|
defer u.connMutex.RUnlock()
|
||||||
if u.prevConn != nil {
|
if u.prevConn != nil {
|
||||||
@@ -233,7 +233,7 @@ func (u *udpHopPacketConn) SetDeadline(t time.Time) error {
|
|||||||
return u.currentConn.SetDeadline(t)
|
return u.currentConn.SetDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) SetReadDeadline(t time.Time) error {
|
func (u *UdpHopPacketConn) SetReadDeadline(t time.Time) error {
|
||||||
u.connMutex.RLock()
|
u.connMutex.RLock()
|
||||||
defer u.connMutex.RUnlock()
|
defer u.connMutex.RUnlock()
|
||||||
if u.prevConn != nil {
|
if u.prevConn != nil {
|
||||||
@@ -242,7 +242,7 @@ func (u *udpHopPacketConn) SetReadDeadline(t time.Time) error {
|
|||||||
return u.currentConn.SetReadDeadline(t)
|
return u.currentConn.SetReadDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) SetWriteDeadline(t time.Time) error {
|
func (u *UdpHopPacketConn) SetWriteDeadline(t time.Time) error {
|
||||||
u.connMutex.RLock()
|
u.connMutex.RLock()
|
||||||
defer u.connMutex.RUnlock()
|
defer u.connMutex.RUnlock()
|
||||||
if u.prevConn != nil {
|
if u.prevConn != nil {
|
||||||
@@ -253,7 +253,7 @@ func (u *udpHopPacketConn) SetWriteDeadline(t time.Time) error {
|
|||||||
|
|
||||||
// UDP-specific methods below
|
// UDP-specific methods below
|
||||||
|
|
||||||
func (u *udpHopPacketConn) SetReadBuffer(bytes int) error {
|
func (u *UdpHopPacketConn) SetReadBuffer(bytes int) error {
|
||||||
u.connMutex.Lock()
|
u.connMutex.Lock()
|
||||||
defer u.connMutex.Unlock()
|
defer u.connMutex.Unlock()
|
||||||
u.readBufferSize = bytes
|
u.readBufferSize = bytes
|
||||||
@@ -263,7 +263,7 @@ func (u *udpHopPacketConn) SetReadBuffer(bytes int) error {
|
|||||||
return trySetReadBuffer(u.currentConn, bytes)
|
return trySetReadBuffer(u.currentConn, bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) SetWriteBuffer(bytes int) error {
|
func (u *UdpHopPacketConn) SetWriteBuffer(bytes int) error {
|
||||||
u.connMutex.Lock()
|
u.connMutex.Lock()
|
||||||
defer u.connMutex.Unlock()
|
defer u.connMutex.Unlock()
|
||||||
u.writeBufferSize = bytes
|
u.writeBufferSize = bytes
|
||||||
@@ -273,7 +273,7 @@ func (u *udpHopPacketConn) SetWriteBuffer(bytes int) error {
|
|||||||
return trySetWriteBuffer(u.currentConn, bytes)
|
return trySetWriteBuffer(u.currentConn, bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *udpHopPacketConn) SyscallConn() (syscall.RawConn, error) {
|
func (u *UdpHopPacketConn) SyscallConn() (syscall.RawConn, error) {
|
||||||
u.connMutex.RLock()
|
u.connMutex.RLock()
|
||||||
defer u.connMutex.RUnlock()
|
defer u.connMutex.RUnlock()
|
||||||
sc, ok := u.currentConn.(syscall.Conn)
|
sc, ok := u.currentConn.(syscall.Conn)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package kcp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
reflect "reflect"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
@@ -10,6 +11,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/dice"
|
"github.com/xtls/xray-core/common/dice"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
@@ -49,24 +51,47 @@ func DialKCP(ctx context.Context, dest net.Destination, streamSettings *internet
|
|||||||
dest.Network = net.Network_UDP
|
dest.Network = net.Network_UDP
|
||||||
errors.LogInfo(ctx, "dialing mKCP to ", dest)
|
errors.LogInfo(ctx, "dialing mKCP to ", dest)
|
||||||
|
|
||||||
rawConn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to dial to dest: ", err).AtWarning().Base(err)
|
return nil, errors.New("failed to dial to dest: ", err).AtWarning().Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if streamSettings.UdpmaskManager != nil {
|
if streamSettings.UdpmaskManager != nil {
|
||||||
wrapper, ok := rawConn.(*internet.PacketConnWrapper)
|
switch c := conn.(type) {
|
||||||
if !ok {
|
case *internet.PacketConnWrapper:
|
||||||
rawConn.Close()
|
pktConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(c.PacketConn)
|
||||||
return nil, errors.New("raw is not PacketConnWrapper")
|
if err != nil {
|
||||||
}
|
conn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
raw := wrapper.Conn
|
}
|
||||||
|
c.PacketConn = pktConn
|
||||||
wrapper.Conn, err = streamSettings.UdpmaskManager.WrapPacketConnClient(raw)
|
case *net.UDPConn:
|
||||||
if err != nil {
|
pktConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(c)
|
||||||
raw.Close()
|
if err != nil {
|
||||||
return nil, errors.New("mask err").Base(err)
|
conn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
conn = &internet.PacketConnWrapper{
|
||||||
|
PacketConn: pktConn,
|
||||||
|
Dest: c.RemoteAddr().(*net.UDPAddr),
|
||||||
|
}
|
||||||
|
case *cnc.Connection:
|
||||||
|
fakeConn := &internet.FakePacketConn{Conn: c}
|
||||||
|
pktConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(fakeConn)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
conn = &internet.PacketConnWrapper{
|
||||||
|
PacketConn: pktConn,
|
||||||
|
Dest: &net.UDPAddr{
|
||||||
|
IP: []byte{0, 0, 0, 0},
|
||||||
|
Port: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
conn.Close()
|
||||||
|
return nil, errors.New("unknown conn ", reflect.TypeOf(c))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,12 +101,12 @@ func DialKCP(ctx context.Context, dest net.Destination, streamSettings *internet
|
|||||||
|
|
||||||
conv := uint16(atomic.AddUint32(&globalConv, 1))
|
conv := uint16(atomic.AddUint32(&globalConv, 1))
|
||||||
session := NewConnection(ConnMetadata{
|
session := NewConnection(ConnMetadata{
|
||||||
LocalAddr: rawConn.LocalAddr(),
|
LocalAddr: conn.LocalAddr(),
|
||||||
RemoteAddr: rawConn.RemoteAddr(),
|
RemoteAddr: conn.RemoteAddr(),
|
||||||
Conversation: conv,
|
Conversation: conv,
|
||||||
}, rawConn, rawConn, kcpSettings)
|
}, conn, conn, kcpSettings)
|
||||||
|
|
||||||
go fetchInput(ctx, rawConn, reader, session)
|
go fetchInput(ctx, conn, reader, session)
|
||||||
|
|
||||||
var iConn stat.Connection = session
|
var iConn stat.Connection = session
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
"github.com/xtls/xray-core/common/uuid"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/browser_dialer"
|
"github.com/xtls/xray-core/transport/internet/browser_dialer"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
"github.com/xtls/xray-core/transport/internet/reality"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
@@ -118,6 +118,15 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamSettings.TcpmaskManager != nil {
|
||||||
|
newConn, err := streamSettings.TcpmaskManager.WrapConnClient(conn)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
conn = newConn
|
||||||
|
}
|
||||||
|
|
||||||
if realityConfig != nil {
|
if realityConfig != nil {
|
||||||
return reality.UClient(conn, realityConfig, ctxInner, dest)
|
return reality.UClient(conn, realityConfig, ctxInner, dest)
|
||||||
}
|
}
|
||||||
@@ -174,7 +183,7 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
|||||||
switch c := conn.(type) {
|
switch c := conn.(type) {
|
||||||
case *internet.PacketConnWrapper:
|
case *internet.PacketConnWrapper:
|
||||||
var ok bool
|
var ok bool
|
||||||
udpConn, ok = c.Conn.(*net.UDPConn)
|
udpConn, ok = c.PacketConn.(*net.UDPConn)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("PacketConnWrapper does not contain a UDP connection")
|
return nil, errors.New("PacketConnWrapper does not contain a UDP connection")
|
||||||
}
|
}
|
||||||
@@ -196,6 +205,15 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamSettings.UdpmaskManager != nil {
|
||||||
|
pktConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(udpConn)
|
||||||
|
if err != nil {
|
||||||
|
udpConn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
udpConn = pktConn
|
||||||
|
}
|
||||||
|
|
||||||
quicConn, err := quic.DialEarly(ctx, udpConn, udpAddr, tlsCfg, cfg)
|
quicConn, err := quic.DialEarly(ctx, udpConn, udpAddr, tlsCfg, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -422,7 +440,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||||||
// code relies on this behavior. Subtract 1 so that together with
|
// code relies on this behavior. Subtract 1 so that together with
|
||||||
// uploadWriter wrapper, exact size limits can be enforced
|
// uploadWriter wrapper, exact size limits can be enforced
|
||||||
// uploadPipeReader, uploadPipeWriter := pipe.New(pipe.WithSizeLimit(maxUploadSize - 1))
|
// uploadPipeReader, uploadPipeWriter := pipe.New(pipe.WithSizeLimit(maxUploadSize - 1))
|
||||||
uploadPipeReader, uploadPipeWriter := pipe.New(pipe.WithSizeLimit(max(0, maxUploadSize - buf.Size)))
|
uploadPipeReader, uploadPipeWriter := pipe.New(pipe.WithSizeLimit(max(0, maxUploadSize-buf.Size)))
|
||||||
|
|
||||||
conn.writer = uploadWriter{
|
conn.writer = uploadWriter{
|
||||||
uploadPipeWriter,
|
uploadPipeWriter,
|
||||||
|
|||||||
@@ -463,6 +463,16 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to listen UDP for XHTTP/3 on ", address, ":", port).Base(err)
|
return nil, errors.New("failed to listen UDP for XHTTP/3 on ", address, ":", port).Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamSettings.UdpmaskManager != nil {
|
||||||
|
pktConn, err := streamSettings.UdpmaskManager.WrapPacketConnServer(Conn)
|
||||||
|
if err != nil {
|
||||||
|
Conn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
Conn = pktConn
|
||||||
|
}
|
||||||
|
|
||||||
l.h3listener, err = quic.ListenEarly(Conn, tlsConfig, nil)
|
l.h3listener, err = quic.ListenEarly(Conn, tlsConfig, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to listen QUIC for XHTTP/3 on ", address, ":", port).Base(err)
|
return nil, errors.New("failed to listen QUIC for XHTTP/3 on ", address, ":", port).Base(err)
|
||||||
@@ -511,6 +521,10 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||||||
errors.LogInfo(ctx, "listening TCP for XHTTP on ", address, ":", port)
|
errors.LogInfo(ctx, "listening TCP for XHTTP on ", address, ":", port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !l.isH3 && streamSettings.TcpmaskManager != nil {
|
||||||
|
l.listener, _ = streamSettings.TcpmaskManager.WrapListener(l.listener)
|
||||||
|
}
|
||||||
|
|
||||||
// tcp/unix (h1/h2)
|
// tcp/unix (h1/h2)
|
||||||
if l.listener != nil {
|
if l.listener != nil {
|
||||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package internet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math/rand"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -83,8 +82,8 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &PacketConnWrapper{
|
return &PacketConnWrapper{
|
||||||
Conn: packetConn,
|
PacketConn: packetConn,
|
||||||
Dest: destAddr,
|
Dest: destAddr,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
// Chrome defaults
|
// Chrome defaults
|
||||||
@@ -150,59 +149,23 @@ func (d *DefaultSystemDialer) DestIpAddress() net.IP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PacketConnWrapper struct {
|
type PacketConnWrapper struct {
|
||||||
Conn net.PacketConn
|
net.PacketConn
|
||||||
Dest net.Addr
|
Dest net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PacketConnWrapper) Close() error {
|
func (c *PacketConnWrapper) Read(p []byte) (int, error) {
|
||||||
return c.Conn.Close()
|
n, _, err := c.PacketConn.ReadFrom(p)
|
||||||
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PacketConnWrapper) LocalAddr() net.Addr {
|
func (c *PacketConnWrapper) Write(p []byte) (int, error) {
|
||||||
return c.Conn.LocalAddr()
|
return c.PacketConn.WriteTo(p, c.Dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PacketConnWrapper) RemoteAddr() net.Addr {
|
func (c *PacketConnWrapper) RemoteAddr() net.Addr {
|
||||||
return c.Dest
|
return c.Dest
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PacketConnWrapper) Write(p []byte) (int, error) {
|
|
||||||
return c.Conn.WriteTo(p, c.Dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConnWrapper) Read(p []byte) (int, error) {
|
|
||||||
n, _, err := c.Conn.ReadFrom(p)
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConnWrapper) WriteTo(p []byte, d net.Addr) (int, error) {
|
|
||||||
return c.Conn.WriteTo(p, d)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConnWrapper) ReadFrom(p []byte) (int, net.Addr, error) {
|
|
||||||
return c.Conn.ReadFrom(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConnWrapper) SetDeadline(t time.Time) error {
|
|
||||||
return c.Conn.SetDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConnWrapper) SetReadDeadline(t time.Time) error {
|
|
||||||
return c.Conn.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConnWrapper) SetWriteDeadline(t time.Time) error {
|
|
||||||
return c.Conn.SetWriteDeadline(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PacketConnWrapper) SyscallConn() (syscall.RawConn, error) {
|
|
||||||
sc, ok := c.Conn.(syscall.Conn)
|
|
||||||
if !ok {
|
|
||||||
return nil, syscall.EINVAL
|
|
||||||
}
|
|
||||||
return sc.SyscallConn()
|
|
||||||
}
|
|
||||||
|
|
||||||
type SystemDialerAdapter interface {
|
type SystemDialerAdapter interface {
|
||||||
Dial(network string, address string) (net.Conn, error)
|
Dial(network string, address string) (net.Conn, error)
|
||||||
}
|
}
|
||||||
@@ -269,14 +232,15 @@ func (c *FakePacketConn) WriteTo(p []byte, _ net.Addr) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakePacketConn) LocalAddr() net.Addr {
|
func (c *FakePacketConn) LocalAddr() net.Addr {
|
||||||
return &net.TCPAddr{
|
return &net.UDPAddr{
|
||||||
IP: net.IP{byte(rand.Intn(256)), byte(rand.Intn(256)), byte(rand.Intn(256)), byte(rand.Intn(256))},
|
IP: []byte{0, 0, 0, 0},
|
||||||
Port: rand.Intn(65536),
|
Port: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FakePacketConn) SetReadBuffer(bytes int) error {
|
func (c *FakePacketConn) RemoteAddr() net.Addr {
|
||||||
// do nothing, this function is only there to suppress quic-go printing
|
return &net.UDPAddr{
|
||||||
// random warnings about UDP buffers to stdout
|
IP: []byte{0, 0, 0, 0},
|
||||||
return nil
|
Port: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamSettings.TcpmaskManager != nil {
|
||||||
|
newConn, err := streamSettings.TcpmaskManager.WrapConnClient(conn)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
conn = newConn
|
||||||
|
}
|
||||||
|
|
||||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
mitmServerName := session.MitmServerNameFromContext(ctx)
|
mitmServerName := session.MitmServerNameFromContext(ctx)
|
||||||
mitmAlpn11 := session.MitmAlpn11FromContext(ctx)
|
mitmAlpn11 := session.MitmAlpn11FromContext(ctx)
|
||||||
|
|||||||
@@ -64,6 +64,10 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSe
|
|||||||
errors.LogInfo(ctx, "listening TCP on ", address, ":", port)
|
errors.LogInfo(ctx, "listening TCP on ", address, ":", port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamSettings.TcpmaskManager != nil {
|
||||||
|
listener, _ = streamSettings.TcpmaskManager.WrapListener(listener)
|
||||||
|
}
|
||||||
|
|
||||||
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
|
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
|
||||||
errors.LogWarning(ctx, "accepting PROXY protocol")
|
errors.LogWarning(ctx, "accepting PROXY protocol")
|
||||||
}
|
}
|
||||||
@@ -108,6 +112,7 @@ func (v *Listener) keepAccepting() {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if v.tlsConfig != nil {
|
if v.tlsConfig != nil {
|
||||||
conn = tls.Server(conn, v.tlsConfig)
|
conn = tls.Server(conn, v.tlsConfig)
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package udp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
)
|
)
|
||||||
@@ -23,18 +25,41 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if streamSettings != nil && streamSettings.UdpmaskManager != nil {
|
if streamSettings != nil && streamSettings.UdpmaskManager != nil {
|
||||||
wrapper, ok := conn.(*internet.PacketConnWrapper)
|
switch c := conn.(type) {
|
||||||
if !ok {
|
case *internet.PacketConnWrapper:
|
||||||
|
pktConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(c.PacketConn)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
c.PacketConn = pktConn
|
||||||
|
case *net.UDPConn:
|
||||||
|
pktConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(c)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
conn = &internet.PacketConnWrapper{
|
||||||
|
PacketConn: pktConn,
|
||||||
|
Dest: c.RemoteAddr().(*net.UDPAddr),
|
||||||
|
}
|
||||||
|
case *cnc.Connection:
|
||||||
|
fakeConn := &internet.FakePacketConn{Conn: c}
|
||||||
|
pktConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(fakeConn)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
conn = &internet.PacketConnWrapper{
|
||||||
|
PacketConn: pktConn,
|
||||||
|
Dest: &net.UDPAddr{
|
||||||
|
IP: []byte{0, 0, 0, 0},
|
||||||
|
Port: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
default:
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return nil, errors.New("conn is not PacketConnWrapper")
|
return nil, errors.New("unknown conn ", reflect.TypeOf(c))
|
||||||
}
|
|
||||||
|
|
||||||
raw := wrapper.Conn
|
|
||||||
|
|
||||||
wrapper.Conn, err = streamSettings.UdpmaskManager.WrapPacketConnClient(raw)
|
|
||||||
if err != nil {
|
|
||||||
raw.Close()
|
|
||||||
return nil, errors.New("mask err").Base(err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,21 @@ func dialWebSocket(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
|
|
||||||
dialer := &websocket.Dialer{
|
dialer := &websocket.Dialer{
|
||||||
NetDial: func(network, addr string) (net.Conn, error) {
|
NetDial: func(network, addr string) (net.Conn, error) {
|
||||||
return internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if streamSettings.TcpmaskManager != nil {
|
||||||
|
newConn, err := streamSettings.TcpmaskManager.WrapConnClient(conn)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
conn = newConn
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn, err
|
||||||
},
|
},
|
||||||
ReadBufferSize: 4 * 1024,
|
ReadBufferSize: 4 * 1024,
|
||||||
WriteBufferSize: 4 * 1024,
|
WriteBufferSize: 4 * 1024,
|
||||||
@@ -70,6 +84,16 @@ func dialWebSocket(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
errors.LogErrorInner(ctx, err, "failed to dial to "+addr)
|
errors.LogErrorInner(ctx, err, "failed to dial to "+addr)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamSettings.TcpmaskManager != nil {
|
||||||
|
newConn, err := streamSettings.TcpmaskManager.WrapConnClient(pconn)
|
||||||
|
if err != nil {
|
||||||
|
pconn.Close()
|
||||||
|
return nil, errors.New("mask err").Base(err)
|
||||||
|
}
|
||||||
|
pconn = newConn
|
||||||
|
}
|
||||||
|
|
||||||
// TLS and apply the handshake
|
// TLS and apply the handshake
|
||||||
cn := tls.UClient(pconn, tlsConfig, fingerprint).(*tls.UConn)
|
cn := tls.UClient(pconn, tlsConfig, fingerprint).(*tls.UConn)
|
||||||
if err := cn.WebsocketHandshakeContext(ctx); err != nil {
|
if err := cn.WebsocketHandshakeContext(ctx); err != nil {
|
||||||
|
|||||||
@@ -129,6 +129,10 @@ func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||||||
errors.LogInfo(ctx, "listening TCP(for WS) on ", address, ":", port)
|
errors.LogInfo(ctx, "listening TCP(for WS) on ", address, ":", port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamSettings.TcpmaskManager != nil {
|
||||||
|
listener, _ = streamSettings.TcpmaskManager.WrapListener(listener)
|
||||||
|
}
|
||||||
|
|
||||||
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
|
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
|
||||||
errors.LogWarning(ctx, "accepting PROXY protocol")
|
errors.LogWarning(ctx, "accepting PROXY protocol")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user