Ограничение доступа к метрикам Node Exporter по IP-адресам
- воскресенье, 23 февраля 2025 г. в 00:00:09
В современных инфраструктурах информационной безопасности одной из ключевых задач является ограничение доступа к системным метрикам. По умолчанию Prometheus Node Exporter предоставляет метрики в открытом доступе, что может привести к утечке информации о состоянии системы или атаке на сервис мониторинга.
Для повышения безопасности необходимо реализовать возможность ограничения доступа к метрикам только для определённых IP-адресов, что позволит контролировать, какие клиенты могут запрашивать метрики.
В данной статье рассмотрим, как внести соответствующие изменения в код Node Exporter, а также процесс сборки обновленного пакета.
Изменение кода
Добавление нового флага командной строки
Для управления доступом по IP-адресам добавим новый аргумент --web.client-ip-only, который будет содержать список разрешённых IP-адресов, разделённых запятыми. Если параметр не указан, метрики будут доступны для всех.
В файле main.go регистрируем новый флаг:
clientIPOnly = kingpin.Flag(
"web.client-ip-only",
"Comma-separated list of allowed client IPs (e.g., '192.168.1.1,10.0.0.2'). Leave empty to allow all.",
).Default("").String()
Добавим middleware для обработки входящих HTTP-запросов и проверки IP-адреса клиента:
func ipFilterMiddleware(next http.Handler, allowedIPs map[string]struct{}, logger *slog.Logger) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
clientIP, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
logger.Warn("Failed to parse client IP", "error", err)
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
if len(allowedIPs) > 0 {
if _, allowed := allowedIPs[clientIP]; !allowed {
logger.Warn("Access denied", "client_ip", clientIP)
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
}
next.ServeHTTP(w, r)
})
}
В main.go изменим обработчик HTTP-запросов:
allowedIPs := make(map[string]struct{})
if *clientIPOnly != "" {
for _, ip := range strings.Split(*clientIPOnly, ",") {
allowedIPs[strings.TrimSpace(ip)] = struct{}{}
}
}
http.Handle(*metricsPath, ipFilterMiddleware(newHandler(!*disableExporterMetrics, *maxRequests, logger), allowedIPs, logger))
Добавим отображение разрешённых IP-адресов на веб-странице:
clientIPDisplay := "*"
if *clientIPOnly != "" {
clientIPDisplay = *clientIPOnly
}
landingConfig := web.LandingConfig{
Name: "Node Exporter",
Description: "Prometheus Node Exporter",
Version: version.Info(),
Links: []web.LandingLinks{
{
Address: *metricsPath,
Text: "Metrics",
},
{
Address: "#",
Text: "Allowed IPs: " + clientIPDisplay,
},
},
}
После внесения изменений необходимо пересобрать Node Exporter. Для этого выполните следующие шаги:
Установите Go и зависимости:
sudo apt update && sudo apt install -y golang
Склонируйте исходный код Node Exporter:
git clone https://github.com/prometheus/node_exporter.git
cd node_exporter
Скомпилируйте бинарный файл:
make build
Проверяем версию и новые параметры:
./node_exporter --version
Запускаем с ограничением по IP:
./node_exporter --web.client-ip-only="192.168.1.1,10.0.0.2"
Добавление параметра --web.client-ip-only позволяет ограничить доступ к метрикам только для указанных IP-адресов. Это значительно повышает уровень безопасности и снижает риск несанкционированного доступа к системной информации.
Теперь, благодаря middleware-фильтрации, Node Exporter будет обслуживать только доверенные IP-адреса, а пользователи смогут легко настраивать этот параметр через командную строку.
Кому лень всем этим заниматься, можете воспользоваться готовым из моего репозитория:
https://github.com/MaxSimba/node-exporter
З.Ы. Просьба не пинать сильно, я не волшебник только учусь! Но за конструктивные предложения, плюс в карму! За сим откланиваюсь! По просьбам могу собрать пакет для deb или RPM репозитория.