diff --git a/cmd/cloudflared/tunnel/cmd.go b/cmd/cloudflared/tunnel/cmd.go index db1cb5af..52b75fc9 100644 --- a/cmd/cloudflared/tunnel/cmd.go +++ b/cmd/cloudflared/tunnel/cmd.go @@ -552,6 +552,13 @@ func StartServer( tracker := tunnelstate.NewConnTracker(log) observer.RegisterSink(tracker) + ipv4, ipv6, err := determineICMPSources(c, log) + sources := make([]string, 0) + if err == nil { + sources = append(sources, ipv4.String()) + sources = append(sources, ipv6.String()) + } + readinessServer := metrics.NewReadyServer(clientID, tracker) diagnosticHandler := diagnostic.NewDiagnosticHandler( log, @@ -562,6 +569,7 @@ func StartServer( tracker, c, nonSecretFlagsList, + sources, ) metricsConfig := metrics.Config{ ReadyServer: readinessServer, diff --git a/cmd/cloudflared/tunnel/configuration.go b/cmd/cloudflared/tunnel/configuration.go index 4e06fc0b..e04a1c76 100644 --- a/cmd/cloudflared/tunnel/configuration.go +++ b/cmd/cloudflared/tunnel/configuration.go @@ -352,20 +352,9 @@ func adjustIPVersionByBindAddress(ipVersion allregions.ConfigIPVersion, ip net.I } func newICMPRouter(c *cli.Context, logger *zerolog.Logger) (ingress.ICMPRouterServer, error) { - ipv4Src, err := determineICMPv4Src(c.String("icmpv4-src"), logger) + ipv4Src, ipv6Src, err := determineICMPSources(c, logger) if err != nil { - return nil, errors.Wrap(err, "failed to determine IPv4 source address for ICMP proxy") - } - logger.Info().Msgf("ICMP proxy will use %s as source for IPv4", ipv4Src) - - ipv6Src, zone, err := determineICMPv6Src(c.String("icmpv6-src"), logger, ipv4Src) - if err != nil { - return nil, errors.Wrap(err, "failed to determine IPv6 source address for ICMP proxy") - } - if zone != "" { - logger.Info().Msgf("ICMP proxy will use %s in zone %s as source for IPv6", ipv6Src, zone) - } else { - logger.Info().Msgf("ICMP proxy will use %s as source for IPv6", ipv6Src) + return nil, err } icmpRouter, err := ingress.NewICMPRouter(ipv4Src, ipv6Src, logger, icmpFunnelTimeout) @@ -375,6 +364,28 @@ func newICMPRouter(c *cli.Context, logger *zerolog.Logger) (ingress.ICMPRouterSe return icmpRouter, nil } +func determineICMPSources(c *cli.Context, logger *zerolog.Logger) (netip.Addr, netip.Addr, error) { + ipv4Src, err := determineICMPv4Src(c.String("icmpv4-src"), logger) + if err != nil { + return netip.Addr{}, netip.Addr{}, errors.Wrap(err, "failed to determine IPv4 source address for ICMP proxy") + } + + logger.Info().Msgf("ICMP proxy will use %s as source for IPv4", ipv4Src) + + ipv6Src, zone, err := determineICMPv6Src(c.String("icmpv6-src"), logger, ipv4Src) + if err != nil { + return netip.Addr{}, netip.Addr{}, errors.Wrap(err, "failed to determine IPv6 source address for ICMP proxy") + } + + if zone != "" { + logger.Info().Msgf("ICMP proxy will use %s in zone %s as source for IPv6", ipv6Src, zone) + } else { + logger.Info().Msgf("ICMP proxy will use %s as source for IPv6", ipv6Src) + } + + return ipv4Src, ipv6Src, nil +} + func determineICMPv4Src(userDefinedSrc string, logger *zerolog.Logger) (netip.Addr, error) { if userDefinedSrc != "" { addr, err := netip.ParseAddr(userDefinedSrc) diff --git a/diagnostic/diagnostic_utils_test.go b/diagnostic/diagnostic_utils_test.go index b068abd1..ecd2001a 100644 --- a/diagnostic/diagnostic_utils_test.go +++ b/diagnostic/diagnostic_utils_test.go @@ -25,7 +25,7 @@ func helperCreateServer(t *testing.T, listeners *gracenet.Net, tunnelID uuid.UUI require.NoError(t, err) log := zerolog.Nop() tracker := tunnelstate.NewConnTracker(&log) - handler := diagnostic.NewDiagnosticHandler(&log, 0, nil, tunnelID, connectorID, tracker, nil, []string{}) + handler := diagnostic.NewDiagnosticHandler(&log, 0, nil, tunnelID, connectorID, tracker, nil, []string{}, []string{}) router := http.NewServeMux() router.HandleFunc("/diag/tunnel", handler.TunnelStateHandler) server := &http.Server{ diff --git a/diagnostic/handlers.go b/diagnostic/handlers.go index a137802e..a49d4aa3 100644 --- a/diagnostic/handlers.go +++ b/diagnostic/handlers.go @@ -26,6 +26,7 @@ type Handler struct { tracker *tunnelstate.ConnTracker cli *cli.Context flagInclusionList []string + icmpSources []string } func NewDiagnosticHandler( @@ -37,6 +38,7 @@ func NewDiagnosticHandler( tracker *tunnelstate.ConnTracker, cli *cli.Context, flagInclusionList []string, + icmpSources []string, ) *Handler { logger := log.With().Logger() if timeout == 0 { @@ -52,6 +54,7 @@ func NewDiagnosticHandler( tracker: tracker, cli: cli, flagInclusionList: flagInclusionList, + icmpSources: icmpSources, } } @@ -105,6 +108,7 @@ type TunnelState struct { TunnelID uuid.UUID `json:"tunnelID,omitempty"` ConnectorID uuid.UUID `json:"connectorID,omitempty"` Connections []tunnelstate.IndexedConnectionInfo `json:"connections,omitempty"` + ICMPSources []string `json:"icmp_sources,omitempty"` } func (handler *Handler) TunnelStateHandler(writer http.ResponseWriter, _ *http.Request) { @@ -117,6 +121,7 @@ func (handler *Handler) TunnelStateHandler(writer http.ResponseWriter, _ *http.R handler.tunnelID, handler.connectorID, handler.tracker.GetActiveConnections(), + handler.icmpSources, } encoder := json.NewEncoder(writer) diff --git a/diagnostic/handlers_test.go b/diagnostic/handlers_test.go index cc456045..fd2b9c27 100644 --- a/diagnostic/handlers_test.go +++ b/diagnostic/handlers_test.go @@ -123,7 +123,7 @@ func TestSystemHandler(t *testing.T) { t.Run(tCase.name, func(t *testing.T) { t.Parallel() - handler := diagnostic.NewDiagnosticHandler(&log, 0, &SystemCollectorMock{}, uuid.New(), uuid.New(), nil, nil, nil) + handler := diagnostic.NewDiagnosticHandler(&log, 0, &SystemCollectorMock{}, uuid.New(), uuid.New(), nil, nil, nil, nil) recorder := httptest.NewRecorder() ctx := setCtxValuesForSystemCollector(tCase.systemInfo, tCase.rawInfo, tCase.err) request, err := http.NewRequestWithContext(ctx, http.MethodGet, "/diag/syste,", nil) @@ -156,6 +156,7 @@ func TestTunnelStateHandler(t *testing.T) { tunnelID uuid.UUID clientID uuid.UUID connections []tunnelstate.IndexedConnectionInfo + icmpSources []string }{ { name: "case1", @@ -163,9 +164,10 @@ func TestTunnelStateHandler(t *testing.T) { clientID: uuid.New(), }, { - name: "case2", - tunnelID: uuid.New(), - clientID: uuid.New(), + name: "case2", + tunnelID: uuid.New(), + clientID: uuid.New(), + icmpSources: []string{"172.17.0.3", "::1"}, connections: []tunnelstate.IndexedConnectionInfo{{ ConnectionInfo: tunnelstate.ConnectionInfo{ IsConnected: true, @@ -181,7 +183,17 @@ func TestTunnelStateHandler(t *testing.T) { t.Run(tCase.name, func(t *testing.T) { t.Parallel() tracker := newTrackerFromConns(t, tCase.connections) - handler := diagnostic.NewDiagnosticHandler(&log, 0, nil, tCase.tunnelID, tCase.clientID, tracker, nil, nil) + handler := diagnostic.NewDiagnosticHandler( + &log, + 0, + nil, + tCase.tunnelID, + tCase.clientID, + tracker, + nil, + nil, + tCase.icmpSources, + ) recorder := httptest.NewRecorder() handler.TunnelStateHandler(recorder, nil) decoder := json.NewDecoder(recorder.Body) @@ -193,6 +205,7 @@ func TestTunnelStateHandler(t *testing.T) { assert.Equal(t, tCase.tunnelID, response.TunnelID) assert.Equal(t, tCase.clientID, response.ConnectorID) assert.Equal(t, tCase.connections, response.Connections) + assert.Equal(t, tCase.icmpSources, response.ICMPSources) }) } } @@ -237,7 +250,7 @@ func TestConfigurationHandler(t *testing.T) { t.Parallel() ctx := buildCliContext(t, tCase.flags) - handler := diagnostic.NewDiagnosticHandler(&log, 0, nil, uuid.New(), uuid.New(), nil, ctx, []string{"b", "c", "d"}) + handler := diagnostic.NewDiagnosticHandler(&log, 0, nil, uuid.New(), uuid.New(), nil, ctx, []string{"b", "c", "d"}, nil) recorder := httptest.NewRecorder() handler.ConfigurationHandler(recorder, nil) decoder := json.NewDecoder(recorder.Body)