Как запустить утилиту ping из пользовательского пространства (user space) без прав root, чтобы она взаимодействовала с ядром (kernel space)?

«Как запустить утилиту ping из пользовательского пространства (user space) без прав root, чтобы она взаимодействовала с ядром (kernel space)?» — вопрос из категории Linux, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для работы ping без прав суперпользователя необходимо настроить Linux capabilities или параметры ядра, так как ping использует raw sockets для отправки ICMP-пакетов, что по умолчанию требует привилегий.

1. Настройка через Linux Capabilities (предпочтительный метод):

# Устанавливаю CAP_NET_RAW capability на бинарник ping
sudo setcap cap_net_raw+ep /bin/ping

# Проверяю
getcap /bin/ping
# Ожидаемый вывод: /bin/ping = cap_net_raw+ep

Что это дает: Флаг +ep (Effective, Permitted) позволяет процессу ping использовать raw sockets. После этой настройки любой пользователь сможет выполнять ping.

2. Настройка через параметр ядра ping_group_range (Linux 5.7+):

# Разрешаю неограниченному диапазону групп использовать ICMP sockets
echo "net.ipv4.ping_group_range = 0 2147483647" | sudo tee -a /etc/sysctl.conf

# Или для IPv6
echo "net.ipv6.ping_group_range = 0 2147483647" | sudo tee -a /etc/sysctl.conf

# Применяю изменения
sudo sysctl -p

Этот метод позволяет процессам, чей GID находится в указанном диапазоне, создавать ICMP sockets напрямую через системный вызов socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP), без необходимости в raw sockets.

3. Практическое применение в DevOps: В контейнеризированных средах (Docker/Kubernetes) часто приходится настраивать это для sidecar-контейнеров мониторинга. Например, в Dockerfile:

FROM alpine:latest
RUN apk add --no-cache iputils && 
    setcap cap_net_raw+ep /bin/ping
# Теперь контейнер может использовать ping без привилегий

Или в securityContext Pod в Kubernetes:

securityContext:
  capabilities:
    add: ["NET_RAW"]  # Добавляем capability контейнеру

Архитектурный контекст: Когда обычный пользователь запускает ping с CAP_NET_RAW, процесс выполняет системный вызов socket() с типом SOCK_RAW и протоколом IPPROTO_ICMP. Ядро проверяет capabilities процесса (через capable(CAP_NET_RAW)) и, если проверка проходит, создает raw socket, через который процесс может отправлять и принимать ICMP-пакеты напрямую.