Bagaimana cara menonaktifkan pencarian AAAA?

35

... untuk mengkompensasi server DNS yang rusak yang berada di luar kendali kami.

Masalah kami: Kami menggunakan perangkat tertanam yang mengumpulkan data sensor di berbagai, sebagian besar situs IPv4 saja. Beberapa situs memiliki jaringan yang tidak dikelola dengan baik, mis. Konfigurasi yang salah atau cache DNS yang rusak dan / atau firewall yang mengabaikan kueri AAAA sama sekali, atau meresponsnya dengan balasan yang rusak (mis. IP sumber salah!). Sebagai pemasok eksternal ke departemen fasilitas, kami hampir tidak memiliki pengaruh pada departemen TI (terkadang enggan). Kemungkinan mereka memperbaiki server DNS / firewall mereka dalam waktu dekat sangat kecil.

Efeknya pada perangkat kami adalah bahwa dengan setiap gethostbyname (), proses harus menunggu sampai AAAA meminta waktu habis, pada saat mana beberapa proses telah habis waktu upaya koneksi mereka sama sekali.

Saya mencari solusi yang ...

  • seluruh sistem. Saya tidak dapat mengkonfigurasi ulang lusinan aplikasi secara individual
  • tidak permanen dan dapat dikonfigurasi. Kita perlu (kembali) mengaktifkan IPv6 di mana / ketika itu diperbaiki / diluncurkan. Reboot tidak apa-apa.
  • Jika suatu solusi memerlukan pustaka inti seperti glibc untuk diganti, paket pustaka pengganti harus tersedia dari repositori yang dikenal dengan baik (misalnya Pengujian Debian, Ubuntu universe, EPEL). Membangun sendiri bukanlah suatu pilihan karena begitu banyak alasan sehingga saya bahkan tidak tahu harus mulai dari mana, jadi saya tidak menuliskannya sama sekali ...

Solusi yang paling jelas adalah mengkonfigurasi perpustakaan resolver mis. Via / etc / { resolv , nsswitch , gai } .conf untuk tidak meminta catatan AAAA. Sebuah pilihan resolv.conf no-inet6seperti yang disarankan di sini akan menjadi persis apa yang saya cari. Sayangnya itu tidak diterapkan, setidaknya tidak pada sistem kami (libc6-2.13-38 + deb7u4 pada Debian 7; libc6-2.19-0ubuntu6.3 di Ubuntu 14.04)

Jadi bagaimana? Satu menemukan metode berikut disarankan pada SF dan di tempat lain, tetapi tidak ada yang bekerja:

  • Menonaktifkan IPv6 secara bersamaan, misalnya dengan memasukkan daftar hitam IPM6 LKM di /etc/modprobe.d/, atau sysctl -w net.ipv6.conf.all.disable_ipv6=1. ( Karena penasaran: Mengapa resolver meminta AAAA di mana IPv6 dinonaktifkan? )
  • Menghapus options inet6dari /etc/resolv.conf. Itu tidak ada di tempat pertama, inet6hanya diaktifkan secara default hari ini.
  • Pengaturan options single-requestdi /etc/resolv.conf. Ini hanya memastikan bahwa kueri A dan AAAA dilakukan secara berurutan daripada secara paralel
  • Mengubah precedence/etc/gai.conf. Itu tidak memengaruhi kueri DNS, hanya bagaimana beberapa balasan diproses.
  • Menggunakan resolvers eksternal (atau menjalankan daemon resolver lokal yang menghindari server DNS yang rusak) akan membantu, tetapi biasanya tidak diizinkan oleh kebijakan firewall perusahaan. Dan itu dapat membuat sumber daya internal tidak dapat diakses.

Gagasan jelek alternatif:

  • Jalankan cache DNS di localhost. Konfigurasikan untuk meneruskan semua pertanyaan non-AAAA, tetapi untuk menanggapi pertanyaan AAAA dengan NOERROR atau NXDOMAIN (tergantung pada hasil dari kueri-A yang sesuai). Saya tidak mengetahui adanya cache DNS yang dapat melakukan ini.
  • Gunakan beberapa kecocokan iptables pintar u32, atau modul DNS iptables Ondrej Caletka untuk mencocokkan permintaan AAAA, untuk menolak icmp-mereka (bagaimana lver resolver bereaksi terhadap hal itu?), Atau untuk mengarahkan mereka ke server DNS lokal yang merespons semuanya dengan NOERROR kosong.

Perhatikan bahwa ada pertanyaan serupa yang terkait pada SE. Pertanyaan saya berbeda sejauh menguraikan masalah aktual yang saya coba pecahkan, karena daftar persyaratan eksplisit, karena daftar hitam beberapa solusi yang tidak bekerja sering disarankan, dan karena tidak spesifik untuk satu aplikasi. Setelah diskusi ini , saya memposting pertanyaan saya.

Nils Toedtmann
sumber
13
PS: Bertentangan dengan kepercayaan populer di sini di SF, ada beberapa alasan bagus untuk menonaktifkan IPv6 / AAAA pada mesin di jaringan khusus IPv4, bahkan di mana DNS bekerja: Mengurangi beban siaran; Kurangi beban pada resolver DNS hampir 50%; Kurangi waktu memulai koneksi (secara signifikan ketika cache DNS lambat); Ikuti praktik terbaik untuk menonaktifkan fitur non-fungsional untuk meningkatkan keamanan dan stabilitas. Memang, jika saya lupa untuk mengaktifkan kembali IPv6 setelah tersedia, maka sistem saya menjadi ballast legacy IPv4 yang menghambat peluncuran IPv6. Seseorang harus diizinkan untuk menimbang pro yang terdaftar terhadap penipu ini.
Nils Toedtmann
Ada alasan mengapa Anda tidak menjalankan resolver penuh di localhost? Dengan begitu Anda menghilangkan ketergantungan pada resolver DNS orang lain (tampaknya) tidak dapat diandalkan sama sekali.
Sander Steffann
Kebijakan firewall @SanderSteffann Company biasanya melarang itu. Tapi di tempat lain itu pilihan. Saya akan menambahkannya ke pertanyaan saya nanti.
Nils Toedtmann
3
@joeqwerty Kami tidak membuat asumsi tentang apakah IPv6 didukung di situs atau tidak. Kami membuat asumsi meskipun server DNS sesuai standar. Juga, beberapa departemen TI sayangnya tidak memiliki keterampilan untuk mengkonfigurasi infrastruktur mereka dengan benar. Maaf sudah berterus terang tentang hal itu.
Nils Toedtmann
4
Saya mengerti apa yang Anda katakan. Anda perlu membuat kotak Anda berfungsi di jaringan mereka bukan sebaliknya, dan itulah yang Anda tanyakan di sini. Saya hanya sedikit jengkel ketika kita di bidang IT menyalahkan pelanggan kita dan tidak menghormati mereka. Mereka adalah roti dan mentega kami. Baik atau buruk, kita perlu menghargai itu dan menghormati mereka. Pelanggan kami bukan halangan untuk bisnis kami, mereka adalah alasan untuk bisnis kami.
joeqwerty

Jawaban:

9

Berhenti menggunakan gethostbyname(). Anda seharusnya menggunakan getaddrinfo(), dan seharusnya sudah bertahun-tahun sekarang. Halaman manual bahkan memperingatkan Anda tentang ini.

Fungsi gethostbyname * (), gethostbyaddr * (), herror (), dan hstrerror () sudah usang. Aplikasi harus menggunakan getaddrinfo (3), getnameinfo (3), dan gai_strerror (3) sebagai gantinya.

Berikut ini adalah contoh program cepat di C yang menunjukkan hanya mencari catatan A untuk nama, dan penangkapan Wireshark menunjukkan bahwa hanya pencarian catatan A pergi melalui jaringan.

Secara khusus, Anda perlu set ai_familyuntuk AF_INETjika Anda hanya ingin Sebuah catatan pencarian dilakukan. Program sampel ini hanya mencetak alamat IP yang dikembalikan. Lihat getaddrinfo()halaman manual untuk contoh yang lebih lengkap tentang cara membuat koneksi keluar.

Dalam penangkapan Wireshark , 172.25.50.3 adalah resolver DNS lokal; tangkapan diambil di sana, jadi Anda juga melihat pertanyaan dan respons keluarnya. Perhatikan bahwa hanya catatan A yang diminta. Tidak ada pencarian AAAA yang pernah dilakukan.

#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);
}
Michael Hampton
sumber
Menarik! Saya akan menyelidiki aplikasi mana yang memicu permintaan AAAA. Jika hanya milik kami, maka saya akan menyampaikan saran Anda ke pengembang kami. Tapi saya punya firasat kuat bahwa banyak perangkat lunak Debian / Ubuntu paket menderita dari ini, dan kami tidak akan menambal mereka.
Nils Toedtmann
Aplikasi Anda mungkin yang paling penting. Bahkan jika Anda tidak dapat memperbaiki yang lain, itu dapat memperbaiki situasi.
Michael Hampton
4

Jika ragu, buka kode sumber! Jadi, mari kita lihat ... gethostbyname () terlihat menarik; yang menggambarkan dengan tepat apa yang kita lihat: coba IPv6 terlebih dahulu, lalu kembali ke IPv4 jika Anda tidak mendapatkan jawaban yang Anda suka. RES_USE_INET6Bendera apa ini ? Menelusuri kembali, itu berasal dari res_setoptions () . Di sinilah resolv.confdibaca.

Dan .... itu saya kehabisan ide. Saya benar-benar tidak jelas bagaimana RES_USE_INET6pengaturannya jika tidak resolv.conf.

BMDan
sumber
RES_USE_INET6 dapat diatur melalui options inet6in resolv.conf. Saya kira masalah saya adalah bahwa hal itu tidak dapat diset setelah itu ditetapkan pada waktu kompilasi, yang semua distro utama tampaknya lakukan hari ini (benar?). Oleh karena itu permintaan fitur untuk options no_inet6yang saya sebutkan di atas.
Nils Toedtmann
1
Sayangnya, seperti yang Anda lihat dari kode, sepertinya tidak ada no_inet6opsi di res_setoptions(). Namun, seperti yang Anda lihat dari (tidak-) ip6-dotint, ini merupakan perubahan yang mudah untuk ditambahkan. Untuk menguji teori bahwa ia diset secara default oleh distro Anda, saya akan mengambil file source paket dan mengkompilasinya sekali "virgin" (untuk mengonfirmasi bahwa paket mereplikasi perilaku) dan kemudian menambahkan: { STRnLEN ("no-inet6"), 1, ~RES_USE_INET6 },ke options[]array dan melihat apakah masalah hilang saat Anda mengatur opsi itu di resolv.conf.
BMDan
1
Terakhir: untuk apa nilainya, saya akan menyelesaikan ini dengan menjalankan cache DNS di localhost (seperti referensi Anda, di atas). Ini akan menjadi heckuva jauh lebih mudah untuk mempertahankan sendiri, proksi / cache DNS yang diretas daripada mempertahankan versi yang diretas dari pustaka sistem inti.
BMDan
3

Anda dapat menggunakan BIND sebagai resolver lokal, ia memiliki opsi untuk memfilter AAAA:

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

Robert Kerr
sumber
2
Itu cukup berat untuk perangkat yang disematkan.
Michael Hampton
Terima kasih, saya tidak mengetahui filter AAAA Bind. Seperti yang disebutkan Michael, itu mungkin bukan solusi bagi kita karena jejak besar Bind. Tetapi bagi mereka yang ingin menyaring tanggapan AAAA dalam skenario lain mungkin cara yang layak. Ubuntu sebenarnya membuat binding dengan "--enable-filter-aaaa", setidaknya pada 14,04. Tidak yakin tentang Debian. - Lihat juga ipamworldwide.blogspot.co.uk/2011/09/...
Nils Toedtmann
1
Saya menggunakan 14,04 dan sepertinya opsi penyaringan ini tidak tersedia.
Zitrax
0

Apakah Anda mencoba men-setup PDNS-recursor, meletakkannya di /etc/resolv.conf Anda dan menolak pencarian "AAAA" di dalamnya? Menggunakan sesuatu sepertiquery-local-address6=

Glueon
sumber
1
query-local-address6=melakukan sesuatu yang berbeda (dari mana alamat IPv6 mengirim pertanyaan - perhatikan bahwa meskipun IPv6 dinonaktifkan, permintaan AAAA masih akan diselesaikan melalui IPv4). Juga saya tidak dapat mengidentifikasi pengaturan lain yang akan memfilter kueri AAAA ( doc.powerdns.com/html/built-in-recursor.html ). Tanpa informasi itu, jawaban Anda tidak terlalu membantu :(
Nils Toedtmann