Việc giải quyết tên máy chủ mất 5 giây


8

Tôi có một bind9máy chủ DNS chính và 2 máy chủ nô lệ chạy trên IPv4 (Debian Jessie), sử dụng /etc/bind/named.conf:

listen-on-v6 { none; };

Khi tôi cố gắng kết nối từ (các) máy chủ khác nhau, mỗi kết nối mất ít nhất 5 giây (Tôi đang sử dụng thông tin thời gian của Joseph để gỡ lỗi):

$ 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

Theo đó curl, việc tra cứu chiếm phần lớn thời gian, tuy nhiên tiêu chuẩn nslookuprất nhanh:

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

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

Sau khi buộc curlphải sử dụng IPv4, nó trở nên tốt hơn nhiều:

$ 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

Tôi đã tắt IPv6 trên máy chủ:

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

mặc dù vấn đề vẫn tồn tại Tôi đã thử chạy straceđể xem lý do hết giờ:

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)

Dường như đó không phải là sự cố tường lửa vì nslookup(hoặc curl -4) đang sử dụng cùng một máy chủ DNS. Bất cứ ý tưởng những gì có thể là sai?

Đây là tcpdumptừ máy chủ lưu trữ 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: Trong nhật ký liên kết thường xuất hiện thông báo này:

error sending response: host unreachable

Mặc dù, mỗi truy vấn cuối cùng được trả lời (chỉ mất 5 giây). Tất cả các máy đều là máy chủ vật lý (không phải lỗi của NAT), nhiều khả năng các gói đang bị chặn bởi bộ định tuyến. Đây là câu hỏi khá có khả năng liên quan: Tra cứu DNS đôi khi mất 5 giây .


1
strace -ttsẽ làm cho dấu vết nhiều thông tin hơn khi theo dõi sự chậm trễ.
JigglyNaga

Cảm ơn, nó không giúp được gì nhiều trong trường hợp này. Nó dường như bị mắc kẹt trong một cái nhìn trong khi thử lại cùng một kết nối với thời gian chờ tăng lên poll(0, 0, 1000) = 0 (Timeout). Về phía máy chủ DNS, tôi gặp lỗi thường xuyên error sending response: host unreachable, có vẻ như gói tin đi bị chặn (nhưng không phải cho nslookup).
Tombart

Điều này có vẻ tương tự- philippecloutier.com/ Từ
Jeff Schaller

Câu trả lời:


9

Câu trả lời ngắn:

Một cách giải quyết là buộc glibcphải sử dụng lại một ổ cắm để tra cứu AAAAAghi lại, bằng cách thêm một dòng vào /etc/resolv.conf:

options single-request-reopen

Nguyên nhân thực sự của vấn đề này có thể là:

Câu trả lời dài:

Các chương trình như curlhoặc wgetsử dụng chức năng của glibc getaddrinfo () , cố gắng tương thích với cả IPv4 và IPv6 bằng cách tra cứu song song cả hai bản ghi DNS. Nó không trả về kết quả cho đến khi cả hai hồ sơ được nhận (có một số vấn đề liên quan đến hành vi đó ) - điều này giải thích straceở trên. Khi IPv4 bị bắt buộc, như curl -4bên trong gethostbyname()chỉ truy vấn để Aghi lại.

Từ tcpdumpchúng ta có thể thấy rằng:

  • -> A? hai yêu cầu được gửi ở đầu
  • -> AAAA? (yêu cầu địa chỉ IPv6)
  • <- AAAA Đáp lại
  • -> A? yêu cầu lại địa chỉ IPv4
  • <- A đã trả lời
  • -> AAAA? yêu cầu IPv6 một lần nữa
  • <- AAAA Đáp lại

Một Acâu trả lời bị bỏ vì một số lý do, đó là thông báo lỗi này:

error sending response: host unreachable

Tuy nhiên, điều đó không rõ ràng với tôi tại sao cần có AAAAtruy vấn thứ hai .

Để xác minh rằng bạn đang gặp vấn đề tương tự, bạn có thể cập nhật thời gian chờ trong /etc/resolv.conf:

options timeout:3

như được mô tả ở đây :

$ 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

Có hai lựa chọn liên quan khác trong man resolv.conf:

yêu cầu đơn (kể từ glibc 2.10) đặt RES_SNGLKUP trong _res.options. Theo mặc định, glibc thực hiện song song tìm kiếm IPv4 và IPv6 kể từ phiên bản 2.9. Một số máy chủ DNS của thiết bị không thể xử lý các truy vấn này đúng cách và hết thời gian yêu cầu. Tùy chọn này vô hiệu hóa hành vi và làm cho glibc thực hiện các yêu cầu IPv6 và IPv4 một cách tuần tự (với chi phí làm chậm quá trình giải quyết).

đơn yêu cầu mở lại (kể từ glibc 2.9) Bộ giải quyết sử dụng cùng một ổ cắm cho các yêu cầu A và AAAA. Một số phần cứng nhầm gửi lại chỉ một trả lời. Khi điều đó xảy ra, hệ thống máy khách sẽ ngồi và chờ phản hồi thứ hai. Bật tùy chọn này sẽ thay đổi hành vi này để nếu hai yêu cầu từ cùng một cổng không được xử lý chính xác, nó sẽ đóng ổ cắm và mở một yêu cầu mới trước khi gửi yêu cầu thứ hai.

Các vấn đề liên quan:


@RuiFRibeiro Hoàn toàn dựa trên mức tăng, có vẻ như người dùng đã tìm thấy câu trả lời khác hữu ích hơn. Không có vi phạm nghĩa.
Tombart

4

Như @Tombart nói, sự chậm trễ là do chờ hết thời gian giải quyết IPv6.

Một cách hành động khả thi khác là ưu tiên cho IPv4 trong /etc/gai.conf

Từ các bình luận trong /etc/gai.conf

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

Sau khi thay đổi gai.conf, bạn cần khởi động lại bất kỳ ứng dụng nào bằng thư viện trình phân giải DNS để thay đổi có hiệu lực.

Xin lưu ý rằng nếu bạn đang sử dụng máy chủ BIND không có kết nối IPv6, tôi khuyên bạn nên vô hiệu hóa IPv6 trong namedvà lấy từ các gợi ý gốc địa chỉ IPv6. Rõ ràng là nó vẫn sẽ cố gắng giải quyết các địa chỉ AAAA.

Vì vậy, đối với cấu hình BIND,

Trong / etc / default / bind9, thêm -4 cho địa chỉ IPv4:

OPTIONS="-4 -u bind"

và trong /etc/bind/db.root, xóa tất cả các dòng có gốc DNS AAAA.


2

Tôi đã có một vấn đề tương tự trong khi sử dụng BIND9. Để sửa lỗi này, tôi cần thêm:

filter-aaaa-on-v4 yes;

tùy chọn của tôi named.conf.

( Thêm thông tin )

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.