Menyelesaikan nama host membutuhkan waktu 5 detik

8

Saya memiliki bind9server DNS master dan 2 server slave yang berjalan di IPv4 (Debian Jessie), menggunakan /etc/bind/named.conf:

listen-on-v6 { none; };

Ketika saya mencoba untuk terhubung dari server yang berbeda, setiap koneksi membutuhkan setidaknya 5 detik (saya menggunakan info waktu Joseph untuk debugging):

$ curl -w "@curl-format.txt" -o /dev/null -s https://example.com
            time_namelookup:  5.512
               time_connect:  5.512
            time_appconnect:  5.529
           time_pretransfer:  5.529
              time_redirect:  0.000
         time_starttransfer:  5.531
                            ----------
                 time_total:  5.531

Menurut curl, pencarian membutuhkan sebagian besar waktu, namun standar nslookupsangat cepat:

$ time nslookup example.com > /dev/null 2>&1

real    0m0.018s
user    0m0.016s
sys     0m0.000s

Setelah memaksa curluntuk menggunakan IPv4, itu menjadi jauh lebih baik:

$ curl -4 -w "@curl-format.txt" -o /dev/null -s https://example.com

            time_namelookup:  0.004
               time_connect:  0.005
            time_appconnect:  0.020
           time_pretransfer:  0.020
              time_redirect:  0.000
         time_starttransfer:  0.022
                            ----------
                 time_total:  0.022

Saya telah menonaktifkan IPv6 pada host:

echo 1 > /proc/sys/net/ipv6/conf/eth0/disable_ipv6

meskipun masalahnya tetap ada. Saya sudah mencoba berlari straceuntuk melihat apa alasan dari timeout:

write(2, "*", 1*)                        = 1
write(2, " ", 1 )                        = 1
write(2, "Hostname was NOT found in DNS ca"..., 36Hostname was NOT found in DNS cache
) = 36
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 4
close(4)                                = 0
mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f220bcf8000
mprotect(0x7f220bcf8000, 4096, PROT_NONE) = 0
clone(child_stack=0x7f220c4f7fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f220c4f89d0, tls=0x7f220c4f8700, child_tidptr=0x7f220c4f89d0) = 2004
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
poll(0, 0, 4)                           = 0 (Timeout)
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
poll(0, 0, 8)                           = 0 (Timeout)
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
poll(0, 0, 16)                          = 0 (Timeout)
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
poll(0, 0, 32)                          = 0 (Timeout)
rt_sigaction(SIGPIPE, NULL, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f22102e08d0}, NULL, 8) = 0
poll(0, 0, 64)                          = 0 (Timeout)

Tampaknya tidak menjadi masalah firewall karena nslookup(atau curl -4) menggunakan server DNS yang sama. Adakah yang tahu apa yang salah?

Ini tcpdumpdari tuan rumah tcpdump -vvv -s 0 -l -n port 53:

tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:14:52.542526 IP (tos 0x0, ttl 64, id 35839, offset 0, flags [DF], proto UDP (17), length 63)
    192.168.1.1.59163 > 192.168.1.2.53: [bad udp cksum 0xf9f3 -> 0x96c7!] 39535+ A? example.com. (35)
20:14:52.542540 IP (tos 0x0, ttl 64, id 35840, offset 0, flags [DF], proto UDP (17), length 63)
    192.168.1.1.59163 > 192.168.1.2.53: [bad udp cksum 0xf9f3 -> 0x6289!] 45997+ AAAA? example.com. (35)
20:14:52.543281 IP (tos 0x0, ttl 61, id 63674, offset 0, flags [none], proto UDP (17), length 158)
    192.168.1.2.53 > 192.168.1.1.59163: [udp sum ok] 45997* q: AAAA? example.com. 1/1/0 example.com. [1h] CNAME s01.example.com. ns: example.com. [10m] SOA ns01.example.com. ns51.domaincontrol.com. 2016062008 28800 7200 1209600 600 (130)
20:14:57.547439 IP (tos 0x0, ttl 64, id 36868, offset 0, flags [DF], proto UDP (17), length 63)
    192.168.1.1.59163 > 192.168.1.2.53: [bad udp cksum 0xf9f3 -> 0x96c7!] 39535+ A? example.com. (35)
20:14:57.548188 IP (tos 0x0, ttl 61, id 64567, offset 0, flags [none], proto UDP (17), length 184)
    192.168.1.2.53 > 192.168.1.1.59163: [udp sum ok] 39535* q: A? example.com. 2/2/2 example.com. [1h] CNAME s01.example.com., s01.example.com. [1h] A 136.243.154.168 ns: example.com. [30m] NS ns01.example.com., example.com. [30m] NS ns02.example.com. ar: ns01.example.com. [1h] A 136.243.154.168, ns02.example.com. [1h] A 192.168.1.2 (156)
20:14:57.548250 IP (tos 0x0, ttl 64, id 36869, offset 0, flags [DF], proto UDP (17), length 63)
    192.168.1.1.59163 > 192.168.1.2.53: [bad udp cksum 0xf9f3 -> 0x6289!] 45997+ AAAA? example.com. (35)
20:14:57.548934 IP (tos 0x0, ttl 61, id 64568, offset 0, flags [none], proto UDP (17), length 158)
    192.168.1.2.53 > 192.168.1.1.59163: [udp sum ok] 45997* q: AAAA? example.com. 1/1/0 example.com. [1h] CNAME s01.example.com. ns: example.com. [10m] SOA ns01.example.com. ns51.domaincontrol.com. 2016062008 28800 7200 1209600 600 (130)

EDIT: Di bind log sering muncul pesan ini:

error sending response: host unreachable

Padahal, setiap permintaan akhirnya dijawab (hanya butuh 5s). Semua mesin adalah server fisik (bukan karena kesalahan NAT), kemungkinan besar paket diblokir oleh router. Berikut ini kemungkinan pertanyaan terkait: Pencarian DNS terkadang membutuhkan waktu 5 detik .

Tombart
sumber
1
strace -ttakan membuat jejak lebih informatif saat melacak penundaan.
JigglyNaga
Terima kasih, ini tidak banyak membantu dalam kasus ini. Tampaknya macet saat mencoba lagi koneksi yang sama dengan batas waktu yang meningkat poll(0, 0, 1000) = 0 (Timeout). Di sisi server DNS saya sering mendapatkan kesalahan error sending response: host unreachableyang sepertinya paket keluar diblokir (tetapi tidak untuk nslookup).
Tombart
Ini terlihat mirip- philippecloutier.com/...
Jeff Schaller

Jawaban:

9

Jawaban singkat:

Solusi memaksa glibcuntuk menggunakan kembali soket untuk mencari AAAAdan Acatatan, dengan menambahkan baris ke /etc/resolv.conf:

options single-request-reopen

Penyebab sebenarnya dari masalah ini mungkin:

Jawaban panjang:

Program menyukai curlatau wgetmenggunakan fungsi glibc's getaddrinfo () , yang mencoba untuk kompatibel dengan IPv4 dan IPv6 dengan mencari kedua catatan DNS secara paralel. Itu tidak mengembalikan hasil sampai kedua catatan diterima (ada beberapa masalah yang terkait dengan perilaku tersebut ) - ini menjelaskan hal di straceatas. Ketika IPv4 dipaksakan, seperti secara curl -4internal gethostbyname()yang meminta Acatatan saja.

Dari tcpdumpkita dapat melihat bahwa:

  • -> A? dua permintaan dikirim di awal
  • -> AAAA? (meminta alamat IPv6)
  • <- AAAA balasan
  • -> A? meminta lagi alamat IPv4
  • <- A mendapat balasan
  • -> AAAA? meminta IPv6 lagi
  • <- AAAA balasan

Satu Abalasan dibatalkan karena beberapa alasan, itulah pesan kesalahan ini:

error sending response: host unreachable

Namun tidak jelas bagi saya mengapa ada kebutuhan untuk AAAApermintaan kedua .

Untuk memverifikasi bahwa Anda mengalami masalah yang sama, Anda dapat memperbarui batas waktu di /etc/resolv.conf:

options timeout:3

seperti yang dijelaskan di sini :

$ curl -w "@curl-format.txt" -o /dev/null -s https://example.com

            time_namelookup:  3.511
               time_connect:  3.511
            time_appconnect:  3.528
           time_pretransfer:  3.528
              time_redirect:  0.000
         time_starttransfer:  3.531
                            ----------
                 time_total:  3.531

Ada dua opsi terkait lainnya di man resolv.conf:

permintaan tunggal (karena glibc 2.10) set RES_SNGLKUP di _res.options. Secara default, glibc melakukan pencarian IPv4 dan IPv6 secara paralel sejak versi 2.9. Beberapa server DNS alat tidak dapat menangani pertanyaan ini dengan benar dan membuat permintaan waktu habis. Opsi ini menonaktifkan perilaku dan membuat glibc melakukan permintaan IPv6 dan IPv4 secara berurutan (dengan mengorbankan beberapa proses penyelesaian yang lambat).

single-request-reopen (sejak glibc 2.9) Resolver menggunakan soket yang sama untuk permintaan A dan AAAA. Beberapa perangkat keras secara keliru mengirimkan kembali hanya satu balasan. Ketika itu terjadi, sistem klien akan duduk dan menunggu jawaban kedua. Mengaktifkan opsi ini akan mengubah perilaku ini sehingga jika dua permintaan dari port yang sama tidak ditangani dengan benar, ia akan menutup soket dan membuka yang baru sebelum mengirim permintaan kedua.

Masalah terkait:

Tombart
sumber
@RuiFRibeiro Semata-mata berdasarkan pada naik-volt tampaknya pengguna menemukan jawaban lain lebih bermanfaat. Bukan berarti tersinggung.
Tombart
4

Seperti @Tombart katakan, penundaan itu karena menunggu batas waktu resolusi IPv6.

Tindakan lain yang mungkin dilakukan adalah memprioritaskan IPv4 di /etc/gai.conf

Dari komentar di /etc/gai.conf

#   For sites which prefer IPv4 connections change the last line to
#
precedence ::ffff:0:0/96  100

Setelah berubah gai.conf, Anda harus memulai ulang aplikasi apa pun menggunakan pustaka resolver DNS agar perubahan diterapkan.

Pikiran Anda bahwa jika Anda menggunakan server BIND tanpa konektivitas IPv6, saya sarankan menonaktifkan IPv6 nameddan mengambil dari petunjuk root alamat IPv6. Jelas itu masih akan mencoba untuk menyelesaikan alamat AAAA.

Jadi untuk konfigurasi BIND,

Di / etc / default / bind9, tambahkan -4 untuk alamat IPv4:

OPTIONS="-4 -u bind"

dan dalam /etc/bind/db.root, hapus semua baris dengan root DNS AAAA.

Rui F Ribeiro
sumber
2

Saya memiliki masalah serupa saat menggunakan BIND9. Untuk memperbaikinya saya perlu menambahkan:

filter-aaaa-on-v4 yes;

opsi untuk named.conf.

( Informasi lebih lanjut )

xtavras
sumber