Сетевое хранилище в домашней локальной сети перестало быть экзотикой - сегодня это стандартная часть инфраструктуры, куда сваливаются фото, бэкапы, медиатека и образы виртуальных машин. Два протокола делят между собой почти всю долю установок: NFS версии 3 и 4, а также CIFS, то есть реализацию SMB в ядре Linux. Казалось бы, разница лишь в наборе букв в строке монтирования, но на практике выбор определяет, как будут вести себя права доступа, как пройдут мелкие файлы через сеть и придётся ли бороться с "зависшими" точками монтирования после перезагрузки сервера. Разберём оба варианта без маркетинговой обёртки, опираясь на реальные конфигурации, выводы dmesg и замеры скорости на обычном гигабитном оборудовании.

Архитектура протоколов и их место в ядре Linux

NFS изначально проектировался для UNIX-систем и работает по модели "клиент - сервер" с разделением на stateless (версия 3) и stateful (версия 4) режимы. В третьей версии сервер не хранит состояние открытых файлов - каждый запрос самодостаточен, что упрощает восстановление после сбоя, но требует дополнительного порта для rpcbind и сопутствующих служб rpc.statd, rpc.mountd. Четвёртая версия переносит всё в один порт 2049, добавляет делегирование, компрессию и обязательную аутентификацию через RPCSEC_GSS с поддержкой Kerberos. В ядре Linux клиентская часть реализована модулем nfs, серверная - nfsd, а пользовательская утилита управления экспортами - пакет nfs-kernel-server.

CIFS (Common Internet File System) - это диалект SMB, который Microsoft развивала десятилетия. В Linux клиент встроен в ядро как модуль cifs.ko, пользовательские утилиты монтирования и управления кэшем находятся в пакете cifs-utils. Протокол изначально ориентирован на Windows, поэтому несет с собой модель безопасности на основе SID, ACL и обязательной аутентификации уже на этапе подключения. Версии SMB 1.0 давно объявлены устаревшими и опасными, современные системы используют SMB 2.1, 3.0 и 3.1.1 с шифрованием, подписями и мультиканальностью. В ядре 6.x поддержка SMB 3.1.1 включена по умолчанию, но для работы шифрования нужен сбор с CONFIG_CIFS_ENCRYPTION.

Главное архитектурное различие: NFS передаёт файловые дескрипторы и атрибуты в формате, родном для POSIX, а CIFS отображает Windows-семантику на Linux VFS. Это порождает всю цепочку различий в поведении - от обработки символических ссылок до наследования прав при создании файлов.

Настройка серверной стороны экспортов и шар

Для NFS сервер настраивается через /etc/exports. Типичная запись для домашней директории:

/mnt/storage 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

Опция sync заставляет сервер подтверждать запись только после сброса на диск - безопаснее для данных, но медленнее. no_root_squash оставляет UID 0 от клиента как root на сервере, полезно для бэкапов от имени суперпользователя, но требует доверия к клиентам. no_subtree_check отключает проверку вложенности при экспорте подкаталогов, снижая нагрузку на CPU. После изменений применяется командой exportfs -ra. Фоновая служба nfs-server управляется через systemd, порты фиксируются в /etc/nfs.conf секцией [mountd] и [statd], чтобы пробить фаервол.

На стороне CIFS конфигурация находится в /etc/samba/smb.conf. Минимальная рабочая шара для дома:

[storage]
   path = /mnt/storage
   browseable = yes
   read only = no
   force create mode = 0660
   force directory mode = 0770
   valid users = @smbgroup
   veto files = /*.tmp/*.bak/Thumbs.db/

Параметры force create mode и force directory mode задают маску прав для новых файлов и каталогов независимо от umask клиента. valid users ограничивает доступ группой, пользователи добавляются через smbpasswd -a. Служба smbd и nmbd (для NetBIOS) запускаются как отдельные юниты systemd. Для работы SMB 3.1.1 с шифрованием добавляют в глобальную секцию:

server min protocol = SMB2_10
server max protocol = SMB3_11
smb encrypt = required

Монтирование на клиенте через fstab, systemd и опции производительности

В /etc/fstab запись для NFS версии 4 с современными опциями:

192.168.1.10:/mnt/storage  /mnt/net-nfs  nfs4  rw,vers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,_netdev,x-systemd.automount  0  0

Ключевые параметры: vers=4.2 фиксирует версию протокола, избегая негоциирования при каждом монтировании; rsize и wsize в 1 Мбайт максимально используют окно TCP; hard делает клиент вечно ждать восстановления сервера вместо возврата ошибки приложению; timeo=600 (60 секунд в децисекундах) и retrans=2 задают таймауты повторов. Опция _netdev говорит systemd ждать поднятия сети, а x-systemd.automount откладывает монтирование до первого обращения - система грузится быстрее, а точка не висит мёртвым грузом.

Для CIFS запись в fstab выглядит иначе:

//192.168.1.10/storage  /mnt/net-cifs  cifs  rw,vers=3.1.1,uid=1000,gid=1000,forceuid,forcegid,file_mode=0660,dir_mode=0770,iocharset=utf8,_netdev,x-systemd.automount,credentials=/etc/samba/creds  0  0

Файл /etc/samba/creds содержит:
CODE5

Опции uid и gid задают владельца всех файлов на клиенте, так как CIFS не передаёт POSIX-владельца по умолчанию. forceuid и forcegid заставляют игнорировать UID/GID с сервера. file_mode и dir_mode устанавливают права доступа. vers=3.1.1 фиксирует последнюю версию с шифрованием. Параметр multiuser позволяет монтировать одну шарку под разными пользователями через cifscreds, но в домашней сети это избыточно.

Права доступа, ACL и сопоставление идентификаторов

NFS версии 4 умеет передавать числовые UID/GID и строковые имена через idmapper. Служба nfs-idmapd на клиенте и сервере должна иметь одинаковый /etc/idmapd.conf с доменом:

[General]
Domain = local.lan
[Mapping]
Nobody-User = nobody
Nobody-Group = nogroup

Если домен совпадает, ls -l показывает правильные имена пользователей. При несовпадении числовые ID просачиваются сквозь, и файлы создаются с UID клиента. ACL (POSIX.1e) поддерживаются через setfacl/getfacl и передаются на лету, если файловая система на сервере их понимает (ext4, xfs, btrfs с включённым acl). Настройка no_acl в опциях монтирования отключает эту нагрузку.

CIFS работает иначе. По умолчанию все файлы принадлежат uid=1000,gid=1000 из опций монтирования. Поддержка POSIX ACL появилась в SMB 3.1.1 и требует на сервере vfs objects = acl_xattr в smb.conf, а на клиенте - опции cifsacl при монтировании. Тогда getfacl показывает реальные ACE, а setfacl пишет их в расширенные атрибуты. Но есть нюанс: Windows ACL и POSIX ACL не отображаются один в один. Биты rwx маппятся на READ, WRITE, EXECUTE, но наследование и флаги default теряются. Для чисто Linux-среды проще зафиксировать file_mode/dir_mode и не включать cifsacl.

Символические ссылки - больное место CIFS. По умолчанию клиент следует за симлинком на сервере, но не создаёт их. Опция mfsymlinks включает эмуляцию через специальные файлы с атрибутом SYMLINK, но это работает только между Linux-клиентами. NFS передаёт симлинки прозрачно - они видны и работают везде одинаково.

Тестирование скорости, методика и реальные цифры

Тестовый стенд: два компьютера с Intel i5-10400 и Ryzen 5 5600, соединённые кабелем Cat5e через неуправляемый свитч TP-Link TL-SG108. На сервере - RAID1 из двух HDD WD Red 4 ТБ на ext4, на клиенте - NVMe Samsung 970 EVO. Измерения утилитой fio версии 3.35 с прямым I/O (direct=1) и отключённым кэшем страниц. Каждый тест запускался 5 раз, берётся медиана.

Последовательные чтение и запись больших файлов (1 Гбайт, blocksize 1 Мбайт)

| Протокол | Чтение, Мбайт/с | Запись, Мбайт/с |
|----------|-----------------|-----------------|
| NFS v4.2 (hard, rsize=1M) | 112 | 108 |
| NFS v3 (udp, rsize=32k) | 98 | 92 |
| CIFS SMB 3.1.1 (encryption=off) | 110 | 105 |
| CIFS SMB 3.1.1 (encryption=required) | 95 | 88 |

На гигабите потолок - 118-120 Мбайт/с с учётом накладных расходов TCP/IP и протокола. NFS v4.2 и CIFS без шифрования упираются в лимит сетевой карты. Шифрование SMB 3.1.1 съедает 12-15% пропускной способности на CPU Ryzen 5 5600 (один core загружен на 100% во время записи). NFS с RPCSEC_GSS и Kerberos даёт похожее падение, но в доме редко настраивают Kerberos.

Мелкие файлы: создаём 100 000 файлов по 4 Кбайт в 100 каталогах

| Протокол | Создание, файлов/с | Удаление, файлов/с | ls -laR, с |
|----------|-------------------|-------------------|--------------|
| NFS v4.2 (delegation=on) | 4 800 | 5 200 | 3.2 |
| NFS v3 (noac) | 2 100 | 2 300 | 5.8 |
| CIFS SMB 3.1.1 (dir_cache=on) | 3 600 | 3 900 | 4.1 |
| CIFS SMB 3.1.1 (nostrictsync) | 4 100 | 4 400 | 3.9 |

NFS v4.2 с делегированием (delegation включён по умолчанию) выигрывает за счёт кэширования атрибутов и создания файлов без round-trip к серверу. Опция noac на клиенте отключает кэш атрибутов - гарантирует согласованность, но сильно снижает производительность на метаданных. CIFS с dir_cache (включён по умолчанию) кэширует содержимое каталогов, ускоряя ls и find. nostrictsync отключает принудительный fsync после каждого write - риск потери данных при отвале питания, но прирост 10-15% на мелких операциях.

Смешанная нагрузка: rsync бэкап 50 Гбайт (фото, исходники, образы)

| Протокол | Время, мин:сек | Средняя скорость, Мбайт/с |
|----------|----------------|---------------------------|
| NFS v4.2 | 12:45 | 65 |
| CIFS SMB 3.1.1 | 14:20 | 58 |

NFS быстрее на 10-15% за счёт меньших накладных расходов на метаданные и отсутствия преобразования путей в Unicode. Разница заметна, но не критична - обе укладываются в пределах окна ночного бэкапа.

Устойчивость к сбоям и поведение при перезагрузке сервера

NFS с hard и intr (прерывание по Ctrl+C) заставляет процессы ждать возвращения сервера бесконечно. При soft клиент возвращает ошибку EIO после retrans попыток - приложения падают, данные могут повредиться. В версии 4 добавлена операция RECLAIM_COMPLETE и клиентский кэш открытых файлов, что позволяет восстановить состояние после перезагрузки сервера без ошибок у приложений. Но если сервер ушёл надолго, процессы на клиенте висят в состоянии D (uninterruptible sleep), их нельзя прервать даже kill -9. Помогает только перезагрузка клиента или umount -f -l (lazy unmount) с последующим mount.

CIFS при потере соединения пытается переподключиться автоматически (опция reconnect, включена по умолчанию). При SMB 3.0+ используются устойчивые дескрипторы (persistent handles) - открытые файлы выживают при кратковременном отвале сети до 60 секунд (настраивается durable_timeout на сервере). Если сервер перезагрузился, клиент восстанавливает сессию и открытые файлы прозрачно для приложения. Но есть подвох: при cache=strict (по умолчанию) кэш страниц сбрасывается на сервер при каждом fsync, а при cache=loose - может рассинхронизироваться. Для бэкапов лучше cache=strict, для медиатеки - cache=none (обходит страничный кэш, читает напрямую).

В dmesg при проблемах NFS пишет:
CODE7

CIFS выдаёт:
CODE8

Оба протокола умеют автовосстановление, но CIFS делает это менее инвазивно для пользовательских процессов.

Реальные сценарии выбора, тонкости и итог

Если в сети только Linux-машины, FreeBSD, macOS и, возможно, Android через Termux - NFS v4.2 естественный выбор. Он родной для POSIX, не требует настройки пользователей и паролей отдельно от системы, передаёт права, владельца, симлинки, расширенные атрибуты и ACL без дополнительных телодвижений. Настройка займёт 10 минут: установить nfs-kernel-server, поправить /etc/exports, прописать fstab с vers=4.2 и x-systemd.automount. Бэкапы, образы ВМ, сборки проектов - всё работает быстро и предсказуемо.

Если в сети есть Windows-клиенты, смарт-телевизоры, медиаплееры на Android TV, принтеры с поддержкой SMB - CIFS неизбежен. Samba раздаёт шары всем подряд, аутентификация через пароли понятна пользователям, корзина (vfs objects = recycle) спасает от случайного удаления. Для Linux-клиентов добавляют запись в fstab с credentials и uid/gid, получают работающую точку монтирования. Цена - накладные расходы на шифрование, если включено, и немного меньшая скорость на метаданных.

Гибридный вариант: на сервере подняты оба протокола. NFS для Linux-машин (бэкапы, /home, контейнеры), CIFS для Windows и бытовых устройств. Экспортируют одну и ту же директорию /mnt/storage через /etc/exports и [storage] в smb.conf. Конфликтов нет - протоколы работают на разных портах и не пересекаются в кэшах. Единственное внимание: при записи через CIFS создаются файлы с Windows-атрибутами (archive, hidden), которые NFS-клиент видит как обычные биты режима. chattr +i на сервере защищает критичные файлы от изменения через любой протокол.

Опция vers=4.2 в fstab не гарантирует использование 4.2 - если сервер старый, клиент упадёт на 4.1 или 4.0. Жёстко зафиксировать можно только vers=4.2,minorversion=2, но тогда монтирование упадёт с ошибкой при несовпадении. Лучше оставить vers=4 и проверить в /proc/fs/nfsfs/volumes реальную версию после монтирования.

В CIFS опция serverino (включена по умолчанию) использует inode с сервера. На больших шарах с миллионами файлов это экономит память клиента на кэше inode. Но если сервер - Samba на ZFS с dedup, inode могут не быть уникальными. Лечится noserverino, но тогда ls -i покажет локальные номера.

NFS не любит, когда серверная файловая система забита под завязку. При заполнении выше 90% производительность записью падает нелинейно из-за фрагментации свободного пространства. df -i показывает inode - на ext4 их число фиксировано при создании, на xfs и btrfs выделяется динамически. Для NFS-хранилища лучше xfs или btrfs с nodatacow на датасете бэкапов.

CIFS кэширует атрибуты каталогов 10 секунд (параметр actimeo не работает, есть dir_cache_timeout в модуле ядра). После создания файла на сервере он появится в ls на клиенте с задержкой. echo 0 > /proc/fs/cifs/DirectoryCacheTimeout отключает кэш полностью - полезно для синхронизации скриптов.

Автомонтирование через x-systemd.automount в fstab работает для обоих протоколов, но при hard NFS первый доступ может зависнуть на минуту, если сервер недоступен. Добавляют x-systemd.mount-timeout=30 - systemd прервёт попытку через 30 секунд и вернёт ошибку приложению.

Для бэкапов по расписанию (systemd timer + rsync/restic/borg) лучше монтировать точку в скрипте перед запуском и размонтировать после - systemd-run --wait --user mount /mnt/net-nfs и umount в ExecStopPost. Это исключает зависание таймера на недоступном сервере.

NFS и CIFS решают разные задачи, хотя и выглядят похоже - сетевая папка в файловом менеджере. NFS даёт нативную POSIX-семантику, максимальную скорость на Linux-клиентах, прозрачные симлинки и ACL, простое управление через UID/GID. Требует доверенной сети, не шифрует трафик из коробки, при проблемах с сервером может зависнуть клиентский процесс необратимо. CIFS даёт универсальный доступ от Windows до телевизора, встроенное шифрование, устойчивые дескрипторы, привычную аутентификацию по паролям. Платит за это накладными расходами на метаданные, неполной поддержкой POSIX-прав, необходимостью мапинга UID/GID на клиенте.

В чисто Linux-домашней сети с парой настольных, ноутбука и сервера - NFS v4.2 с hard,rsize=1M,wsize=1M,x-systemd.automount даст меньше головной боли и больше скорости. Если в сети живёт Windows-хост или умный телевизор - поднимают Samba рядом, экспортируют те же диски, и каждый клиент работает по своему протоколу. Это не компромисс, а правильная инженерия: используй инструмент под задачу, а не под привычку.