Java, DNS Önbelleğe Alma Zaman Aşımını nasıl onurlandırabilir?


102

Coğrafi dağıtım ve yük dengeleme için GSLB kullanıyoruz. Her hizmete sabit bir alan adı atanır. Bazı DNS sihri sayesinde, alan adı, sunucuya en az yük ile en yakın IP'ye çözümlenir. Yük dengelemenin çalışması için, uygulama sunucusunun DNS yanıtından gelen TTL'yi dikkate alması ve önbellek zaman aşımına uğradığında etki alanı adını yeniden çözümlemesi gerekir. Ancak bunu Java'da yapmanın bir yolunu bulamadım.

Uygulama, Linux (Centos 5) üzerinde çalışan Java 5 içindedir.

Yanıtlar:


77

Byron cevap gereğince, ayarlayamıyor networkaddress.cache.ttlveya networkaddress.cache.negative.ttlSistem Özellikleri olarak kullanarak -Dbayrak veya çağıran System.setPropertybu sistem özellikleri olmadıklarından - olduklarını Güvenlik özellikleri.

Bu davranışı tetiklemek için bir Sistem özelliği kullanmak istiyorsanız (böylece -Dbayrağı veya çağrıyı kullanabilirsiniz System.setProperty), aşağıdaki Sistem özelliğini ayarlamak isteyeceksiniz :

-Dsun.net.inetaddr.ttl=0

Bu sistem özelliği, istenen etkiyi sağlayacaktır.

Ancak unutmayın: -DJVM sürecini başlatırken bayrağı kullanmazsanız ve bunun yerine bunu koddan çağırmayı seçerseniz :

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

Bu kod , JVM'deki diğer herhangi bir kod ağ işlemlerini gerçekleştirmeye çalışmadan önce yürütülmelidir.

Bu önemlidir, çünkü, örneğin, Security.setPropertybir .war dosyasını çağırıp bu .war'ı Tomcat'e konuşlandırdıysanız, bu işe yaramaz: Tomcat, .war kodunuzun çalıştırılmasından çok daha önce kendisini başlatmak için Java ağ yığınını kullanır. Bu 'yarış durumu' nedeniyle -D, JVM sürecini başlatırken genellikle bayrağı kullanmak daha uygundur .

Kullanmaz -Dsun.net.inetaddr.ttl=0veya arama yapmazsanız , o dosyadaki güvenlik özelliklerini Security.setPropertydüzenlemeniz $JRE_HOME/lib/security/java.securityve ayarlamanız gerekir , örn.

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

Ancak bu mülkleri çevreleyen yorumlardaki güvenlik uyarılarına dikkat edin. Bunu yalnızca DNS sahtekarlığı saldırılarına karşı duyarlı olmadığınızdan makul ölçüde eminseniz yapın .


2
FQN java.security.Security(en azından jdk7'de)
Pablo Fernandez

1
Sadece bir yorum, bu güvenlik uyarıları çoğunlukla güvenlik yöneticileri ve uzaktan yükleme ile ilgilidir. DNS'ye bir dereceye kadar güvenen herhangi bir normal sunucu uygulaması için TTL'yi düşürmek iyidir. (Bununla birlikte, 0'ın iyi bir minimum olduğunu ve güvenlik dışı yöneticiler için varsayılan 30'ların çoğu durumda gayet iyi olduğunu düşünmüyorum).
Eckes

3
Sistem Özelliği OpenJDK ile de çalışıyor mu yoksa Oracle'a özel mi?
mhlz

İlk aramadan sonra DNS'yi bir daha asla kontrol etmemek sizi sahtekarlık saldırılarından korumaz, bir sahtekarlık saldırısını geçici yerine kalıcı hale getirir.
kbolino

67

Java'nın bazı ciddi garip DNS önbellekleme davranışları var. En iyi bahsiniz, dns önbelleğe almayı kapatmak veya 5 saniye gibi düşük bir sayıya ayarlamaktır.

networkaddress.cache.ttl (varsayılan: -1)
Ad hizmetinden başarılı ad aramaları için önbelleğe alma ilkesini gösterir. Değer, başarılı aramanın önbelleğe alınacağı saniye sayısını belirtmek için tamsayı olarak belirtilir. -1 değeri "sonsuza kadar önbellek" anlamına gelir.

networkaddress.cache.negative.ttl (varsayılan: 10)
Ad hizmetinden başarısız olan ad aramaları için önbelleğe alma ilkesini belirtir. Değer, başarılı olmayan aramalar için arızanın önbelleğe alınacağı saniye sayısını belirtmek üzere tamsayı olarak belirtilir. 0 değeri, "asla önbelleğe almayın" anlamına gelir. -1 değeri "sonsuza kadar önbellek" anlamına gelir.


7
Not: Bu, işletim sisteminizdeki tüm DNS önbelleğe almayı devre dışı bırakmaz. Yalnızca Java'nın kitaplıkta kendi bozuk bellek içi önbelleğe alma özelliğini devre dışı bırakır. JVM'yi çağırdığınızda, bu özellikleri komut satırında kolayca ayarlayabilirsiniz.
Nelson

2
"Kırık" ın geçerli olduğunu bilmiyorum. Java (güvenlik nedeniyle) DNS girdilerini sonsuza kadar veya JVM yeniden başlatılıncaya kadar (hangisi önce gelirse) önbelleğe alır. Bu (anlayabildiğim kadarıyla) tasarım gereğiydi. Ayarlar java.security politika dosyasında veya komut satırında yapılabilir. Ayarlar her biri için farklıdır. Referans: rgagnon.com/javadetails/java-0445.html
Milner

4
Bunları Sistem özellikleri olarak (yani -D bayraklarını veya System.setProperty kullanarak) ayarlayamayacağınızı unutmayın çünkü bunlar sistem özellikleri değildir - bunlar Güvenlik özellikleridir.
Les Hazlewood

6
Bu belge 1.7'de biraz farklıdır. Spesifik olarak, önbellek artık yalnızca bir güvenlik yöneticisi mevcut olduğunda gerçekleşir: "Varsayılan davranış, bir güvenlik yöneticisi yüklendiğinde sonsuza kadar önbelleğe almak ve bir güvenlik yöneticisi yüklenmediğinde belirli bir süre için uygulama için önbelleğe almaktır." docs.oracle.com/javase/7/docs/technotes/guides/net/…
Brett Okken

1
@Michael bkz System.getSecurityManager(). Java 8 için Dokümanlar: docs.oracle.com/javase/8/docs/api/java/lang/…
gesellix

22

Bu açıkça daha yeni sürümlerde (SE 6 ve 7) düzeltildi. Tcpdump kullanarak 53 numaralı bağlantı noktası etkinliğini izlerken aşağıdaki kod parçacığını çalıştırırken maksimum 30 saniyelik önbellekleme süresi yaşıyorum.

/**
 * 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();
        }
    }
}

16
Evet, Java 1.5 varsayılan bir sonsuz önbelleğe alma değerine sahipti. Java 1.6 ve 1.7'nin 30 saniyelik bir varsayılanı vardır.
Michael

7
1.7 belgeleri bunun yalnızca bir güvenlik yöneticisinin bulunmadığı durumlarda doğru olabileceğini belirtir: "Varsayılan davranış, bir güvenlik yöneticisi yüklendiğinde sonsuza kadar önbelleğe almak ve bir güvenlik yönetici yüklü değil. " docs.oracle.com/javase/7/docs/technotes/guides/net/…
Brett Okken

1
@Michael bu bilginin kaynağını paylaşmak ister mi?
rustyx

4
@rustyx Oracle'ın 1.6 ve 1.7 JDK'sı, networkaddress.cache.ttl için jre / lib / security / java.security'de buna sahiptir: "# varsayılan değer sonsuzdur (SONSUZA). Güvenlik nedenlerinden dolayı, bu # önbelleğe alma, bir güvenlik yöneticisi olduğunda sonsuza kadar yapılır ayarlandı. Bir güvenlik # yöneticisi ayarlanmadığında, varsayılan davranış 30 saniye önbelleğe almaktır. " Yani Java Web Start aracılığıyla dağıtılan apletler ve uygulamalar sonsuza kadar önbelleğe alınır, aksi takdirde 30 saniyedir.
Michael

1
İşte OpenJDK 8'in java.security'i için bir kod işaretçisi, bir güvenlik yöneticisi olmadan TTL'nin 30s olduğunu söylüyor: hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/f940e7a48b72/src/share/… . Bunu Mac OS X ve Ubuntu 14.04'te test ettim.
tro

18

Byron'ın cevabını genişletmek için, bu değişikliği etkilemek java.securityiçin %JRE_HOME%\lib\securitydizindeki dosyayı düzenlemeniz gerektiğine inanıyorum .

İşte ilgili bölüm:

#
# 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 

java.securityDosyadaki belgeler burada .


5
Buna ek olarak, tomcat6'yı kullanırken lib / security dosyamı değiştirmek zorunda kaldım, networkaddress.cache.ttl veya sun.net.inetaddr.ttl'yi programlı olarak veya JAVA_OPTS değişkeni aracılığıyla ayarlamak işe yaramadı.
bramp

1
@bramp Teşekkürler kardeşim, ben de aynı problemle karşı karşıyayım ve yorumunuzu ve cevaplarınızı +1 kullanarak yorum ve cevap için çözdüm.
Bhavik Ambani

7

Diğer yanıtları özetlemek için, içinde <jre-path>/lib/security/java.securityözelliğin değerini, networkaddress.cache.ttlDNS aramalarının nasıl önbelleğe alınacağını ayarlamak için ayarlayabilirsiniz. Bu olduğunu unutmayın değil bir sistem özelliği ancak bir güvenlik özelliği. Bunu kullanarak ayarlayabildim:

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

Bu, sistem özelliği tarafından da ayarlanabilir, -Dsun.net.inetaddr.ttlancak bu, başka bir yerde ayarlanmışsa bir güvenlik özelliğini geçersiz kılmaz.

Ayrıca, benim gibi WebSphere'deki web hizmetlerinde bu sorunu görüyorsanız, ayarlamanın networkaddress.cache.ttlyeterli olmayacağını da eklemek isterim . Sistem özelliğini disableWSAddressCachingolarak ayarlamanız gerekir true. Yaşam süresi özelliğinden farklı olarak, bu bir JVM bağımsız değişkeni olarak veya aracılığıyla System.setProperty) ayarlanabilir .

IBM, WebSphere'in burada DNS önbelleğe almayı nasıl işlediği konusunda oldukça ayrıntılı bir gönderiye sahip . Yukarıdakilerle ilgili parça:

Web hizmetleri için adres önbelleğe almayı devre dışı bırakmak için, ek bir JVM özel özelliği disableWSAddressCaching özelliğini true olarak ayarlamanız gerekir. Web hizmetleri için adres önbelleğe almayı devre dışı bırakmak için bu özelliği kullanın. Sisteminiz genellikle çok sayıda istemci iş parçacığı ile çalışıyorsa ve wsAddrCache önbelleğinde kilit çekişmesiyle karşılaşırsanız, Web hizmetleri verilerinin önbelleğe alınmasını önlemek için bu özel özelliği true olarak ayarlayabilirsiniz.


2

Göre resmi oracle java özelliklerine , sun.net.inetaddr.ttl"gelecek sürümlerde desteklenmiyor olabilir" Güneş uygulaması özgü bir özelliktir. "tercih edilen yol, güvenlik özelliğini kullanmaktır" networkaddress.cache.ttl.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.