mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 20:09:58 +00:00
TUN-6592: Decrement TTL and return ICMP time exceed if it's 0
This commit is contained in:
@@ -115,7 +115,7 @@ func (snf echoFunnelID) String() string {
|
||||
return strconv.FormatUint(uint64(snf), 10)
|
||||
}
|
||||
|
||||
func newICMPProxy(listenIP netip.Addr, logger *zerolog.Logger, idleTimeout time.Duration) (ICMPProxy, error) {
|
||||
func newICMPProxy(listenIP netip.Addr, logger *zerolog.Logger, idleTimeout time.Duration) (*icmpProxy, error) {
|
||||
conn, err := newICMPConn(listenIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -3,14 +3,29 @@
|
||||
package ingress
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"github.com/cloudflare/cloudflared/packet"
|
||||
)
|
||||
|
||||
func newICMPProxy(listenIP netip.Addr, logger *zerolog.Logger, idleTimeout time.Duration) (ICMPProxy, error) {
|
||||
return nil, fmt.Errorf("ICMP proxy is not implemented on %s", runtime.GOOS)
|
||||
var errICMPProxyNotImplemented = fmt.Errorf("ICMP proxy is not implemented on %s", runtime.GOOS)
|
||||
|
||||
type icmpProxy struct{}
|
||||
|
||||
func (ip icmpProxy) Request(pk *packet.ICMP, responder packet.FunnelUniPipe) error {
|
||||
return errICMPProxyNotImplemented
|
||||
}
|
||||
|
||||
func (ip *icmpProxy) Serve(ctx context.Context) error {
|
||||
return errICMPProxyNotImplemented
|
||||
}
|
||||
|
||||
func newICMPProxy(listenIP netip.Addr, logger *zerolog.Logger, idleTimeout time.Duration) (*icmpProxy, error) {
|
||||
return nil, errICMPProxyNotImplemented
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ type icmpProxy struct {
|
||||
idleTimeout time.Duration
|
||||
}
|
||||
|
||||
func newICMPProxy(listenIP netip.Addr, logger *zerolog.Logger, idleTimeout time.Duration) (ICMPProxy, error) {
|
||||
func newICMPProxy(listenIP netip.Addr, logger *zerolog.Logger, idleTimeout time.Duration) (*icmpProxy, error) {
|
||||
if err := testPermission(listenIP); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -96,6 +96,7 @@ func (ief *icmpEchoFlow) returnToSrc(reply *echoReply) error {
|
||||
Src: reply.from,
|
||||
Dst: ief.Src,
|
||||
Protocol: layers.IPProtocol(reply.msg.Type.Protocol()),
|
||||
TTL: packet.DefaultTTL,
|
||||
},
|
||||
Message: reply.msg,
|
||||
}
|
||||
|
@@ -224,7 +224,7 @@ type icmpProxy struct {
|
||||
encoderPool sync.Pool
|
||||
}
|
||||
|
||||
func newICMPProxy(listenIP netip.Addr, logger *zerolog.Logger, idleTimeout time.Duration) (ICMPProxy, error) {
|
||||
func newICMPProxy(listenIP netip.Addr, logger *zerolog.Logger, idleTimeout time.Duration) (*icmpProxy, error) {
|
||||
var (
|
||||
srcSocketAddr *sockAddrIn6
|
||||
handle uintptr
|
||||
@@ -302,6 +302,7 @@ func (ip *icmpProxy) handleEchoReply(request *packet.ICMP, echoReq *icmp.Echo, d
|
||||
Src: request.Dst,
|
||||
Dst: request.Src,
|
||||
Protocol: layers.IPProtocol(request.Type.Protocol()),
|
||||
TTL: packet.DefaultTTL,
|
||||
},
|
||||
Message: &icmp.Message{
|
||||
Type: replyType,
|
||||
|
@@ -134,7 +134,6 @@ func TestSendEchoErrors(t *testing.T) {
|
||||
func testSendEchoErrors(t *testing.T, listenIP netip.Addr) {
|
||||
proxy, err := newICMPProxy(listenIP, &noopLogger, time.Second)
|
||||
require.NoError(t, err)
|
||||
winProxy := proxy.(*icmpProxy)
|
||||
|
||||
echo := icmp.Echo{
|
||||
ID: 6193,
|
||||
@@ -145,7 +144,7 @@ func testSendEchoErrors(t *testing.T, listenIP netip.Addr) {
|
||||
if listenIP.Is6() {
|
||||
documentIP = netip.MustParseAddr("2001:db8::1")
|
||||
}
|
||||
resp, err := winProxy.icmpEchoRoundtrip(documentIP, &echo)
|
||||
resp, err := proxy.icmpEchoRoundtrip(documentIP, &echo)
|
||||
require.Error(t, err)
|
||||
require.Nil(t, resp)
|
||||
}
|
||||
|
@@ -26,22 +26,14 @@ var (
|
||||
errPacketNil = fmt.Errorf("packet is nil")
|
||||
)
|
||||
|
||||
// ICMPProxy sends ICMP messages and listens for their responses
|
||||
type ICMPProxy interface {
|
||||
// Serve starts listening for responses to the requests until context is done
|
||||
Serve(ctx context.Context) error
|
||||
// Request sends an ICMP message
|
||||
Request(pk *packet.ICMP, responder packet.FunnelUniPipe) error
|
||||
}
|
||||
|
||||
type icmpRouter struct {
|
||||
ipv4Proxy ICMPProxy
|
||||
ipv6Proxy ICMPProxy
|
||||
ipv4Proxy *icmpProxy
|
||||
ipv6Proxy *icmpProxy
|
||||
}
|
||||
|
||||
// NewICMPProxy doesn't return an error if either ipv4 proxy or ipv6 proxy can be created. The machine might only
|
||||
// NewICMPRouter doesn't return an error if either ipv4 proxy or ipv6 proxy can be created. The machine might only
|
||||
// support one of them
|
||||
func NewICMPProxy(logger *zerolog.Logger) (ICMPProxy, error) {
|
||||
func NewICMPRouter(logger *zerolog.Logger) (*icmpRouter, error) {
|
||||
// TODO: TUN-6741: don't bind to all interface
|
||||
ipv4Proxy, ipv4Err := newICMPProxy(netip.IPv4Unspecified(), logger, funnelIdleTimeout)
|
||||
ipv6Proxy, ipv6Err := newICMPProxy(netip.IPv6Unspecified(), logger, funnelIdleTimeout)
|
||||
@@ -49,11 +41,11 @@ func NewICMPProxy(logger *zerolog.Logger) (ICMPProxy, error) {
|
||||
return nil, fmt.Errorf("cannot create ICMPv4 proxy: %v nor ICMPv6 proxy: %v", ipv4Err, ipv6Err)
|
||||
}
|
||||
if ipv4Err != nil {
|
||||
logger.Warn().Err(ipv4Err).Msg("failed to create ICMPv4 proxy, only ICMPv6 proxy is created")
|
||||
logger.Debug().Err(ipv4Err).Msg("failed to create ICMPv4 proxy, only ICMPv6 proxy is created")
|
||||
ipv4Proxy = nil
|
||||
}
|
||||
if ipv6Err != nil {
|
||||
logger.Warn().Err(ipv6Err).Msg("failed to create ICMPv6 proxy, only ICMPv4 proxy is created")
|
||||
logger.Debug().Err(ipv6Err).Msg("failed to create ICMPv6 proxy, only ICMPv4 proxy is created")
|
||||
ipv6Proxy = nil
|
||||
}
|
||||
return &icmpRouter{
|
||||
|
@@ -30,24 +30,24 @@ var (
|
||||
// Note: if this test fails on your device under Linux, then most likely you need to make sure that your user
|
||||
// is allowed in ping_group_range. See the following gist for how to do that:
|
||||
// https://github.com/ValentinBELYN/icmplib/blob/main/docs/6-use-icmplib-without-privileges.md
|
||||
func TestICMPProxyEcho(t *testing.T) {
|
||||
testICMPProxyEcho(t, true)
|
||||
testICMPProxyEcho(t, false)
|
||||
func TestICMPRouterEcho(t *testing.T) {
|
||||
testICMPRouterEcho(t, true)
|
||||
testICMPRouterEcho(t, false)
|
||||
}
|
||||
|
||||
func testICMPProxyEcho(t *testing.T, sendIPv4 bool) {
|
||||
func testICMPRouterEcho(t *testing.T, sendIPv4 bool) {
|
||||
const (
|
||||
echoID = 36571
|
||||
endSeq = 20
|
||||
)
|
||||
|
||||
proxy, err := NewICMPProxy(&noopLogger)
|
||||
router, err := NewICMPRouter(&noopLogger)
|
||||
require.NoError(t, err)
|
||||
|
||||
proxyDone := make(chan struct{})
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
proxy.Serve(ctx)
|
||||
router.Serve(ctx)
|
||||
close(proxyDone)
|
||||
}()
|
||||
|
||||
@@ -67,6 +67,7 @@ func testICMPProxyEcho(t *testing.T, sendIPv4 bool) {
|
||||
Src: localIP,
|
||||
Dst: localIP,
|
||||
Protocol: protocol,
|
||||
TTL: packet.DefaultTTL,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +89,7 @@ func testICMPProxyEcho(t *testing.T, sendIPv4 bool) {
|
||||
},
|
||||
},
|
||||
}
|
||||
require.NoError(t, proxy.Request(&pk, &responder))
|
||||
require.NoError(t, router.Request(&pk, &responder))
|
||||
responder.validate(t, &pk)
|
||||
}
|
||||
}
|
||||
@@ -97,7 +98,7 @@ func testICMPProxyEcho(t *testing.T, sendIPv4 bool) {
|
||||
}
|
||||
|
||||
// TestICMPProxyRejectNotEcho makes sure it rejects messages other than echo
|
||||
func TestICMPProxyRejectNotEcho(t *testing.T) {
|
||||
func TestICMPRouterRejectNotEcho(t *testing.T) {
|
||||
msgs := []icmp.Message{
|
||||
{
|
||||
Type: ipv4.ICMPTypeDestinationUnreachable,
|
||||
@@ -122,7 +123,7 @@ func TestICMPProxyRejectNotEcho(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
testICMPProxyRejectNotEcho(t, localhostIP, msgs)
|
||||
testICMPRouterRejectNotEcho(t, localhostIP, msgs)
|
||||
msgsV6 := []icmp.Message{
|
||||
{
|
||||
Type: ipv6.ICMPTypeDestinationUnreachable,
|
||||
@@ -147,11 +148,11 @@ func TestICMPProxyRejectNotEcho(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
testICMPProxyRejectNotEcho(t, localhostIPv6, msgsV6)
|
||||
testICMPRouterRejectNotEcho(t, localhostIPv6, msgsV6)
|
||||
}
|
||||
|
||||
func testICMPProxyRejectNotEcho(t *testing.T, srcDstIP netip.Addr, msgs []icmp.Message) {
|
||||
proxy, err := NewICMPProxy(&noopLogger)
|
||||
func testICMPRouterRejectNotEcho(t *testing.T, srcDstIP netip.Addr, msgs []icmp.Message) {
|
||||
router, err := NewICMPRouter(&noopLogger)
|
||||
require.NoError(t, err)
|
||||
|
||||
responder := echoFlowResponder{
|
||||
@@ -168,10 +169,11 @@ func testICMPProxyRejectNotEcho(t *testing.T, srcDstIP netip.Addr, msgs []icmp.M
|
||||
Src: srcDstIP,
|
||||
Dst: srcDstIP,
|
||||
Protocol: protocol,
|
||||
TTL: packet.DefaultTTL,
|
||||
},
|
||||
Message: &m,
|
||||
}
|
||||
require.Error(t, proxy.Request(&pk, &responder))
|
||||
require.Error(t, router.Request(&pk, &responder))
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user