mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 19:29:57 +00:00
TUN-6741: ICMP proxy tries to listen on specific IPv4 & IPv6 when possible
If it cannot determine the correct interface IP, it will fallback to all interfaces. This commit also introduces the icmpv4-src and icmpv6-src flags
This commit is contained in:
@@ -2,18 +2,11 @@ package packet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var (
|
||||
// Source IP in documentation range to return ICMP error messages if we can't determine the IP of this machine
|
||||
icmpv4ErrFallbackSrc = netip.MustParseAddr("192.0.2.30")
|
||||
icmpv6ErrFallbackSrc = netip.MustParseAddr("2001:db8::")
|
||||
)
|
||||
|
||||
// ICMPRouter sends ICMP messages and listens for their responses
|
||||
type ICMPRouter interface {
|
||||
// Serve starts listening for responses to the requests until context is done
|
||||
@@ -28,32 +21,31 @@ type Upstream interface {
|
||||
ReceivePacket(ctx context.Context) (RawPacket, error)
|
||||
}
|
||||
|
||||
// Router routes packets between Upstream and ICMPRouter. Currently it rejects all other type of ICMP packets
|
||||
type Router struct {
|
||||
upstream Upstream
|
||||
returnPipe FunnelUniPipe
|
||||
icmpProxy ICMPRouter
|
||||
icmpRouter ICMPRouter
|
||||
ipv4Src netip.Addr
|
||||
ipv6Src netip.Addr
|
||||
logger *zerolog.Logger
|
||||
}
|
||||
|
||||
func NewRouter(upstream Upstream, returnPipe FunnelUniPipe, icmpProxy ICMPRouter, logger *zerolog.Logger) *Router {
|
||||
ipv4Src, err := findLocalAddr(net.ParseIP("1.1.1.1"), 53)
|
||||
if err != nil {
|
||||
logger.Warn().Err(err).Msgf("Failed to determine the IPv4 for this machine. It will use %s as source IP for error messages such as ICMP TTL exceed", icmpv4ErrFallbackSrc)
|
||||
ipv4Src = icmpv4ErrFallbackSrc
|
||||
}
|
||||
ipv6Src, err := findLocalAddr(net.ParseIP("2606:4700:4700::1111"), 53)
|
||||
if err != nil {
|
||||
logger.Warn().Err(err).Msgf("Failed to determine the IPv6 for this machine. It will use %s as source IP for error messages such as ICMP TTL exceed", icmpv6ErrFallbackSrc)
|
||||
ipv6Src = icmpv6ErrFallbackSrc
|
||||
}
|
||||
// GlobalRouterConfig is the configuration shared by all instance of Router.
|
||||
type GlobalRouterConfig struct {
|
||||
ICMPRouter ICMPRouter
|
||||
IPv4Src netip.Addr
|
||||
IPv6Src netip.Addr
|
||||
Zone string
|
||||
}
|
||||
|
||||
func NewRouter(globalConfig *GlobalRouterConfig, upstream Upstream, returnPipe FunnelUniPipe, logger *zerolog.Logger) *Router {
|
||||
return &Router{
|
||||
upstream: upstream,
|
||||
returnPipe: returnPipe,
|
||||
icmpProxy: icmpProxy,
|
||||
ipv4Src: ipv4Src,
|
||||
ipv6Src: ipv6Src,
|
||||
icmpRouter: globalConfig.ICMPRouter,
|
||||
ipv4Src: globalConfig.IPv4Src,
|
||||
ipv6Src: globalConfig.IPv6Src,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
@@ -80,7 +72,7 @@ func (r *Router) Serve(ctx context.Context) error {
|
||||
}
|
||||
icmpPacket.TTL--
|
||||
|
||||
if err := r.icmpProxy.Request(icmpPacket, r.returnPipe); err != nil {
|
||||
if err := r.icmpRouter.Request(icmpPacket, r.returnPipe); err != nil {
|
||||
r.logger.Err(err).
|
||||
Str("src", icmpPacket.Src.String()).
|
||||
Str("dst", icmpPacket.Dst.String()).
|
||||
@@ -106,21 +98,3 @@ func (r *Router) sendTTLExceedMsg(pk *ICMP, rawPacket RawPacket, encoder *Encode
|
||||
}
|
||||
return r.returnPipe.SendPacket(pk.Src, encodedTTLExceed)
|
||||
}
|
||||
|
||||
// findLocalAddr tries to dial UDP and returns the local address picked by the OS
|
||||
func findLocalAddr(dst net.IP, port int) (netip.Addr, error) {
|
||||
udpConn, err := net.DialUDP("udp", nil, &net.UDPAddr{
|
||||
IP: dst,
|
||||
Port: port,
|
||||
})
|
||||
if err != nil {
|
||||
return netip.Addr{}, err
|
||||
}
|
||||
defer udpConn.Close()
|
||||
localAddrPort, err := netip.ParseAddrPort(udpConn.LocalAddr().String())
|
||||
if err != nil {
|
||||
return netip.Addr{}, err
|
||||
}
|
||||
localAddr := localAddrPort.Addr()
|
||||
return localAddr, nil
|
||||
}
|
||||
|
@@ -26,7 +26,12 @@ func TestRouterReturnTTLExceed(t *testing.T) {
|
||||
returnPipe := &mockFunnelUniPipe{
|
||||
uniPipe: make(chan RawPacket),
|
||||
}
|
||||
router := NewRouter(upstream, returnPipe, &mockICMPRouter{}, &noopLogger)
|
||||
packetConfig := &GlobalRouterConfig{
|
||||
ICMPRouter: &mockICMPRouter{},
|
||||
IPv4Src: netip.MustParseAddr("172.16.0.1"),
|
||||
IPv6Src: netip.MustParseAddr("fd51:2391:523:f4ee::1"),
|
||||
}
|
||||
router := NewRouter(packetConfig, upstream, returnPipe, &noopLogger)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
routerStopped := make(chan struct{})
|
||||
go func() {
|
||||
|
Reference in New Issue
Block a user