github.com/xraypb/Xray-core@v1.8.1/transport/internet/system_dialer.go (about) 1 package internet 2 3 import ( 4 "context" 5 "syscall" 6 "time" 7 8 "github.com/xraypb/Xray-core/common/net" 9 "github.com/xraypb/Xray-core/common/session" 10 "github.com/xraypb/Xray-core/features/dns" 11 "github.com/xraypb/Xray-core/features/outbound" 12 ) 13 14 var effectiveSystemDialer SystemDialer = &DefaultSystemDialer{} 15 16 type SystemDialer interface { 17 Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *SocketConfig) (net.Conn, error) 18 } 19 20 type DefaultSystemDialer struct { 21 controllers []controller 22 dns dns.Client 23 obm outbound.Manager 24 } 25 26 func resolveSrcAddr(network net.Network, src net.Address) net.Addr { 27 if src == nil || src == net.AnyIP { 28 return nil 29 } 30 31 if network == net.Network_TCP { 32 return &net.TCPAddr{ 33 IP: src.IP(), 34 Port: 0, 35 } 36 } 37 38 return &net.UDPAddr{ 39 IP: src.IP(), 40 Port: 0, 41 } 42 } 43 44 func hasBindAddr(sockopt *SocketConfig) bool { 45 return sockopt != nil && len(sockopt.BindAddress) > 0 && sockopt.BindPort > 0 46 } 47 48 func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { 49 newError("dialing to " + dest.String()).AtDebug().WriteToLog() 50 51 if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) { 52 srcAddr := resolveSrcAddr(net.Network_UDP, src) 53 if srcAddr == nil { 54 srcAddr = &net.UDPAddr{ 55 IP: []byte{0, 0, 0, 0}, 56 Port: 0, 57 } 58 } 59 packetConn, err := ListenSystemPacket(ctx, srcAddr, sockopt) 60 if err != nil { 61 return nil, err 62 } 63 destAddr, err := net.ResolveUDPAddr("udp", dest.NetAddr()) 64 if err != nil { 65 return nil, err 66 } 67 return &PacketConnWrapper{ 68 Conn: packetConn, 69 Dest: destAddr, 70 }, nil 71 } 72 goStdKeepAlive := time.Duration(0) 73 if sockopt != nil && (sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0) { 74 goStdKeepAlive = time.Duration(-1) 75 } 76 dialer := &net.Dialer{ 77 Timeout: time.Second * 16, 78 LocalAddr: resolveSrcAddr(dest.Network, src), 79 KeepAlive: goStdKeepAlive, 80 } 81 82 if sockopt != nil || len(d.controllers) > 0 { 83 dialer.Control = func(network, address string, c syscall.RawConn) error { 84 return c.Control(func(fd uintptr) { 85 if sockopt != nil { 86 if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil { 87 newError("failed to apply socket options").Base(err).WriteToLog(session.ExportIDToError(ctx)) 88 } 89 if dest.Network == net.Network_UDP && hasBindAddr(sockopt) { 90 if err := bindAddr(fd, sockopt.BindAddress, sockopt.BindPort); err != nil { 91 newError("failed to bind source address to ", sockopt.BindAddress).Base(err).WriteToLog(session.ExportIDToError(ctx)) 92 } 93 } 94 } 95 96 for _, ctl := range d.controllers { 97 if err := ctl(network, address, fd); err != nil { 98 newError("failed to apply external controller").Base(err).WriteToLog(session.ExportIDToError(ctx)) 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 func(network, address string, fd uintptr) error) 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 }