Назад | Перейти на главную страницу

Как работает реализация setclientid в Linux NFS-сервере?

Кто-нибудь понимает протокол NFS (версия 4) или его реализацию на сервере Linux NFS достаточно хорошо, чтобы объяснить, как setclientid согласовывает аутентификацию?

Задний план:

У меня есть сервер CentOS 7, на котором работает сервер NFS4 с аутентификацией Kerberos, интеграция с Kerberos обеспечивается PowerBroker Identity Services Open. Этот сервер находится в производстве и используется ежедневно. Я пытался создать идентичный сервер, но, похоже, не могу. Я настроил все на старом сервере около шести месяцев назад, и мне кажется, что я достаточно хорошо задокументировал то, что сделал, но, похоже, это больше не работает. Вдобавок к этому я попытался максимально упростить настройку, но ничего не изменилось. Ни при каких обстоятельствах я не могу монтировать экспорт с использованием Kerberos. Я не уверен, почему это так, но после устранения этой проблемы, которая кажется вечностью, я считаю, что определил, где возникает проблема.

Наблюдаемое поведение setclientid:

Ниже приведены два фрагмента (имена и IP-адреса заменены) из системного журнала на тестовой системе, с которой я пробовал подключиться, она работает под управлением Ubuntu 16.04 Desktop (ubuntu-1604x, 192.168.1.30).

Оба сервера работают под управлением CentOS 7 и кажутся идентичными (я безуспешно пытался использовать разные версии программного обеспечения на сервере B).

Сервер A (192.168.1.125):

Nov  8 19:36:04 ubuntu-1604x kernel: [316817.783379] NFS call  setclientid auth=RPCSEC_GSS, 'Linux NFSv4.0 192.168.1.30/192.168.1.125 tcp'
Nov  8 19:36:04 ubuntu-1604x kernel: [316817.854777] NFS reply setclientid: 0
Nov  8 19:36:04 ubuntu-1604x kernel: [316817.854781] NFS call  setclientid_confirm auth=RPCSEC_GSS, (client ID 11cfcd5b138b872c)
Nov  8 19:36:04 ubuntu-1604x kernel: [316817.855413] NFS reply setclientid_confirm: 0

Сервер B (192.168.1.250):

Nov  8 19:34:59 ubuntu-1604x kernel: [316752.414152] NFS call  setclientid auth=RPCSEC_GSS, 'Linux NFSv4.0 192.168.1.30/192.168.1.250 tcp'
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.455212] NFS reply setclientid: -13
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.455217] NFS call  setclientid auth=RPCSEC_GSS, 'Linux NFSv4.0 192.168.1.30/192.168.1.250 tcp'
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.490325] NFS reply setclientid: -13
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.490358] NFS call  setclientid auth=UNIX, 'Linux NFSv4.0 192.168.1.30/192.168.1.250 tcp
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.490768] NFS reply setclientid: 0
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.490772] NFS call  setclientid_confirm auth=UNIX, (client ID 1580e45bf5783af5)
Nov  8 19:34:59 ubuntu-1604x kernel: [316752.491354] NFS reply setclientid_confirm: 0

Вопрос:

Нижний приводит к ошибке «Permission denied», которая имеет для меня смысл, поскольку экспорт разрешает только аутентификацию Kerberos, но я не могу понять ответ -13 и переключение на другой механизм аутентификации. Кто-нибудь может мне это объяснить?

Изменить: после 7 обновлений и ошибок, которые, казалось бы, были исправлены, вопрос по-прежнему остается таким же, как указано выше.

Источники, на которые я смотрел:

Помимо различных сообщений, которые я нашел разбросанными по Интернету, я изучил RFC 7530, 7531 и 7931. Я еще не читал подробно все документы, но я внимательно прочитал часть о setclientid. и 'setclientid_confirm' в RFC 7530 несколько раз, и я просто не могу понять, что вышесказанное имеет смысл - я думаю, что мое понимание ошибочно.

Обновить

Я считаю, что -13 - это ошибка RPC. Глядя на исходный код nfs4proc Я так понимаю, что -13 в выводе исходит от rpc_run_task. Заглянув в rpc_run_task, я понял, что он запускает rpc_execute - я не знаю, что именно выполняется, но, предположительно, реализация соответствует RFC 5531, который удобно имеет 14 различных ошибок аутентификации, из которых номер 13 - `` нет учетных данных для пользователя '', ошибка I За время тестирования несколько раз видел вывод rpc.gssd.

Обновление 2

Ошибка, которую я видел в rpc.gssd:

ERROR: No credentials found for connection to server nfsserver.example.org

Оглядываясь назад, я видел это только при тестировании на одном хосте, и я никогда не подтверждал, что он может подключаться к другому серверу. Я нигде не могу найти это задокументировано, но я вижу много ссылок на другую ошибку RPC 13 в другом месте: Ошибка RPC 13 (RPC был прерван из-за тайм-аута) Учитывая, что я могу нормально смонтировать другой сервер, возможно, это я получаю ошибку?

Обновление 3

Я запустил strace для процесса rpc.gssd на обоих серверах и сделал еще одну попытку монтирования. Сервер A ничего не выдал, предположительно потому, что я подключался раньше. Сервер B выводит следующее:

strace: Process 843 attached
epoll_wait(4, [{EPOLLIN, {u32=8, u64=8}}], 32, -1) = 1
read(8, "\r\0\0\0\0\2\0\0\0\0\0\0\20\0\0\0info\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 80
inotify_rm_watch(8, 13)                 = -1 EINVAL (Invalid argument)
inotify_add_watch(8, "nfsd4_cb/clnt3", IN_CREATE|IN_DELETE) = 14
openat(7, "nfsd4_cb/clnt3", O_RDONLY)   = 3
openat(3, "gssd", O_RDWR|O_NONBLOCK)    = -1 ENOENT (No such file or directory)
openat(3, "krb5", O_RDWR|O_NONBLOCK)    = -1 ENOENT (No such file or directory)
close(3)                                = 0
read(8, 0x7ffd2945e280, 4096)           = -1 EAGAIN (Resource temporarily unavailable)
epoll_wait(4,

Я обнаружил указанную папку (nfsd4_cb) в / var / lib / nfs / rpc_pipefs, и ее содержимое не идентично на двух серверах. У рабочего есть длинный список папок, они, кажется, представляют клиентов, которые ранее подключились / подключены в настоящее время - возможно, всех назначенных клиентов. Возможно, это свободный конец.

Я вижу каталог gssd в / var / lib / nfs / rpc_pipefs, поэтому сообщение «Нет такого файла или каталога» сбивает с толку. Изменить: я полагаю, он мог искать в другой папке, я не знаю, что означает первый аргумент openat, и он другой. Кто-нибудь это понимает?

Обновление 4

Я захватил сетевой трафик из своего тестирования и проверил пакет setclientid. Учетные данные, которые отправляются на сервер A, имеют вид RPCSEC_GSS, но учетные данные, которые отправляются серверу B, имеют вид 'AUTH_UNIX'. В файле журнала было похоже, что было сделано 3 вызова setclientid, и сервер ответил, но отправляется только один, поэтому «отклонение» должно происходить локально на клиенте.

Я использую ту же команду монтирования с замененным именем хоста.

Обновление 5

Когда все выходные данные отладки RPC включены, я просмотрел файл журнала и нашел то, что, по моему мнению, является результатом выполнения задачи RPC, запущенной SETCLIENTID (если я правильно понимаю это, то есть. См.Обновить').

Итак, сравнивая вывод работающего монтирования и того, что не удалось, я считаю, что отследил, где эта вещь RPC идет не так, но я не совсем понимаю, что происходит.

Фрагмент из рабочего крепления:

Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150180] NFS call  setclientid auth=RPCSEC_GSS, 'Linux NFSv4.0 192.168.1.30/192.168.1.125 tcp'
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150181] RPC:       new task initialized, procpid 12556
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150182] RPC:       allocated task ffff880034f92500
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150183] RPC:  2251 __rpc_execute flags=0x5280
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150184] RPC:  2251 call_start nfs4 proc SETCLIENTID (sync)
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150185] RPC:  2251 call_reserve (status 0)
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150186] RPC:  2251 reserved req ffff880211697600 xid 29a970ab
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150187] RPC:       wake_up_first(ffff880130755190 "xprt_sending")
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150187] RPC:  2251 call_reserveresult (status 0)
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150188] RPC:  2251 call_refresh (status 0)
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150190] RPC:       gss_create_cred for uid 0, flavor 390004
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150191] RPC:       gss_create_upcall for uid 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.150196] RPC:       __gss_find_upcall found nothing
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171925] RPC:       __gss_find_upcall found msg ffff8800db521000
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171938] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171939] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171944] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171944] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171950] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171951] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171954] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171954] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171957] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171958] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171961] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171962] RPC:       krb5_encrypt returns 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171964] RPC:       gss_import_sec_context_kerberos: returning 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171965] RPC:       gss_fill_context Success. gc_expiry 4438759401 now 4431124651 timeout 30539 acceptor
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171968] RPC:       gss_pipe_downcall returning 80
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171985] RPC:       gss_create_upcall for uid 0 result 0
Nov 11 10:57:48 ubuntu-1604x kernel: [544916.171987] RPC:  2251 refreshing RPCSEC_GSS cred ffff8802121513c0

Фрагмент неработающего монтирования:

Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738317] NFS call  setclientid auth=RPCSEC_GSS, 'Linux NFSv4.0 192.168.1.30/192.168.1.250 tcp'
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738318] RPC:       new task initialized, procpid 12672
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738319] RPC:       allocated task ffff880158862200
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738320] RPC:  2280 __rpc_execute flags=0x5280
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738322] RPC:  2280 call_start nfs4 proc SETCLIENTID (sync)
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738323] RPC:  2280 call_reserve (status 0)
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738324] RPC:  2280 reserved req ffff8801b5ef2800 xid ab6b57ae
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738325] RPC:       wake_up_first(ffff880130751990 "xprt_sending")
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738326] RPC:  2280 call_reserveresult (status 0)
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738327] RPC:  2280 call_refresh (status 0)
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738328] RPC:       gss_create_cred for uid 0, flavor 390004
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738330] RPC:       gss_create_upcall for uid 0
Nov 11 10:59:41 ubuntu-1604x kernel: [545029.738332] RPC:       __gss_find_upcall found nothing
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835573] RPC:       __gss_find_upcall found msg ffff8801b5ef3400
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835576] RPC:       gss_fill_context returns error 13
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835580] RPC:       gss_pipe_downcall returning 16
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835593] RPC:       gss_create_upcall for uid 0 result -13
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835597] RPC:  2280 call_refreshresult (status -13)
Nov 11 10:59:42 ubuntu-1604x kernel: [545029.835598] RPC:  2280 call_refreshresult: refresh creds failed with error -13

Ошибка -13 должна быть этой, и вполне может быть RPCSEC_GSS_CREDPROBLEM = 13, / * нет учетных данных для пользователя * / ссылка на RFC 5531. __gss_find_upcall найдено сообщение отличается от рабочего, но я не уверен, что это значит. При рабочем монтировании явно регистрируется, что учетные данные проверяются позже, поэтому не может быть, что учетные данные не прошли проверку, они должны быть не найдены.

Nov 11 10:57:48 ubuntu-1604x kernel: [544916.172735] RPC:  2251 validating RPCSEC_GSS cred ffff8802121513c0

Используемая команда монтирования точно такая же, за исключением имени хоста. Как имя хоста влияет на поиск «учетных данных»? Куда это смотрит? Кто-нибудь знает, что происходит?

Обновление 6

Прямо перед вызовом setclientid NFS есть некоторый трафик на сервер KDC. А 'TGS-REQ'запрос отправлен, и сервер отвечает'KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN'. Я недостаточно хорошо это понимаю, чтобы понять, что именно отправляется в KDC, а трафик зашифрован. Оба сервера имеют одинаковые SPN (с собственным именем хоста). Кто-нибудь понимает это достаточно хорошо, чтобы помочь определить, как имя хоста моей команды монтирования влияет на TGS-REQ что отправлено? У меня нет доступа к KDC, поэтому я не могу там устранять неполадки.

Обновление 7

Вышеупомянутая ошибка была вызвана неправильной записью обратного DNS. Исправив это, KDC теперь возвращает билет при получении TGS-REQ. Но наблюдаемое поведение такое же, монтирование не выполняется, вывод setclientid NFS в журнале точно такой же, вывод RPC выглядит так же. Что-то не так с полученным билетом - кто-нибудь знает, как это отладить?

Обновление 8

Билет кажется правильным. Я использовал Wireshark для захвата трафика и снова сравнил рабочий с нерабочим. Я заметил, что перед вызовом setclientid выполняются вызовы NULL.

Сначала тот, у кого нет учетных данных, затем тот, у которого есть правильные учетные данные. Оба сервера получают ответ на первый вызов NULL без учетных данных, но только рабочий сервер получает ответ на второй, другой пытается 4 раза без ответов.

Что это за вызовы NULL, которые я вижу, и как я могу отладить отсутствие ответа? Порт назначения - порт 2049, и другой трафик до 2049 получает ответ.

Строка rpc.gssd на серверах по-прежнему дает тот же результат, что и в обновлении 3.

Кроме того, я использовал lsof для подтверждения рабочего каталога rpc.gssd:

rpc.gssd    892                 root  cwd       DIR               0,39         0      12726 /var/lib/nfs/rpc_pipefs

Вот результат ls -la для этой папки:

total 0
dr-xr-xr-x. 11 root root   0 Nov 14 14:33 .
drwxr-xr-x.  6 root root 179 Nov 14 15:17 ..
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 cache
dr-xr-xr-x.  3 root root   0 Nov 14 14:33 gssd
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 lockd
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 mount
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 nfs
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 nfsd
dr-xr-xr-x.  2 root root   0 Nov 14 22:31 nfsd4_cb
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 portmap
dr-xr-xr-x.  2 root root   0 Nov 14 14:33 statd

Есть папка gssd, почему ошибка ENOENT?

openat(3, "gssd", O_RDWR|O_NONBLOCK)    = -1 ENOENT (No such file or directory)
openat(3, "krb5", O_RDWR|O_NONBLOCK)    = -1 ENOENT (No such file or directory)

Изменить: вышеуказанное также происходит на рабочем сервере при первом подключении.