2009-12-02 38 views
18

Có cách nào để xem/kết xuất bộ đệm DNS được sử dụng bởi java.net api không?Trình xem bộ nhớ cache DNS DNS

+0

Hiểu biết của tôi là bạn phải có máy chủ DNS để thực hiện bộ nhớ đệm - bản thân máy chủ không lưu trữ yêu cầu DNS. –

+2

Không có bộ nhớ cache lưu trữ. Thật vậy, JRE (chạy với trình quản lý bảo mật) và trình duyệt tra cứu DNS "ghim". –

+0

Các thư viện giải quyết dns thường lưu trữ các kết quả dns để chúng không phải làm phiền máy chủ quá nhiều và cung cấp phản hồi nhanh hơn cho các cuộc gọi – nos

Trả lời

18

Đây là tập lệnh để in bộ đệm địa chỉ DNS tích cực và tiêu cực.

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); 
    } 
    } 
} 
+0

Phản ánh? – Pacerier

+0

Mẫu đẹp :-) –

+0

Trong trường hợp ai đó muốn chạy mã trên sử dụng trình quản lý bảo mật. (hoặc chuyển đổi nó để chạy trong một động cơ servlet đang chạy bằng trình quản lý bảo mật), các mục sau trong tệp chính sách sẽ giúp: cấp { quyền java.lang.RuntimePermission "accessClassInPackage.sun.net"; quyền java.lang.RuntimePermission "accessDeclaredMembers"; quyền java.lang.reflect.ReflectPermission "suppressAccessChecks"; quyền java.net.SocketPermission "*", "chấp nhận, kết nối, giải quyết"; –

17

java.net.InetAddress sử dụng bộ nhớ đệm của độ phân giải tên máy chủ thành công và không thành công.

Từ javadoc của nó:

Các InetAddress lớp có một bộ nhớ cache để cửa hàng thành công cũng như thất bại độ phân giải tên máy chủ.

Theo mặc định, khi một người quản lý an ninh được cài đặt, để bảo vệ chống lại các cuộc tấn công giả mạo DNS , kết quả của độ phân giải tên máy chủ tích cực được cache mãi mãi. Khi người quản lý bảo mật không được cài đặt, hành vi mặc định là lưu vào bộ nhớ cache cho các thời hạn hữu hạn (phụ thuộc thực hiện) . Kết quả của độ phân giải tên máy chủ không thành công là được lưu trong một khoảng thời gian rất ngắn (10 giây) để cải thiện hiệu suất.

Nếu hành vi mặc định không phải là mong muốn, thì một thuộc tính bảo mật Java có thể được đặt thành giá trị thời gian sống khác nhau (TTL). Tương tự, quản trị viên hệ thống có thể định cấu hình giá trị TTL bộ nhớ đệm âm khác nhau khi cần.

Hai thuộc tính bảo mật Java kiểm soát các giá trị TTL được sử dụng để tích cực và tiêu cực bộ nhớ đệm có độ phân giải tên máy chủ:

  • networkaddress.cache.ttl
    Cho biết chính sách bộ nhớ đệm cho tra cứu tên thành công từ tên dịch vụ . Giá trị được chỉ định là số nguyên để cho biết số lượng giây để lưu bộ nhớ tra cứu thành công . Cài đặt mặc định là bộ nhớ cache cho thời gian thực hiện cụ thể .

    Giá trị -1 cho biết "bộ nhớ cache mãi mãi".

  • networkaddress.cache.negative.ttl (mặc định: 10)
    Cho biết bộ nhớ đệm chính sách cho un-thành công tên tra cứu từ dịch vụ tên. Giá trị là được chỉ định làm số nguyên để chỉ ra số số giây để lưu trữ lỗi cho các lần tra cứu không thành công.

    Giá trị bằng 0 cho biết "không bao giờ có bộ nhớ cache". Giá trị -1 cho biết "bộ nhớ cache mãi mãi".

Nếu những gì bạn có trong tâm trí là bán phá giá các cache (loại java.net.InetAddress$Cache) được sử dụng bởi java.net.InetAddress, họ là chi tiết thực hiện nội bộ và do đó 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); 

Vì vậy, tôi nghi ngờ bạn sẽ tìm thấy bất cứ điều gì làm điều này ra khỏi hộp và đoán rằng bạn sẽ phải chơi với sự phản ánh để đạt được mục tiêu của bạn.

1

Câu trả lời phía trên không hoạt động trong Java 8 nữa. Đây là một sự thích ứng nhỏ:

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); 
     } 
    } 
} 
Các vấn đề liên quan