วิธีปิดการใช้งานการค้นหา AAAA


35

... เพื่อชดเชยเซิร์ฟเวอร์ DNS ที่เสียหายซึ่งอยู่นอกเหนือการควบคุมของเรา

ปัญหาของเรา: เราปรับใช้อุปกรณ์ฝังตัวที่รวบรวมข้อมูลเซ็นเซอร์ในไซต์ต่างๆซึ่งส่วนใหญ่เป็น IPv4 เท่านั้น บางเว็บไซต์มีเครือข่ายที่ได้รับการบำรุงรักษาไม่ดีเช่น DNS ที่กำหนดค่าผิดหรือแคชในลักษณะอื่นและ / หรือไฟร์วอลล์ที่ละเว้นการสืบค้น AAAA ทั้งหมดหรือตอบกลับด้วยการตอบกลับที่ขาด (เช่น IP ผิดแหล่ง! ในฐานะผู้จัดหาภายนอกให้กับแผนกสิ่งอำนวยความสะดวกเราไม่มีอิทธิพลใด ๆ ต่อแผนกไอที (บางครั้งลังเล) โอกาสที่พวกเขาจะแก้ไขเซิร์ฟเวอร์ DNS / ไฟร์วอลล์ของพวกเขาเมื่อใดก็ตามที่เร็ว ๆ นี้นั้นมีขนาดเล็กที่สุด

ผลกระทบที่เกิดขึ้นกับอุปกรณ์ของเราคือแต่ละ gethostbyname () กระบวนการต้องรอจนกว่า AAAA จะหมดเวลาสอบถามซึ่งบางกระบวนการได้หมดเวลาเชื่อมต่อแล้ว

ฉันกำลังมองหาวิธีแก้ปัญหาที่ ...

  • ทั้งระบบ ฉันไม่สามารถกำหนดค่าแอปพลิเคชันหลายสิบรายการแยกกัน
  • ไม่ถาวรและกำหนดค่าได้ เราจำเป็นต้อง (เปิดใช้งานใหม่) เปิดใช้งาน IPv6 ตำแหน่ง / เมื่อได้รับการแก้ไข / เปิดใช้งาน รีบูตก็โอเค
  • หากโซลูชันต้องการไลบรารีหลักเช่น glibc ที่จะถูกแทนที่แพคเกจไลบรารีทดแทนควรพร้อมใช้งานจากแหล่งเก็บข้อมูลที่ทราบดีว่ามีการบำรุงรักษาที่ดี (เช่น Debian Testing, Ubuntu universe, EPEL) การสร้างตัวเองไม่ใช่ตัวเลือกด้วยเหตุผลมากมายที่ฉันไม่รู้ด้วยซ้ำว่าจะเริ่มต้นที่ใดดังนั้นฉันจึงไม่แสดงรายการเหล่านั้นเลย ...

ทางออกที่ชัดเจนที่สุดคือการกำหนดค่าไลบรารีตัวแก้ไขเช่นผ่าน / etc / { resolv , nsswitch , gai } .conf เพื่อไม่ให้สืบค้นระเบียน AAAA ตัวเลือกที่ resolv.conf no-inet6เป็นข้อเสนอแนะที่นี่จะว่าสิ่งที่ฉันกำลังมองหา น่าเสียดายที่ไม่มีการใช้งานอย่างน้อยไม่ได้อยู่ในระบบของเรา (libc6-2.13-38 + deb7u4 บน Debian 7; libc6-2.19-0ubuntu6.3 บน Ubuntu 14.04)

แล้วงั้นเหรอ? หนึ่งค้นหาวิธีการต่อไปนี้ที่แนะนำใน SF และที่อื่น ๆ แต่ไม่ใช่วิธีการทำงาน:

  • IPv6 ปิดการใช้งานทั้งหมดเช่นบัญชีดำโดย LKM IPv6 ใน /etc/modprobe.d/ sysctl -w net.ipv6.conf.all.disable_ipv6=1หรือ ( หมดความอยากรู้: ทำไมตัวแก้ไขปัญหาจึงขอ AAAA เมื่อปิดใช้งาน IPv6 แล้ว )
  • การลบoptions inet6จาก /etc/resolv.conf มันไม่ได้มีอยู่ในสถานที่แรกinet6มีการเปิดใช้งานเพียงแค่เริ่มต้นวันนี้
  • การตั้งค่าoptions single-requestใน /etc/resolv.conf สิ่งนี้ช่วยให้มั่นใจได้ว่าแบบสอบถาม A และ AAAA นั้นทำตามลำดับแทนที่จะเป็นแบบขนาน
  • การเปลี่ยนprecedenceใน /etc/gai.conf ที่ไม่ส่งผลต่อการสืบค้น DNS จะมีการประมวลผลการตอบกลับหลายวิธีเท่านั้น
  • การใช้ตัวแก้ไขภายนอก (หรือเรียกใช้ภูตตัวแก้ปัญหาในท้องถิ่นที่หลีกเลี่ยงเซิร์ฟเวอร์ DNS ที่เสีย) จะช่วยได้ แต่โดยทั่วไปจะไม่ได้รับอนุญาตจากนโยบายไฟร์วอลล์ของ บริษัท และสามารถทำให้ทรัพยากรภายในไม่สามารถเข้าถึงได้

แนวคิดทางเลือกที่น่าเกลียด:

  • เรียกใช้แคช DNS บน localhost กำหนดค่าเพื่อส่งต่อข้อความค้นหาที่ไม่ใช่ AAAA ทั้งหมด แต่ตอบกลับไปยังข้อความค้นหา AAAA ด้วย NOERROR หรือ NXDOMAIN (ขึ้นอยู่กับผลลัพธ์ของแบบสอบถาม A ที่สอดคล้องกัน) ฉันไม่ทราบว่าแคช DNS สามารถทำสิ่งนี้ได้
  • ใช้การจับคู่ iptables u32 ที่ชาญฉลาดหรือโมดูล iptables DNSของ Ondrej Caletka เพื่อจับคู่การสืบค้น AAAA เพื่อที่จะปฏิเสธการใช้งาน icmp (ตัวแก้ไข lib จะตอบสนองต่อสิ่งนั้นอย่างไร) หรือเปลี่ยนเส้นทางไปยังเซิร์ฟเวอร์ DNS ภายในที่ตอบสนองต่อ ทุกสิ่งด้วย NOERROR ที่ว่างเปล่า

โปรดทราบว่ามีคำถามที่คล้ายกันและเกี่ยวข้องใน SE คำถามของฉันแตกต่างกันไปตามที่อธิบายถึงปัญหาที่แท้จริงที่ฉันพยายามแก้ไขเนื่องจากมีการระบุข้อกำหนดที่ชัดเจนเนื่องจากบัญชีดำมีคำแนะนำที่ไม่ได้ผลสำหรับการใช้งานบางรายการและเนื่องจากไม่ใช่เฉพาะแอปพลิเคชันเดียว หลังจากการสนทนานี้ฉันโพสต์คำถามของฉัน


13
PS: ตรงกันข้ามกับความเชื่อที่นิยมใน SF มีเหตุผลที่ดีที่จะปิดการใช้งาน IPv6 / AAAA บนเครื่องในเครือข่ายเฉพาะ IPv4 เท่านั้นแม้ว่าที่ DNS ทำงาน: ลดภาระการออกอากาศ ลดภาระการแก้ปัญหา DNS เกือบ 50% ลดเวลาเริ่มต้นการเชื่อมต่อ (อย่างมีนัยสำคัญที่แคช DNS มีความล่าช้า) ปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดเพื่อปิดการใช้งานคุณสมบัติที่ไม่สามารถใช้งานได้เพื่อเพิ่มความปลอดภัยและความมั่นคง เป็นที่ยอมรับหากฉันลืมเปิดใช้งาน IPv6 อีกครั้งเมื่อพร้อมใช้งานแล้วระบบของฉันจะกลายเป็นบัลลาสต์ดั้งเดิมของ IPv4 ที่ขัดขวางการเปิดใช้งาน IPv6 หนึ่งควรได้รับอนุญาตให้ชั่งน้ำหนักผู้เชี่ยวชาญระบุไว้ต่อต้านการต่อต้าน
Nils Toedtmann

เหตุผลใดที่คุณไม่ได้ใช้ตัวแก้ไขแบบเต็มบน localhost? ด้วยวิธีนี้คุณจะกำจัดการพึ่งพาตัวแก้ไข DNS ที่ไม่น่าเชื่อถือของผู้อื่นโดยสิ้นเชิง
Sander Steffann

@SanderSteffann นโยบายไฟร์วอลล์ของ บริษัท มักจะไม่อนุญาต แต่ที่อื่นคือตัวเลือก ฉันจะเพิ่มลงในคำถามของฉันในภายหลัง
Nils Toedtmann

3
@joeqwerty เราไม่ได้ทำการตั้งสมมติฐานใด ๆ เกี่ยวกับว่าสนับสนุน IPv6 ในไซต์หรือไม่ เราทำการสันนิษฐานว่าเซิร์ฟเวอร์ DNS นั้นเป็นไปตามมาตรฐาน นอกจากนี้บางแผนกไอทียังขาดทักษะในการกำหนดค่าโครงสร้างพื้นฐานอย่างเหมาะสม ขอโทษที่ทื่อถึงเรื่องนั้น
Nils Toedtmann

4
ฉันเข้าใจสิ่งที่คุณพูด คุณต้องทำให้กล่องของคุณทำงานบนเครือข่ายของพวกเขาไม่ใช่วิธีอื่นและนั่นคือสิ่งที่คุณถาม ฉันเพิ่งได้รับ miffed เล็กน้อยเมื่อเราในด้านไอทีตำหนิลูกค้าของเราและไม่เคารพพวกเขา พวกเขาเป็นขนมปังและเนยของเรา สำหรับดีหรือไม่ดีเราต้องเคารพและเคารพพวกเขา ลูกค้าของเราไม่ได้เป็นอุปสรรคต่อธุรกิจของเราพวกเขาเป็นเหตุผลสำหรับธุรกิจของเรา
joeqwerty

คำตอบ:


9

gethostbyname()หยุดใช้ คุณควรจะใช้getaddrinfo()แทนและน่าจะเป็นมานานหลายปีแล้ว หน้าคนเตือนคุณถึงสิ่งนี้

ฟังก์ชัน gethostbyname * (), gethostbyaddr * (), herror () และ hstrerror () นั้นล้าสมัยแล้ว แอปพลิเคชันควรใช้ getaddrinfo (3), getnameinfo (3) และ gai_strerror (3) แทน

นี่คือโปรแกรมตัวอย่างด่วนใน C ซึ่งแสดงให้เห็นการค้นหาเฉพาะระเบียน A สำหรับชื่อและการจับภาพ Wireshark แสดงว่ามีการค้นหาระเบียนเพียงอย่างเดียวผ่านเครือข่าย

โดยเฉพาะอย่างยิ่งคุณจะต้องตั้งai_familyไปAF_INETถ้าคุณต้องการเพียงการค้นหาบันทึกทำ โปรแกรมตัวอย่างนี้พิมพ์ที่อยู่ IP ที่ส่งคืนเท่านั้น ดูgetaddrinfo()หน้า man สำหรับตัวอย่างที่สมบูรณ์มากขึ้นของวิธีการเชื่อมต่อขาออก

ในการดักจับ Wireshark 172.25.50.3 เป็นตัวแก้ไข DNS ในเครื่อง การจับภาพถูกนำไปที่นั่นดังนั้นคุณจึงเห็นข้อความค้นหาและคำตอบที่ส่งออก โปรดทราบว่าเพียงระเบียน A ได้รับการร้องขอ ไม่เคยทำการค้นหา AAAA

#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <stdio.h>

int main(void) {
    struct addrinfo hints;
    struct addrinfo *result, *rp;
    int s;
    char host[256];

    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = 0;

    s = getaddrinfo("www.facebook.com", NULL, &hints, &result);
    if (s != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
        exit(EXIT_FAILURE);
    }

    for (rp = result; rp != NULL; rp = rp->ai_next) {
        getnameinfo(rp->ai_addr, rp->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
        printf("%s\n", host);
    }
    freeaddrinfo(result);
}

! ที่น่าสนใจ ฉันจะตรวจสอบว่าแอปพลิเคชันใดที่เรียกคำขอ AAAA หากเป็นเพียงของเราฉันจะส่งข้อเสนอแนะของคุณไปยังผู้พัฒนาของเรา แต่ฉันมีลางสังหรณ์ที่รัดกุมซึ่งมีซอฟต์แวร์บรรจุภัณฑ์ Debian / Ubuntu จำนวนมากกำลังประสบกับปัญหานี้และเราจะไม่ทำการแก้ไขซอฟต์แวร์เหล่านั้น
Nils Toedtmann

ใบสมัครของคุณน่าจะเป็นสิ่งที่สำคัญที่สุด แม้ว่าคุณจะไม่สามารถแก้ไขสิ่งอื่นได้ทั้งหมด แต่ก็อาจปรับปรุงสถานการณ์ได้
Michael Hampton

4

เมื่อสงสัยให้ไปที่ซอร์สโค้ด! ดังนั้นเรามาดู ... gethostbyname ()ดูน่าสนใจ; ที่อธิบายสิ่งที่เราเห็น: ลองใช้ IPv6 ก่อนจากนั้นกลับสู่ IPv4 หากคุณไม่ได้รับคำตอบที่ต้องการ RES_USE_INET6ธงนี้คืออะไร? ติดตามมันกลับมาก็มาจากres_setoptions () นี่คือที่resolv.confอ่าน

และ .... นั่นคือฉันออกจากความคิด ฉันไม่มีความชัดเจนสมบูรณ์วิธีการที่จะที่จะถูกตั้งค่าถ้าไม่ได้อยู่ในRES_USE_INET6resolv.conf


RES_USE_INET6 สามารถตั้งค่าผ่านทางในoptions inet6 resolv.confฉันเดาว่าปัญหาของฉันคือมันไม่สามารถยกเลิกการตั้งค่าได้เมื่อตั้งเวลารวบรวมซึ่ง distros ที่สำคัญทั้งหมดดูเหมือนจะทำวันนี้ (ถูกต้อง?) ดังนั้นคำขอคุณลักษณะสำหรับoptions no_inet6ฉันที่กล่าวถึงข้างต้น
Nils Toedtmann

1
แต่น่าเสียดายที่ในขณะที่คุณสามารถดูจากรหัสที่มีไม่ปรากฏเป็นตัวเลือกในno_inet6 res_setoptions()อย่างไรก็ตามอย่างที่คุณเห็นจาก (ไม่ใช่ -) ip6-dotintมันเป็นการเปลี่ยนแปลงที่ง่ายในการเพิ่ม เพื่อทดสอบทฤษฏีที่ตั้งไว้โดยค่าเริ่มต้นของดิสทริบิวชั่นของคุณฉันจะหยิบไฟล์ซอร์สแพ็กเกจและคอมไพล์ครั้งเดียว "บริสุทธิ์" (เพื่อยืนยันว่าแพ็กเกจทำซ้ำพฤติกรรม) แล้วเพิ่ม: { STRnLEN ("no-inet6"), 1, ~RES_USE_INET6 },เข้ากับoptions[]อาเรย์ resolv.confปัญหาจะหายไปเมื่อคุณตั้งค่าตัวเลือกในการที่
BMDan

1
สุดท้าย: สำหรับสิ่งที่คุ้มค่าฉันจะแก้ปัญหานี้โดยใช้แคช DNS บน localhost (ตามที่คุณอ้างอิงด้านบน) มันจะเป็นเรื่องง่ายกว่าที่จะรักษา heckuva ของคุณเอง, แฮ็ค DNS พร็อกซี / แคชของคุณเองมากกว่าที่จะรักษาไลบรารี่หลักของระบบในระบบ
BMDan

3

คุณสามารถใช้ BIND เป็นเครื่องมือแก้ปัญหาในตัวเครื่องมีตัวเลือกในการกรอง AAAA:

https://kb.isc.org/article/AA-00576/0/Filter-AAAA-option-in-BIND-9-.html


2
นั่นเป็นรุ่นที่ค่อนข้างหนักสำหรับอุปกรณ์ฝังตัว
Michael Hampton

ขอบคุณฉันไม่รู้ตัวกรอง AAAA ของ Bind ดังที่ไมเคิลกล่าวถึงมันอาจไม่ใช่วิธีแก้ปัญหาสำหรับเราเนื่องจากรอยขนาดใหญ่ของ Bind แต่สำหรับผู้ที่ต้องการกรองการตอบกลับ AAAA ในสถานการณ์อื่น ๆ อาจเป็นวิธีที่ทำงานได้ Ubuntu สร้างตัวเชื่อมโยงกับ "--enable-filter-aaaa" อย่างน้อยในวันที่ 14.04 ไม่แน่ใจเกี่ยวกับ Debian - ดูipamworldwide.blogspot.co.uk/2011/09/…
Nils Toedtmann

1
ฉันอายุ 14.04 และดูเหมือนว่าตัวเลือกการกรองนี้จะไม่พร้อมใช้งาน
Zitrax

0

คุณลองตั้งค่า PDNS-recursor แล้วตั้งค่าใน /etc/resolv.conf ของคุณและปฏิเสธการค้นหา "AAAA" ในนั้นหรือไม่? ใช้สิ่งที่ชอบquery-local-address6=


1
query-local-address6=ทำสิ่งที่แตกต่าง (ที่อยู่ IPv6 ที่จะส่งคำสั่งจาก - โปรดทราบว่าแม้เมื่อปิดการใช้งาน IPv6 คำขอ AAAA จะยังคงได้รับการแก้ไขผ่าน IPv4) นอกจากนี้ฉันไม่สามารถระบุการตั้งค่าอื่น ๆ ที่จะกรองการสืบค้น AAAA ( doc.powerdns.com/html/built-in-recursor.html ) คำตอบของคุณไม่มีประโยชน์มาก :(
Nils Toedtmann
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.