Ответ
Для работы 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-пакеты напрямую.