endpoint: Fix UDP resolved destination
This commit is contained in:
@@ -145,3 +145,7 @@ type ParallelNetworkDialer interface {
|
|||||||
DialParallelNetwork(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
|
DialParallelNetwork(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
|
||||||
ListenSerialNetworkPacket(ctx context.Context, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, netip.Addr, error)
|
ListenSerialNetworkPacket(ctx context.Context, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, netip.Addr, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PacketDialerWithDestination interface {
|
||||||
|
ListenPacketWithDestination(ctx context.Context, destination M.Socksaddr) (net.PacketConn, netip.Addr, error)
|
||||||
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
||||||
_ adapter.DirectRouteOutbound = (*Endpoint)(nil)
|
_ adapter.DirectRouteOutbound = (*Endpoint)(nil)
|
||||||
|
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -518,19 +519,7 @@ func (t *Endpoint) DialContext(ctx context.Context, network string, destination
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Endpoint) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (t *Endpoint) listenPacketWithAddress(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
t.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
|
||||||
if destination.IsFqdn() {
|
|
||||||
destinationAddresses, err := t.dnsRouter.Lookup(ctx, destination.Fqdn, adapter.DNSQueryOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
packetConn, _, err := N.ListenSerial(ctx, t, destination, destinationAddresses)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return packetConn, err
|
|
||||||
}
|
|
||||||
addr4, addr6 := t.server.TailscaleIPs()
|
addr4, addr6 := t.server.TailscaleIPs()
|
||||||
bind := tcpip.FullAddress{
|
bind := tcpip.FullAddress{
|
||||||
NIC: 1,
|
NIC: 1,
|
||||||
@@ -556,6 +545,44 @@ func (t *Endpoint) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
|||||||
return udpConn, nil
|
return udpConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Endpoint) ListenPacketWithDestination(ctx context.Context, destination M.Socksaddr) (net.PacketConn, netip.Addr, error) {
|
||||||
|
t.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
||||||
|
if destination.IsFqdn() {
|
||||||
|
destinationAddresses, err := t.dnsRouter.Lookup(ctx, destination.Fqdn, adapter.DNSQueryOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, netip.Addr{}, err
|
||||||
|
}
|
||||||
|
var errors []error
|
||||||
|
for _, address := range destinationAddresses {
|
||||||
|
packetConn, packetErr := t.listenPacketWithAddress(ctx, M.SocksaddrFrom(address, destination.Port))
|
||||||
|
if packetErr == nil {
|
||||||
|
return packetConn, address, nil
|
||||||
|
}
|
||||||
|
errors = append(errors, packetErr)
|
||||||
|
}
|
||||||
|
return nil, netip.Addr{}, E.Errors(errors...)
|
||||||
|
}
|
||||||
|
packetConn, err := t.listenPacketWithAddress(ctx, destination)
|
||||||
|
if err != nil {
|
||||||
|
return nil, netip.Addr{}, err
|
||||||
|
}
|
||||||
|
if destination.IsIP() {
|
||||||
|
return packetConn, destination.Addr, nil
|
||||||
|
}
|
||||||
|
return packetConn, netip.Addr{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Endpoint) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
packetConn, destinationAddress, err := t.ListenPacketWithDestination(ctx, destination)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if destinationAddress.IsValid() && destination != M.SocksaddrFrom(destinationAddress, destination.Port) {
|
||||||
|
return bufio.NewNATPacketConn(bufio.NewPacketConn(packetConn), M.SocksaddrFrom(destinationAddress, destination.Port), destination), nil
|
||||||
|
}
|
||||||
|
return packetConn, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) {
|
func (t *Endpoint) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) {
|
||||||
tsFilter := t.filter.Load()
|
tsFilter := t.filter.Load()
|
||||||
if tsFilter != nil {
|
if tsFilter != nil {
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ import (
|
|||||||
"github.com/sagernet/sing/service"
|
"github.com/sagernet/sing/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
var (
|
||||||
|
_ adapter.OutboundWithPreferredRoutes = (*Endpoint)(nil)
|
||||||
|
_ dialer.PacketDialerWithDestination = (*Endpoint)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
func RegisterEndpoint(registry *endpoint.Registry) {
|
func RegisterEndpoint(registry *endpoint.Registry) {
|
||||||
endpoint.Register[option.WireGuardEndpointOptions](registry, C.TypeWireGuard, NewEndpoint)
|
endpoint.Register[option.WireGuardEndpointOptions](registry, C.TypeWireGuard, NewEndpoint)
|
||||||
@@ -219,20 +222,34 @@ func (w *Endpoint) DialContext(ctx context.Context, network string, destination
|
|||||||
return w.endpoint.DialContext(ctx, network, destination)
|
return w.endpoint.DialContext(ctx, network, destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Endpoint) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (w *Endpoint) ListenPacketWithDestination(ctx context.Context, destination M.Socksaddr) (net.PacketConn, netip.Addr, error) {
|
||||||
w.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
w.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
||||||
if destination.IsFqdn() {
|
if destination.IsFqdn() {
|
||||||
destinationAddresses, err := w.dnsRouter.Lookup(ctx, destination.Fqdn, adapter.DNSQueryOptions{})
|
destinationAddresses, err := w.dnsRouter.Lookup(ctx, destination.Fqdn, adapter.DNSQueryOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, netip.Addr{}, err
|
||||||
}
|
}
|
||||||
packetConn, _, err := N.ListenSerial(ctx, w.endpoint, destination, destinationAddresses)
|
return N.ListenSerial(ctx, w.endpoint, destination, destinationAddresses)
|
||||||
|
}
|
||||||
|
packetConn, err := w.endpoint.ListenPacket(ctx, destination)
|
||||||
|
if err != nil {
|
||||||
|
return nil, netip.Addr{}, err
|
||||||
|
}
|
||||||
|
if destination.IsIP() {
|
||||||
|
return packetConn, destination.Addr, nil
|
||||||
|
}
|
||||||
|
return packetConn, netip.Addr{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Endpoint) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
packetConn, destinationAddress, err := w.ListenPacketWithDestination(ctx, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return packetConn, err
|
if destinationAddress.IsValid() && destination != M.SocksaddrFrom(destinationAddress, destination.Port) {
|
||||||
|
return bufio.NewNATPacketConn(bufio.NewPacketConn(packetConn), M.SocksaddrFrom(destinationAddress, destination.Port), destination), nil
|
||||||
}
|
}
|
||||||
return w.endpoint.ListenPacket(ctx, destination)
|
return packetConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Endpoint) PreferredDomain(domain string) bool {
|
func (w *Endpoint) PreferredDomain(domain string) bool {
|
||||||
|
|||||||
@@ -188,6 +188,8 @@ func (m *ConnectionManager) NewPacketConnection(ctx context.Context, this N.Dial
|
|||||||
} else {
|
} else {
|
||||||
if len(metadata.DestinationAddresses) > 0 {
|
if len(metadata.DestinationAddresses) > 0 {
|
||||||
remotePacketConn, destinationAddress, err = dialer.ListenSerialNetworkPacket(ctx, this, metadata.Destination, metadata.DestinationAddresses, metadata.NetworkStrategy, metadata.NetworkType, metadata.FallbackNetworkType, metadata.FallbackDelay)
|
remotePacketConn, destinationAddress, err = dialer.ListenSerialNetworkPacket(ctx, this, metadata.Destination, metadata.DestinationAddresses, metadata.NetworkStrategy, metadata.NetworkType, metadata.FallbackNetworkType, metadata.FallbackDelay)
|
||||||
|
} else if packetDialer, withDestination := this.(dialer.PacketDialerWithDestination); withDestination {
|
||||||
|
remotePacketConn, destinationAddress, err = packetDialer.ListenPacketWithDestination(ctx, metadata.Destination)
|
||||||
} else {
|
} else {
|
||||||
remotePacketConn, err = this.ListenPacket(ctx, metadata.Destination)
|
remotePacketConn, err = this.ListenPacket(ctx, metadata.Destination)
|
||||||
}
|
}
|
||||||
@@ -218,11 +220,16 @@ func (m *ConnectionManager) NewPacketConnection(ctx context.Context, this N.Dial
|
|||||||
}
|
}
|
||||||
if natConn, loaded := common.Cast[bufio.NATPacketConn](conn); loaded {
|
if natConn, loaded := common.Cast[bufio.NATPacketConn](conn); loaded {
|
||||||
natConn.UpdateDestination(destinationAddress)
|
natConn.UpdateDestination(destinationAddress)
|
||||||
} else if metadata.Destination != M.SocksaddrFrom(destinationAddress, metadata.Destination.Port) {
|
|
||||||
if metadata.UDPDisableDomainUnmapping {
|
|
||||||
remotePacketConn = bufio.NewUnidirectionalNATPacketConn(bufio.NewPacketConn(remotePacketConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), originDestination)
|
|
||||||
} else {
|
} else {
|
||||||
remotePacketConn = bufio.NewNATPacketConn(bufio.NewPacketConn(remotePacketConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), originDestination)
|
destination := M.SocksaddrFrom(destinationAddress, metadata.Destination.Port)
|
||||||
|
if metadata.Destination != destination {
|
||||||
|
if metadata.UDPDisableDomainUnmapping {
|
||||||
|
remotePacketConn = bufio.NewUnidirectionalNATPacketConn(bufio.NewPacketConn(remotePacketConn), destination, originDestination)
|
||||||
|
} else {
|
||||||
|
remotePacketConn = bufio.NewNATPacketConn(bufio.NewPacketConn(remotePacketConn), destination, originDestination)
|
||||||
|
}
|
||||||
|
} else if metadata.RouteOriginalDestination.IsValid() && metadata.RouteOriginalDestination != metadata.Destination {
|
||||||
|
remotePacketConn = bufio.NewDestinationNATPacketConn(bufio.NewPacketConn(remotePacketConn), metadata.Destination, metadata.RouteOriginalDestination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if metadata.RouteOriginalDestination.IsValid() && metadata.RouteOriginalDestination != metadata.Destination {
|
} else if metadata.RouteOriginalDestination.IsValid() && metadata.RouteOriginalDestination != metadata.Destination {
|
||||||
|
|||||||
Reference in New Issue
Block a user