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

Как устранить неполадки в ядре Linux dns_resolver

Linux предоставляет средство, которое позволяет ядру и его модулям разрешать имена DNS, полагаясь на инструменты пользовательского пространства. Это, например, используется CIFS для поддержки ссылок в DFS.

Проблема, которую я вижу, заключается в том, что я не могу заставить ядро ​​разрешать конкретное DNS-имя, и я не понимаю, почему это не удается.

Чтобы понять основную причину, я включил вывод отладки как в CIFS, так и в DNS-преобразователе ядра, выполнив следующие команды:

echo "1" >  /sys/module/dns_resolver/parameters/debug  # dns_resolver
echo "7" > /proc/fs/cifs/cifsFYI  # CIFS

Вот что я вижу в dmesg, когда происходит сбой:

fs/cifs/cifs_dfs_ref.c: DFS: ref path: \ESOTEST\dfstest\FS_SERV
fs/cifs/cifs_dfs_ref.c: DFS: node path: \FS\FS_SERV
fs/cifs/cifs_dfs_ref.c: DFS: fl: 2, srv_type: 0
fs/cifs/cifs_dfs_ref.c: DFS: ref_flags: 0, path_consumed: 24
fs/cifs/netmisc.c: address conversion returned 0 for FS
fs/cifs/netmisc.c: address conversion returned 0 for FS
[ls    ] ==> dns_query((null),FS,2,(null))
fs/cifs/dns_resolve.c: dns_resolve_server_name_to_ip: unable to resolve: FS
fs/cifs/cifs_dfs_ref.c: cifs_compose_mount_options: Failed to resolve server part of \\FS\FS_SERV to IP:

-22

И это результат успешного разрешения:

fs/cifs/cifs_dfs_ref.c: DFS: node path: \ESOTEST\File-Server
fs/cifs/cifs_dfs_ref.c: DFS: fl: 2, srv_type: 0
fs/cifs/cifs_dfs_ref.c: DFS: ref_flags: 0, path_consumed: 28
fs/cifs/netmisc.c: address conversion returned 0 for ESOTEST
fs/cifs/netmisc.c: address conversion returned 0 for ESOTEST
[ls    ] ==> dns_query((null),ESOTEST,7,(null))
[ls    ] call request_key(,ESOTEST,)
[ls    ] ==> dns_resolver_match(ESOTEST,ESOTEST)
[ls    ] <== dns_resolver_match() = 1
[ls    ] <== dns_query() = 14
fs/cifs/dns_resolve.c: dns_resolve_server_name_to_ip: resolved: ESOTEST to 192.168.56.102
fs/cifs/cifsfs.c: Devname: \\ESOTEST\File-Server flags: 0

Я использую Windows в качестве DNS-сервера и могу разрешить имя "FS" с машины:

$ ping FS
PING FS.esodomain.com (192.168.56.104) 56(84) bytes of data.
64 bytes from fs.esodomain.com (192.168.56.104): icmp_seq=1 ttl=128 time=1.37 ms
64 bytes from fs.esodomain.com (192.168.56.104): icmp_seq=2 ttl=128 time=0.630 ms

Я также пробовал использовать key.dns_resolver для ручного выполнения теста, и, похоже, он работает:

$ key.dns_resolver -vv -D "FS" 'hello'
I: Key description: 'dns_resolver;-1;-1;0;FS'
I: Callout info: 'hello'
D: Get A/AAAA RR for hostname:'FS', options:'hello'
D: Opt hello
D: Resolve 'FS' with 1ff
D: getaddrinfo = 0
D: RR: 0,2,1,6,10,(null)
D: append '192.168.56.104'
I: The key instantiation data is '192.168.56.104'

Содержимое /etc/request-key.conf:

create  dns_resolver *      *               /sbin/key.dns_resolver %k
create  user    debug:*     negate      /bin/keyctl negate %k 30 %S
create  user    debug:*         rejected        /bin/keyctl reject %k 30 %c %S
create  user    debug:*         expired         /bin/keyctl reject %k 30 %c %S
create  user    debug:*         revoked         /bin/keyctl reject %k 30 %c %S
create  user    debug:loop:*    *       |/bin/cat
create  user    debug:*     *       /usr/share/keyutils/request-key-debug.sh %k %d %c %S
negate  *   *       *       /bin/keyctl negate %k 30 %S

Причина, по которой я возился с этим, заключается в том, что я пытаюсь успешно смонтировать общий ресурс Windows DFS. Я могу монтировать и получать доступ к папкам, которые размещены на корневом сервере, но когда я пытаюсь получить доступ к подпапке, которая относится к внешнему серверу, я получаю:

ls: cannot access /mnt/dfstest/FS_SERV/: Invalid argument

Я на ядре 3.7.10:

Linux gentoo 3.7.10-gentoo-r1 #3 SMP Fri Apr 19 17:32:20 PDT 2013 x86_64 Intel(R) Xeon(R) CPU E5620 @ 2.40GHz GenuineIntel GNU/Linux

При захвате сети я не вижу никаких DNS-запросов для «FS», в то время как я вижу запрос для «ESOTEST». Это говорит о том, что запрос никогда не поступал.

Какие следующие шаги вы бы порекомендовали для устранения этой проблемы?

Похоже, это вызвано ядром Linux. В частности, файлом dns_resolver. "FS" даже не пытается разрешить.

Следующие строки в dns_resolver (net / dns_resolver / dns_query.c), похоже, вызывают это:

if (namelen < 3)
    return -EINVAL;

Я не знаю, зачем нужна эта проверка. Я попробую переименовать другой сервер с «FS» на что-нибудь более длинное. Я попробую перекомпилировать ядро ​​без этой проверки.

ОБНОВЛЕНИЕ: да, это была причина, и он работает после переименования имени хоста на более длинное имя

Также, по-видимому ядро dns_resolver не соблюдает TTL. Чтобы очистить кеш DNS ядра:

sudo keyctl clear $ ((16 # $ (sudo cat / proc / keys | grep .dns_resolver | awk '{print $ 1;}'))))