Стандартная конфигурация NFS оставляет ваши данные уязвимыми для перехвата трафика, спуфинга IP-адресов и несанкционированного доступа. Это руководство предоставляет готовое, проверенное на практике решение для трех ключевых аспектов безопасности: внедрение сильной аутентификации Kerberos, настройка сетевого контроля доступа с помощью фаервола и корректировка прав доступа в файле /etc/exports. Вы получите последовательные инструкции с командами и конфигурационными файлами для RHEL/CentOS и Ubuntu/Debian, которые можно адаптировать под свою инфраструктуру и применить с первого раза.
Зачем усиливать безопасность NFS и с чего начать
NFS по умолчанию использует механизм аутентификации sec=sys, который полагается на передачу идентификаторов пользователя (UID/GID) в открытом виде по сети. Это создает несколько критических уязвимостей. Злоумышленник в той же сети может перехватить трафик (sniffing), подменить свой IP-адрес на адрес доверенного клиента (IP spoofing) и получить доступ к данным. Если в конфигурации экспорта используется параметр no_root_squash, удаленный пользователь root получает полные права root на файловой системе сервера.
Безопасная конфигурация NFS строится на трех компонентах. Kerberos (krb5) заменяет ненадежную аутентификацию по UID/GID на криптографически стойкую проверку подлинности с использованием билетов. Фаервол (nftables или iptables) ограничивает доступ к портам NFS только доверенным хостам или подсетям, минимизируя поверхность атаки. Тонкая настройка файла /etc/exports с помощью параметров root_squash и ограничений по IP обеспечивает контроль на уровне файловой системы.
Общий план действий выглядит так: подготовить инфраструктуру Kerberos (KDC), настроить сервер и клиенты NFS для работы с билетами, сконфигурировать правила фаервола и отредактировать /etc/exports. Важное предварительное условие для Kerberos - синхронизированное время на всех узлах (используйте NTP).
Уязвимости стандартной конфигурации NFS
Основные риски при использовании sec=sys:
- Спуфинг IP-адреса и UID/GID: Атакующий может выдать себя за доверенный хост или пользователя, так как проверка подлинности основана на легко подделываемых данных.
- Перехват трафика (sniffing): Данные и команды управления передаются в незашифрованном виде. Внутренний злоумышленник или кто-то, получивший доступ к сети, может читать и модифицировать передаваемые файлы.
- Несанкционированный доступ от имени root: Параметр
no_root_squashв/etc/exportsпозволяет любому удаленному пользователю root получить права суперпользователя на сервере. Это прямое нарушение принципа минимальных привилегий. - Открытые порты: По умолчанию порты NFS (2049/tcp, 111/tcp/udp для portmapper в v3) могут быть доступны из любой точки сети, если не настроен фаервол.
Соответствие требованиям стандартов безопасности, таких как PCI DSS, HIPAA или внутренним политикам компаний, часто требует устранения этих уязвимостей.
Обзор архитектуры решения: Kerberos + Firewall + ACL
Решение создает многоуровневую защиту. Kerberos обеспечивает аутентификацию и, при выборе krb5p, шифрование трафика. Центральным элементом является сервер Key Distribution Center (KDC), который выдает билеты. Клиент NFS перед монтированием получает билет от KDC (команда kinit). При попытке доступа к ресурсу сервер NFS проверяет этот билет через KDC.
Фаервол работает на сетевом уровне, фильтруя пакеты до того, как они достигнут службы NFS. Он разрешает соединения только с определенных IP-адресов или подсетей, блокируя все остальные. Это первая линия обороны.
Файл /etc/exports определяет конечные правила доступа на уровне файловой системы. Здесь вы указываете, какие хосты (по IP или имени) могут монтировать какой каталог, с какими правами (чтение/запись) и как обрабатываются учетные записи (например, root_squash). Эти три слоя - аутентификация, сетевая фильтрация и права файловой системы - работают вместе.
Подготовка инфраструктуры Kerberos для NFS
Настройка Kerberos - самый сложный этап. Следуйте инструкциям для вашего дистрибутива. В этом примере используется realm EXAMPLE.LOCAL. Замените его на имя вашего домена в верхнем регистре.
Установка пакетов и базовая конфигурация KDC
Установите необходимые пакеты. На сервере, который будет KDC, нужны серверные компоненты. На клиентах и NFS-сервере - клиентские утилиты.
Для RHEL/CentOS 7/8, Rocky Linux, AlmaLinux:
# На сервере KDC
sudo yum install krb5-server krb5-workstation
# На клиентах и NFS-сервере
sudo yum install krb5-workstation krb5-libs
Для Ubuntu/Debian 20.04/22.04:
# На сервере KDC
sudo apt-get install krb5-kdc krb5-admin-server krb5-config
# На клиентах и NFS-сервере
sudo apt-get install krb5-user libpam-krb5
Во время установки вас могут спросить параметры realm и KDC. Если нет, отредактируйте основной файл конфигурации /etc/krb5.conf. Приведенная ниже конфигурация - минимально рабочая.
[libdefaults]
default_realm = EXAMPLE.LOCAL
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
[realms]
EXAMPLE.LOCAL = {
kdc = kdc-server.example.local
admin_server = kdc-server.example.local
}
[domain_realm]
.example.local = EXAMPLE.LOCAL
example.local = EXAMPLE.LOCAL
На сервере KDC также настройте /var/kerberos/krb5kdc/kdc.conf (путь может отличаться в Ubuntu: /etc/krb5kdc/kdc.conf).
[kdcdefaults]
kdc_ports = 88,750
[realms]
EXAMPLE.LOCAL = {
database_name = /var/kerberos/krb5kdc/principal
admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab
acl_file = /etc/krb5kdc/kadm5.acl
key_stash_file = /var/kerberos/krb5kdc/.k5.EXAMPLE.LOCAL
max_life = 24h 0m 0s
max_renewable_life = 7d 0h 0m 0s
master_key_type = aes256-cts-hmac-sha1-96
supported_enctypes = aes256-cts:normal aes128-cts:normal
}
Инициализируйте базу данных KDC и создайте пароль для базы:
sudo kdb5_util create -s -r EXAMPLE.LOCAL
Создайте ACL-файл для административного доступа (/etc/krb5kdc/kadm5.acl):
*/admin@EXAMPLE.LOCAL *
Запустите и добавьте в автозагрузку службы KDC и административного сервера:
# Для systemd (большинство современных дистрибутивов)
sudo systemctl start krb5kdc kadmin
sudo systemctl enable krb5kdc kadmin
Создание принципалов и keytab-файлов для NFS
Принципалы - это уникальные идентификаторы для служб и хостов. Для NFS требуется создать принципалы для службы NFS и для хоста на каждом сервере и клиенте, участвующем в обмене.
Войдите в утилиту администратора Kerberos на KDC:
sudo kadmin.local
В интерактивной оболочке kadmin выполните следующие команды, заменив nfs-server.example.local на полное доменное имя вашего NFS-сервера:
addprinc -randkey nfs/nfs-server.example.local@EXAMPLE.LOCAL
addprinc -randkey host/nfs-server.example.local@EXAMPLE.LOCAL
Повторите для каждого клиента, создав принципал хоста:
addprinc -randkey host/client1.example.local@EXAMPLE.LOCAL
Теперь создайте keytab-файл для NFS-сервера. Keytab - это файл, содержащий ключи для аутентификации без ввода пароля. Выполните в kadmin.local:
ktadd -k /etc/krb5.keytab nfs/nfs-server.example.local@EXAMPLE.LOCAL
ktadd -k /etc/krb5.keytab host/nfs-server.example.local@EXAMPLE.LOCAL
Скопируйте этот файл на NFS-сервер (или создайте его там же, если KDC и NFS-сервер - одна машина). Установите строгие права:
sudo chown root:root /etc/krb5.keytab
sudo chmod 600 /etc/krb5.keytab
Аналогично создайте и распространите keytab-файлы для клиентов, содержащие только их принципал хоста (host/client1.example.local).
Настройка NFS с аутентификацией Kerberos: выбор уровня защиты
Kerberos для NFS предлагает три уровня безопасности, задаваемые опцией sec= в /etc/exports и при монтировании.
krb5, krb5i или krb5p: что выбрать для вашего случая
Выбор зависит от требований к безопасности и допустимой нагрузки на процессор.
| Уровень (sec=) | Что обеспечивает | Нагрузка на CPU | Рекомендуемый сценарий |
|---|---|---|---|
krb5 |
Только аутентификация. Проверяет подлинность клиента и сервера. | Низкая | Внутренние доверенные сети, где угроза перехвата трафика минимальна, но требуется надежная аутентификация вместо sec=sys. |
krb5i |
Аутентификация + целостность данных (integrity). Добавляет криптографические хеши (HMAC) к каждому RPC-пакету, защищая от подмены данных в пути. | Средняя | Стандартный выбор для большинства рабочих сред. Защищает от спуфинга и модификации данных. Используется в сетях, где есть риск атаки "man-in-the-middle". |
krb5p |
Аутентификация + целостность + конфиденциальность (privacy). Полностью шифрует весь трафик NFS. | Высокая | Передача конфиденциальных данных (персональные данные, финансовые отчеты) по недоверенным сетям или для соответствия строгим compliance-требованиям (PCI DSS, GDPR). Может снизить производительность на 10-30%. |
Для большинства корпоративных сред оптимальным балансом безопасности и производительности является krb5i. Используйте krb5p, если политика безопасности или регуляторы явно требуют шифрования данных в движении.
Конфигурация сервера и клиента для работы с Kerberos
На NFS-сервере отредактируйте файл /etc/exports. Укажите опцию sec=krb5p (или выбранный вами уровень) для экспортируемой файловой системы.
/shared/data 192.168.1.0/24(rw,sync,sec=krb5p,root_squash)
Эта строка разрешает доступ к каталогу /shared/data только с подсети 192.168.1.0/24 с правами на чтение и запись, с синхронной записью, использованием Kerberos с шифрованием и отображением удаленного пользователя root в пользователя nobody.
Примените изменения:
sudo exportfs -ra
Убедитесь, что службы NFS и RPC связаны с Kerberos. В RHEL/CentOS 8+ и Ubuntu 20.04+ это обычно настраивается автоматически при установке пакета nfs-utils с поддержкой Kerberos. Проверьте, что в файле /etc/sysconfig/nfs (RHEL) или /etc/default/nfs-common (Ubuntu) нет параметров, отключающих Kerberos.
На клиенте убедитесь, что у пользователя есть действующий билет Kerberos (Ticket-Granting Ticket, TGT):
kinit username@EXAMPLE.LOCAL
klist # Проверить наличие билета
Смонтируйте раздел, явно указав версию NFS 4.2 (или 4.1) и уровень безопасности:
sudo mount -t nfs4 -o sec=krb5p,vers=4.2 nfs-server.example.local:/shared/data /mnt/data
Проверьте монтирование и доступ:
mount | grep /mnt/data
cd /mnt/data && touch test_file
Для постоянного монтирования добавьте запись в /etc/fstab:
nfs-server.example.local:/shared/data /mnt/data nfs4 sec=krb5p,vers=4.2,_netdev 0 0
Ограничение доступа на сетевом уровне: настройка firewall (nftables/iptables)
Фаервол - это обязательный второй уровень защиты. Он ограничивает доступ к портам NFS только доверенным IP-адресам.
Какие порты открывает NFS и как их контролировать
Набор необходимых портов зависит от версии NFS. NFSv4 значительно безопаснее и проще в настройке, так как использует один фиксированный порт.
| Сервис | Порт NFSv3 | Порт NFSv4 | Протокол | Примечание |
|---|---|---|---|---|
| NFS (ядро) | 2049 | 2049 | TCP/UDP | Основной порт. В v4 используется только TCP. |
| Portmapper (rpcbind) | 111 | Не требуется | TCP/UDP | NFSv4 не использует portmapper. |
| Mountd | Динамический (через rpcbind) | Не требуется | TCP/UDP | В v3 требует фиксации порта в /etc/sysconfig/nfs. |
| Statd | Динамический | Не требуется | TCP/UDP | Сложен для управления фаерволом. |
Рекомендация - использовать NFSv4 (минимум 4.1) для упрощения конфигурации и повышения безопасности. Это избавляет от необходимости управлять портами rpcbind, mountd и statd. Для проверки открытых портов на сервере используйте:
sudo rpcinfo -p | grep nfs
sudo ss -tlnp | grep 2049
Готовые правила для nftables и iptables
Приведенные ниже правила разрешают доступ к NFS только с доверенной подсети 192.168.1.0/24. Замените ее на свою.
Конфигурация для nftables (рекомендуется для новых систем):
Создайте файл конфигурации, например, /etc/nftables.conf.nfs:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
set trusted_nfs_clients {
type ipv4_addr
flags interval
elements = { 192.168.1.0/24 }
}
chain input {
type filter hook input priority 0; policy drop;
# Разрешить established/related соединения
ct state established,related accept
# Разрешить loopback
iif lo accept
# Разрешить ICMP (ping)
ip protocol icmp accept
# Разрешить SSH (для администрирования)
tcp dport 22 accept
# --- Правила для NFSv4 (только порт 2049/tcp) ---
# Разрешить NFS только с доверенных клиентов
tcp dport 2049 ip saddr @trusted_nfs_clients accept
# --- Правила для NFSv3 (если необходимо) ---
# tcp dport { 111, 2049 } ip saddr @trusted_nfs_clients accept
# udp dport { 111, 2049 } ip saddr @trusted_nfs_clients accept
# Для mountd/statd потребуется фиксация портов.
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
Загрузите правила и включите службу:
sudo nft -f /etc/nftables.conf.nfs
sudo systemctl enable --now nftables
Конфигурация для iptables (legacy):
# Очистить старые правила (осторожно!)
sudo iptables -F
sudo iptables -X
# Установить политику DROP по умолчанию
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
# Разрешить loopback и established соединения
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Разрешить SSH
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# --- Правила для NFSv4 ---
# Разрешить NFS (порт 2049) только с доверенной подсети
sudo iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 2049 -j ACCEPT
# Для NFSv3 также потребуются порты 111/tcp, 111/udp, 2049/udp и фиксированные порты mountd/statd.
# Сохранить правила (зависит от дистрибутива)
# Для RHEL/CentOS: sudo service iptables save
# Для Ubuntu: sudo apt-get install iptables-persistent; sudo netfilter-persistent save
Перед применением этих правил в рабочей среде протестируйте их на не критически важном сервере или добавьте правило, разрешающее ваш текущий IP-адрес для SSH, чтобы не потерять доступ. Более детально о настройке фаервола и аудите безопасности Linux-серверов вы можете прочитать в нашем практическом руководстве по харденингу Linux.
Тонкая настройка прав доступа в /etc/exports: squash-опции и ACL
Файл /etc/exports - это последний рубеж контроля. Его правильная настройка предотвращает эскалацию привилегий и минимизирует ущерб в случае компрометации одного из узлов.
root_squash vs no_root_squash: как не дать root доступ извне
Параметр root_squash - одна из самых важных настроек безопасности. Он отображает удаленного пользователя root (UID 0) в не привилегированного пользователя, обычно nobody (UID 65534 или другого, указанного в anonuid). Это предотвращает ситуацию, когда администратор на клиентской машине получает неограниченный доступ к файловой системе сервера.
# Безопасно: удаленный root становится nobody
/shared/data client1(rw,sync,root_squash)
# ОПАСНО: удаленный root остается root. Использовать ТОЛЬКО в исключительных, изолированных средах.
/shared/data client1(rw,sync,no_root_squash)
Параметр no_root_squash следует использовать крайне редко, например, для бесшовного резервного копирования определенными инструментами, и только для строго определенных хостов. В 99% случаев должен использоваться root_squash.
Параметр all_squash отображает всех пользователей (не только root) в анонимного пользователя. Это полезно для публичных каталогов только для чтения, например, для распространения ПО или медиафайлов.
# Все пользователи становятся nobody
/public/iso *(ro,sync,all_squash)
Вы можете задать конкретные UID и GID для отображения с помощью anonuid и anongid. Это полезно, когда определенной группе клиентов нужны особые, но не root-права.
/shared/app_data 192.168.1.10(rw,sync,root_squash,anonuid=1001,anongid=1001)
Ограничение экспорта по IP и использование сетевых групп
Самая эффективная мера - разрешить доступ только конкретным хостам. Указывайте IP-адреса или подсети явно.
# Разрешить доступ только одному конкретному хосту
/shared/confidential client1.example.com(rw,sync,sec=krb5p,root_squash)
# Разрешить доступ всей доверенной подсети
/shared/team 192.168.1.0/24(rw,sync,sec=krb5i,root_squash)
# НЕБЕЗОПАСНО: разрешить доступ всем (*)
/shared/data *(rw,sync,root_squash) # НЕ ДЕЛАЙТЕ ТАК
Использование DNS-имен (client1.example.com) возможно, но зависит от надежности и безопасности вашего DNS. Если DNS скомпрометирован, атака становится проще. Использование IP-адресов надежнее.
Пример полной безопасной строки экспорта, сочетающей все лучшие практики:
/srv/project_x 192.168.10.20(rw,sync,sec=krb5i,root_squash) 192.168.10.21(ro,sync,sec=krb5i,all_squash)
Эта строка разрешает хосту 192.168.10.20 читать и писать с аутентификацией Kerberos и отображением root, а хосту 192.168.10.21 - только читать, при этом все его пользователи будут отображены в nobody.
Диагностика проблем и проверка работоспособности
После настройки проверьте всю цепочку. Типичные проблемы связаны с расхождением времени, ошибками в keytab-файлах и блокировкой портов фаерволом.
Чек-лист: как убедиться, что NFS защищен
- Синхронизация времени: На всех узлах (KDC, сервер, клиенты) время должно отличаться не более чем на 5 минут для Kerberos. Проверьте:
timedatectl statusилиntpstat. - Наличие билетов Kerberos: На клиенте выполните
klist. Должны быть видны билет для вашего пользователя и принципалhost/.... Если билетов нет, выполнитеkinit. - Проверка keytab-файлов: На сервере и клиентах проверьте права и содержимое keytab:
ls -la /etc/krb5.keytab(должны быть 600, root:root). Просмотреть принципалы в keytab можно так:sudo klist -k /etc/krb5.keytab. - Публикация экспорта: На сервере выполните
sudo exportfs -v. Убедитесь, что ваш экспорт опубликован с правильными опциями (sec=krb5p/i). - Открытые порты: На сервере проверьте, что служба слушает на ожидаемых портах:
sudo ss -tlnp | grep -E ':2049|:111'. - Правила фаервола: Проверьте активные правила:
sudo nft list rulesetилиsudo iptables -L -n -v. Убедитесь, что есть разрешающие правила для вашей подсети на порт 2049/tcp. - Монтирование и доступ: На клиенте проверьте
mount | grep nfsи попробуйте создать тестовый файл.
Решение частых ошибок: от «Access denied» до проблем с портами
| Симптом (ошибка) | Возможная причина | Диагностика | Решение |
|---|---|---|---|
mount.nfs: access denied by server |
1. Несоответствие опции sec= на клиенте и сервере.2. Отсутствие действующего билета Kerberos на клиенте. 3. Неправильный или отсутствующий keytab на сервере. 4. Хост клиента не указан в /etc/exports. |
1. Сравнить опции в /etc/exports и команде mount.2. Выполнить klist.3. Проверить журналы сервера: journalctl -u nfs-server.4. Проверить exportfs -v. |
1. Убедиться, что sec=krb5p указан и там, и там.2. Выполнить kinit.3. Пересоздать и перераспространить keytab. 4. Добавить IP клиента в /etc/exports. |
mount.nfs: Connection timed out или RPC: Port mapper failure |
Фаервол блокирует порты NFS. | С клиента попробовать telnet nfs-server 2049. Проверить логи фаервола на сервере. |
Добавить правило фаервола, разрешающее трафик с IP клиента на порт 2049/tcp (и 111/tcp/udp для NFSv3). Убедиться, что используется NFSv4. |
Clock skew too great при выполнении kinit |
Расхождение времени между клиентом и KDC превышает допустимый лимит (обычно 5 минут). | Выполнить date на клиенте и KDC. |
Настроить и запустить службу NTP (chrony или systemd-timesyncd) на всех узлах. |
| Монтирование работает, но запись файлов невозможна | 1. Используется all_squash без указания anonuid/anongid.2. Проблемы с правами на файловой системе сервера. |
1. Проверить опции экспорта. 2. Проверить права (ls -la) на каталоге сервера. |
1. Настроить anonuid/anongid на существующего пользователя с правами записи.2. Изменить владельца каталога экспорта или его права (chmod). |
Если вы столкнулись с проблемами производительности после настройки, например, при работе с большими файлами, обратитесь к нашему руководству по тонкой настройке NFS для максимальной скорости. Для комплексного подхода к развертыванию NFS-сервера, включая настройку производительности и отказоустойчивости, изучите практическое руководство по настройке NFS в TrueNAS. Если вы все еще используете устаревшую третью версию протокола, рекомендуем ознакомиться с пошаговым планом миграции с NFSv3 на NFSv4.
Для автоматизации рутинных задач администрирования и управления серверами вы можете использовать специализированные инструменты. Например, сервис AiTunnel предоставляет единый API-интерфейс для доступа к более чем 200 моделям ИИ, что может быть полезно для создания скриптов мониторинга, анализа логов или генерации отчетов по безопасности вашей инфраструктуры.