mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 16:19:57 +00:00

Introduces a new `UDPOriginProxy` interface and `UDPOriginService` to standardize how UDP connections are dialed to origins. Allows for future overrides of the ingress service for specific dial destinations. Simplifies dependency injection for UDP dialing throughout both datagram v2 and v3 by using the same ingress service. Previous invocations called into a DialUDP function in the ingress package that was a light wrapper over `net.DialUDP`. Now a reference is passed into both datagram controllers that allows more control over the DialUDP method. Closes TUN-9469
67 lines
2.0 KiB
Go
67 lines
2.0 KiB
Go
package ingress
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"net/netip"
|
|
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
// UDPOriginService provides a proxy UDP dialer to origin services while allowing reserved
|
|
// services to be provided. These reserved services are assigned to specific [netip.AddrPort]s
|
|
// and provide their own [UDPOriginProxy]s to handle UDP origin dialing.
|
|
type UDPOriginService struct {
|
|
// Reserved services for reserved AddrPort values
|
|
reservedServices map[netip.AddrPort]UDPOriginProxy
|
|
// The default UDP Dialer used if no reserved services are found for an origin request.
|
|
defaultDialer UDPOriginProxy
|
|
|
|
logger *zerolog.Logger
|
|
}
|
|
|
|
// UDPOriginProxy provides a UDP dial operation to a requested addr.
|
|
type UDPOriginProxy interface {
|
|
DialUDP(addr netip.AddrPort) (*net.UDPConn, error)
|
|
}
|
|
|
|
func NewUDPOriginService(reserved map[netip.AddrPort]UDPOriginProxy, logger *zerolog.Logger) *UDPOriginService {
|
|
return &UDPOriginService{
|
|
reservedServices: reserved,
|
|
defaultDialer: DefaultUDPDialer,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// SetUDPDialer updates the default UDP Dialer used.
|
|
// Typically used in unit testing.
|
|
func (s *UDPOriginService) SetDefaultDialer(dialer UDPOriginProxy) {
|
|
s.defaultDialer = dialer
|
|
}
|
|
|
|
// DialUDP will perform a dial UDP to the requested addr.
|
|
func (s *UDPOriginService) DialUDP(addr netip.AddrPort) (*net.UDPConn, error) {
|
|
// Check to see if any reserved services are available for this addr and call their dialer instead.
|
|
if dialer, ok := s.reservedServices[addr]; ok {
|
|
return dialer.DialUDP(addr)
|
|
}
|
|
return s.defaultDialer.DialUDP(addr)
|
|
}
|
|
|
|
type defaultUDPDialer struct{}
|
|
|
|
var DefaultUDPDialer UDPOriginProxy = &defaultUDPDialer{}
|
|
|
|
func (d *defaultUDPDialer) DialUDP(dest netip.AddrPort) (*net.UDPConn, error) {
|
|
addr := net.UDPAddrFromAddrPort(dest)
|
|
|
|
// We use nil as local addr to force runtime to find the best suitable local address IP given the destination
|
|
// address as context.
|
|
udpConn, err := net.DialUDP("udp", nil, addr)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to dial udp to origin %s: %w", dest, err)
|
|
}
|
|
|
|
return udpConn, nil
|
|
}
|