Я мог бы найти другой способ получить время разрешения DNS и разрешенный IP-адрес, избегая кеширования благодаря коду VisualBasi c из этого сообщения
Решение состоит в отправке DatagramPacket с указанием c запроса к IP-распознавателю DNS через сокет, затем мы ждем ответа, который является временем разрешения, и анализируем ответ, чтобы найти разрешенный IP-адрес.
См. Код:
В новом потоке мы создаем пакет, отправляем его, получаем и декодируем:
public void getDnsStuff() {
backgroundHandler.post(new Runnable() {
@Override
public void run() {
byte [] lololo;
try {
DatagramPacket sendPacket;
String string = "linkedin.com";
lololo = giveMeX3(urlToUse);
sendPacket = new DatagramPacket(lololo, lololo.length, InetAddress.getByName("8.8.8.8"), 53);
Log.e("kanto_extra", "host: " + string + ", DNS: GoogleDNS");
socket = new DatagramSocket();
socket.send(sendPacket);
byte[] buf = new byte[512];
DatagramPacket receivePacket = new DatagramPacket(buf, buf.length);
Long currentTime = SystemClock.elapsedRealtime();
socket.setSoTimeout(1000);
socket.receive(receivePacket);
Long now = SystemClock.elapsedRealtime() - currentTime;
Log.v("Kanto_time", now.toString());
int[] bufUnsigned = new int[receivePacket.getLength()];
for (int x = 0; x < receivePacket.getLength(); x++){
bufUnsigned[x] = (int) receivePacket.getData()[x] & 0xFF;
}
Log.v("Kanto_unsigned", bufUnsigned.toString());
letsDoSomethingWIthThoseBytes(bufUnsigned, receivePacket.getData(), lololo, now);
} catch (IOException e) {
e.printStackTrace();
}
socket.close();
socket.disconnect();
}
});
}
Метод, который кодирует отправляемый запрос (giveMeX3):
private byte[] giveMeX3(String host){
String TransactionID1="Q1";
String TypeString="\u0001"+"\u0000"+"\u0000"+"\u0001"+"\u0000"+"\u0000"+"\u0000"+"\u0000"+"\u0000"+"\u0000";
String TrailerString="\u0000"+"\u0000"+"\u0001"+"\u0000"+"\u0001";
String URLNameStart = host.substring(0, host.indexOf("."));
String DomainName = host.substring(host.indexOf(".") + 1);
String QueryString = TransactionID1 + TypeString + (char)URLNameStart.length() + URLNameStart + (char)DomainName.length() + DomainName + TrailerString;
byte[] buffer = new byte[0];
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
buffer = QueryString.getBytes(StandardCharsets.US_ASCII);
}
return buffer;
}
Метод, который декодирует байтовый массив ответа (letDoSomethingWIthThoseBytes):
public void letsDoSomethingWIthThoseBytes(int[] bytesList, byte[] bytesListTrue, byte[] sentBytes, Long time){
int index = 0;
if (bytesList[0] == sentBytes[0] && (bytesList[1] == 0x31) || (bytesList[1] == 0x32)) {
if (bytesList[2] == 0x81 && bytesList[3] == 0x80) {
// Decode the answers
// Find the URL that was returned
int TransactionDNS = bytesList[1];
String ReceiveString = "";// = Encoding.ASCII.GetString(Receivebytes);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
ReceiveString = new String(bytesListTrue, StandardCharsets.US_ASCII);
}
index=12;
int URLNameStartLength = bytesListTrue[index];
index++;
String URLNameStart = ReceiveString.substring(index,URLNameStartLength + index);
index=index+URLNameStartLength;
int DomainNameLength = bytesListTrue[index];
index++;
String DomainName = ReceiveString.substring(index,DomainNameLength + index);
index=index+DomainNameLength;
index=index+8;
// Get the record type
int ResponseType = bytesListTrue[index];
index=index+9;
int listLenght = bytesList.length;
String IPResponse = String.valueOf(bytesList[index])+"."
+ String.valueOf(bytesList[index + 1])+"."
+ String.valueOf(bytesList[index + 2])+"."
+ String.valueOf(bytesList[index + 3]);
this.resultString = URLNameStart + "." + DomainName + " - " + IPResponse + " - " + time.toString();
Log.v("Kanto DNS answer", URLNameStart + "." + DomainName + " - " + IPResponse + " - " + time.toString());
}
}
}
Дополнительная информация:
Насколько я знаю, запрос для отправки на сервер может быть изменен в зависимости от того, что вам нужно получить от DNS-сервера. Вы можете узнать больше о протоколе DNS здесь
В этом примере я общаюсь с Google DNS (8.8.8.8 / 8.8.4.4), но я проверил еще несколько, и все они с портом 53, поэтому они должны работать. Проверьте какой-нибудь DNS-сервер:
("Google", "8.8.8.8", "8.8.4.4", "https://developers.google.com/speed/public-dns");
("Quad9", "9.9.9.9", "149.112.112.112", "https://www.quad9.net/");
("Level 3", "209.244.0.3", "209.244.0.4", "https://www.centurylink.com/business.html?rid=lvltmigration");
("Yandex", "77.88.8.8", "77.88.8.1", "https://dns.yandex.com/");
("DNSWatch", "84.200.69.80", "84.200.70.40", "https://dns.watch/index");
("Verisign", "64.6.64.6", "64.6.65.6", "https://www.verisign.com/en_GB/security-services/public-dns/index.xhtml");
("OpenDNS", "208.67.222.222", "208.67.220.220", "https://www.opendns.com/");
("FreeDNS", "37.235.1.174", "37.235.1.177", "https://freedns.zone");
("Cloudflare", "1.1.1.1", "1.0.0.1", "https://1.1.1.1");
("AdGuard", "176.103.130.130", "176.103.130.131", "https://adguard.com/en/adguard-dns/overview.html#instruction");
("French Data Network", "80.67.169.12", "80.67.169.40", "https://www.fdn.fr/actions/dns/");
("Comodo", "8.26.56.26", "8.20.247.20", "https://www.comodo.com/secure-dns/");
("Alternate DNS", "23.253.163.53", "198.101.242.72", "https://alternate-dns.com/");
("Freenom World", "80.80.80.80", "80.80.81.81", "https://www.freenom.com");
("Keweon", "176.9.62.58", "176.9.62.62", "https://forum.xda-developers.com/android/software-hacking/keweon-privacy-online-security-t3681139");
("Quad101", "101.101.101.101", "101.102.103.104", "https://101.101.101.101/index_en.html");
("SafeDNS", "195.46.39.39", "195.46.39.40", "https://www.safedns.com/en/");
("UncensoredDNS", "91.239.100.100", "89.233.43.71", "https://blog.uncensoreddns.org/");
- Большинство ответов, которые я получил от большинства DNS-серверов, содержали разрешенный IP-адрес в конце байтового массива, в частности последние 4 байта, однако, это не относится ко всем из них.
Надеюсь, это решение будет полезно для некоторых.