mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-23 01:27:04 +00:00
Transport: Refactor to be based on Finalmask's dialer & listener (#6754)
https://github.com/XTLS/Xray-core/pull/6327#issuecomment-5645958010 https://github.com/XTLS/Xray-core/pull/6754#issuecomment-5720818254 https://github.com/XTLS/Xray-core/pull/6754#issuecomment-5751585906
This commit is contained in:
@@ -14,7 +14,6 @@ import (
|
|||||||
googleuuid "github.com/google/uuid"
|
googleuuid "github.com/google/uuid"
|
||||||
"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/transport/internet"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask/fragment"
|
"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/custom"
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask/mkcp/aes128gcm"
|
"github.com/xtls/xray-core/transport/internet/finalmask/mkcp/aes128gcm"
|
||||||
@@ -909,22 +908,13 @@ func (c *Realm) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UDPHop struct {
|
type UDPHop struct {
|
||||||
Sockopt *SocketConfig `json:"sockopt"`
|
Mode string `json:"mode"`
|
||||||
Mode string `json:"mode"`
|
Interval Int32Range `json:"interval"`
|
||||||
Interval Int32Range `json:"interval"`
|
RemoteIPs []string `json:"remoteIPs"`
|
||||||
RemotePorts PortList `json:"remotePorts"`
|
RemotePorts PortList `json:"remotePorts"`
|
||||||
RemoteIPs []string `json:"remoteIPs"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *UDPHop) Build() (proto.Message, error) {
|
func (c *UDPHop) Build() (proto.Message, error) {
|
||||||
var sockopt *internet.SocketConfig
|
|
||||||
if c.Sockopt != nil {
|
|
||||||
var err error
|
|
||||||
sockopt, err = c.Sockopt.Build()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var local, remote, remoteOnce bool
|
var local, remote, remoteOnce bool
|
||||||
for _, mode := range strings.Split(c.Mode, ",") {
|
for _, mode := range strings.Split(c.Mode, ",") {
|
||||||
switch strings.ToLower(mode) {
|
switch strings.ToLower(mode) {
|
||||||
@@ -953,14 +943,13 @@ func (c *UDPHop) Build() (proto.Message, error) {
|
|||||||
return nil, errors.New("invalid ip ", ip)
|
return nil, errors.New("invalid ip ", ip)
|
||||||
}
|
}
|
||||||
return &udphop.Config{
|
return &udphop.Config{
|
||||||
Sockopt: sockopt,
|
|
||||||
Local: local,
|
Local: local,
|
||||||
Remote: remote,
|
Remote: remote,
|
||||||
RemoteOnce: remoteOnce,
|
RemoteOnce: remoteOnce,
|
||||||
IntervalMin: int64(c.Interval.From),
|
IntervalMin: int64(c.Interval.From),
|
||||||
IntervalMax: int64(c.Interval.To),
|
IntervalMax: int64(c.Interval.To),
|
||||||
RemotePorts: c.RemotePorts.Build().Ports(),
|
|
||||||
RemoteIPs: remoteIPs,
|
RemoteIPs: remoteIPs,
|
||||||
|
RemotePorts: c.RemotePorts.Build().Ports(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-17
@@ -28,6 +28,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/features/stats"
|
"github.com/xtls/xray-core/features/stats"
|
||||||
"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"
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -293,26 +294,26 @@ func (h *Handler) init(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conn, err := internet.DialSystem(ctx, dest, h.streamSettings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var pktConn net.PacketConn
|
var pktConn net.PacketConn
|
||||||
switch c := conn.(type) {
|
if h.streamSettings.FinalMask != nil {
|
||||||
case *internet.PacketConnWrapper:
|
conn, err := h.streamSettings.FinalMask.DialUDP(ctx, dest)
|
||||||
pktConn = c.PacketConn
|
|
||||||
case *cnc.Connection:
|
|
||||||
pktConn = &internet.FakePacketConn{Conn: c}
|
|
||||||
default:
|
|
||||||
panic(reflect.TypeOf(c))
|
|
||||||
}
|
|
||||||
if h.streamSettings.UdpmaskManager != nil {
|
|
||||||
newConn, err := h.streamSettings.UdpmaskManager.WrapPacketConnClient(pktConn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pktConn.Close()
|
return nil, errors.New("failed to dial to dest").Base(err)
|
||||||
return nil, errors.New("mask err").Base(err)
|
}
|
||||||
|
pktConn = conn.(*finalmask.PacketConnWrapper).PacketConn
|
||||||
|
} else {
|
||||||
|
conn, err := internet.DialSystem(ctx, dest, h.streamSettings.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to dial to dest").Base(err)
|
||||||
|
}
|
||||||
|
switch c := conn.(type) {
|
||||||
|
case *internet.PacketConnWrapper:
|
||||||
|
pktConn = c.PacketConn
|
||||||
|
case *cnc.Connection:
|
||||||
|
pktConn = &internet.FakePacketConn{Conn: c}
|
||||||
|
default:
|
||||||
|
panic(reflect.TypeOf(c))
|
||||||
}
|
}
|
||||||
pktConn = newConn
|
|
||||||
}
|
}
|
||||||
if h.uplinkCounter != nil || h.downlinkCounter != nil {
|
if h.uplinkCounter != nil || h.downlinkCounter != nil {
|
||||||
pktConn = &PacketCounterConnection{
|
pktConn = &PacketCounterConnection{
|
||||||
|
|||||||
@@ -258,18 +258,16 @@ func (s *Server) Start() error {
|
|||||||
return errors.New("address is domain")
|
return errors.New("address is domain")
|
||||||
}
|
}
|
||||||
listenFunc := func() (net.PacketConn, error) {
|
listenFunc := func() (net.PacketConn, error) {
|
||||||
pktConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{IP: s.src.Address.IP(), Port: int(s.src.Port)}, s.streamSettings.SocketSettings)
|
var pktConn net.PacketConn
|
||||||
|
var err error
|
||||||
|
if s.streamSettings.FinalMask != nil {
|
||||||
|
pktConn, err = s.streamSettings.FinalMask.ListenPacket(context.Background(), &net.UDPAddr{IP: s.src.Address.IP(), Port: int(s.src.Port)})
|
||||||
|
} else {
|
||||||
|
pktConn, err = internet.ListenSystemPacket(context.Background(), &net.UDPAddr{IP: s.src.Address.IP(), Port: int(s.src.Port)}, s.streamSettings.SocketSettings)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if s.streamSettings.UdpmaskManager != nil {
|
|
||||||
newConn, err := s.streamSettings.UdpmaskManager.WrapPacketConnServer(pktConn)
|
|
||||||
if err != nil {
|
|
||||||
pktConn.Close()
|
|
||||||
return nil, errors.New("mask err").Base(err)
|
|
||||||
}
|
|
||||||
pktConn = newConn
|
|
||||||
}
|
|
||||||
if s.uplinkCounter != nil || s.downlinkCounter != nil {
|
if s.uplinkCounter != nil || s.downlinkCounter != nil {
|
||||||
pktConn = &PacketCounterConnection{
|
pktConn = &PacketCounterConnection{
|
||||||
PacketConn: pktConn,
|
PacketConn: pktConn,
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ func TestWireguard(t *testing.T) {
|
|||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||||
}),
|
}),
|
||||||
|
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -104,6 +105,7 @@ func TestWireguard(t *testing.T) {
|
|||||||
AllowedIps: []string{"0.0.0.0/0", "::0/0"},
|
AllowedIps: []string{"0.0.0.0/0", "::0/0"},
|
||||||
}},
|
}},
|
||||||
}),
|
}),
|
||||||
|
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,103 +2,291 @@ package finalmask
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Udpmask interface {
|
type Dialer struct {
|
||||||
WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error)
|
DialTCP func(net.Destination) (net.Conn, error)
|
||||||
WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error)
|
DialUDP func(net.Destination) (net.Conn, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UdpmaskManager struct {
|
type ListenConfig struct {
|
||||||
udpmasks []Udpmask
|
Listen func(net.Addr) (net.Listener, error)
|
||||||
|
ListenPacket func(net.Addr) (net.PacketConn, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUdpmaskManager(udpmasks []Udpmask) *UdpmaskManager {
|
type TCPMask interface {
|
||||||
slices.Reverse(udpmasks)
|
WrapConnClient(net.Conn, *net.Destination, *Dialer) (net.Conn, error)
|
||||||
return &UdpmaskManager{udpmasks: udpmasks}
|
WrapConnServer(net.Conn) (net.Conn, error)
|
||||||
|
// Listen(net.Listener) (net.Listener, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UdpmaskManager) WrapPacketConnClient(raw net.PacketConn) (net.PacketConn, error) {
|
type UDPMask interface {
|
||||||
var sizes []int
|
WrapPacketConnClient(net.PacketConn, *net.Destination, *Dialer) (net.PacketConn, error)
|
||||||
var conns []net.PacketConn
|
WrapPacketConnServer(net.PacketConn, net.Addr, *ListenConfig) (net.PacketConn, error)
|
||||||
for i, mask := range m.udpmasks {
|
}
|
||||||
if _, ok := mask.(headerConn); ok {
|
|
||||||
conn, err := mask.WrapPacketConnClient(nil, i, len(m.udpmasks)-1)
|
type FinalMask struct {
|
||||||
if err != nil {
|
tcpMasks []TCPMask
|
||||||
return nil, err
|
udpMasks []UDPMask
|
||||||
}
|
dialTCP func(context.Context, net.Destination) (net.Conn, error)
|
||||||
sizes = append(sizes, conn.(headerSize).Size())
|
listen func(context.Context, net.Addr) (net.Listener, error)
|
||||||
conns = append(conns, conn)
|
dialUDP func(context.Context, net.Destination) (net.PacketConn, net.Addr, error)
|
||||||
} else {
|
listenPacket func(context.Context, net.Addr) (net.PacketConn, error)
|
||||||
if len(conns) > 0 {
|
}
|
||||||
raw = &headerManagerConn{sizes: sizes, conns: conns, PacketConn: raw}
|
|
||||||
sizes = nil
|
func NewFinalMask(tcpMasks []TCPMask, udpMasks []UDPMask, dialTCP func(context.Context, net.Destination) (net.Conn, error), listen func(context.Context, net.Addr) (net.Listener, error), dialUDP func(context.Context, net.Destination) (net.PacketConn, net.Addr, error), listenPacket func(context.Context, net.Addr) (net.PacketConn, error)) *FinalMask {
|
||||||
conns = nil
|
slices.Reverse(tcpMasks)
|
||||||
}
|
slices.Reverse(udpMasks)
|
||||||
var err error
|
return &FinalMask{
|
||||||
raw, err = mask.WrapPacketConnClient(raw, i, len(m.udpmasks)-1)
|
tcpMasks: tcpMasks,
|
||||||
if err != nil {
|
udpMasks: udpMasks,
|
||||||
return nil, err
|
dialTCP: dialTCP,
|
||||||
|
dialUDP: dialUDP,
|
||||||
|
listen: listen,
|
||||||
|
listenPacket: listenPacket,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fm *FinalMask) DialTCP(ctx context.Context, dest net.Destination) (net.Conn, error) {
|
||||||
|
if len(fm.tcpMasks) == 0 {
|
||||||
|
return fm.dialTCP(ctx, dest)
|
||||||
|
}
|
||||||
|
for i := range fm.tcpMasks {
|
||||||
|
if i > 0 {
|
||||||
|
if _, ok := fm.tcpMasks[i].(interface{ HandleDial() }); ok {
|
||||||
|
return nil, fmt.Errorf("incorrect index: %d %T", i, fm.tcpMasks[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var conn net.Conn
|
||||||
if len(conns) > 0 {
|
var err error
|
||||||
raw = &headerManagerConn{sizes: sizes, conns: conns, PacketConn: raw}
|
if _, ok := fm.tcpMasks[0].(interface{ HandleDial() }); !ok {
|
||||||
sizes = nil
|
conn, err = fm.dialTCP(ctx, dest)
|
||||||
conns = nil
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return raw, nil
|
dialer := &Dialer{
|
||||||
|
DialTCP: func(dest net.Destination) (net.Conn, error) {
|
||||||
|
return fm.dialTCP(ctx, dest)
|
||||||
|
},
|
||||||
|
DialUDP: func(dest net.Destination) (net.Conn, error) {
|
||||||
|
conn, addr, err := fm.dialUDP(ctx, dest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &PacketConnWrapper{PacketConn: conn, udpAddr: addr}, err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i := range fm.tcpMasks {
|
||||||
|
var newConn net.Conn
|
||||||
|
newConn, err = fm.tcpMasks[i].WrapConnClient(conn, &dest, dialer)
|
||||||
|
if err != nil {
|
||||||
|
_ = conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn = newConn
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UdpmaskManager) WrapPacketConnServer(raw net.PacketConn) (net.PacketConn, error) {
|
func (fm *FinalMask) Listen(ctx context.Context, addr net.Addr) (net.Listener, error) {
|
||||||
var sizes []int
|
if len(fm.tcpMasks) == 0 {
|
||||||
var conns []net.PacketConn
|
return fm.listen(ctx, addr)
|
||||||
for i, mask := range m.udpmasks {
|
}
|
||||||
if _, ok := mask.(headerConn); ok {
|
off := 0
|
||||||
conn, err := mask.WrapPacketConnServer(nil, i, len(m.udpmasks)-1)
|
listener, err := fm.listen(ctx, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
}
|
||||||
|
for i := range fm.tcpMasks {
|
||||||
|
if _, ok := fm.tcpMasks[i].(interface {
|
||||||
|
Listen(net.Listener) (net.Listener, error)
|
||||||
|
}); ok {
|
||||||
|
if i-off == 0 {
|
||||||
|
l, err := fm.tcpMasks[i].(interface {
|
||||||
|
Listen(net.Listener) (net.Listener, error)
|
||||||
|
}).Listen(listener)
|
||||||
|
if err != nil {
|
||||||
|
listener.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
listener = l
|
||||||
|
} else {
|
||||||
|
l, err := fm.tcpMasks[i].(interface {
|
||||||
|
Listen(net.Listener) (net.Listener, error)
|
||||||
|
}).Listen(&TCPListener{Listener: listener, tcpMasks: fm.tcpMasks[off:i]})
|
||||||
|
if err != nil {
|
||||||
|
listener.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
listener = l
|
||||||
}
|
}
|
||||||
sizes = append(sizes, conn.(headerSize).Size())
|
off = i + 1
|
||||||
conns = append(conns, conn)
|
}
|
||||||
} else {
|
}
|
||||||
if len(conns) > 0 {
|
if off < len(fm.tcpMasks) {
|
||||||
raw = &headerManagerConn{sizes: sizes, conns: conns, PacketConn: raw}
|
return &TCPListener{Listener: listener, tcpMasks: fm.tcpMasks[off:]}, nil
|
||||||
sizes = nil
|
}
|
||||||
conns = nil
|
return listener, nil
|
||||||
}
|
}
|
||||||
var err error
|
|
||||||
raw, err = mask.WrapPacketConnServer(raw, i, len(m.udpmasks)-1)
|
func (fm *FinalMask) DialUDP(ctx context.Context, dest net.Destination) (net.Conn, error) {
|
||||||
if err != nil {
|
if len(fm.udpMasks) == 0 {
|
||||||
return nil, err
|
conn, addr, err := fm.dialUDP(ctx, dest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &PacketConnWrapper{PacketConn: conn, udpAddr: addr}, nil
|
||||||
|
}
|
||||||
|
for i := range fm.udpMasks {
|
||||||
|
if i > 0 {
|
||||||
|
if _, ok := fm.udpMasks[i].(interface{ HandleDial() }); ok {
|
||||||
|
return nil, fmt.Errorf("incorrect index: %d %T", i, fm.udpMasks[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var conn net.PacketConn
|
||||||
|
var addr net.Addr
|
||||||
|
var err error
|
||||||
|
if _, ok := fm.udpMasks[0].(interface{ HandleDial() }); !ok {
|
||||||
|
conn, addr, err = fm.dialUDP(ctx, dest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialer := &Dialer{
|
||||||
|
DialTCP: func(dest net.Destination) (net.Conn, error) {
|
||||||
|
return fm.dialTCP(ctx, dest)
|
||||||
|
},
|
||||||
|
DialUDP: func(dest net.Destination) (net.Conn, error) {
|
||||||
|
conn, addr, err := fm.dialUDP(ctx, dest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &PacketConnWrapper{PacketConn: conn, udpAddr: addr}, err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var sizes []int
|
||||||
|
var conns []net.PacketConn
|
||||||
|
for i := range fm.udpMasks {
|
||||||
|
var newConn net.PacketConn
|
||||||
|
if _, ok := fm.udpMasks[i].(interface{ HeaderConn() }); ok {
|
||||||
|
newConn, err = fm.udpMasks[i].WrapPacketConnClient(nil, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
_ = conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sizes = append(sizes, newConn.(interface{ Size() int }).Size())
|
||||||
|
conns = append(conns, newConn)
|
||||||
|
} else {
|
||||||
|
if len(conns) > 0 {
|
||||||
|
conn = &headerManagerConn{PacketConn: conn, sizes: sizes, conns: conns}
|
||||||
|
sizes = nil
|
||||||
|
conns = nil
|
||||||
|
}
|
||||||
|
newConn, err = fm.udpMasks[i].WrapPacketConnClient(conn, &dest, dialer)
|
||||||
|
if err != nil {
|
||||||
|
_ = conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn = newConn
|
||||||
|
}
|
||||||
|
}
|
||||||
if len(conns) > 0 {
|
if len(conns) > 0 {
|
||||||
raw = &headerManagerConn{sizes: sizes, conns: conns, PacketConn: raw}
|
conn = &headerManagerConn{PacketConn: conn, sizes: sizes, conns: conns}
|
||||||
sizes = nil
|
sizes = nil
|
||||||
conns = nil
|
conns = nil
|
||||||
}
|
}
|
||||||
return raw, nil
|
if addr == nil {
|
||||||
|
addr = &net.UDPAddr{IP: []byte{0, 0, 0, 0}}
|
||||||
|
}
|
||||||
|
return &PacketConnWrapper{PacketConn: conn, udpAddr: addr}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fm *FinalMask) ListenPacket(ctx context.Context, addr net.Addr) (net.PacketConn, error) {
|
||||||
|
if len(fm.udpMasks) == 0 {
|
||||||
|
return fm.listenPacket(ctx, addr)
|
||||||
|
}
|
||||||
|
for i := range fm.udpMasks {
|
||||||
|
if i > 0 {
|
||||||
|
if _, ok := fm.udpMasks[i].(interface{ HandleListen() }); ok {
|
||||||
|
return nil, fmt.Errorf("incorrect index: %d %T", i, fm.udpMasks[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var conn net.PacketConn
|
||||||
|
var err error
|
||||||
|
if _, ok := fm.udpMasks[0].(interface{ HandleListen() }); !ok {
|
||||||
|
conn, err = fm.listenPacket(ctx, addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lc := &ListenConfig{
|
||||||
|
Listen: func(addr net.Addr) (net.Listener, error) { return fm.listen(ctx, addr) },
|
||||||
|
ListenPacket: func(addr net.Addr) (net.PacketConn, error) { return fm.listenPacket(ctx, addr) },
|
||||||
|
}
|
||||||
|
var sizes []int
|
||||||
|
var conns []net.PacketConn
|
||||||
|
for i := range fm.udpMasks {
|
||||||
|
var newConn net.PacketConn
|
||||||
|
if _, ok := fm.udpMasks[i].(interface{ HeaderConn() }); ok {
|
||||||
|
newConn, err = fm.udpMasks[i].WrapPacketConnServer(nil, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
_ = conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sizes = append(sizes, newConn.(interface{ Size() int }).Size())
|
||||||
|
conns = append(conns, newConn)
|
||||||
|
} else {
|
||||||
|
if len(conns) > 0 {
|
||||||
|
conn = &headerManagerConn{PacketConn: conn, sizes: sizes, conns: conns}
|
||||||
|
sizes = nil
|
||||||
|
conns = nil
|
||||||
|
}
|
||||||
|
newConn, err = fm.udpMasks[i].WrapPacketConnServer(conn, addr, lc)
|
||||||
|
if err != nil {
|
||||||
|
_ = conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn = newConn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(conns) > 0 {
|
||||||
|
conn = &headerManagerConn{PacketConn: conn, sizes: sizes, conns: conns}
|
||||||
|
sizes = nil
|
||||||
|
conns = nil
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
UDPSize = 4096
|
UDPSize = 4096
|
||||||
)
|
)
|
||||||
|
|
||||||
type headerConn interface {
|
type PacketConnWrapper struct {
|
||||||
HeaderConn()
|
net.PacketConn
|
||||||
|
udpAddr net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
type headerSize interface {
|
func (c *PacketConnWrapper) RemoteAddr() net.Addr {
|
||||||
Size() int
|
return c.udpAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PacketConnWrapper) Read(b []byte) (n int, err error) {
|
||||||
|
n, _, err = c.PacketConn.ReadFrom(b)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PacketConnWrapper) Write(b []byte) (n int, err error) {
|
||||||
|
return c.PacketConn.WriteTo(b, c.udpAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
type headerManagerConn struct {
|
type headerManagerConn struct {
|
||||||
@@ -191,72 +379,27 @@ func (c *headerManagerConn) WriteTo(p []byte, addr net.Addr) (n int, err error)
|
|||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tcpmask interface {
|
type TCPListener struct {
|
||||||
WrapConnClient(net.Conn) (net.Conn, error)
|
|
||||||
WrapConnServer(net.Conn) (net.Conn, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type TcpmaskManager struct {
|
|
||||||
tcpmasks []Tcpmask
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTcpmaskManager(tcpmasks []Tcpmask) *TcpmaskManager {
|
|
||||||
slices.Reverse(tcpmasks)
|
|
||||||
return &TcpmaskManager{tcpmasks: tcpmasks}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TcpmaskManager) WrapConnClient(raw net.Conn) (net.Conn, error) {
|
|
||||||
var err error
|
|
||||||
for _, mask := range m.tcpmasks {
|
|
||||||
raw, err = mask.WrapConnClient(raw)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return raw, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TcpmaskManager) WrapConnServer(raw net.Conn) (net.Conn, error) {
|
|
||||||
var err error
|
|
||||||
for _, mask := range m.tcpmasks {
|
|
||||||
raw, err = mask.WrapConnServer(raw)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return raw, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *TcpmaskManager) WrapListener(l net.Listener) (net.Listener, error) {
|
|
||||||
return NewTcpListener(m, l)
|
|
||||||
}
|
|
||||||
|
|
||||||
type tcpListener struct {
|
|
||||||
m *TcpmaskManager
|
|
||||||
net.Listener
|
net.Listener
|
||||||
|
tcpMasks []TCPMask
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTcpListener(m *TcpmaskManager, l net.Listener) (net.Listener, error) {
|
func (l *TCPListener) Accept() (net.Conn, error) {
|
||||||
return &tcpListener{
|
|
||||||
m: m,
|
|
||||||
Listener: l,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *tcpListener) Accept() (net.Conn, error) {
|
|
||||||
conn, err := l.Listener.Accept()
|
conn, err := l.Listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
|
|
||||||
newConn, err := l.m.WrapConnServer(conn)
|
for i := range l.tcpMasks {
|
||||||
if err != nil {
|
var newConn net.Conn
|
||||||
errors.LogDebugInner(context.Background(), err, "mask err")
|
newConn, err = l.tcpMasks[i].WrapConnServer(conn)
|
||||||
_ = conn.Close()
|
if err != nil {
|
||||||
return nil, err
|
_ = conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn = newConn
|
||||||
}
|
}
|
||||||
|
return conn, nil
|
||||||
return newConn, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TcpMaskConn interface {
|
type TcpMaskConn interface {
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package fragment
|
package fragment
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
|
)
|
||||||
|
|
||||||
func (c *Config) WrapConnClient(raw net.Conn) (net.Conn, error) {
|
func (c *Config) WrapConnClient(conn net.Conn, dest *net.Destination, dialer *finalmask.Dialer) (net.Conn, error) {
|
||||||
return NewConnClient(c, raw, false)
|
return NewConnClient(c, conn, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapConnServer(raw net.Conn) (net.Conn, error) {
|
func (c *Config) WrapConnServer(conn net.Conn) (net.Conn, error) {
|
||||||
return NewConnServer(c, raw, true)
|
return NewConnServer(c, conn, true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,30 @@
|
|||||||
package custom
|
package custom
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *TCPConfig) WrapConnClient(raw net.Conn) (net.Conn, error) {
|
func (c *TCPConfig) WrapConnClient(conn net.Conn, dest *net.Destination, dialer *finalmask.Dialer) (net.Conn, error) {
|
||||||
return NewConnClientTCP(c, raw)
|
return NewConnClientTCP(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TCPConfig) WrapConnServer(raw net.Conn) (net.Conn, error) {
|
func (c *TCPConfig) WrapConnServer(conn net.Conn) (net.Conn, error) {
|
||||||
return NewConnServerTCP(c, raw)
|
return NewConnServerTCP(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *UDPConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *UDPConfig) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
return NewConnClientUDP(c, raw)
|
return NewConnClientUDP(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *UDPConfig) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *UDPConfig) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
return NewConnServerUDP(c, raw)
|
return NewConnServerUDP(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *UDPStandaloneConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *UDPStandaloneConfig) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
return NewConnClientUDPStandalone(c, raw)
|
return NewConnClientUDPStandalone(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *UDPStandaloneConfig) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *UDPStandaloneConfig) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
return NewConnServerUDPStandalone(c, raw)
|
return NewConnServerUDPStandalone(c, conn)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMetadataEvaluatorRejectsUnknownName(t *testing.T) {
|
func TestMetadataEvaluatorRejectsUnknownName(t *testing.T) {
|
||||||
@@ -156,7 +154,7 @@ func TestMetadataUDPStandaloneWriteUsesRemotePort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
client, err := finalmask.NewUdpmaskManager([]finalmask.Udpmask{cfg}).WrapPacketConnClient(clientRaw)
|
client, err := cfg.WrapPacketConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -301,7 +299,7 @@ func TestMetadataTCPHandshakeUsesEndpointPorts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
client, err := clientCfg.WrapConnClient(clientRaw)
|
client, err := clientCfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/transport/internet/finalmask"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func mustSendRecvUDP(t *testing.T, from net.PacketConn, to net.PacketConn, msg []byte) {
|
func mustSendRecvUDP(t *testing.T, from net.PacketConn, to net.PacketConn, msg []byte) {
|
||||||
@@ -48,7 +46,6 @@ func TestStateUDPResponseReusesPriorCapturedValues(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
maskManager := finalmask.NewUdpmaskManager([]finalmask.Udpmask{cfg})
|
|
||||||
|
|
||||||
clientRaw, err := net.ListenPacket("udp", "127.0.0.1:0")
|
clientRaw, err := net.ListenPacket("udp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -62,11 +59,11 @@ func TestStateUDPResponseReusesPriorCapturedValues(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
client, err := maskManager.WrapPacketConnClient(clientRaw)
|
client, err := cfg.WrapPacketConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
server, err := maskManager.WrapPacketConnServer(serverRaw)
|
server, err := cfg.WrapPacketConnServer(serverRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func TestDSLTCPHandshakeReusesCapturedValue(t *testing.T) {
|
|||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
client, err := cfg.WrapConnClient(clientRaw)
|
client, err := cfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ func TestDSLTCPClientRejectsMismatchedResponseSequence(t *testing.T) {
|
|||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
client, err := clientCfg.WrapConnClient(clientRaw)
|
client, err := clientCfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package aes128gcm
|
package aes128gcm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) HeaderConn() {}
|
func (c *Config) HeaderConn() {}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw)
|
return NewConnClient(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw)
|
return NewConnServer(c, conn)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package header
|
package header
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) HeaderConn() {}
|
func (c *Config) HeaderConn() {}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw)
|
return NewConnClient(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw)
|
return NewConnServer(c, conn)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package original
|
package original
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) HeaderConn() {}
|
func (c *Config) HeaderConn() {}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw)
|
return NewConnClient(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw)
|
return NewConnServer(c, conn)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package noise
|
package noise
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
|
)
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
return NewConnClient(c, raw)
|
return NewConnClient(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
return NewConnServer(c, raw)
|
return NewConnServer(c, conn)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,14 @@
|
|||||||
package realm
|
package realm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
_, ok1 := raw.(*internet.FakePacketConn)
|
return NewConnClient(c, conn)
|
||||||
if level != 0 || ok1 {
|
|
||||||
return nil, errors.New("realm requires being at the outermost level")
|
|
||||||
}
|
|
||||||
return NewConnClient(c, raw)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
if level != 0 {
|
return NewConnServer(c, conn)
|
||||||
return nil, errors.New("realm requires being at the outermost level")
|
|
||||||
}
|
|
||||||
return NewConnServer(c, raw)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,24 @@
|
|||||||
package salamander
|
package salamander
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) HeaderConn() {}
|
func (c *Config) HeaderConn() {}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
return NewSalamanderConnClient(c, raw)
|
return NewSalamanderConnClient(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
return NewSalamanderConnServer(c, raw)
|
return NewSalamanderConnServer(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GeckoConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *GeckoConfig) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
return NewGeckoConnClient(c, raw)
|
return NewGeckoConnClient(c, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GeckoConfig) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *GeckoConfig) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
return NewGeckoConnServer(c, raw)
|
return NewGeckoConnServer(c, conn)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
package sudoku
|
package sudoku
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sudoku in finalmask mode is a pure appearance transform with no standalone handshake.
|
// Sudoku in finalmask mode is a pure appearance transform with no standalone handshake.
|
||||||
// TCP always keeps classic sudoku on uplink and uses packed downlink optimization on server writes.
|
// TCP always keeps classic sudoku on uplink and uses packed downlink optimization on server writes.
|
||||||
func (c *Config) WrapConnClient(raw net.Conn) (net.Conn, error) {
|
func (c *Config) WrapConnClient(conn net.Conn, dest *net.Destination, dialer *finalmask.Dialer) (net.Conn, error) {
|
||||||
return newPackedDirectionalConn(raw, c, true)
|
return newPackedDirectionalConn(conn, c, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapConnServer(raw net.Conn) (net.Conn, error) {
|
func (c *Config) WrapConnServer(conn net.Conn) (net.Conn, error) {
|
||||||
return newPackedDirectionalConn(raw, c, false)
|
return newPackedDirectionalConn(conn, c, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPackedDirectionalConn(raw net.Conn, config *Config, readPacked bool) (net.Conn, error) {
|
func newPackedDirectionalConn(raw net.Conn, config *Config, readPacked bool) (net.Conn, error) {
|
||||||
@@ -36,16 +35,10 @@ func newPackedDirectionalConn(raw net.Conn, config *Config, readPacked bool) (ne
|
|||||||
return newWrappedConn(raw, reader, writer), nil
|
return newWrappedConn(raw, reader, writer), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
if level != levelCount {
|
return NewUDPConn(conn, c)
|
||||||
return nil, errors.New("sudoku udp mask must be the innermost mask in chain")
|
|
||||||
}
|
|
||||||
return NewUDPConn(raw, c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
if level != levelCount {
|
return NewUDPConn(conn, c)
|
||||||
return nil, errors.New("sudoku udp mask must be the innermost mask in chain")
|
|
||||||
}
|
|
||||||
return NewUDPConn(raw, c)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ package finalmask_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
gonet "net"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
"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/custom"
|
||||||
)
|
)
|
||||||
@@ -20,11 +22,14 @@ func mustSendRecvTcp(
|
|||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
waitCh := make(chan error)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
_, err := from.Write(msg)
|
_, err := from.Write(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
close(waitCh)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
@@ -40,18 +45,23 @@ func mustSendRecvTcp(
|
|||||||
if !bytes.Equal(buf[:n], msg) {
|
if !bytes.Equal(buf[:n], msg) {
|
||||||
t.Fatalf("unexpected data %q", buf[:n])
|
t.Fatalf("unexpected data %q", buf[:n])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<-waitCh
|
||||||
}
|
}
|
||||||
|
|
||||||
type layerMaskTcp struct {
|
type layerMaskTcp struct {
|
||||||
name string
|
name string
|
||||||
mask finalmask.Tcpmask
|
mask finalmask.TCPMask
|
||||||
}
|
}
|
||||||
|
|
||||||
type failingWrapMask struct{}
|
type failingWrapMask struct{}
|
||||||
|
|
||||||
func (failingWrapMask) TCP() {}
|
func (failingWrapMask) TCP() {}
|
||||||
func (f failingWrapMask) WrapConnClient(raw net.Conn) (net.Conn, error) { return raw, nil }
|
func (f failingWrapMask) WrapConnClient(conn net.Conn, dest *net.Destination, dialer *finalmask.Dialer) (net.Conn, error) {
|
||||||
func (f failingWrapMask) WrapConnServer(raw net.Conn) (net.Conn, error) {
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f failingWrapMask) WrapConnServer(conn net.Conn) (net.Conn, error) {
|
||||||
return nil, io.ErrClosedPipe
|
return nil, io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,32 +102,31 @@ func TestConnReadWrite(t *testing.T) {
|
|||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
mask := c.mask
|
mask := c.mask
|
||||||
|
|
||||||
maskManager := finalmask.NewTcpmaskManager([]finalmask.Tcpmask{mask})
|
dialTCP := func(ctx context.Context, dest net.Destination) (net.Conn, error) {
|
||||||
|
return net.Dial("tcp", dest.NetAddr())
|
||||||
|
}
|
||||||
|
listen := func(ctx context.Context, addr net.Addr) (net.Listener, error) {
|
||||||
|
return net.Listen("tcp", addr.String())
|
||||||
|
}
|
||||||
|
finalMask := finalmask.NewFinalMask([]finalmask.TCPMask{mask}, nil, dialTCP, listen, nil, nil)
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
listener, err := finalMask.Listen(context.Background(), &net.TCPAddr{IP: net.LocalHostIP.IP()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
t.Cleanup(func() { listener.Close() })
|
||||||
|
|
||||||
client, err := net.Dial("tcp", ln.Addr().String())
|
client, err := finalMask.DialTCP(context.Background(), net.TCPDestination(net.IPAddress(listener.Addr().(*net.TCPAddr).IP), net.Port(listener.Addr().(*net.TCPAddr).Port)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
t.Cleanup(func() { client.Close() })
|
||||||
|
|
||||||
client, err = maskManager.WrapConnClient(client)
|
server, err := listener.Accept()
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
server, err := ln.Accept()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
server, err = maskManager.WrapConnServer(server)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
t.Cleanup(func() { server.Close() })
|
||||||
|
|
||||||
_ = client.SetDeadline(time.Now().Add(time.Second))
|
_ = client.SetDeadline(time.Now().Add(time.Second))
|
||||||
_ = server.SetDeadline(time.Now().Add(time.Second))
|
_ = server.SetDeadline(time.Now().Add(time.Second))
|
||||||
@@ -150,34 +159,32 @@ func TestTCPcustomStaticHandshakeRoundTrip(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
maskManager := finalmask.NewTcpmaskManager([]finalmask.Tcpmask{cfg})
|
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
dialTCP := func(ctx context.Context, dest net.Destination) (net.Conn, error) {
|
||||||
if err != nil {
|
return net.Dial("tcp", dest.NetAddr())
|
||||||
t.Fatal(err)
|
|
||||||
}
|
}
|
||||||
defer ln.Close()
|
listen := func(ctx context.Context, addr net.Addr) (net.Listener, error) {
|
||||||
|
return net.Listen("tcp", addr.String())
|
||||||
|
}
|
||||||
|
finalMask := finalmask.NewFinalMask([]finalmask.TCPMask{cfg}, nil, dialTCP, listen, nil, nil)
|
||||||
|
|
||||||
clientRaw, err := net.Dial("tcp", ln.Addr().String())
|
listener, err := finalMask.Listen(context.Background(), &net.TCPAddr{IP: net.LocalHostIP.IP()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer clientRaw.Close()
|
defer listener.Close()
|
||||||
|
|
||||||
serverRaw, err := ln.Accept()
|
client, err := finalMask.DialTCP(context.Background(), net.TCPDestination(net.IPAddress(listener.Addr().(*net.TCPAddr).IP), net.Port(listener.Addr().(*net.TCPAddr).Port)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer serverRaw.Close()
|
defer client.Close()
|
||||||
|
|
||||||
client, err := maskManager.WrapConnClient(clientRaw)
|
server, err := listener.Accept()
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
server, err := maskManager.WrapConnServer(serverRaw)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
_ = client.SetDeadline(time.Now().Add(time.Second))
|
_ = client.SetDeadline(time.Now().Add(time.Second))
|
||||||
_ = server.SetDeadline(time.Now().Add(time.Second))
|
_ = server.SetDeadline(time.Now().Add(time.Second))
|
||||||
@@ -220,11 +227,11 @@ func TestTCPcustomClientRejectsMismatchedServerSequence(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
clientRaw, serverRaw := net.Pipe()
|
clientRaw, serverRaw := gonet.Pipe()
|
||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
client, err := clientCfg.WrapConnClient(clientRaw)
|
client, err := clientCfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -257,42 +264,37 @@ func TestTCPcustomClientRejectsMismatchedServerSequence(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTCPWrapListenerRejectsImmediateWrapErrors(t *testing.T) {
|
func TestTCPWrapListenerRejectsImmediateWrapErrors(t *testing.T) {
|
||||||
clientManager := finalmask.NewTcpmaskManager([]finalmask.Tcpmask{failingWrapMask{}})
|
dialTCP := func(ctx context.Context, dest net.Destination) (net.Conn, error) {
|
||||||
serverManager := finalmask.NewTcpmaskManager([]finalmask.Tcpmask{failingWrapMask{}})
|
return net.Dial("tcp", dest.NetAddr())
|
||||||
|
}
|
||||||
|
listen := func(ctx context.Context, addr net.Addr) (net.Listener, error) {
|
||||||
|
return net.Listen("tcp", addr.String())
|
||||||
|
}
|
||||||
|
finalMask := finalmask.NewFinalMask([]finalmask.TCPMask{failingWrapMask{}}, nil, dialTCP, listen, nil, nil)
|
||||||
|
|
||||||
rawLn, err := net.Listen("tcp", "127.0.0.1:0")
|
listener, err := finalMask.Listen(context.Background(), &net.TCPAddr{IP: net.LocalHostIP.IP()})
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer rawLn.Close()
|
|
||||||
|
|
||||||
ln, err := serverManager.WrapListener(rawLn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer listener.Close()
|
||||||
|
|
||||||
accepted := make(chan struct {
|
accepted := make(chan struct {
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
err error
|
err error
|
||||||
}, 1)
|
}, 1)
|
||||||
go func() {
|
go func() {
|
||||||
conn, err := ln.Accept()
|
conn, err := listener.Accept()
|
||||||
accepted <- struct {
|
accepted <- struct {
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
err error
|
err error
|
||||||
}{conn: conn, err: err}
|
}{conn: conn, err: err}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
clientRaw, err := net.Dial("tcp", rawLn.Addr().String())
|
client, err := finalMask.DialTCP(context.Background(), net.TCPDestination(net.IPAddress(listener.Addr().(*net.TCPAddr).IP), net.Port(listener.Addr().(*net.TCPAddr).Port)))
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer clientRaw.Close()
|
|
||||||
|
|
||||||
client, err := clientManager.WrapConnClient(clientRaw)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
_ = client.SetDeadline(time.Now().Add(time.Second))
|
_ = client.SetDeadline(time.Now().Add(time.Second))
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,15 @@ package finalmask_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
gonet "net"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
"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/custom"
|
||||||
@@ -51,7 +53,7 @@ func mustSendRecv(
|
|||||||
|
|
||||||
type layerMask struct {
|
type layerMask struct {
|
||||||
name string
|
name string
|
||||||
mask finalmask.Udpmask
|
mask finalmask.UDPMask
|
||||||
layers int
|
layers int
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,25 +215,23 @@ func newStandaloneStunLikeUDPServerConfig() *custom.UDPStandaloneConfig {
|
|||||||
func newUDPClientServerPair(t *testing.T, cfg *custom.UDPStandaloneConfig) (net.PacketConn, net.PacketConn, net.PacketConn, net.PacketConn) {
|
func newUDPClientServerPair(t *testing.T, cfg *custom.UDPStandaloneConfig) (net.PacketConn, net.PacketConn, net.PacketConn, net.PacketConn) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
clientRaw, err := net.ListenPacket("udp", "127.0.0.1:0")
|
clientRaw, err := gonet.ListenPacket("udp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
t.Cleanup(func() { _ = clientRaw.Close() })
|
t.Cleanup(func() { _ = clientRaw.Close() })
|
||||||
|
|
||||||
serverRaw, err := net.ListenPacket("udp", "127.0.0.1:0")
|
serverRaw, err := gonet.ListenPacket("udp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
t.Cleanup(func() { _ = serverRaw.Close() })
|
t.Cleanup(func() { _ = serverRaw.Close() })
|
||||||
|
|
||||||
maskManager := finalmask.NewUdpmaskManager([]finalmask.Udpmask{cfg})
|
client, err := cfg.WrapPacketConnClient(clientRaw, nil, nil)
|
||||||
|
|
||||||
client, err := maskManager.WrapPacketConnClient(clientRaw)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
server, err := maskManager.WrapPacketConnServer(serverRaw)
|
server, err := cfg.WrapPacketConnServer(serverRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -348,31 +348,39 @@ func TestPacketConnReadWrite(t *testing.T) {
|
|||||||
if layers <= 0 {
|
if layers <= 0 {
|
||||||
layers = 1
|
layers = 1
|
||||||
}
|
}
|
||||||
masks := make([]finalmask.Udpmask, 0, layers)
|
masks := make([]finalmask.UDPMask, 0, layers)
|
||||||
for i := 0; i < layers; i++ {
|
for i := 0; i < layers; i++ {
|
||||||
masks = append(masks, mask)
|
masks = append(masks, mask)
|
||||||
}
|
}
|
||||||
maskManager := finalmask.NewUdpmaskManager(masks)
|
|
||||||
|
|
||||||
client, err := net.ListenPacket("udp", "127.0.0.1:0")
|
dialUDP := func(ctx context.Context, dest net.Destination) (net.PacketConn, net.Addr, error) {
|
||||||
|
udpAddr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
conn, err := gonet.ListenPacket("udp", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return conn, udpAddr, nil
|
||||||
|
}
|
||||||
|
listenPacket := func(ctx context.Context, addr net.Addr) (net.PacketConn, error) {
|
||||||
|
return gonet.ListenPacket(addr.Network(), addr.String())
|
||||||
|
}
|
||||||
|
finalMask := finalmask.NewFinalMask(nil, masks, nil, nil, dialUDP, listenPacket)
|
||||||
|
|
||||||
|
server, err := finalMask.ListenPacket(context.Background(), &net.UDPAddr{IP: net.LocalHostIP.IP()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
t.Cleanup(func() { server.Close() })
|
||||||
|
|
||||||
client, err = maskManager.WrapPacketConnClient(client)
|
clientConn, err := finalMask.DialUDP(context.Background(), net.UDPDestination(net.IPAddress(server.LocalAddr().(*net.UDPAddr).IP), net.Port(server.LocalAddr().(*net.UDPAddr).Port)))
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
server, err := net.ListenPacket("udp", "127.0.0.1:0")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
server, err = maskManager.WrapPacketConnServer(server)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
t.Cleanup(func() { clientConn.Close() })
|
||||||
|
client := clientConn.(*finalmask.PacketConnWrapper).PacketConn
|
||||||
|
|
||||||
_ = client.SetDeadline(time.Now().Add(time.Second))
|
_ = client.SetDeadline(time.Now().Add(time.Second))
|
||||||
_ = server.SetDeadline(time.Now().Add(time.Second))
|
_ = server.SetDeadline(time.Now().Add(time.Second))
|
||||||
@@ -397,21 +405,20 @@ func TestUDPcustomStaticHeaderWireShape(t *testing.T) {
|
|||||||
{Rand: 1, RandMin: 0x30, RandMax: 0x40},
|
{Rand: 1, RandMin: 0x30, RandMax: 0x40},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
maskManager := finalmask.NewUdpmaskManager([]finalmask.Udpmask{cfg})
|
|
||||||
|
|
||||||
clientRaw, err := net.ListenPacket("udp", "127.0.0.1:0")
|
clientRaw, err := gonet.ListenPacket("udp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
|
|
||||||
serverRaw, err := net.ListenPacket("udp", "127.0.0.1:0")
|
serverRaw, err := gonet.ListenPacket("udp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
client, err := maskManager.WrapPacketConnClient(clientRaw)
|
client, err := cfg.WrapPacketConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -642,11 +649,11 @@ func TestSudokuBDD(t *testing.T) {
|
|||||||
Ascii: "prefer_ascii",
|
Ascii: "prefer_ascii",
|
||||||
}
|
}
|
||||||
|
|
||||||
clientRaw, serverRaw := net.Pipe()
|
clientRaw, serverRaw := gonet.Pipe()
|
||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
clientConn, err := cfg.WrapConnClient(clientRaw)
|
clientConn, err := cfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -683,11 +690,11 @@ func TestSudokuBDD(t *testing.T) {
|
|||||||
PaddingMax: 0,
|
PaddingMax: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
clientRaw, serverRaw := net.Pipe()
|
clientRaw, serverRaw := gonet.Pipe()
|
||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
clientConn, err := cfg.WrapConnClient(clientRaw)
|
clientConn, err := cfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -738,10 +745,10 @@ func TestSudokuBDD(t *testing.T) {
|
|||||||
countWireBytes := func(wrapServer func(net.Conn, *sudoku.Config) (net.Conn, error), cfg *sudoku.Config) int64 {
|
countWireBytes := func(wrapServer func(net.Conn, *sudoku.Config) (net.Conn, error), cfg *sudoku.Config) int64 {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
clientRaw, serverRaw := net.Pipe()
|
clientRaw, serverRaw := gonet.Pipe()
|
||||||
watchedServerRaw := &countingConn{Conn: serverRaw}
|
watchedServerRaw := &countingConn{Conn: serverRaw}
|
||||||
|
|
||||||
clientConn, err := cfg.WrapConnClient(clientRaw)
|
clientConn, err := cfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -793,11 +800,11 @@ func TestSudokuBDD(t *testing.T) {
|
|||||||
CustomTables: []string{"xpxvvpvv", "vxpvxvvp"},
|
CustomTables: []string{"xpxvvpvv", "vxpvxvvp"},
|
||||||
}
|
}
|
||||||
|
|
||||||
clientRaw, serverRaw := net.Pipe()
|
clientRaw, serverRaw := gonet.Pipe()
|
||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
clientConn, err := cfg.WrapConnClient(clientRaw)
|
clientConn, err := cfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -835,11 +842,11 @@ func TestSudokuBDD(t *testing.T) {
|
|||||||
PaddingMax: 0,
|
PaddingMax: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
clientRaw, serverRaw := net.Pipe()
|
clientRaw, serverRaw := gonet.Pipe()
|
||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
clientConn, err := cfg.WrapConnClient(clientRaw)
|
clientConn, err := cfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -868,19 +875,6 @@ func TestSudokuBDD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("GivenSudokuUDPMask_WhenNotInnermost_ThenWrapFails", func(t *testing.T) {
|
|
||||||
cfg := &sudoku.Config{Password: "sudoku-udp"}
|
|
||||||
raw, err := net.ListenPacket("udp", "127.0.0.1:0")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer raw.Close()
|
|
||||||
|
|
||||||
if _, err := cfg.WrapPacketConnClient(raw, 0, 1); err == nil {
|
|
||||||
t.Fatal("expected innermost check failure")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("GivenSudokuMultiTableUDPMask_WhenClientSendsMultipleDatagrams_ThenPayloadMatches", func(t *testing.T) {
|
t.Run("GivenSudokuMultiTableUDPMask_WhenClientSendsMultipleDatagrams_ThenPayloadMatches", func(t *testing.T) {
|
||||||
cfg := &sudoku.Config{
|
cfg := &sudoku.Config{
|
||||||
Password: "sudoku-udp-multi",
|
Password: "sudoku-udp-multi",
|
||||||
@@ -889,25 +883,24 @@ func TestSudokuBDD(t *testing.T) {
|
|||||||
PaddingMin: 0,
|
PaddingMin: 0,
|
||||||
PaddingMax: 0,
|
PaddingMax: 0,
|
||||||
}
|
}
|
||||||
maskManager := finalmask.NewUdpmaskManager([]finalmask.Udpmask{cfg})
|
|
||||||
|
|
||||||
clientRaw, err := net.ListenPacket("udp", "127.0.0.1:0")
|
clientRaw, err := gonet.ListenPacket("udp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
|
|
||||||
serverRaw, err := net.ListenPacket("udp", "127.0.0.1:0")
|
serverRaw, err := gonet.ListenPacket("udp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
client, err := maskManager.WrapPacketConnClient(clientRaw)
|
client, err := cfg.WrapPacketConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
server, err := maskManager.WrapPacketConnServer(serverRaw)
|
server, err := cfg.WrapPacketConnServer(serverRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -961,7 +954,7 @@ func TestSudokuBDD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
clientConn, err := cfg.WrapConnClient(clientRaw)
|
clientConn, err := cfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -1008,11 +1001,11 @@ func TestSudokuBDD(t *testing.T) {
|
|||||||
Ascii: "prefer_entropy",
|
Ascii: "prefer_entropy",
|
||||||
}
|
}
|
||||||
|
|
||||||
clientRaw, serverRaw := net.Pipe()
|
clientRaw, serverRaw := gonet.Pipe()
|
||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
clientConn, err := cfg.WrapConnClient(clientRaw)
|
clientConn, err := cfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -1032,11 +1025,11 @@ func TestSudokuBDD(t *testing.T) {
|
|||||||
Ascii: "prefer_entropy",
|
Ascii: "prefer_entropy",
|
||||||
}
|
}
|
||||||
|
|
||||||
clientRaw, serverRaw := net.Pipe()
|
clientRaw, serverRaw := gonet.Pipe()
|
||||||
defer clientRaw.Close()
|
defer clientRaw.Close()
|
||||||
defer serverRaw.Close()
|
defer serverRaw.Close()
|
||||||
|
|
||||||
clientConn, err := cfg.WrapConnClient(clientRaw)
|
clientConn, err := cfg.WrapConnClient(clientRaw, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,17 @@
|
|||||||
package udphop
|
package udphop
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
|
|
||||||
"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/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) HandleDial() {}
|
||||||
_, ok1 := raw.(*internet.FakePacketConn)
|
|
||||||
if level != 0 || ok1 {
|
func (c *Config) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
return nil, errors.New("udphop requires being at the outermost level")
|
return NewUDPHopConn(c, dest, dialer)
|
||||||
}
|
|
||||||
return NewUDPHopConn(c, raw)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
return nil, errors.New("udphop: client only")
|
return nil, errors.New("udphop: client only")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
package udphop
|
package udphop
|
||||||
|
|
||||||
import (
|
import (
|
||||||
internet "github.com/xtls/xray-core/transport/internet"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -24,14 +23,13 @@ const (
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Sockopt *internet.SocketConfig `protobuf:"bytes,1,opt,name=sockopt,proto3" json:"sockopt,omitempty"`
|
|
||||||
Local bool `protobuf:"varint,2,opt,name=local,proto3" json:"local,omitempty"`
|
Local bool `protobuf:"varint,2,opt,name=local,proto3" json:"local,omitempty"`
|
||||||
Remote bool `protobuf:"varint,3,opt,name=remote,proto3" json:"remote,omitempty"`
|
Remote bool `protobuf:"varint,3,opt,name=remote,proto3" json:"remote,omitempty"`
|
||||||
RemoteOnce bool `protobuf:"varint,4,opt,name=remote_once,json=remoteOnce,proto3" json:"remote_once,omitempty"`
|
RemoteOnce bool `protobuf:"varint,4,opt,name=remote_once,json=remoteOnce,proto3" json:"remote_once,omitempty"`
|
||||||
IntervalMin int64 `protobuf:"varint,5,opt,name=interval_min,json=intervalMin,proto3" json:"interval_min,omitempty"`
|
IntervalMin int64 `protobuf:"varint,5,opt,name=interval_min,json=intervalMin,proto3" json:"interval_min,omitempty"`
|
||||||
IntervalMax int64 `protobuf:"varint,6,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"`
|
IntervalMax int64 `protobuf:"varint,6,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"`
|
||||||
RemotePorts []uint32 `protobuf:"varint,7,rep,packed,name=remote_ports,json=remotePorts,proto3" json:"remote_ports,omitempty"`
|
RemoteIPs []string `protobuf:"bytes,7,rep,name=remoteIPs,proto3" json:"remoteIPs,omitempty"`
|
||||||
RemoteIPs []string `protobuf:"bytes,8,rep,name=remoteIPs,proto3" json:"remoteIPs,omitempty"`
|
RemotePorts []uint32 `protobuf:"varint,8,rep,packed,name=remote_ports,json=remotePorts,proto3" json:"remote_ports,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@@ -66,13 +64,6 @@ func (*Config) Descriptor() ([]byte, []int) {
|
|||||||
return file_transport_internet_finalmask_udphop_config_proto_rawDescGZIP(), []int{0}
|
return file_transport_internet_finalmask_udphop_config_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetSockopt() *internet.SocketConfig {
|
|
||||||
if x != nil {
|
|
||||||
return x.Sockopt
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetLocal() bool {
|
func (x *Config) GetLocal() bool {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Local
|
return x.Local
|
||||||
@@ -108,16 +99,16 @@ func (x *Config) GetIntervalMax() int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetRemotePorts() []uint32 {
|
func (x *Config) GetRemoteIPs() []string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.RemotePorts
|
return x.RemoteIPs
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetRemoteIPs() []string {
|
func (x *Config) GetRemotePorts() []uint32 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.RemoteIPs
|
return x.RemotePorts
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -126,17 +117,16 @@ var File_transport_internet_finalmask_udphop_config_proto protoreflect.FileDescr
|
|||||||
|
|
||||||
const file_transport_internet_finalmask_udphop_config_proto_rawDesc = "" +
|
const file_transport_internet_finalmask_udphop_config_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"0transport/internet/finalmask/udphop/config.proto\x12(xray.transport.internet.finalmask.udphop\x1a\x1ftransport/internet/config.proto\"\x9f\x02\n" +
|
"0transport/internet/finalmask/udphop/config.proto\x12(xray.transport.internet.finalmask.udphop\"\xe4\x01\n" +
|
||||||
"\x06Config\x12?\n" +
|
"\x06Config\x12\x14\n" +
|
||||||
"\asockopt\x18\x01 \x01(\v2%.xray.transport.internet.SocketConfigR\asockopt\x12\x14\n" +
|
|
||||||
"\x05local\x18\x02 \x01(\bR\x05local\x12\x16\n" +
|
"\x05local\x18\x02 \x01(\bR\x05local\x12\x16\n" +
|
||||||
"\x06remote\x18\x03 \x01(\bR\x06remote\x12\x1f\n" +
|
"\x06remote\x18\x03 \x01(\bR\x06remote\x12\x1f\n" +
|
||||||
"\vremote_once\x18\x04 \x01(\bR\n" +
|
"\vremote_once\x18\x04 \x01(\bR\n" +
|
||||||
"remoteOnce\x12!\n" +
|
"remoteOnce\x12!\n" +
|
||||||
"\finterval_min\x18\x05 \x01(\x03R\vintervalMin\x12!\n" +
|
"\finterval_min\x18\x05 \x01(\x03R\vintervalMin\x12!\n" +
|
||||||
"\finterval_max\x18\x06 \x01(\x03R\vintervalMax\x12!\n" +
|
"\finterval_max\x18\x06 \x01(\x03R\vintervalMax\x12\x1c\n" +
|
||||||
"\fremote_ports\x18\a \x03(\rR\vremotePorts\x12\x1c\n" +
|
"\tremoteIPs\x18\a \x03(\tR\tremoteIPs\x12!\n" +
|
||||||
"\tremoteIPs\x18\b \x03(\tR\tremoteIPsB\x9a\x01\n" +
|
"\fremote_ports\x18\b \x03(\rR\vremotePortsJ\x04\b\x01\x10\x02B\x9a\x01\n" +
|
||||||
",com.xray.transport.internet.finalmask.udphopP\x01Z=github.com/xtls/xray-core/transport/internet/finalmask/udphop\xaa\x02(Xray.Transport.Internet.Finalmask.Udphopb\x06proto3"
|
",com.xray.transport.internet.finalmask.udphopP\x01Z=github.com/xtls/xray-core/transport/internet/finalmask/udphop\xaa\x02(Xray.Transport.Internet.Finalmask.Udphopb\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -153,16 +143,14 @@ func file_transport_internet_finalmask_udphop_config_proto_rawDescGZIP() []byte
|
|||||||
|
|
||||||
var file_transport_internet_finalmask_udphop_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
var file_transport_internet_finalmask_udphop_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||||
var file_transport_internet_finalmask_udphop_config_proto_goTypes = []any{
|
var file_transport_internet_finalmask_udphop_config_proto_goTypes = []any{
|
||||||
(*Config)(nil), // 0: xray.transport.internet.finalmask.udphop.Config
|
(*Config)(nil), // 0: xray.transport.internet.finalmask.udphop.Config
|
||||||
(*internet.SocketConfig)(nil), // 1: xray.transport.internet.SocketConfig
|
|
||||||
}
|
}
|
||||||
var file_transport_internet_finalmask_udphop_config_proto_depIdxs = []int32{
|
var file_transport_internet_finalmask_udphop_config_proto_depIdxs = []int32{
|
||||||
1, // 0: xray.transport.internet.finalmask.udphop.Config.sockopt:type_name -> xray.transport.internet.SocketConfig
|
0, // [0:0] is the sub-list for method output_type
|
||||||
1, // [1:1] is the sub-list for method output_type
|
0, // [0:0] is the sub-list for method input_type
|
||||||
1, // [1:1] is the sub-list for method input_type
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
1, // [1:1] is the sub-list for extension type_name
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
1, // [1:1] is the sub-list for extension extendee
|
0, // [0:0] is the sub-list for field type_name
|
||||||
0, // [0:1] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_transport_internet_finalmask_udphop_config_proto_init() }
|
func init() { file_transport_internet_finalmask_udphop_config_proto_init() }
|
||||||
|
|||||||
@@ -6,16 +6,14 @@ option go_package = "github.com/xtls/xray-core/transport/internet/finalmask/udph
|
|||||||
option java_package = "com.xray.transport.internet.finalmask.udphop";
|
option java_package = "com.xray.transport.internet.finalmask.udphop";
|
||||||
option java_multiple_files = true;
|
option java_multiple_files = true;
|
||||||
|
|
||||||
import "transport/internet/config.proto";
|
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
xray.transport.internet.SocketConfig sockopt = 1;
|
reserved 1;
|
||||||
bool local = 2;
|
bool local = 2;
|
||||||
bool remote = 3;
|
bool remote = 3;
|
||||||
bool remote_once = 4;
|
bool remote_once = 4;
|
||||||
int64 interval_min = 5;
|
int64 interval_min = 5;
|
||||||
int64 interval_max = 6;
|
int64 interval_max = 6;
|
||||||
repeated uint32 remote_ports = 7;
|
repeated string remoteIPs = 7;
|
||||||
repeated string remoteIPs = 8;
|
repeated uint32 remote_ports = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import (
|
|||||||
goerrors "errors"
|
goerrors "errors"
|
||||||
"io"
|
"io"
|
||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
gonet "net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"reflect"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -16,8 +14,6 @@ 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/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/finalmask"
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,16 +30,14 @@ type packet struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type udpHopConn struct {
|
type udpHopConn struct {
|
||||||
conn net.PacketConn
|
dialer *finalmask.Dialer
|
||||||
sockopt *internet.SocketConfig
|
local bool
|
||||||
local bool
|
remote bool
|
||||||
remote bool
|
|
||||||
remoteOnce bool
|
|
||||||
|
|
||||||
intervalMin int64
|
intervalMin int64
|
||||||
intervalMax int64
|
intervalMax int64
|
||||||
remotePorts []uint32
|
|
||||||
remoteIPs []netip.Prefix
|
remoteIPs []netip.Prefix
|
||||||
|
remotePorts []uint32
|
||||||
|
|
||||||
deadline time.Time
|
deadline time.Time
|
||||||
readDeadline time.Time
|
readDeadline time.Time
|
||||||
@@ -55,10 +49,10 @@ type udpHopConn struct {
|
|||||||
readCh chan packet
|
readCh chan packet
|
||||||
closeCh chan struct{}
|
closeCh chan struct{}
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
mu sync.Mutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUDPHopConn(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
func NewUDPHopConn(c *Config, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
if c.IntervalMin < 5 || c.IntervalMax < 5 {
|
if c.IntervalMin < 5 || c.IntervalMax < 5 {
|
||||||
return nil, errors.New("invalid interval")
|
return nil, errors.New("invalid interval")
|
||||||
}
|
}
|
||||||
@@ -66,22 +60,40 @@ func NewUDPHopConn(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
|||||||
for _, ip := range c.RemoteIPs {
|
for _, ip := range c.RemoteIPs {
|
||||||
remoteIPs = append(remoteIPs, netip.MustParsePrefix(ip))
|
remoteIPs = append(remoteIPs, netip.MustParsePrefix(ip))
|
||||||
}
|
}
|
||||||
conn := &udpHopConn{
|
remotePorts := c.RemotePorts
|
||||||
conn: raw,
|
if c.Remote || c.RemoteOnce {
|
||||||
sockopt: c.Sockopt,
|
if len(remoteIPs) > 0 {
|
||||||
local: c.Local,
|
dest.Address = net.IPAddress(randPrefix(remoteIPs[mrand.Intn(len(remoteIPs))]))
|
||||||
remote: c.Remote,
|
}
|
||||||
remoteOnce: c.RemoteOnce,
|
if len(remotePorts) > 0 {
|
||||||
|
dest.Port = net.Port(remotePorts[mrand.Intn(len(remotePorts))])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conn, err := dialer.DialUDP(*dest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cur := conn.(*finalmask.PacketConnWrapper).PacketConn
|
||||||
|
addr := conn.RemoteAddr().(*net.UDPAddr)
|
||||||
|
client := &udpHopConn{
|
||||||
|
dialer: dialer,
|
||||||
|
local: c.Local,
|
||||||
|
remote: c.Remote,
|
||||||
|
|
||||||
intervalMin: c.IntervalMin,
|
intervalMin: c.IntervalMin,
|
||||||
intervalMax: c.IntervalMax,
|
intervalMax: c.IntervalMax,
|
||||||
remotePorts: c.RemotePorts,
|
|
||||||
remoteIPs: remoteIPs,
|
remoteIPs: remoteIPs,
|
||||||
|
remotePorts: remotePorts,
|
||||||
|
|
||||||
|
cur: cur,
|
||||||
|
addr: addr,
|
||||||
readCh: make(chan packet),
|
readCh: make(chan packet),
|
||||||
closeCh: make(chan struct{}),
|
closeCh: make(chan struct{}),
|
||||||
}
|
}
|
||||||
return conn, nil
|
go client.run()
|
||||||
|
client.wg.Add(1)
|
||||||
|
go client.recv(client.cur)
|
||||||
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpHopConn) closed() bool {
|
func (c *udpHopConn) closed() bool {
|
||||||
@@ -93,61 +105,67 @@ func (c *udpHopConn) closed() bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpHopConn) hop(addr *net.UDPAddr) {
|
func (c *udpHopConn) run() {
|
||||||
|
ticker := time.NewTicker(time.Second * time.Duration(crypto.RandBetween(c.intervalMin, c.intervalMax+1)))
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-c.closeCh:
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
ticker.Reset(time.Second * time.Duration(crypto.RandBetween(c.intervalMin, c.intervalMax+1)))
|
||||||
|
c.hop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *udpHopConn) hop() {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
if c.closed() {
|
if c.closed() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newAddr := &net.UDPAddr{IP: addr.IP, Port: addr.Port}
|
oldIP := c.addr.IP
|
||||||
newConn := c.conn
|
oldPort := c.addr.Port
|
||||||
if c.remote || c.remoteOnce && c.addr == nil {
|
if c.remote {
|
||||||
if len(c.remotePorts) > 0 {
|
|
||||||
newAddr.Port = int(c.remotePorts[mrand.Intn(len(c.remotePorts))])
|
|
||||||
}
|
|
||||||
if len(c.remoteIPs) > 0 {
|
if len(c.remoteIPs) > 0 {
|
||||||
newAddr.IP = randPrefix(c.remoteIPs[mrand.Intn(len(c.remoteIPs))])
|
c.addr.IP = randPrefix(c.remoteIPs[mrand.Intn(len(c.remoteIPs))])
|
||||||
|
}
|
||||||
|
if len(c.remotePorts) > 0 {
|
||||||
|
c.addr.Port = int(c.remotePorts[mrand.Intn(len(c.remotePorts))])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.local {
|
if c.local {
|
||||||
raw, err := internet.DialSystem(context.Background(), net.UDPDestination(net.IPAddress(newAddr.IP), net.Port(newAddr.Port)), c.sockopt)
|
conn, err := c.dialer.DialUDP(net.UDPDestination(net.IPAddress(c.addr.IP), net.Port(c.addr.Port)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
c.addr.IP = oldIP
|
||||||
|
c.addr.Port = oldPort
|
||||||
errors.LogErrorInner(context.Background(), err, "hop err")
|
errors.LogErrorInner(context.Background(), err, "hop err")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch c := raw.(type) {
|
conn.SetDeadline(c.deadline)
|
||||||
case *internet.PacketConnWrapper:
|
conn.SetReadDeadline(c.readDeadline)
|
||||||
newConn = c.PacketConn
|
conn.SetWriteDeadline(c.writeDeadline)
|
||||||
case *cnc.Connection:
|
|
||||||
newConn = &internet.FakePacketConn{Conn: c}
|
|
||||||
default:
|
|
||||||
panic(reflect.TypeOf(c))
|
|
||||||
}
|
|
||||||
newConn.SetDeadline(c.deadline)
|
|
||||||
newConn.SetReadDeadline(c.readDeadline)
|
|
||||||
newConn.SetWriteDeadline(c.writeDeadline)
|
|
||||||
if c.pre != nil {
|
if c.pre != nil {
|
||||||
_ = c.pre.Close()
|
_ = c.pre.Close()
|
||||||
}
|
}
|
||||||
c.pre = c.cur
|
c.pre = c.cur
|
||||||
|
c.cur = conn.(*finalmask.PacketConnWrapper).PacketConn
|
||||||
c.wg.Add(1)
|
c.wg.Add(1)
|
||||||
go c.recv(newConn)
|
go c.recv(c.cur)
|
||||||
}
|
}
|
||||||
c.addr = newAddr
|
|
||||||
c.cur = newConn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpHopConn) recv(conn net.PacketConn) {
|
func (c *udpHopConn) recv(conn net.PacketConn) {
|
||||||
defer c.wg.Done()
|
defer c.wg.Done()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if c.closed() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p := pool.Get().([]byte)
|
p := pool.Get().([]byte)
|
||||||
n, addr, err := conn.ReadFrom(p)
|
n, addr, err := conn.ReadFrom(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pool.Put(p[:cap(p)])
|
pool.Put(p[:cap(p)])
|
||||||
if goerrors.Is(err, io.EOF) || goerrors.Is(err, io.ErrClosedPipe) || goerrors.Is(err, gonet.ErrClosed) {
|
if c.closed() {
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
var netErr net.Error
|
var netErr net.Error
|
||||||
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
||||||
@@ -156,9 +174,10 @@ func (c *udpHopConn) recv(conn net.PacketConn) {
|
|||||||
case <-c.closeCh:
|
case <-c.closeCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
errors.LogErrorInner(context.Background(), err, "recv err")
|
errors.LogErrorInner(context.Background(), err, "recv err")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case c.readCh <- packet{p: p[:n], addr: addr}:
|
case c.readCh <- packet{p: p[:n], addr: addr}:
|
||||||
@@ -169,22 +188,6 @@ func (c *udpHopConn) recv(conn net.PacketConn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpHopConn) hopLoop() {
|
|
||||||
ticker := time.NewTicker(time.Second * time.Duration(crypto.RandBetween(c.intervalMin, c.intervalMax+1)))
|
|
||||||
defer ticker.Stop()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
ticker.Reset(time.Second * time.Duration(crypto.RandBetween(c.intervalMin, c.intervalMax+1)))
|
|
||||||
c.mu.Lock()
|
|
||||||
c.hop(c.addr)
|
|
||||||
c.mu.Unlock()
|
|
||||||
case <-c.closeCh:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *udpHopConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
func (c *udpHopConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||||
packet, ok := <-c.readCh
|
packet, ok := <-c.readCh
|
||||||
if ok {
|
if ok {
|
||||||
@@ -194,21 +197,12 @@ func (c *udpHopConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
|||||||
}
|
}
|
||||||
return n, packet.addr, packet.err
|
return n, packet.addr, packet.err
|
||||||
}
|
}
|
||||||
return 0, nil, io.EOF
|
return 0, nil, io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpHopConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
func (c *udpHopConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||||
c.mu.Lock()
|
c.mu.RLock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.RUnlock()
|
||||||
|
|
||||||
if c.cur == nil {
|
|
||||||
c.hop(addr.(*net.UDPAddr))
|
|
||||||
if c.cur == nil {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
go c.hopLoop()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = c.cur.WriteTo(p, c.addr)
|
_, err = c.cur.WriteTo(p, c.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(context.Background(), err, "send err")
|
errors.LogErrorInner(context.Background(), err, "send err")
|
||||||
@@ -227,15 +221,12 @@ func (c *udpHopConn) Close() error {
|
|||||||
if c.pre != nil {
|
if c.pre != nil {
|
||||||
_ = c.pre.Close()
|
_ = c.pre.Close()
|
||||||
}
|
}
|
||||||
if c.cur != nil {
|
_ = c.cur.Close()
|
||||||
_ = c.cur.Close()
|
|
||||||
}
|
|
||||||
_ = c.conn.Close()
|
|
||||||
c.wg.Wait()
|
c.wg.Wait()
|
||||||
select {
|
select {
|
||||||
case p := <-c.readCh:
|
case packet := <-c.readCh:
|
||||||
if p.p != nil {
|
if packet.p != nil {
|
||||||
pool.Put(p.p[:cap(p.p)])
|
pool.Put(packet.p[:cap(packet.p)])
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@@ -244,7 +235,9 @@ func (c *udpHopConn) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpHopConn) LocalAddr() net.Addr {
|
func (c *udpHopConn) LocalAddr() net.Addr {
|
||||||
return c.conn.LocalAddr()
|
c.mu.RLock()
|
||||||
|
defer c.mu.RUnlock()
|
||||||
|
return c.cur.LocalAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpHopConn) SetDeadline(t time.Time) error {
|
func (c *udpHopConn) SetDeadline(t time.Time) error {
|
||||||
@@ -254,10 +247,7 @@ func (c *udpHopConn) SetDeadline(t time.Time) error {
|
|||||||
if c.pre != nil {
|
if c.pre != nil {
|
||||||
_ = c.pre.SetDeadline(t)
|
_ = c.pre.SetDeadline(t)
|
||||||
}
|
}
|
||||||
if c.cur != nil {
|
return c.cur.SetDeadline(t)
|
||||||
_ = c.cur.SetDeadline(t)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpHopConn) SetReadDeadline(t time.Time) error {
|
func (c *udpHopConn) SetReadDeadline(t time.Time) error {
|
||||||
@@ -267,10 +257,7 @@ func (c *udpHopConn) SetReadDeadline(t time.Time) error {
|
|||||||
if c.pre != nil {
|
if c.pre != nil {
|
||||||
_ = c.pre.SetReadDeadline(t)
|
_ = c.pre.SetReadDeadline(t)
|
||||||
}
|
}
|
||||||
if c.cur != nil {
|
return c.cur.SetReadDeadline(t)
|
||||||
_ = c.cur.SetReadDeadline(t)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpHopConn) SetWriteDeadline(t time.Time) error {
|
func (c *udpHopConn) SetWriteDeadline(t time.Time) error {
|
||||||
@@ -280,10 +267,7 @@ func (c *udpHopConn) SetWriteDeadline(t time.Time) error {
|
|||||||
if c.pre != nil {
|
if c.pre != nil {
|
||||||
_ = c.pre.SetWriteDeadline(t)
|
_ = c.pre.SetWriteDeadline(t)
|
||||||
}
|
}
|
||||||
if c.cur != nil {
|
return c.cur.SetWriteDeadline(t)
|
||||||
_ = c.cur.SetWriteDeadline(t)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func randPrefix(p netip.Prefix) []byte {
|
func randPrefix(p netip.Prefix) []byte {
|
||||||
|
|||||||
@@ -1,21 +1,14 @@
|
|||||||
package xdns
|
package xdns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
// _, ok1 := raw.(*internet.FakePacketConn)
|
return NewConnClient(c, conn)
|
||||||
// _, ok2 := raw.(*udphop.UdpHopPacketConn)
|
|
||||||
// if level != 0 || ok1 || ok2 {
|
|
||||||
// return nil, errors.New("xdns requires being at the outermost level")
|
|
||||||
// }
|
|
||||||
return NewConnClient(c, raw)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
// if level != 0 {
|
return NewConnServer(c, conn)
|
||||||
// return nil, errors.New("xdns requires being at the outermost level")
|
|
||||||
// }
|
|
||||||
return NewConnServer(c, raw)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ import (
|
|||||||
goerrors "errors"
|
goerrors "errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
mathrand "math/rand"
|
mrand "math/rand"
|
||||||
"net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -17,6 +16,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/transport/internet/finalmask"
|
"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"
|
||||||
@@ -36,11 +36,11 @@ type packet struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type xicmpConnClient struct {
|
type xicmpConnClient struct {
|
||||||
conn net.PacketConn
|
|
||||||
icmp4 *icmp.PacketConn
|
icmp4 *icmp.PacketConn
|
||||||
icmp6 *icmp.PacketConn
|
icmp6 *icmp.PacketConn
|
||||||
udp bool
|
udp bool
|
||||||
ips []netip.Addr
|
ips []netip.Addr
|
||||||
|
ip net.IP
|
||||||
clientID [8]byte
|
clientID [8]byte
|
||||||
id int
|
id int
|
||||||
seq int
|
seq int
|
||||||
@@ -50,7 +50,7 @@ type xicmpConnClient struct {
|
|||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
func NewConnClient(c *Config, dest *net.Destination) (net.PacketConn, error) {
|
||||||
var icmp4, icmp6 *icmp.PacketConn
|
var icmp4, icmp6 *icmp.PacketConn
|
||||||
var err4, err6 error
|
var err4, err6 error
|
||||||
if c.DGRAM {
|
if c.DGRAM {
|
||||||
@@ -69,17 +69,24 @@ func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
|||||||
ips = append(ips, netip.MustParseAddr(ip))
|
ips = append(ips, netip.MustParseAddr(ip))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ip net.IP
|
||||||
|
if len(ips) > 0 {
|
||||||
|
ip = ips[mrand.Intn(len(ips))].AsSlice()
|
||||||
|
} else {
|
||||||
|
ip = dest.Address.IP()
|
||||||
|
}
|
||||||
|
|
||||||
var clientID [8]byte
|
var clientID [8]byte
|
||||||
common.Must2(rand.Read(clientID[:]))
|
common.Must2(rand.Read(clientID[:]))
|
||||||
|
|
||||||
conn := &xicmpConnClient{
|
conn := &xicmpConnClient{
|
||||||
conn: raw,
|
|
||||||
icmp4: icmp4,
|
icmp4: icmp4,
|
||||||
icmp6: icmp6,
|
icmp6: icmp6,
|
||||||
udp: c.DGRAM,
|
udp: c.DGRAM,
|
||||||
ips: ips,
|
ips: ips,
|
||||||
|
ip: ip,
|
||||||
clientID: clientID,
|
clientID: clientID,
|
||||||
id: mathrand.Intn(65536),
|
id: mrand.Intn(65536),
|
||||||
seq: 1,
|
seq: 1,
|
||||||
readCh: make(chan packet),
|
readCh: make(chan packet),
|
||||||
closeCh: make(chan struct{}),
|
closeCh: make(chan struct{}),
|
||||||
@@ -92,10 +99,6 @@ func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnClient) ring(a, b uint16) uint16 {
|
|
||||||
return min(a-b, b-a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *xicmpConnClient) closed() bool {
|
func (c *xicmpConnClient) closed() bool {
|
||||||
select {
|
select {
|
||||||
case <-c.closeCh:
|
case <-c.closeCh:
|
||||||
@@ -110,12 +113,11 @@ func (c *xicmpConnClient) recv4() {
|
|||||||
|
|
||||||
var b [finalmask.UDPSize]byte
|
var b [finalmask.UDPSize]byte
|
||||||
for {
|
for {
|
||||||
if c.closed() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n, addr, err := c.icmp4.ReadFrom(b[:])
|
n, addr, err := c.icmp4.ReadFrom(b[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if c.closed() {
|
||||||
|
return
|
||||||
|
}
|
||||||
var netErr net.Error
|
var netErr net.Error
|
||||||
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
||||||
select {
|
select {
|
||||||
@@ -125,9 +127,10 @@ func (c *xicmpConnClient) recv4() {
|
|||||||
case <-c.closeCh:
|
case <-c.closeCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
errors.LogErrorInner(context.Background(), err, "recv4 err")
|
errors.LogErrorInner(context.Background(), err, "recv err 4")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := icmp.ParseMessage(1, b[:n])
|
msg, err := icmp.ParseMessage(1, b[:n])
|
||||||
@@ -150,10 +153,6 @@ func (c *xicmpConnClient) recv4() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.ring(uint16(echo.Seq), uint16(c.seq)) > 1000 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(echo.Data) > 8 && bytes.Equal(echo.Data[:8], c.clientID[:]) {
|
if len(echo.Data) > 8 && bytes.Equal(echo.Data[:8], c.clientID[:]) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -182,12 +181,11 @@ func (c *xicmpConnClient) recv6() {
|
|||||||
|
|
||||||
var b [finalmask.UDPSize]byte
|
var b [finalmask.UDPSize]byte
|
||||||
for {
|
for {
|
||||||
if c.closed() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n, addr, err := c.icmp6.ReadFrom(b[:])
|
n, addr, err := c.icmp6.ReadFrom(b[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if c.closed() {
|
||||||
|
return
|
||||||
|
}
|
||||||
var netErr net.Error
|
var netErr net.Error
|
||||||
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
||||||
select {
|
select {
|
||||||
@@ -197,9 +195,10 @@ func (c *xicmpConnClient) recv6() {
|
|||||||
case <-c.closeCh:
|
case <-c.closeCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
errors.LogErrorInner(context.Background(), err, "recv6 err")
|
errors.LogErrorInner(context.Background(), err, "recv err 6")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := icmp.ParseMessage(58, b[:n])
|
msg, err := icmp.ParseMessage(58, b[:n])
|
||||||
@@ -222,10 +221,6 @@ func (c *xicmpConnClient) recv6() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.ring(uint16(echo.Seq), uint16(c.seq)) > 1000 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(echo.Data) > 8 && bytes.Equal(echo.Data[:8], c.clientID[:]) {
|
if len(echo.Data) > 8 && bytes.Equal(echo.Data[:8], c.clientID[:]) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -273,9 +268,9 @@ func (c *xicmpConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
|||||||
c.seq %= 65536
|
c.seq %= 65536
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
|
|
||||||
ip := addr.(*net.UDPAddr).IP
|
ip := c.ip
|
||||||
if len(c.ips) > 0 {
|
if len(c.ips) > 0 {
|
||||||
ip = c.ips[mathrand.Intn(len(c.ips))].AsSlice()
|
ip = c.ips[mrand.Intn(len(c.ips))].AsSlice()
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.udp {
|
if c.udp {
|
||||||
@@ -314,7 +309,6 @@ func (c *xicmpConnClient) Close() error {
|
|||||||
close(c.closeCh)
|
close(c.closeCh)
|
||||||
_ = c.icmp4.Close()
|
_ = c.icmp4.Close()
|
||||||
_ = c.icmp6.Close()
|
_ = c.icmp6.Close()
|
||||||
_ = c.conn.Close()
|
|
||||||
c.wg.Wait()
|
c.wg.Wait()
|
||||||
select {
|
select {
|
||||||
case p := <-c.readCh:
|
case p := <-c.readCh:
|
||||||
@@ -328,7 +322,7 @@ func (c *xicmpConnClient) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnClient) LocalAddr() net.Addr {
|
func (c *xicmpConnClient) LocalAddr() net.Addr {
|
||||||
return c.conn.LocalAddr()
|
return &net.UDPAddr{IP: []byte{0, 0, 0, 0}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnClient) SetDeadline(t time.Time) error {
|
func (c *xicmpConnClient) SetDeadline(t time.Time) error {
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
package xicmp
|
package xicmp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"errors"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) HandleDial() {}
|
||||||
_, ok1 := raw.(*internet.FakePacketConn)
|
|
||||||
if level != 0 || ok1 {
|
func (c *Config) HandleListen() {}
|
||||||
return nil, errors.New("xicmp requires being at the outermost level")
|
|
||||||
|
func (c *Config) WrapPacketConnClient(conn net.PacketConn, dest *net.Destination, dialer *finalmask.Dialer) (net.PacketConn, error) {
|
||||||
|
if dest.Address.Family().IsDomain() && len(c.IPs) == 0 {
|
||||||
|
return nil, errors.New("empty ip addresses")
|
||||||
}
|
}
|
||||||
return NewConnClient(c, raw)
|
return NewConnClient(c, dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
|
func (c *Config) WrapPacketConnServer(conn net.PacketConn, addr net.Addr, lc *finalmask.ListenConfig) (net.PacketConn, error) {
|
||||||
if level != 0 {
|
return NewConnServer(c)
|
||||||
return nil, errors.New("xicmp requires being at the outermost level")
|
|
||||||
}
|
|
||||||
return NewConnServer(c, raw)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ type record struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type xicmpConnServer struct {
|
type xicmpConnServer struct {
|
||||||
conn net.PacketConn
|
|
||||||
icmp4 *icmp.PacketConn
|
icmp4 *icmp.PacketConn
|
||||||
icmp6 *icmp.PacketConn
|
icmp6 *icmp.PacketConn
|
||||||
ips map[netip.Addr]struct{}
|
ips map[netip.Addr]struct{}
|
||||||
@@ -48,7 +47,7 @@ type xicmpConnServer struct {
|
|||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
func NewConnServer(c *Config) (net.PacketConn, error) {
|
||||||
icmp4, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
|
icmp4, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -64,7 +63,6 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conn := &xicmpConnServer{
|
conn := &xicmpConnServer{
|
||||||
conn: raw,
|
|
||||||
icmp4: icmp4,
|
icmp4: icmp4,
|
||||||
icmp6: icmp6,
|
icmp6: icmp6,
|
||||||
ips: ips,
|
ips: ips,
|
||||||
@@ -115,12 +113,11 @@ func (c *xicmpConnServer) recv4() {
|
|||||||
|
|
||||||
var b [finalmask.UDPSize]byte
|
var b [finalmask.UDPSize]byte
|
||||||
for {
|
for {
|
||||||
if c.closed() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n, addr, err := c.icmp4.ReadFrom(b[:])
|
n, addr, err := c.icmp4.ReadFrom(b[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if c.closed() {
|
||||||
|
return
|
||||||
|
}
|
||||||
var netErr net.Error
|
var netErr net.Error
|
||||||
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
||||||
select {
|
select {
|
||||||
@@ -130,9 +127,10 @@ func (c *xicmpConnServer) recv4() {
|
|||||||
case <-c.closeCh:
|
case <-c.closeCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
errors.LogErrorInner(context.Background(), err, "recv4 err")
|
errors.LogErrorInner(context.Background(), err, "recv err 4")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := icmp.ParseMessage(1, b[:n])
|
msg, err := icmp.ParseMessage(1, b[:n])
|
||||||
@@ -195,12 +193,11 @@ func (c *xicmpConnServer) recv6() {
|
|||||||
|
|
||||||
var b [finalmask.UDPSize]byte
|
var b [finalmask.UDPSize]byte
|
||||||
for {
|
for {
|
||||||
if c.closed() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n, addr, err := c.icmp6.ReadFrom(b[:])
|
n, addr, err := c.icmp6.ReadFrom(b[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if c.closed() {
|
||||||
|
return
|
||||||
|
}
|
||||||
var netErr net.Error
|
var netErr net.Error
|
||||||
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
||||||
select {
|
select {
|
||||||
@@ -210,9 +207,10 @@ func (c *xicmpConnServer) recv6() {
|
|||||||
case <-c.closeCh:
|
case <-c.closeCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
errors.LogErrorInner(context.Background(), err, "recv6 err")
|
errors.LogErrorInner(context.Background(), err, "recv err 6")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := icmp.ParseMessage(58, b[:n])
|
msg, err := icmp.ParseMessage(58, b[:n])
|
||||||
@@ -330,7 +328,6 @@ func (c *xicmpConnServer) Close() error {
|
|||||||
close(c.closeCh)
|
close(c.closeCh)
|
||||||
_ = c.icmp4.Close()
|
_ = c.icmp4.Close()
|
||||||
_ = c.icmp6.Close()
|
_ = c.icmp6.Close()
|
||||||
_ = c.conn.Close()
|
|
||||||
c.wg.Wait()
|
c.wg.Wait()
|
||||||
select {
|
select {
|
||||||
case p := <-c.readCh:
|
case p := <-c.readCh:
|
||||||
@@ -344,7 +341,7 @@ func (c *xicmpConnServer) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnServer) LocalAddr() net.Addr {
|
func (c *xicmpConnServer) LocalAddr() net.Addr {
|
||||||
return c.conn.LocalAddr()
|
return &net.UDPAddr{IP: []byte{0, 0, 0, 0}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnServer) SetDeadline(t time.Time) error {
|
func (c *xicmpConnServer) SetDeadline(t time.Time) error {
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ type record struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type xicmpConnServer struct {
|
type xicmpConnServer struct {
|
||||||
conn net.PacketConn
|
|
||||||
icmp4 *icmp.PacketConn
|
icmp4 *icmp.PacketConn
|
||||||
icmp6 *icmp.PacketConn
|
icmp6 *icmp.PacketConn
|
||||||
ipv4PC *ipv4.PacketConn
|
ipv4PC *ipv4.PacketConn
|
||||||
@@ -52,7 +51,7 @@ type xicmpConnServer struct {
|
|||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
func NewConnServer(c *Config) (net.PacketConn, error) {
|
||||||
icmp4, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
|
icmp4, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -68,7 +67,6 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conn := &xicmpConnServer{
|
conn := &xicmpConnServer{
|
||||||
conn: raw,
|
|
||||||
icmp4: icmp4,
|
icmp4: icmp4,
|
||||||
icmp6: icmp6,
|
icmp6: icmp6,
|
||||||
ipv4PC: icmp4.IPv4PacketConn(),
|
ipv4PC: icmp4.IPv4PacketConn(),
|
||||||
@@ -124,12 +122,11 @@ func (c *xicmpConnServer) recv4() {
|
|||||||
|
|
||||||
var b [finalmask.UDPSize]byte
|
var b [finalmask.UDPSize]byte
|
||||||
for {
|
for {
|
||||||
if c.closed() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n, cm, addr, err := c.ipv4PC.ReadFrom(b[:])
|
n, cm, addr, err := c.ipv4PC.ReadFrom(b[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if c.closed() {
|
||||||
|
return
|
||||||
|
}
|
||||||
var netErr net.Error
|
var netErr net.Error
|
||||||
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
||||||
select {
|
select {
|
||||||
@@ -139,9 +136,10 @@ func (c *xicmpConnServer) recv4() {
|
|||||||
case <-c.closeCh:
|
case <-c.closeCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
errors.LogErrorInner(context.Background(), err, "recv4 err")
|
errors.LogErrorInner(context.Background(), err, "recv err 4")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := icmp.ParseMessage(1, b[:n])
|
msg, err := icmp.ParseMessage(1, b[:n])
|
||||||
@@ -205,12 +203,11 @@ func (c *xicmpConnServer) recv6() {
|
|||||||
|
|
||||||
var b [finalmask.UDPSize]byte
|
var b [finalmask.UDPSize]byte
|
||||||
for {
|
for {
|
||||||
if c.closed() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
n, cm, addr, err := c.ipv6PC.ReadFrom(b[:])
|
n, cm, addr, err := c.ipv6PC.ReadFrom(b[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if c.closed() {
|
||||||
|
return
|
||||||
|
}
|
||||||
var netErr net.Error
|
var netErr net.Error
|
||||||
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
if goerrors.As(err, &netErr) && netErr.Timeout() {
|
||||||
select {
|
select {
|
||||||
@@ -220,9 +217,10 @@ func (c *xicmpConnServer) recv6() {
|
|||||||
case <-c.closeCh:
|
case <-c.closeCh:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
errors.LogErrorInner(context.Background(), err, "recv6 err")
|
errors.LogErrorInner(context.Background(), err, "recv err 6")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg, err := icmp.ParseMessage(58, b[:n])
|
msg, err := icmp.ParseMessage(58, b[:n])
|
||||||
@@ -341,7 +339,6 @@ func (c *xicmpConnServer) Close() error {
|
|||||||
close(c.closeCh)
|
close(c.closeCh)
|
||||||
_ = c.icmp4.Close()
|
_ = c.icmp4.Close()
|
||||||
_ = c.icmp6.Close()
|
_ = c.icmp6.Close()
|
||||||
_ = c.conn.Close()
|
|
||||||
c.wg.Wait()
|
c.wg.Wait()
|
||||||
select {
|
select {
|
||||||
case p := <-c.readCh:
|
case p := <-c.readCh:
|
||||||
@@ -355,7 +352,7 @@ func (c *xicmpConnServer) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnServer) LocalAddr() net.Addr {
|
func (c *xicmpConnServer) LocalAddr() net.Addr {
|
||||||
return c.conn.LocalAddr()
|
return &net.UDPAddr{IP: []byte{0, 0, 0, 0}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *xicmpConnServer) SetDeadline(t time.Time) error {
|
func (c *xicmpConnServer) SetDeadline(t time.Time) error {
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package xmc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) WrapConnClient(conn net.Conn) (net.Conn, error) {
|
func (c *Config) WrapConnClient(conn net.Conn, dest *net.Destination, dialer *finalmask.Dialer) (net.Conn, error) {
|
||||||
profiles, err := profilesFromConfig(c.Profiles)
|
profiles, err := profilesFromConfig(c.Profiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("minecraft finalmask: %w", err)
|
return nil, fmt.Errorf("minecraft finalmask: %w", err)
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
}
|
}
|
||||||
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
||||||
realityConfig := reality.ConfigFromStreamSettings(streamSettings)
|
realityConfig := reality.ConfigFromStreamSettings(streamSettings)
|
||||||
sockopt := streamSettings.SocketSettings
|
|
||||||
grpcSettings := streamSettings.ProtocolSettings.(*Config)
|
grpcSettings := streamSettings.ProtocolSettings.(*Config)
|
||||||
|
|
||||||
if client, found := globalDialerMap[dialerConf{dest, streamSettings}]; found && client.GetState() != connectivity.Shutdown {
|
if client, found := globalDialerMap[dialerConf{dest, streamSettings}]; found && client.GetState() != connectivity.Shutdown {
|
||||||
@@ -124,17 +123,13 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
gctx = session.ContextWithOutbounds(gctx, session.OutboundsFromContext(ctx))
|
gctx = session.ContextWithOutbounds(gctx, session.OutboundsFromContext(ctx))
|
||||||
gctx = session.ContextWithTimeoutOnly(gctx, true)
|
gctx = session.ContextWithTimeoutOnly(gctx, true)
|
||||||
|
|
||||||
c, err := internet.DialSystem(gctx, net.TCPDestination(address, port), sockopt)
|
var c net.Conn
|
||||||
|
if streamSettings.FinalMask != nil {
|
||||||
|
c, err = streamSettings.FinalMask.DialTCP(gctx, net.TCPDestination(address, port))
|
||||||
|
} else {
|
||||||
|
c, err = internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||||
|
}
|
||||||
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(tls.WithDestination(dest))
|
config := tlsConfig.GetTLSConfig(tls.WithDestination(dest))
|
||||||
if fingerprint := tls.GetFingerprint(tlsConfig.Fingerprint); fingerprint != nil {
|
if fingerprint := tls.GetFingerprint(tlsConfig.Fingerprint); fingerprint != nil {
|
||||||
|
|||||||
@@ -104,28 +104,20 @@ func Listen(ctx context.Context, address net.Address, port net.Port, settings *i
|
|||||||
go func() {
|
go func() {
|
||||||
var streamListener net.Listener
|
var streamListener net.Listener
|
||||||
var err error
|
var err error
|
||||||
|
var addr net.Addr
|
||||||
if port == net.Port(0) { // unix
|
if port == net.Port(0) { // unix
|
||||||
streamListener, err = internet.ListenSystem(ctx, &net.UnixAddr{
|
addr = &net.UnixAddr{Name: address.Domain(), Net: "unix"}
|
||||||
Name: address.Domain(),
|
|
||||||
Net: "unix",
|
|
||||||
}, settings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
errors.LogErrorInner(ctx, err, "failed to listen on ", address)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else { // tcp
|
} else { // tcp
|
||||||
streamListener, err = internet.ListenSystem(ctx, &net.TCPAddr{
|
addr = &net.TCPAddr{IP: address.IP(), Port: int(port)}
|
||||||
IP: address.IP(),
|
|
||||||
Port: int(port),
|
|
||||||
}, settings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
errors.LogErrorInner(ctx, err, "failed to listen on ", address, ":", port)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if settings.FinalMask != nil {
|
||||||
if settings.TcpmaskManager != nil {
|
streamListener, err = settings.FinalMask.Listen(ctx, addr)
|
||||||
streamListener, _ = settings.TcpmaskManager.WrapListener(streamListener)
|
} else {
|
||||||
|
streamListener, err = internet.ListenSystem(ctx, addr, settings.SocketSettings)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
errors.LogErrorInner(ctx, err, "failed to listen on ", address, ":", port)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
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()+"`")
|
||||||
|
|||||||
@@ -46,21 +46,18 @@ func (c *ConnRF) Read(b []byte) (int, error) {
|
|||||||
func dialhttpUpgrade(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (net.Conn, error) {
|
func dialhttpUpgrade(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (net.Conn, error) {
|
||||||
transportConfiguration := streamSettings.ProtocolSettings.(*Config)
|
transportConfiguration := streamSettings.ProtocolSettings.(*Config)
|
||||||
|
|
||||||
pconn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
var pconn net.Conn
|
||||||
|
var err error
|
||||||
|
if streamSettings.FinalMask != nil {
|
||||||
|
pconn, err = streamSettings.FinalMask.DialTCP(ctx, dest)
|
||||||
|
} else {
|
||||||
|
pconn, err = internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to dial to ", dest)
|
errors.LogErrorInner(ctx, err, "failed to dial to ", dest)
|
||||||
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)
|
||||||
|
|||||||
@@ -124,29 +124,21 @@ func ListenHTTPUpgrade(ctx context.Context, address net.Address, port net.Port,
|
|||||||
}
|
}
|
||||||
var listener net.Listener
|
var listener net.Listener
|
||||||
var err error
|
var err error
|
||||||
|
var addr net.Addr
|
||||||
if port == net.Port(0) { // unix
|
if port == net.Port(0) { // unix
|
||||||
listener, err = internet.ListenSystem(ctx, &net.UnixAddr{
|
addr = &net.UnixAddr{Name: address.Domain(), Net: "unix"}
|
||||||
Name: address.Domain(),
|
|
||||||
Net: "unix",
|
|
||||||
}, streamSettings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to listen unix domain socket(for HttpUpgrade) on ", address).Base(err)
|
|
||||||
}
|
|
||||||
errors.LogInfo(ctx, "listening unix domain socket(for HttpUpgrade) on ", address)
|
|
||||||
} else { // tcp
|
} else { // tcp
|
||||||
listener, err = internet.ListenSystem(ctx, &net.TCPAddr{
|
addr = &net.TCPAddr{IP: address.IP(), Port: int(port)}
|
||||||
IP: address.IP(),
|
|
||||||
Port: int(port),
|
|
||||||
}, streamSettings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to listen TCP(for HttpUpgrade) on ", address, ":", port).Base(err)
|
|
||||||
}
|
|
||||||
errors.LogInfo(ctx, "listening TCP(for HttpUpgrade) on ", address, ":", port)
|
|
||||||
}
|
}
|
||||||
|
if streamSettings.FinalMask != nil {
|
||||||
if streamSettings.TcpmaskManager != nil {
|
listener, err = streamSettings.FinalMask.Listen(ctx, addr)
|
||||||
listener, _ = streamSettings.TcpmaskManager.WrapListener(listener)
|
} else {
|
||||||
|
listener, err = internet.ListenSystem(ctx, addr, streamSettings.SocketSettings)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to listen ", addr.Network(), "(for HttpUpgrade) on ", address, ":", port).Base(err)
|
||||||
|
}
|
||||||
|
errors.LogInfo(ctx, "listening ", addr.Network(), "(for HttpUpgrade) on ", address, ":", port)
|
||||||
|
|
||||||
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")
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package hysteria
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
go_tls "crypto/tls"
|
gotls "crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -28,12 +28,12 @@ import (
|
|||||||
type client struct {
|
type client struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
dest net.Destination
|
dest net.Destination
|
||||||
config *Config
|
config *Config
|
||||||
tlsConfig *go_tls.Config
|
tlsConfig *gotls.Config
|
||||||
socketConfig *internet.SocketConfig
|
socketConfig *internet.SocketConfig
|
||||||
udpmaskManager *finalmask.UdpmaskManager
|
finalMask *finalmask.FinalMask
|
||||||
quicParams *internet.QuicParams
|
quicParams *internet.QuicParams
|
||||||
|
|
||||||
conn *quic.Conn
|
conn *quic.Conn
|
||||||
tr *quic.Transport
|
tr *quic.Transport
|
||||||
@@ -113,30 +113,29 @@ func (c *client) dial(ctx context.Context) error {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
var pktConn net.PacketConn
|
var pktConn net.PacketConn
|
||||||
var udpAddr *net.UDPAddr
|
var udpAddr net.Addr
|
||||||
|
if c.finalMask != nil {
|
||||||
raw, err := internet.DialSystem(ctx, c.dest, c.socketConfig)
|
conn, err := c.finalMask.DialUDP(ctx, c.dest)
|
||||||
if err != nil {
|
|
||||||
return errors.New("failed to dial to dest").Base(err)
|
|
||||||
}
|
|
||||||
switch c := raw.(type) {
|
|
||||||
case *internet.PacketConnWrapper:
|
|
||||||
pktConn = c.PacketConn
|
|
||||||
udpAddr = raw.RemoteAddr().(*net.UDPAddr)
|
|
||||||
case *cnc.Connection:
|
|
||||||
pktConn = &internet.FakePacketConn{Conn: c}
|
|
||||||
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
|
|
||||||
default:
|
|
||||||
panic(reflect.TypeOf(c))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.udpmaskManager != nil {
|
|
||||||
newConn, err := c.udpmaskManager.WrapPacketConnClient(pktConn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pktConn.Close()
|
return errors.New("failed to dial to dest").Base(err)
|
||||||
return errors.New("mask err").Base(err)
|
}
|
||||||
|
pktConn = conn.(*finalmask.PacketConnWrapper).PacketConn
|
||||||
|
udpAddr = conn.RemoteAddr()
|
||||||
|
} else {
|
||||||
|
conn, err := internet.DialSystem(ctx, c.dest, c.socketConfig)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("failed to dial to dest").Base(err)
|
||||||
|
}
|
||||||
|
switch c := conn.(type) {
|
||||||
|
case *internet.PacketConnWrapper:
|
||||||
|
pktConn = c.PacketConn
|
||||||
|
udpAddr = c.RemoteAddr()
|
||||||
|
case *cnc.Connection:
|
||||||
|
pktConn = &internet.FakePacketConn{Conn: c}
|
||||||
|
udpAddr = &net.UDPAddr{IP: []byte{0, 0, 0, 0}}
|
||||||
|
default:
|
||||||
|
panic(reflect.TypeOf(c))
|
||||||
}
|
}
|
||||||
pktConn = newConn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tr := &quic.Transport{Conn: pktConn, DisableGSO: quicParams.DisableGSO}
|
tr := &quic.Transport{Conn: pktConn, DisableGSO: quicParams.DisableGSO}
|
||||||
@@ -150,7 +149,7 @@ func (c *client) dial(ctx context.Context) error {
|
|||||||
rt := &http3.Transport{
|
rt := &http3.Transport{
|
||||||
TLSClientConfig: c.tlsConfig,
|
TLSClientConfig: c.tlsConfig,
|
||||||
QUICConfig: quicConfig,
|
QUICConfig: quicConfig,
|
||||||
Dial: func(ctx context.Context, _ string, tlsCfg *go_tls.Config, cfg *quic.Config) (*quic.Conn, error) {
|
Dial: func(ctx context.Context, _ string, tlsCfg *gotls.Config, cfg *quic.Config) (*quic.Conn, error) {
|
||||||
qc, err := tr.DialEarly(ctx, udpAddr, tlsCfg, cfg)
|
qc, err := tr.DialEarly(ctx, udpAddr, tlsCfg, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -316,12 +315,12 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||||||
c = manager.m[dialerConf{dest, streamSettings}]
|
c = manager.m[dialerConf{dest, streamSettings}]
|
||||||
if c == nil {
|
if c == nil {
|
||||||
c = &client{
|
c = &client{
|
||||||
dest: dest,
|
dest: dest,
|
||||||
config: streamSettings.ProtocolSettings.(*Config),
|
config: streamSettings.ProtocolSettings.(*Config),
|
||||||
tlsConfig: tlsConfig.GetTLSConfig(tls.WithDestination(dest)),
|
tlsConfig: tlsConfig.GetTLSConfig(tls.WithDestination(dest)),
|
||||||
socketConfig: streamSettings.SocketSettings,
|
socketConfig: streamSettings.SocketSettings,
|
||||||
udpmaskManager: streamSettings.UdpmaskManager,
|
finalMask: streamSettings.FinalMask,
|
||||||
quicParams: streamSettings.QuicParams,
|
quicParams: streamSettings.QuicParams,
|
||||||
}
|
}
|
||||||
manager.m[dialerConf{dest, streamSettings}] = c
|
manager.m[dialerConf{dest, streamSettings}] = c
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -316,20 +316,17 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
|||||||
quicConfig.MaxIncomingStreams = 1024
|
quicConfig.MaxIncomingStreams = 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
pktConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{IP: address.IP(), Port: int(port)}, streamSettings.SocketSettings)
|
var pktConn net.PacketConn
|
||||||
|
var err error
|
||||||
|
if streamSettings.FinalMask != nil {
|
||||||
|
pktConn, err = streamSettings.FinalMask.ListenPacket(context.Background(), &net.UDPAddr{IP: address.IP(), Port: int(port)})
|
||||||
|
} else {
|
||||||
|
pktConn, err = internet.ListenSystemPacket(context.Background(), &net.UDPAddr{IP: address.IP(), Port: int(port)}, streamSettings.SocketSettings)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if streamSettings.UdpmaskManager != nil {
|
|
||||||
newConn, err := streamSettings.UdpmaskManager.WrapPacketConnServer(pktConn)
|
|
||||||
if err != nil {
|
|
||||||
pktConn.Close()
|
|
||||||
return nil, errors.New("mask err").Base(err)
|
|
||||||
}
|
|
||||||
pktConn = newConn
|
|
||||||
}
|
|
||||||
|
|
||||||
var k *quic.StatelessResetKey
|
var k *quic.StatelessResetKey
|
||||||
if !quicParams.DisableStatelessReset {
|
if !quicParams.DisableStatelessReset {
|
||||||
k = &quic.StatelessResetKey{}
|
k = &quic.StatelessResetKey{}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ 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"
|
||||||
@@ -11,7 +10,6 @@ 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"
|
||||||
@@ -51,36 +49,17 @@ 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)
|
||||||
|
|
||||||
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
var conn net.Conn
|
||||||
|
var err error
|
||||||
|
if streamSettings.FinalMask != nil {
|
||||||
|
conn, err = streamSettings.FinalMask.DialUDP(ctx, dest)
|
||||||
|
} else {
|
||||||
|
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 {
|
|
||||||
var pktConn net.PacketConn
|
|
||||||
var udpAddr *net.UDPAddr
|
|
||||||
switch c := conn.(type) {
|
|
||||||
case *internet.PacketConnWrapper:
|
|
||||||
pktConn = c.PacketConn
|
|
||||||
udpAddr = c.RemoteAddr().(*net.UDPAddr)
|
|
||||||
case *cnc.Connection:
|
|
||||||
pktConn = &internet.FakePacketConn{Conn: c}
|
|
||||||
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
|
|
||||||
default:
|
|
||||||
panic(reflect.TypeOf(c))
|
|
||||||
}
|
|
||||||
newConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(pktConn)
|
|
||||||
if err != nil {
|
|
||||||
pktConn.Close()
|
|
||||||
return nil, errors.New("mask err").Base(err)
|
|
||||||
}
|
|
||||||
pktConn = newConn
|
|
||||||
conn = &internet.PacketConnWrapper{
|
|
||||||
PacketConn: pktConn,
|
|
||||||
Dest: udpAddr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kcpSettings := streamSettings.ProtocolSettings.(*Config)
|
kcpSettings := streamSettings.ProtocolSettings.(*Config)
|
||||||
|
|
||||||
reader := &KCPPacketReader{}
|
reader := &KCPPacketReader{}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
package internet
|
package internet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
"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/finalmask"
|
"github.com/xtls/xray-core/transport/internet/finalmask"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,8 +17,7 @@ type MemoryStreamConfig struct {
|
|||||||
ProtocolSettings interface{}
|
ProtocolSettings interface{}
|
||||||
SecurityType string
|
SecurityType string
|
||||||
SecuritySettings interface{}
|
SecuritySettings interface{}
|
||||||
TcpmaskManager *finalmask.TcpmaskManager
|
FinalMask *finalmask.FinalMask
|
||||||
UdpmaskManager *finalmask.UdpmaskManager
|
|
||||||
QuicParams *QuicParams
|
QuicParams *QuicParams
|
||||||
SocketSettings *SocketConfig
|
SocketSettings *SocketConfig
|
||||||
DownloadSettings *MemoryStreamConfig
|
DownloadSettings *MemoryStreamConfig
|
||||||
@@ -51,33 +55,53 @@ func ToMemoryStreamConfig(s *StreamConfig) (*MemoryStreamConfig, error) {
|
|||||||
mss.SecuritySettings = ess
|
mss.SecuritySettings = ess
|
||||||
}
|
}
|
||||||
|
|
||||||
if s != nil && len(s.Tcpmasks) > 0 {
|
var tcpMasks []finalmask.TCPMask
|
||||||
var masks []finalmask.Tcpmask
|
var udpMasks []finalmask.UDPMask
|
||||||
for _, msg := range s.Tcpmasks {
|
|
||||||
instance, err := msg.GetInstance()
|
if s != nil {
|
||||||
if err != nil {
|
for i := range s.Tcpmasks {
|
||||||
return nil, err
|
instance := common.Must2(s.Tcpmasks[i].GetInstance())
|
||||||
}
|
tcpMasks = append(tcpMasks, instance.(finalmask.TCPMask))
|
||||||
masks = append(masks, instance.(finalmask.Tcpmask))
|
}
|
||||||
|
for i := range s.Udpmasks {
|
||||||
|
instance := common.Must2(s.Udpmasks[i].GetInstance())
|
||||||
|
udpMasks = append(udpMasks, instance.(finalmask.UDPMask))
|
||||||
}
|
}
|
||||||
mss.TcpmaskManager = finalmask.NewTcpmaskManager(masks)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialTCP := func(ctx context.Context, dest net.Destination) (net.Conn, error) {
|
||||||
|
return DialSystem(ctx, dest, mss.SocketSettings)
|
||||||
|
}
|
||||||
|
listen := func(ctx context.Context, addr net.Addr) (net.Listener, error) {
|
||||||
|
return ListenSystem(ctx, addr, mss.SocketSettings)
|
||||||
|
}
|
||||||
|
dialUDP := func(ctx context.Context, dest net.Destination) (net.PacketConn, net.Addr, error) {
|
||||||
|
conn, err := DialSystem(ctx, dest, mss.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
var newConn net.PacketConn
|
||||||
|
var udpAddr net.Addr
|
||||||
|
switch c := conn.(type) {
|
||||||
|
case *PacketConnWrapper:
|
||||||
|
newConn = c.PacketConn
|
||||||
|
udpAddr = conn.RemoteAddr()
|
||||||
|
case *cnc.Connection:
|
||||||
|
newConn = &FakePacketConn{Conn: c}
|
||||||
|
udpAddr = &net.UDPAddr{IP: []byte{0, 0, 0, 0}, Port: 0}
|
||||||
|
default:
|
||||||
|
panic(reflect.TypeOf(c))
|
||||||
|
}
|
||||||
|
return newConn, udpAddr, nil
|
||||||
|
}
|
||||||
|
listenPacket := func(ctx context.Context, addr net.Addr) (net.PacketConn, error) {
|
||||||
|
return ListenSystemPacket(ctx, addr, mss.SocketSettings)
|
||||||
|
}
|
||||||
|
mss.FinalMask = finalmask.NewFinalMask(tcpMasks, udpMasks, dialTCP, listen, dialUDP, listenPacket)
|
||||||
|
|
||||||
if s != nil && s.QuicParams != nil {
|
if s != nil && s.QuicParams != nil {
|
||||||
mss.QuicParams = s.QuicParams
|
mss.QuicParams = s.QuicParams
|
||||||
}
|
}
|
||||||
|
|
||||||
if s != nil && len(s.Udpmasks) > 0 {
|
|
||||||
var masks []finalmask.Udpmask
|
|
||||||
for _, msg := range s.Udpmasks {
|
|
||||||
instance, err := msg.GetInstance()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
masks = append(masks, instance.(finalmask.Udpmask))
|
|
||||||
}
|
|
||||||
mss.UdpmaskManager = finalmask.NewUdpmaskManager(masks)
|
|
||||||
}
|
|
||||||
|
|
||||||
return mss, nil
|
return mss, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptrace"
|
"net/http/httptrace"
|
||||||
"net/url"
|
"net/url"
|
||||||
reflect "reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"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/finalmask"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion"
|
||||||
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
|
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
"github.com/xtls/xray-core/transport/internet/reality"
|
||||||
@@ -116,20 +117,17 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
|||||||
transportConfig := streamSettings.ProtocolSettings.(*Config)
|
transportConfig := streamSettings.ProtocolSettings.(*Config)
|
||||||
|
|
||||||
dialContext := func(ctxInner context.Context) (net.Conn, error) {
|
dialContext := func(ctxInner context.Context) (net.Conn, error) {
|
||||||
conn, err := internet.DialSystem(ctxInner, dest, streamSettings.SocketSettings)
|
var conn net.Conn
|
||||||
|
var err error
|
||||||
|
if streamSettings.FinalMask != nil {
|
||||||
|
conn, err = streamSettings.FinalMask.DialTCP(ctxInner, dest)
|
||||||
|
} else {
|
||||||
|
conn, err = internet.DialSystem(ctxInner, dest, streamSettings.SocketSettings)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
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)
|
||||||
}
|
}
|
||||||
@@ -196,30 +194,29 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
|
|||||||
TLSClientConfig: gotlsConfig,
|
TLSClientConfig: gotlsConfig,
|
||||||
Dial: func(ctx context.Context, addr string, tlsCfg *gotls.Config, cfg *quic.Config) (*quic.Conn, error) {
|
Dial: func(ctx context.Context, addr string, tlsCfg *gotls.Config, cfg *quic.Config) (*quic.Conn, error) {
|
||||||
var pktConn net.PacketConn
|
var pktConn net.PacketConn
|
||||||
var udpAddr *net.UDPAddr
|
var udpAddr net.Addr
|
||||||
|
if streamSettings.FinalMask != nil {
|
||||||
raw, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
conn, err := streamSettings.FinalMask.DialUDP(ctx, dest)
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to dial to dest").Base(err)
|
|
||||||
}
|
|
||||||
switch c := raw.(type) {
|
|
||||||
case *internet.PacketConnWrapper:
|
|
||||||
pktConn = c.PacketConn
|
|
||||||
udpAddr = raw.RemoteAddr().(*net.UDPAddr)
|
|
||||||
case *cnc.Connection:
|
|
||||||
pktConn = &internet.FakePacketConn{Conn: c}
|
|
||||||
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
|
|
||||||
default:
|
|
||||||
panic(reflect.TypeOf(c))
|
|
||||||
}
|
|
||||||
|
|
||||||
if streamSettings.UdpmaskManager != nil {
|
|
||||||
newConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(pktConn)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pktConn.Close()
|
return nil, errors.New("failed to dial to dest").Base(err)
|
||||||
return nil, errors.New("mask err").Base(err)
|
}
|
||||||
|
pktConn = conn.(*finalmask.PacketConnWrapper).PacketConn
|
||||||
|
udpAddr = conn.RemoteAddr()
|
||||||
|
} else {
|
||||||
|
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to dial to dest").Base(err)
|
||||||
|
}
|
||||||
|
switch c := conn.(type) {
|
||||||
|
case *internet.PacketConnWrapper:
|
||||||
|
pktConn = c.PacketConn
|
||||||
|
udpAddr = c.RemoteAddr()
|
||||||
|
case *cnc.Connection:
|
||||||
|
pktConn = &internet.FakePacketConn{Conn: c}
|
||||||
|
udpAddr = &net.UDPAddr{IP: []byte{0, 0, 0, 0}}
|
||||||
|
default:
|
||||||
|
panic(reflect.TypeOf(c))
|
||||||
}
|
}
|
||||||
pktConn = newConn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tr := &quic.Transport{Conn: pktConn, DisableGSO: quicParams.DisableGSO}
|
tr := &quic.Transport{Conn: pktConn, DisableGSO: quicParams.DisableGSO}
|
||||||
|
|||||||
@@ -463,31 +463,17 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||||||
l.isH3 = len(tlsConfig.NextProtos) == 1 && tlsConfig.NextProtos[0] == "h3"
|
l.isH3 = len(tlsConfig.NextProtos) == 1 && tlsConfig.NextProtos[0] == "h3"
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if port == net.Port(0) { // unix
|
if l.isH3 {
|
||||||
l.listener, err = internet.ListenSystem(ctx, &net.UnixAddr{
|
var pktConn net.PacketConn
|
||||||
Name: address.Domain(),
|
var err error
|
||||||
Net: "unix",
|
if streamSettings.FinalMask != nil {
|
||||||
}, streamSettings.SocketSettings)
|
pktConn, err = streamSettings.FinalMask.ListenPacket(context.Background(), &net.UDPAddr{IP: address.IP(), Port: int(port)})
|
||||||
if err != nil {
|
} else {
|
||||||
return nil, errors.New("failed to listen UNIX domain socket for XHTTP on ", address).Base(err)
|
pktConn, err = internet.ListenSystemPacket(context.Background(), &net.UDPAddr{IP: address.IP(), Port: int(port)}, streamSettings.SocketSettings)
|
||||||
}
|
}
|
||||||
errors.LogInfo(ctx, "listening UNIX domain socket for XHTTP on ", address)
|
|
||||||
} else if l.isH3 { // quic
|
|
||||||
Conn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{
|
|
||||||
IP: address.IP(),
|
|
||||||
Port: int(port),
|
|
||||||
}, streamSettings.SocketSettings)
|
|
||||||
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 {
|
|
||||||
newConn, err := streamSettings.UdpmaskManager.WrapPacketConnServer(Conn)
|
|
||||||
if err != nil {
|
|
||||||
Conn.Close()
|
|
||||||
return nil, errors.New("mask err").Base(err)
|
|
||||||
}
|
|
||||||
Conn = newConn
|
|
||||||
}
|
|
||||||
|
|
||||||
quicParams := streamSettings.QuicParams
|
quicParams := streamSettings.QuicParams
|
||||||
if quicParams == nil {
|
if quicParams == nil {
|
||||||
@@ -512,7 +498,7 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||||||
common.Must2(rand.Read((*k)[:]))
|
common.Must2(rand.Read((*k)[:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
tr := &quic.Transport{Conn: Conn, DisableGSO: quicParams.DisableGSO, StatelessResetKey: k}
|
tr := &quic.Transport{Conn: pktConn, DisableGSO: quicParams.DisableGSO, StatelessResetKey: k}
|
||||||
|
|
||||||
l.h3listener, err = tr.ListenEarly(tlsConfig, quicConfig)
|
l.h3listener, err = tr.ListenEarly(tlsConfig, quicConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -534,21 +520,24 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||||||
errors.LogErrorInner(ctx, err, "failed to serve HTTP/3 for XHTTP/3")
|
errors.LogErrorInner(ctx, err, "failed to serve HTTP/3 for XHTTP/3")
|
||||||
}
|
}
|
||||||
_ = tr.Close()
|
_ = tr.Close()
|
||||||
_ = Conn.Close()
|
_ = pktConn.Close()
|
||||||
}()
|
}()
|
||||||
} else { // tcp
|
} else {
|
||||||
l.listener, err = internet.ListenSystem(ctx, &net.TCPAddr{
|
var addr net.Addr
|
||||||
IP: address.IP(),
|
if port == net.Port(0) { // unix
|
||||||
Port: int(port),
|
addr = &net.UnixAddr{Name: address.Domain(), Net: "unix"}
|
||||||
}, streamSettings.SocketSettings)
|
} else { // tcp
|
||||||
if err != nil {
|
addr = &net.TCPAddr{IP: address.IP(), Port: int(port)}
|
||||||
return nil, errors.New("failed to listen TCP for XHTTP on ", address, ":", port).Base(err)
|
|
||||||
}
|
}
|
||||||
errors.LogInfo(ctx, "listening TCP for XHTTP on ", address, ":", port)
|
if streamSettings.FinalMask != nil {
|
||||||
}
|
l.listener, err = streamSettings.FinalMask.Listen(ctx, addr)
|
||||||
|
} else {
|
||||||
if !l.isH3 && streamSettings.TcpmaskManager != nil {
|
l.listener, err = internet.ListenSystem(ctx, addr, streamSettings.SocketSettings)
|
||||||
l.listener, _ = streamSettings.TcpmaskManager.WrapListener(l.listener)
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to listen ", addr.Network(), " for XHTTP on ", address, ":", port).Base(err)
|
||||||
|
}
|
||||||
|
errors.LogInfo(ctx, "listening ", addr.Network(), " for XHTTP on ", address, ":", port)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tcp/unix (h1/h2)
|
// tcp/unix (h1/h2)
|
||||||
|
|||||||
@@ -235,5 +235,5 @@ 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.UDPAddr{IP: c.Conn.LocalAddr().(*net.TCPAddr).IP, Port: c.Conn.LocalAddr().(*net.TCPAddr).Port}
|
return &net.UDPAddr{IP: []byte{0, 0, 0, 0}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,18 +19,15 @@ import (
|
|||||||
// Dial dials a new TCP connection to the given destination.
|
// Dial dials a new TCP connection to the given destination.
|
||||||
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {
|
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {
|
||||||
errors.LogInfo(ctx, "dialing TCP to ", dest)
|
errors.LogInfo(ctx, "dialing TCP to ", dest)
|
||||||
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
var conn net.Conn
|
||||||
if err != nil {
|
var err error
|
||||||
return nil, err
|
if streamSettings.FinalMask != nil {
|
||||||
|
conn, err = streamSettings.FinalMask.DialTCP(ctx, dest)
|
||||||
|
} else {
|
||||||
|
conn, err = internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
if streamSettings.TcpmaskManager != nil {
|
return nil, errors.New("failed to dial to dest").Base(err)
|
||||||
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 {
|
||||||
|
|||||||
@@ -41,29 +41,21 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSe
|
|||||||
}
|
}
|
||||||
var listener net.Listener
|
var listener net.Listener
|
||||||
var err error
|
var err error
|
||||||
|
var addr net.Addr
|
||||||
if port == net.Port(0) { // unix
|
if port == net.Port(0) { // unix
|
||||||
listener, err = internet.ListenSystem(ctx, &net.UnixAddr{
|
addr = &net.UnixAddr{Name: address.Domain(), Net: "unix"}
|
||||||
Name: address.Domain(),
|
} else { // tcp
|
||||||
Net: "unix",
|
addr = &net.TCPAddr{IP: address.IP(), Port: int(port)}
|
||||||
}, streamSettings.SocketSettings)
|
}
|
||||||
if err != nil {
|
if streamSettings.FinalMask != nil {
|
||||||
return nil, errors.New("failed to listen Unix Domain Socket on ", address).Base(err)
|
listener, err = streamSettings.FinalMask.Listen(ctx, addr)
|
||||||
}
|
|
||||||
errors.LogInfo(ctx, "listening Unix Domain Socket on ", address)
|
|
||||||
} else {
|
} else {
|
||||||
listener, err = internet.ListenSystem(ctx, &net.TCPAddr{
|
listener, err = internet.ListenSystem(ctx, addr, streamSettings.SocketSettings)
|
||||||
IP: address.IP(),
|
|
||||||
Port: int(port),
|
|
||||||
}, streamSettings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to listen TCP on ", address, ":", port).Base(err)
|
|
||||||
}
|
|
||||||
errors.LogInfo(ctx, "listening TCP on ", address, ":", port)
|
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
if streamSettings.TcpmaskManager != nil {
|
return nil, errors.New("failed to listen ", addr.Network(), " on ", address, ":", port).Base(err)
|
||||||
listener, _ = streamSettings.TcpmaskManager.WrapListener(listener)
|
|
||||||
}
|
}
|
||||||
|
errors.LogInfo(ctx, "listening ", addr.Network(), " on ", address, ":", port)
|
||||||
|
|
||||||
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")
|
||||||
|
|||||||
@@ -2,12 +2,9 @@ package udp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"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/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"
|
||||||
)
|
)
|
||||||
@@ -15,40 +12,14 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
common.Must(internet.RegisterTransportDialer(protocolName,
|
common.Must(internet.RegisterTransportDialer(protocolName,
|
||||||
func(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {
|
func(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {
|
||||||
var sockopt *internet.SocketConfig
|
if streamSettings != nil && streamSettings.FinalMask != nil {
|
||||||
if streamSettings != nil {
|
return streamSettings.FinalMask.DialUDP(ctx, dest)
|
||||||
sockopt = streamSettings.SocketSettings
|
} else {
|
||||||
}
|
var sockopt *internet.SocketConfig
|
||||||
conn, err := internet.DialSystem(ctx, dest, sockopt)
|
if streamSettings != nil && streamSettings.SocketSettings != nil {
|
||||||
if err != nil {
|
sockopt = streamSettings.SocketSettings
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if streamSettings != nil && streamSettings.UdpmaskManager != nil {
|
|
||||||
var pktConn net.PacketConn
|
|
||||||
var udpAddr *net.UDPAddr
|
|
||||||
switch c := conn.(type) {
|
|
||||||
case *internet.PacketConnWrapper:
|
|
||||||
pktConn = c.PacketConn
|
|
||||||
udpAddr = c.RemoteAddr().(*net.UDPAddr)
|
|
||||||
case *cnc.Connection:
|
|
||||||
pktConn = &internet.FakePacketConn{Conn: c}
|
|
||||||
udpAddr = &net.UDPAddr{IP: c.RemoteAddr().(*net.TCPAddr).IP, Port: c.RemoteAddr().(*net.TCPAddr).Port}
|
|
||||||
default:
|
|
||||||
panic(reflect.TypeOf(c))
|
|
||||||
}
|
|
||||||
newConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(pktConn)
|
|
||||||
if err != nil {
|
|
||||||
pktConn.Close()
|
|
||||||
return nil, errors.New("mask err").Base(err)
|
|
||||||
}
|
|
||||||
pktConn = newConn
|
|
||||||
conn = &internet.PacketConnWrapper{
|
|
||||||
PacketConn: pktConn,
|
|
||||||
Dest: udpAddr,
|
|
||||||
}
|
}
|
||||||
|
return internet.DialSystem(ctx, dest, sockopt)
|
||||||
}
|
}
|
||||||
|
|
||||||
return conn, nil
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,24 +58,15 @@ func ListenUDP(ctx context.Context, address net.Address, port net.Port, streamSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
hub.conn, err = internet.ListenSystemPacket(ctx, &net.UDPAddr{
|
if streamSettings.FinalMask != nil {
|
||||||
IP: address.IP(),
|
hub.conn, err = streamSettings.FinalMask.ListenPacket(ctx, &net.UDPAddr{IP: address.IP(), Port: int(port)})
|
||||||
Port: int(port),
|
} else {
|
||||||
}, sockopt)
|
hub.conn, err = internet.ListenSystemPacket(ctx, &net.UDPAddr{IP: address.IP(), Port: int(port)}, streamSettings.SocketSettings)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
raw := hub.conn
|
|
||||||
|
|
||||||
if streamSettings.UdpmaskManager != nil {
|
|
||||||
hub.conn, err = streamSettings.UdpmaskManager.WrapPacketConnServer(raw)
|
|
||||||
if err != nil {
|
|
||||||
raw.Close()
|
|
||||||
return nil, errors.New("mask err").Base(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
errors.LogInfo(ctx, "listening UDP on ", address, ":", port)
|
errors.LogInfo(ctx, "listening UDP on ", address, ":", port)
|
||||||
hub.udpConn, _ = hub.conn.(*net.UDPConn)
|
hub.udpConn, _ = hub.conn.(*net.UDPConn)
|
||||||
hub.cache = make(chan *udp.Packet, hub.capacity)
|
hub.cache = make(chan *udp.Packet, hub.capacity)
|
||||||
|
|||||||
@@ -48,20 +48,16 @@ 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) {
|
||||||
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
var conn net.Conn
|
||||||
|
var err error
|
||||||
|
if streamSettings.FinalMask != nil {
|
||||||
|
conn, err = streamSettings.FinalMask.DialTCP(ctx, dest)
|
||||||
|
} else {
|
||||||
|
conn, err = internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.New("failed to dial to dest").Base(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
|
return conn, err
|
||||||
},
|
},
|
||||||
ReadBufferSize: 4 * 1024,
|
ReadBufferSize: 4 * 1024,
|
||||||
@@ -79,19 +75,15 @@ func dialWebSocket(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
if fingerprint := tls.GetFingerprint(tConfig.Fingerprint); fingerprint != nil {
|
if fingerprint := tls.GetFingerprint(tConfig.Fingerprint); fingerprint != nil {
|
||||||
dialer.NetDialTLSContext = func(_ context.Context, _, addr string) (net.Conn, error) {
|
dialer.NetDialTLSContext = func(_ context.Context, _, addr string) (net.Conn, error) {
|
||||||
// Like the NetDial in the dialer
|
// Like the NetDial in the dialer
|
||||||
pconn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
var pconn net.Conn
|
||||||
if err != nil {
|
var err error
|
||||||
errors.LogErrorInner(ctx, err, "failed to dial to "+addr)
|
if streamSettings.FinalMask != nil {
|
||||||
return nil, err
|
pconn, err = streamSettings.FinalMask.DialTCP(ctx, dest)
|
||||||
|
} else {
|
||||||
|
pconn, err = internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
if streamSettings.TcpmaskManager != nil {
|
return nil, errors.New("failed to dial to dest").Base(err)
|
||||||
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
|
||||||
|
|||||||
@@ -97,29 +97,21 @@ func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||||||
}
|
}
|
||||||
var listener net.Listener
|
var listener net.Listener
|
||||||
var err error
|
var err error
|
||||||
|
var addr net.Addr
|
||||||
if port == net.Port(0) { // unix
|
if port == net.Port(0) { // unix
|
||||||
listener, err = internet.ListenSystem(ctx, &net.UnixAddr{
|
addr = &net.UnixAddr{Name: address.Domain(), Net: "unix"}
|
||||||
Name: address.Domain(),
|
|
||||||
Net: "unix",
|
|
||||||
}, streamSettings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to listen unix domain socket(for WS) on ", address).Base(err)
|
|
||||||
}
|
|
||||||
errors.LogInfo(ctx, "listening unix domain socket(for WS) on ", address)
|
|
||||||
} else { // tcp
|
} else { // tcp
|
||||||
listener, err = internet.ListenSystem(ctx, &net.TCPAddr{
|
addr = &net.TCPAddr{IP: address.IP(), Port: int(port)}
|
||||||
IP: address.IP(),
|
|
||||||
Port: int(port),
|
|
||||||
}, streamSettings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to listen TCP(for WS) on ", address, ":", port).Base(err)
|
|
||||||
}
|
|
||||||
errors.LogInfo(ctx, "listening TCP(for WS) on ", address, ":", port)
|
|
||||||
}
|
}
|
||||||
|
if streamSettings.FinalMask != nil {
|
||||||
if streamSettings.TcpmaskManager != nil {
|
listener, err = streamSettings.FinalMask.Listen(ctx, addr)
|
||||||
listener, _ = streamSettings.TcpmaskManager.WrapListener(listener)
|
} else {
|
||||||
|
listener, err = internet.ListenSystem(ctx, addr, streamSettings.SocketSettings)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to listen ", addr.Network(), "(for WS) on ", address, ":", port).Base(err)
|
||||||
|
}
|
||||||
|
errors.LogInfo(ctx, "listening ", addr.Network(), "(for WS) on ", address, ":", port)
|
||||||
|
|
||||||
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")
|
||||||
|
|||||||
@@ -55,17 +55,14 @@ func newServiceClient(streamSettings *internet.MemoryStreamConfig, timeout time.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := internet.DialSystem(ctx, target, sockopt)
|
var conn net.Conn
|
||||||
if err != nil {
|
if streamSettings.FinalMask != nil {
|
||||||
return nil, host, err
|
conn, err = streamSettings.FinalMask.DialTCP(ctx, target)
|
||||||
|
} else {
|
||||||
|
conn, err = internet.DialSystem(ctx, target, sockopt)
|
||||||
}
|
}
|
||||||
if streamSettings != nil && streamSettings.TcpmaskManager != nil {
|
if err != nil {
|
||||||
masked, err := streamSettings.TcpmaskManager.WrapConnClient(conn)
|
return nil, host, errors.New("failed to dial to dest").Base(err)
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, host, errors.New("mask err").Base(err)
|
|
||||||
}
|
|
||||||
conn = masked
|
|
||||||
}
|
}
|
||||||
return conn, host, nil
|
return conn, host, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user