Skip to content

Commit fdddd86

Browse files
committed
TUN-6715: Provide suggestion to add cloudflared to ping_group_range if it failed to open ICMP socket
1 parent b3e2642 commit fdddd86

File tree

1 file changed

+46
-4
lines changed

1 file changed

+46
-4
lines changed

ingress/icmp_linux.go

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import (
1212
"fmt"
1313
"net"
1414
"net/netip"
15+
"os"
16+
"regexp"
17+
"strconv"
1518
"time"
1619

1720
"github.com/pkg/errors"
@@ -21,6 +24,15 @@ import (
2124
"github.com/cloudflare/cloudflared/packet"
2225
)
2326

27+
const (
28+
// https://lwn.net/Articles/550551/ IPv4 and IPv6 share the same path
29+
pingGroupPath = "/proc/sys/net/ipv4/ping_group_range"
30+
)
31+
32+
var (
33+
findGroupIDRegex = regexp.MustCompile(`\d+`)
34+
)
35+
2436
type icmpProxy struct {
2537
srcFunnelTracker *packet.FunnelTracker
2638
listenIP netip.Addr
@@ -30,7 +42,7 @@ type icmpProxy struct {
3042
}
3143

3244
func newICMPProxy(listenIP netip.Addr, zone string, logger *zerolog.Logger, idleTimeout time.Duration) (*icmpProxy, error) {
33-
if err := testPermission(listenIP, zone); err != nil {
45+
if err := testPermission(listenIP, zone, logger); err != nil {
3446
return nil, err
3547
}
3648
return &icmpProxy{
@@ -42,19 +54,49 @@ func newICMPProxy(listenIP netip.Addr, zone string, logger *zerolog.Logger, idle
4254
}, nil
4355
}
4456

45-
func testPermission(listenIP netip.Addr, zone string) error {
57+
func testPermission(listenIP netip.Addr, zone string, logger *zerolog.Logger) error {
4658
// Opens a non-privileged ICMP socket. On Linux the group ID of the process needs to be in ping_group_range
59+
// Only check ping_group_range once for IPv4
60+
if listenIP.Is4() {
61+
if err := checkInPingGroup(); err != nil {
62+
logger.Warn().Err(err).Msgf("The user running cloudflared process has a GID (group ID) that is not within ping_group_range. You might need to add that user to a group within that range, or instead update the range to encompass a group the user is already in by modifying %s. Otherwise cloudflared will not be able to ping this network", pingGroupPath)
63+
return err
64+
}
65+
}
4766
conn, err := newICMPConn(listenIP, zone)
4867
if err != nil {
49-
// TODO: TUN-6715 check if cloudflared is in ping_group_range if the check failed. If not log instruction to
50-
// change the group ID
5168
return err
5269
}
5370
// This conn is only to test if cloudflared has permission to open this type of socket
5471
conn.Close()
5572
return nil
5673
}
5774

75+
func checkInPingGroup() error {
76+
file, err := os.ReadFile(pingGroupPath)
77+
if err != nil {
78+
return err
79+
}
80+
groupID := os.Getgid()
81+
// Example content: 999 59999
82+
found := findGroupIDRegex.FindAll(file, 2)
83+
if len(found) == 2 {
84+
groupMin, err := strconv.ParseUint(string(found[0]), 10, 16)
85+
if err != nil {
86+
return errors.Wrapf(err, "failed to determine minimum ping group ID")
87+
}
88+
groupMax, err := strconv.ParseUint(string(found[1]), 10, 16)
89+
if err != nil {
90+
return errors.Wrapf(err, "failed to determine minimum ping group ID")
91+
}
92+
if groupID < int(groupMin) || groupID > int(groupMax) {
93+
return fmt.Errorf("Group ID %d is not between ping group %d to %d", groupID, groupMin, groupMax)
94+
}
95+
return nil
96+
}
97+
return fmt.Errorf("did not find group range in %s", pingGroupPath)
98+
}
99+
58100
func (ip *icmpProxy) Request(pk *packet.ICMP, responder packet.FunnelUniPipe) error {
59101
if pk == nil {
60102
return errPacketNil

0 commit comments

Comments
 (0)