Bagaimana cara membuat Java menerima DNS Caching Timeout?

102

Kami menggunakan GSLB untuk distribusi geografis dan load-balancing. Setiap layanan diberi nama domain tetap. Melalui beberapa keajaiban DNS, nama domain diselesaikan menjadi IP yang paling dekat dengan server dengan beban paling sedikit. Agar penyeimbang beban berfungsi, server aplikasi harus menerima TTL dari respons DNS dan menyelesaikan nama domain lagi saat cache habis. Namun, saya tidak dapat menemukan cara untuk melakukan ini di Jawa.

Aplikasinya ada di Java 5, berjalan di Linux (Centos 5).

ZZ Coder
sumber

Jawaban:

77

Sesuai jawaban Byron, Anda tidak dapat mengatur networkaddress.cache.ttlatau networkaddress.cache.negative.ttlsebagai Properti Sistem dengan menggunakan -Dbendera atau memanggil System.setPropertykarena ini bukan properti Sistem - ini adalah properti Keamanan .

Jika Anda ingin menggunakan properti Sistem untuk memicu perilaku ini (sehingga Anda dapat menggunakan -Dbendera atau panggilan System.setProperty), Anda perlu menyetel properti Sistem berikut :

-Dsun.net.inetaddr.ttl=0

Properti sistem ini akan mengaktifkan efek yang diinginkan.

Namun perlu diketahui: jika Anda tidak menggunakan -Dflag saat memulai proses JVM dan memilih untuk memanggil ini dari kode:

java.security.Security.setProperty("networkaddress.cache.ttl" , "0")

Kode ini harus dijalankan sebelum kode lain di JVM mencoba melakukan operasi jaringan.

Ini penting karena, misalnya, jika Anda memanggil Security.setPropertyfile .war dan menerapkan .war ke Tomcat, ini tidak akan berhasil: Tomcat menggunakan tumpukan jaringan Java untuk menginisialisasi dirinya jauh lebih awal daripada kode .war Anda dieksekusi. Karena 'kondisi balapan' ini, biasanya lebih nyaman untuk menggunakan-D bendera saat memulai proses JVM.

Jika Anda tidak menggunakan -Dsun.net.inetaddr.ttl=0atau memanggil Security.setProperty, Anda perlu mengedit $JRE_HOME/lib/security/java.securitydan menyetel properti keamanan tersebut dalam file itu, mis

networkaddress.cache.ttl = 0
networkaddress.cache.negative.ttl = 0

Tapi perhatikan peringatan keamanan di komentar seputar properti tersebut. Lakukan ini hanya jika Anda cukup yakin bahwa Anda tidak rentan terhadap serangan spoofing DNS .

Les Hazlewood
sumber
2
FQN adalah java.security.Security(setidaknya di jdk7)
Pablo Fernandez
1
Sekadar komentar, peringatan keamanan tersebut sebagian besar terkait dengan manajer keamanan dan pemuatan jarak jauh. Untuk aplikasi server normal apa pun yang mempercayai DNS untuk beberapa perluasan mengurangi TTL baik-baik saja. (Namun menurut saya 0 adalah minimum yang baik dan default 30-an untuk manajer non-keamanan baik-baik saja dalam banyak kasus).
eckes
3
Apakah Properti Sistem bekerja dengan OpenJDK juga atau apakah itu khusus Oracle?
mhlz
Jangan pernah memeriksa DNS lagi setelah pencarian pertama tidak melindungi Anda dari serangan spoofing, itu membuat serangan spoofing menjadi permanen dan bukan sementara.
kbolino
67

Java memiliki perilaku cache dns yang sangat aneh. Taruhan terbaik Anda adalah mematikan caching dns atau mengaturnya ke angka rendah seperti 5 detik.

networkaddress.cache.ttl (default: -1)
Menunjukkan kebijakan cache untuk pencarian nama yang berhasil dari layanan nama. Nilai ditentukan sebagai integer untuk menunjukkan jumlah detik untuk menyimpan cache pencarian yang berhasil. Nilai -1 menunjukkan "cache forever".

networkaddress.cache.negative.ttl (default: 10)
Menunjukkan kebijakan cache untuk pencarian nama yang tidak berhasil dari layanan nama. Nilai ditentukan sebagai integer untuk menunjukkan jumlah detik untuk menyimpan kegagalan dalam cache untuk pencarian yang tidak berhasil. Nilai 0 menunjukkan "tidak pernah cache". Nilai -1 menunjukkan "cache forever".

Byron Whitlock
sumber
7
Catatan: ini tidak menonaktifkan semua cache DNS di OS Anda. Hanya menonaktifkan cache dalam memori Java yang rusak di perpustakaan. Anda cukup menyetel properti ini pada baris perintah saat Anda menjalankan JVM.
Nelson
2
Saya tidak tahu bahwa "rusak" itu valid. Java (untuk alasan keamanan) menyimpan entri DNS selamanya, atau hingga JVM dimulai ulang, mana saja yang lebih dulu. Ini (dari apa yang saya tahu) adalah desain. Pengaturan dapat dibuat di file kebijakan java.security, atau di baris perintah. Pengaturannya berbeda untuk masing-masing. Referensi: rgagnon.com/javadetails/java-0445.html
Milner
4
Perhatikan bahwa Anda tidak dapat menyetel ini sebagai properti Sistem (yaitu menggunakan tanda -D atau System.setProperty) karena ini bukan properti sistem - ini adalah properti Keamanan.
Les Hazlewood
6
Dokumentasi ini sedikit berbeda di 1.7. Secara khusus, cache selamanya sekarang hanya terjadi ketika manajer keamanan ada: "Perilaku defaultnya adalah menyimpan cache selamanya saat manajer keamanan diinstal, dan menyimpan cache untuk implementasi periode waktu tertentu, saat manajer keamanan tidak diinstal." docs.oracle.com/javase/7/docs/technotes/guides/net/…
Brett Okken
1
@ Michael lihat System.getSecurityManager(). Docs untuk Java 8: docs.oracle.com/javase/8/docs/api/java/lang/…
gesellix
22

Ini jelas telah diperbaiki dalam rilis yang lebih baru (SE 6 dan 7). Saya mengalami waktu caching maksimal 30 detik ketika menjalankan cuplikan kode berikut sambil menonton aktivitas port 53 menggunakan tcpdump.

/**
 * http://stackoverflow.com/questions/1256556/any-way-to-make-java-honor-the-dns-caching-timeout-ttl
 *
 * Result: Java 6 distributed with Ubuntu 12.04 and Java 7 u15 downloaded from Oracle have
 * an expiry time for dns lookups of approx. 30 seconds.
 */

import java.util.*;
import java.text.*;
import java.security.*;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

public class Test {
    final static String hostname = "www.google.com";
    public static void main(String[] args) {
        // only required for Java SE 5 and lower:
        //Security.setProperty("networkaddress.cache.ttl", "30");

        System.out.println(Security.getProperty("networkaddress.cache.ttl"));
        System.out.println(System.getProperty("networkaddress.cache.ttl"));
        System.out.println(Security.getProperty("networkaddress.cache.negative.ttl"));
        System.out.println(System.getProperty("networkaddress.cache.negative.ttl"));

        while(true) {
            int i = 0;
            try {
                makeRequest();
                InetAddress inetAddress = InetAddress.getLocalHost();
                System.out.println(new Date());
                inetAddress = InetAddress.getByName(hostname);
                displayStuff(hostname, inetAddress);
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            try {
                Thread.sleep(5L*1000L);
            } catch(Exception ex) {}
            i++;
        }
    }

    public static void displayStuff(String whichHost, InetAddress inetAddress) {
        System.out.println("Which Host:" + whichHost);
        System.out.println("Canonical Host Name:" + inetAddress.getCanonicalHostName());
        System.out.println("Host Name:" + inetAddress.getHostName());
        System.out.println("Host Address:" + inetAddress.getHostAddress());
    }

    public static void makeRequest() {
        try {
            URL url = new URL("http://"+hostname+"/");
            URLConnection conn = url.openConnection();
            conn.connect();
            InputStream is = conn.getInputStream();
            InputStreamReader ird = new InputStreamReader(is);
            BufferedReader rd = new BufferedReader(ird);
            String res;
            while((res = rd.readLine()) != null) {
                System.out.println(res);
                break;
            }
            rd.close();
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }
}
pengguna1050755
sumber
16
Ya, Java 1.5 memiliki nilai default caching tak terbatas. Java 1.6 dan 1.7 memiliki default 30 detik.
Michael
7
Dokumentasi untuk 1.7 menunjukkan ini mungkin hanya benar dalam kasus di mana manajer keamanan tidak ada: "Perilaku default adalah untuk menyimpan cache selamanya ketika manajer keamanan diinstal, dan untuk cache untuk implementasi periode waktu tertentu, ketika keamanan manajer tidak diinstal. " docs.oracle.com/javase/7/docs/technotes/guides/net/…
Brett Okken
1
@Michael peduli untuk membagikan sumber informasi itu?
rustyx
4
@rustyx Oracle 1.6 dan 1.7 JDK memiliki ini di jre / lib / security / java.security untuk networkaddress.cache.ttl: "# nilai default selamanya (SELAMANYA). Demi alasan keamanan, # caching ini dibuat selamanya ketika seorang manajer keamanan disetel. Jika pengelola # keamanan tidak disetel, perilaku defaultnya adalah menyimpan cache selama 30 detik. " Jadi applet dan aplikasi yang disebarkan melalui Java Web Start masih menyimpan cache selamanya, jika tidak maka 30 detik.
Michael
1
Berikut adalah penunjuk kode ke java.security OpenJDK 8, yang mengatakan bahwa tanpa pengelola keamanan, TTL-nya adalah 30-an: hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/f940e7a48b72/src/share/… . Saya menguji ini di Mac OS X dan Ubuntu 14.04.
tro
18

Untuk memperluas jawaban Byron, saya yakin Anda perlu mengedit file java.securitydi %JRE_HOME%\lib\securitydirektori untuk melakukan perubahan ini.

Inilah bagian yang relevan:

#
# The Java-level namelookup cache policy for successful lookups:
#
# any negative value: caching forever
# any positive value: the number of seconds to cache an address for
# zero: do not cache
#
# default value is forever (FOREVER). For security reasons, this
# caching is made forever when a security manager is set. When a security
# manager is not set, the default behavior is to cache for 30 seconds.
#
# NOTE: setting this to anything other than the default value can have
#       serious security implications. Do not set it unless 
#       you are sure you are not exposed to DNS spoofing attack.
#
#networkaddress.cache.ttl=-1 

Dokumentasi di java.securityfile di sini .

matt b
sumber
5
Untuk menambah ini, ketika menggunakan tomcat6 saya harus mengubah file lib / security saya, karena pengaturan networkaddress.cache.ttl atau sun.net.inetaddr.ttl baik secara terprogram atau melalui variabel JAVA_OPTS tidak berfungsi.
rem
1
@bramp Terima kasih bro, saya juga menghadapi masalah yang sama dan diselesaikan dengan menggunakan komentar dan jawaban Anda +1 untuk komentar dan jawaban.
Bhavik Ambani
7

Untuk meringkas jawaban lainnya, <jre-path>/lib/security/java.securityAnda dapat mengatur nilai properti networkaddress.cache.ttluntuk menyesuaikan bagaimana pencarian DNS di-cache. Perhatikan bahwa ini bukan properti sistem, tetapi properti keamanan. Saya dapat mengatur ini menggunakan:

java.security.Security.setProperty("networkaddress.cache.ttl", "<value>");

Ini juga dapat diatur oleh properti sistem -Dsun.net.inetaddr.ttl meskipun ini tidak akan menggantikan properti keamanan jika disetel di tempat lain.

Saya juga ingin menambahkan bahwa jika Anda melihat masalah ini dengan layanan web di WebSphere, seperti yang saya lakukan sebelumnya, pengaturan networkaddress.cache.ttltidak akan cukup. Anda perlu menyetel properti sistem disableWSAddressCachingke true. Tidak seperti properti time-to-live, ini dapat disetel sebagai argumen JVM atau melalui System.setProperty).

IBM memiliki posting yang cukup rinci tentang bagaimana WebSphere menangani caching DNS di sini . Bagian yang relevan di atas adalah:

Untuk menonaktifkan cache alamat untuk layanan Web, Anda perlu menyetel properti kustom JVM tambahan disableWSAddressCaching ke true. Gunakan properti ini untuk menonaktifkan cache alamat untuk layanan Web. Jika sistem Anda biasanya berjalan dengan banyak utas klien, dan Anda mengalami pertentangan kunci pada cache wsAddrCache, Anda dapat menyetel properti kustom ini ke true, untuk mencegah penyimpanan data layanan Web dalam cache.

akar kuadrat
sumber
2

Menurut properti java oracle resmi , sun.net.inetaddr.ttladalah properti implementasi khusus Sun, yang "mungkin tidak didukung dalam rilis mendatang". "cara yang disukai adalah dengan menggunakan properti keamanan" networkaddress.cache.ttl.

CloudStax
sumber