github.com/moqsien/xraycore@v1.8.5/transport/internet/system_dialer.go (about) 1 package internet 2 3 import ( 4 "context" 5 "syscall" 6 "time" 7 8 "github.com/sagernet/sing/common/control" 9 "github.com/moqsien/xraycore/common/net" 10 "github.com/moqsien/xraycore/common/session" 11 "github.com/moqsien/xraycore/features/dns" 12 "github.com/moqsien/xraycore/features/outbound" 13 ) 14 15 var effectiveSystemDialer SystemDialer = &DefaultSystemDialer{} 16 17 type SystemDialer interface { 18 Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *SocketConfig) (net.Conn, error) 19 } 20 21 type DefaultSystemDialer struct { 22 controllers []control.Func 23 dns dns.Client 24 obm outbound.Manager 25 } 26 27 func resolveSrcAddr(network net.Network, src net.Address) net.Addr { 28 if src == nil || src == net.AnyIP { 29 return nil 30 } 31 32 if network == net.Network_TCP { 33 return &net.TCPAddr{ 34 IP: src.IP(), 35 Port: 0, 36 } 37 } 38 39 return &net.UDPAddr{ 40 IP: src.IP(), 41 Port: 0, 42 } 43 } 44 45 func hasBindAddr(sockopt *SocketConfig) bool { 46 return sockopt != nil && len(sockopt.BindAddress) > 0 && sockopt.BindPort > 0 47 } 48 49 func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { 50 newError("dialing to " + dest.String()).AtDebug().WriteToLog() 51 52 if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) { 53 srcAddr := resolveSrcAddr(net.Network_UDP, src) 54 if srcAddr == nil { 55 srcAddr = &net.UDPAddr{ 56 IP: []byte{0, 0, 0, 0}, 57 Port: 0, 58 } 59 } 60 packetConn, err := ListenSystemPacket(ctx, srcAddr, sockopt) 61 if err != nil { 62 return nil, err 63 } 64 destAddr, err := net.ResolveUDPAddr("udp", dest.NetAddr()) 65 if err != nil { 66 return nil, err 67 } 68 return &PacketConnWrapper{ 69 Conn: packetConn, 70 Dest: destAddr, 71 }, nil 72 } 73 goStdKeepAlive := time.Duration(0) 74 if sockopt != nil && (sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0) { 75 goStdKeepAlive = time.Duration(-1) 76 } 77 dialer := &net.Dialer{ 78 Timeout: time.Second * 16, 79 LocalAddr: resolveSrcAddr(dest.Network, src), 80 KeepAlive: goStdKeepAlive, 81 } 82 83 if sockopt != nil || len(d.controllers) > 0 { 84 dialer.Control = func(network, address string, c syscall.RawConn) error { 85 for _, ctl := range d.controllers { 86 if err := ctl(network, address, c); err != nil { 87 newError("failed to apply external controller").Base(err).WriteToLog(session.ExportIDToError(ctx)) 88 } 89 } 90 return c.Control(func(fd uintptr) { 91 if sockopt != nil { 92 if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil { 93 newError("failed to apply socket options").Base(err).WriteToLog(session.ExportIDToError(ctx)) 94 } 95 if dest.Network == net.Network_UDP && hasBindAddr(sockopt) { 96 if err := bindAddr(fd, sockopt.BindAddress, sockopt.BindPort); err != nil { 97 newError("failed to bind source address to ", sockopt.BindAddress).Base(err).WriteToLog(session.ExportIDToError(ctx)) 98 } 99 } 100 } 101 }) 102 } 103 } 104 105 return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr()) 106 } 107 108 type PacketConnWrapper struct { 109 Conn net.PacketConn 110 Dest net.Addr 111 } 112 113 func (c *PacketConnWrapper) Close() error { 114 return c.Conn.Close() 115 } 116 117 func (c *PacketConnWrapper) LocalAddr() net.Addr { 118 return c.Conn.LocalAddr() 119 } 120 121 func (c *PacketConnWrapper) RemoteAddr() net.Addr { 122 return c.Dest 123 } 124 125 func (c *PacketConnWrapper) Write(p []byte) (int, error) { 126 return c.Conn.WriteTo(p, c.Dest) 127 } 128 129 func (c *PacketConnWrapper) Read(p []byte) (int, error) { 130 n, _, err := c.Conn.ReadFrom(p) 131 return n, err 132 } 133 134 func (c *PacketConnWrapper) WriteTo(p []byte, d net.Addr) (int, error) { 135 return c.Conn.WriteTo(p, d) 136 } 137 138 func (c *PacketConnWrapper) ReadFrom(p []byte) (int, net.Addr, error) { 139 return c.Conn.ReadFrom(p) 140 } 141 142 func (c *PacketConnWrapper) SetDeadline(t time.Time) error { 143 return c.Conn.SetDeadline(t) 144 } 145 146 func (c *PacketConnWrapper) SetReadDeadline(t time.Time) error { 147 return c.Conn.SetReadDeadline(t) 148 } 149 150 func (c *PacketConnWrapper) SetWriteDeadline(t time.Time) error { 151 return c.Conn.SetWriteDeadline(t) 152 } 153 154 type SystemDialerAdapter interface { 155 Dial(network string, address string) (net.Conn, error) 156 } 157 158 type SimpleSystemDialer struct { 159 adapter SystemDialerAdapter 160 } 161 162 func WithAdapter(dialer SystemDialerAdapter) SystemDialer { 163 return &SimpleSystemDialer{ 164 adapter: dialer, 165 } 166 } 167 168 func (v *SimpleSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { 169 return v.adapter.Dial(dest.Network.SystemString(), dest.NetAddr()) 170 } 171 172 // UseAlternativeSystemDialer replaces the current system dialer with a given one. 173 // Caller must ensure there is no race condition. 174 // 175 // xray:api:stable 176 func UseAlternativeSystemDialer(dialer SystemDialer) { 177 if dialer == nil { 178 dialer = &DefaultSystemDialer{} 179 } 180 effectiveSystemDialer = dialer 181 } 182 183 // RegisterDialerController adds a controller to the effective system dialer. 184 // The controller can be used to operate on file descriptors before they are put into use. 185 // It only works when effective dialer is the default dialer. 186 // 187 // xray:api:beta 188 func RegisterDialerController(ctl control.Func) error { 189 if ctl == nil { 190 return newError("nil listener controller") 191 } 192 193 dialer, ok := effectiveSystemDialer.(*DefaultSystemDialer) 194 if !ok { 195 return newError("RegisterListenerController not supported in custom dialer") 196 } 197 198 dialer.controllers = append(dialer.controllers, ctl) 199 return nil 200 }