mirror of
				https://github.com/optim-enterprises-bv/Xray-core.git
				synced 2025-10-30 18:18:04 +00:00 
			
		
		
		
	 498d8eb3cc
			
		
	
	498d8eb3cc
	
	
	
		
			
			* wip * wip * formatting * cnc connection no longer needs to be a Packetconn * dialerProxy: do not cancel connection when Dial context is cancelled
		
			
				
	
	
		
			251 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			251 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package internet
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"math/rand"
 | |
| 	"syscall"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/sagernet/sing/common/control"
 | |
| 	"github.com/xtls/xray-core/common/errors"
 | |
| 	"github.com/xtls/xray-core/common/net"
 | |
| 	"github.com/xtls/xray-core/features/dns"
 | |
| 	"github.com/xtls/xray-core/features/outbound"
 | |
| )
 | |
| 
 | |
| var effectiveSystemDialer SystemDialer = &DefaultSystemDialer{}
 | |
| 
 | |
| type SystemDialer interface {
 | |
| 	Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *SocketConfig) (net.Conn, error)
 | |
| 	DestIpAddress() net.IP
 | |
| }
 | |
| 
 | |
| type DefaultSystemDialer struct {
 | |
| 	controllers []control.Func
 | |
| 	dns         dns.Client
 | |
| 	obm         outbound.Manager
 | |
| }
 | |
| 
 | |
| func resolveSrcAddr(network net.Network, src net.Address) net.Addr {
 | |
| 	if src == nil || src == net.AnyIP {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	if network == net.Network_TCP {
 | |
| 		return &net.TCPAddr{
 | |
| 			IP:   src.IP(),
 | |
| 			Port: 0,
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return &net.UDPAddr{
 | |
| 		IP:   src.IP(),
 | |
| 		Port: 0,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func hasBindAddr(sockopt *SocketConfig) bool {
 | |
| 	return sockopt != nil && len(sockopt.BindAddress) > 0 && sockopt.BindPort > 0
 | |
| }
 | |
| 
 | |
| func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
 | |
| 	errors.LogDebug(ctx, "dialing to "+dest.String())
 | |
| 
 | |
| 	if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) {
 | |
| 		srcAddr := resolveSrcAddr(net.Network_UDP, src)
 | |
| 		if srcAddr == nil {
 | |
| 			srcAddr = &net.UDPAddr{
 | |
| 				IP:   []byte{0, 0, 0, 0},
 | |
| 				Port: 0,
 | |
| 			}
 | |
| 		}
 | |
| 		packetConn, err := ListenSystemPacket(ctx, srcAddr, sockopt)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		destAddr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if sockopt != nil {
 | |
| 			sys, err := packetConn.(*net.UDPConn).SyscallConn()
 | |
| 			if err != nil {
 | |
| 				return nil, err
 | |
| 			}
 | |
| 			sys.Control(func(fd uintptr) {
 | |
| 				if err := applyOutboundSocketOptions("udp", dest.NetAddr(), fd, sockopt); err != nil {
 | |
| 					errors.LogInfo(ctx, err, "failed to apply socket options")
 | |
| 				}
 | |
| 			})
 | |
| 		}
 | |
| 		return &PacketConnWrapper{
 | |
| 			Conn: packetConn,
 | |
| 			Dest: destAddr,
 | |
| 		}, nil
 | |
| 	}
 | |
| 	goStdKeepAlive := time.Duration(0)
 | |
| 	if sockopt != nil && (sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0) {
 | |
| 		goStdKeepAlive = time.Duration(-1)
 | |
| 	}
 | |
| 	dialer := &net.Dialer{
 | |
| 		Timeout:   time.Second * 16,
 | |
| 		LocalAddr: resolveSrcAddr(dest.Network, src),
 | |
| 		KeepAlive: goStdKeepAlive,
 | |
| 	}
 | |
| 
 | |
| 	if sockopt != nil || len(d.controllers) > 0 {
 | |
| 		if sockopt != nil && sockopt.TcpMptcp {
 | |
| 			dialer.SetMultipathTCP(true)
 | |
| 		}
 | |
| 		dialer.Control = func(network, address string, c syscall.RawConn) error {
 | |
| 			for _, ctl := range d.controllers {
 | |
| 				if err := ctl(network, address, c); err != nil {
 | |
| 					errors.LogInfoInner(ctx, err, "failed to apply external controller")
 | |
| 				}
 | |
| 			}
 | |
| 			return c.Control(func(fd uintptr) {
 | |
| 				if sockopt != nil {
 | |
| 					if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil {
 | |
| 						errors.LogInfoInner(ctx, err, "failed to apply socket options")
 | |
| 					}
 | |
| 					if dest.Network == net.Network_UDP && hasBindAddr(sockopt) {
 | |
| 						if err := bindAddr(fd, sockopt.BindAddress, sockopt.BindPort); err != nil {
 | |
| 							errors.LogInfoInner(ctx, err, "failed to bind source address to ", sockopt.BindAddress)
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 			})
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr())
 | |
| }
 | |
| 
 | |
| func (d *DefaultSystemDialer) DestIpAddress() net.IP {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| type PacketConnWrapper struct {
 | |
| 	Conn net.PacketConn
 | |
| 	Dest net.Addr
 | |
| }
 | |
| 
 | |
| func (c *PacketConnWrapper) Close() error {
 | |
| 	return c.Conn.Close()
 | |
| }
 | |
| 
 | |
| func (c *PacketConnWrapper) LocalAddr() net.Addr {
 | |
| 	return c.Conn.LocalAddr()
 | |
| }
 | |
| 
 | |
| func (c *PacketConnWrapper) RemoteAddr() net.Addr {
 | |
| 	return c.Dest
 | |
| }
 | |
| 
 | |
| func (c *PacketConnWrapper) Write(p []byte) (int, error) {
 | |
| 	return c.Conn.WriteTo(p, c.Dest)
 | |
| }
 | |
| 
 | |
| func (c *PacketConnWrapper) Read(p []byte) (int, error) {
 | |
| 	n, _, err := c.Conn.ReadFrom(p)
 | |
| 	return n, err
 | |
| }
 | |
| 
 | |
| func (c *PacketConnWrapper) WriteTo(p []byte, d net.Addr) (int, error) {
 | |
| 	return c.Conn.WriteTo(p, d)
 | |
| }
 | |
| 
 | |
| func (c *PacketConnWrapper) ReadFrom(p []byte) (int, net.Addr, error) {
 | |
| 	return c.Conn.ReadFrom(p)
 | |
| }
 | |
| 
 | |
| func (c *PacketConnWrapper) SetDeadline(t time.Time) error {
 | |
| 	return c.Conn.SetDeadline(t)
 | |
| }
 | |
| 
 | |
| func (c *PacketConnWrapper) SetReadDeadline(t time.Time) error {
 | |
| 	return c.Conn.SetReadDeadline(t)
 | |
| }
 | |
| 
 | |
| func (c *PacketConnWrapper) SetWriteDeadline(t time.Time) error {
 | |
| 	return c.Conn.SetWriteDeadline(t)
 | |
| }
 | |
| 
 | |
| type SystemDialerAdapter interface {
 | |
| 	Dial(network string, address string) (net.Conn, error)
 | |
| }
 | |
| 
 | |
| type SimpleSystemDialer struct {
 | |
| 	adapter SystemDialerAdapter
 | |
| }
 | |
| 
 | |
| func WithAdapter(dialer SystemDialerAdapter) SystemDialer {
 | |
| 	return &SimpleSystemDialer{
 | |
| 		adapter: dialer,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (v *SimpleSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
 | |
| 	return v.adapter.Dial(dest.Network.SystemString(), dest.NetAddr())
 | |
| }
 | |
| 
 | |
| func (d *SimpleSystemDialer) DestIpAddress() net.IP {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // UseAlternativeSystemDialer replaces the current system dialer with a given one.
 | |
| // Caller must ensure there is no race condition.
 | |
| //
 | |
| // xray:api:stable
 | |
| func UseAlternativeSystemDialer(dialer SystemDialer) {
 | |
| 	if dialer == nil {
 | |
| 		dialer = &DefaultSystemDialer{}
 | |
| 	}
 | |
| 	effectiveSystemDialer = dialer
 | |
| }
 | |
| 
 | |
| // RegisterDialerController adds a controller to the effective system dialer.
 | |
| // The controller can be used to operate on file descriptors before they are put into use.
 | |
| // It only works when effective dialer is the default dialer.
 | |
| //
 | |
| // xray:api:beta
 | |
| func RegisterDialerController(ctl control.Func) error {
 | |
| 	if ctl == nil {
 | |
| 		return errors.New("nil listener controller")
 | |
| 	}
 | |
| 
 | |
| 	dialer, ok := effectiveSystemDialer.(*DefaultSystemDialer)
 | |
| 	if !ok {
 | |
| 		return errors.New("RegisterListenerController not supported in custom dialer")
 | |
| 	}
 | |
| 
 | |
| 	dialer.controllers = append(dialer.controllers, ctl)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| type FakePacketConn struct {
 | |
| 	net.Conn
 | |
| }
 | |
| 
 | |
| func (c *FakePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
 | |
| 	n, err = c.Read(p)
 | |
| 	return n, c.RemoteAddr(), err
 | |
| }
 | |
| 
 | |
| func (c *FakePacketConn) WriteTo(p []byte, _ net.Addr) (n int, err error) {
 | |
| 	return c.Write(p)
 | |
| }
 | |
| 
 | |
| func (c *FakePacketConn) LocalAddr() net.Addr {
 | |
| 	return &net.TCPAddr{
 | |
| 		IP:   net.IP{byte(rand.Intn(256)), byte(rand.Intn(256)), byte(rand.Intn(256)), byte(rand.Intn(256))},
 | |
| 		Port: rand.Intn(65536),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (c *FakePacketConn) SetReadBuffer(bytes int) error {
 | |
| 	// do nothing, this function is only there to suppress quic-go printing
 | |
| 	// random warnings about UDP buffers to stdout
 | |
| 	return nil
 | |
| }
 |