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