Средство просмотра DNS-кэша Java - PullRequest
18 голосов
/ 02 декабря 2009

Есть ли способ просмотреть / вывести DNS-кэш, используемый java.net api?

Ответы [ 3 ]

19 голосов
/ 09 декабря 2009

Вот скрипт для печати кеша положительных и отрицательных адресов DNS.

import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class DNSCache {
  public static void main(String[] args) throws Exception {
    InetAddress.getByName("stackoverflow.com");
    InetAddress.getByName("www.google.com");
    InetAddress.getByName("www.yahoo.com");
    InetAddress.getByName("www.example.com");
    try {
        InetAddress.getByName("nowhere.example.com");
    } catch (UnknownHostException e) {

    }

    String addressCache = "addressCache";
    System.out.println(addressCache);
    printDNSCache(addressCache);
    String negativeCache = "negativeCache";
    System.out.println(negativeCache);
    printDNSCache(negativeCache);
  }
  private static void printDNSCache(String cacheName) throws Exception {
    Class<InetAddress> klass = InetAddress.class;
    Field acf = klass.getDeclaredField(cacheName);
    acf.setAccessible(true);
    Object addressCache = acf.get(null);
    Class cacheKlass = addressCache.getClass();
    Field cf = cacheKlass.getDeclaredField("cache");
    cf.setAccessible(true);
    Map<String, Object> cache = (Map<String, Object>) cf.get(addressCache);
    for (Map.Entry<String, Object> hi : cache.entrySet()) {
        Object cacheEntry = hi.getValue();
        Class cacheEntryKlass = cacheEntry.getClass();
        Field expf = cacheEntryKlass.getDeclaredField("expiration");
        expf.setAccessible(true);
        long expires = (Long) expf.get(cacheEntry);

        Field af = cacheEntryKlass.getDeclaredField("address");
        af.setAccessible(true);
        InetAddress[] addresses = (InetAddress[]) af.get(cacheEntry);
        List<String> ads = new ArrayList<String>(addresses.length);
        for (InetAddress address : addresses) {
            ads.add(address.getHostAddress());
        }

        System.out.println(hi.getKey() + " "+new Date(expires) +" " +ads);
    }
  }
}
17 голосов
/ 03 декабря 2009

java.net.InetAddress использует кэширование успешных и неудачных разрешений имен хостов.

Из своего Javadoc:

Класс InetAddress имеет кеш для хранить успешно, а также неудачные разрешения имени хоста.

По умолчанию, когда менеджер безопасности установлен, чтобы защитить от DNS спуфинговые атаки, результат положительные разрешения имени хоста кешируется навсегда. Когда безопасность менеджер не установлен, по умолчанию Поведение заключается в кэшировании записей для конечный (зависит от реализации) промежуток времени. Результат неудачное разрешение имени хоста кэшируется в течение очень короткого периода времени (10 секунд) для улучшения производительности.

Если поведение по умолчанию не желательно, затем свойство безопасности Java можно установить другое время жизни (TTL) значение для положительного кэширования. Аналогично, системный администратор может настроить другое отрицательное значение кэширования TTL когда нужно.

Два элемента управления свойствами безопасности Java значения TTL, используемые для положительного и Кэширование разрешения отрицательного имени хоста:

  • networkaddress.cache.ttl
    Указывает политику кэширования для успешные поиски имени от имени оказание услуг. Значение указывается как целое число для обозначения количества секунд для кеширования удачного уважать. Значением по умолчанию является кеш для конкретной реализации период времени.

    Значение -1 указывает «кеш» навсегда».

  • networkaddress.cache.negative.ttl (по умолчанию: 10)
    Указывает на кеширование политика для неудачных поисков имен из службы имен. Значение указано как целое число для обозначения количество секунд для кеширования ошибка при неудачных поисках.

    Значение 0 указывает «никогда не кэшировать». Значение -1 указывает «кеш» навсегда».

Если вы имеете в виду сброс кешей (типа java.net.InetAddress$Cache), используемых java.net.InetAddress, это внутренние детали реализации и, таким образом, private:

/*
 * Cached addresses - our own litle nis, not!
 */
private static Cache addressCache = new Cache(Cache.Type.Positive);

private static Cache negativeCache = new Cache(Cache.Type.Negative);

Поэтому я сомневаюсь, что вы найдете что-то подобное, и думаю, что вам придется играть с отражением, чтобы достичь своей цели.

3 голосов
/ 17 июля 2017

Ответ выше не работает в Java 8 больше. Здесь небольшая адаптация:

import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class DNSCache {
    public static void main(String[] args) throws Exception {
        InetAddress.getByName("stackoverflow.com");
        InetAddress.getByName("www.google.com");
        InetAddress.getByName("www.yahoo.com");
        InetAddress.getByName("www.example.com");
        try {
            InetAddress.getByName("nowhere.example.com");
        } catch (UnknownHostException e) {

        }

        String addressCache = "addressCache";
        System.out.println(addressCache);
        printDNSCache(addressCache);
        String negativeCache = "negativeCache";
        System.out.println(negativeCache);
        printDNSCache(negativeCache);
    }

    private static void printDNSCache(String cacheName) throws Exception {
        Class<InetAddress> klass = InetAddress.class;
        Field acf = klass.getDeclaredField(cacheName);
        acf.setAccessible(true);
        Object addressCache = acf.get(null);
        Class cacheKlass = addressCache.getClass();
        Field cf = cacheKlass.getDeclaredField("cache");
        cf.setAccessible(true);
        Map<String, Object> cache = (Map<String, Object>) cf.get(addressCache);
        for (Map.Entry<String, Object> hi : cache.entrySet()) {
            Object cacheEntry = hi.getValue();
            Class cacheEntryKlass = cacheEntry.getClass();
            Field expf = cacheEntryKlass.getDeclaredField("expiration");
            expf.setAccessible(true);
            long expires = (Long) expf.get(cacheEntry);

            Field af = cacheEntryKlass.getDeclaredField("addresses");
            af.setAccessible(true);
            InetAddress[] addresses = (InetAddress[]) af.get(cacheEntry);
            List<String> ads = new ArrayList<String>(addresses.length);
            for (InetAddress address : addresses) {
                ads.add(address.getHostAddress());
            }

            System.out.println(hi.getKey() + " expires in "
                    + Instant.now().until(Instant.ofEpochMilli(expires), ChronoUnit.SECONDS) + " seconds " + ads);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...