Implemented DNS over HTTPS (Google JSON)
This commit is contained in:
parent
1a8145971d
commit
fdd28b6b6d
@ -22,7 +22,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
public class HttpsIetfProvider extends HttpsProvider {
|
||||
private static final String HTTPS_SUFFIX = "https://";
|
||||
// implemented https://tools.ietf.org/html/draft-ietf-doh-dns-over-https-11
|
||||
|
||||
private static final OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
|
||||
.connectTimeout(10, TimeUnit.SECONDS)
|
||||
|
@ -0,0 +1,139 @@
|
||||
package org.itxtech.daedalus.provider;
|
||||
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import okhttp3.*;
|
||||
import org.itxtech.daedalus.service.DaedalusVpnService;
|
||||
import org.minidns.dnsmessage.DnsMessage;
|
||||
import org.minidns.dnsname.DnsName;
|
||||
import org.minidns.record.*;
|
||||
import org.pcap4j.packet.IpPacket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Daedalus Project
|
||||
*
|
||||
* @author iTX Technologies
|
||||
* @link https://itxtech.org
|
||||
* <p>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
public class HttpsJsonProvider extends HttpsProvider {
|
||||
/*
|
||||
* Implemented https://developers.cloudflare.com/1.1.1.1/dns-over-https/json-format/
|
||||
* https://developers.google.com/speed/public-dns/docs/dns-over-https
|
||||
*/
|
||||
|
||||
private static final OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
|
||||
.connectTimeout(10, TimeUnit.SECONDS)
|
||||
.readTimeout(10, TimeUnit.SECONDS)
|
||||
.writeTimeout(10, TimeUnit.SECONDS)
|
||||
.addInterceptor((chain) -> {
|
||||
Request original = chain.request();
|
||||
|
||||
Request request = original.newBuilder()
|
||||
.header("Accept", "application/dns-json")
|
||||
.build();
|
||||
|
||||
return chain.proceed(request);
|
||||
})
|
||||
.build();
|
||||
|
||||
public HttpsJsonProvider(ParcelFileDescriptor descriptor, DaedalusVpnService service) {
|
||||
super(descriptor, service);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendRequestToServer(IpPacket parsedPacket, DnsMessage message, String uri) {
|
||||
whqList.add(new WaitingHttpsRequest(parsedPacket) {
|
||||
@Override
|
||||
public void doRequest() {
|
||||
final byte[] rawRequest = message.toArray();
|
||||
Request request = new Request.Builder()
|
||||
.url(HttpUrl.parse(HTTPS_SUFFIX + uri).newBuilder()
|
||||
.addQueryParameter("name", message.getQuestion().name.toString())
|
||||
.addQueryParameter("type", message.getQuestion().type.name())
|
||||
.build())
|
||||
.get()
|
||||
.build();
|
||||
HTTP_CLIENT.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
result = rawRequest;
|
||||
completed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
JsonObject jsonObject = new JsonParser().parse(response.body().string()).getAsJsonObject();
|
||||
DnsMessage.Builder msg = message.asBuilder()
|
||||
.setRecursionDesired(jsonObject.get("RD").getAsBoolean())
|
||||
.setRecursionAvailable(jsonObject.get("RA").getAsBoolean())
|
||||
.setAuthenticData(jsonObject.get("AD").getAsBoolean())
|
||||
.setCheckingDisabled(jsonObject.get("CD").getAsBoolean());
|
||||
if (jsonObject.has("Answer")) {
|
||||
JsonArray answers = jsonObject.get("Answer").getAsJsonArray();
|
||||
for (JsonElement answer : answers) {
|
||||
JsonObject ans = answer.getAsJsonObject();
|
||||
Record.TYPE type = Record.TYPE.getType(ans.get("type").getAsInt());
|
||||
String data = ans.get("data").getAsString();
|
||||
Data recordData = null;
|
||||
switch (type) {
|
||||
case A:
|
||||
recordData = new A(data);
|
||||
break;
|
||||
case AAAA:
|
||||
recordData = new AAAA(data);
|
||||
break;
|
||||
case CNAME:
|
||||
recordData = new CNAME(data);
|
||||
break;
|
||||
case MX:
|
||||
recordData = new MX(5, data);
|
||||
break;
|
||||
case SOA:
|
||||
String[] sections = data.split(" ");
|
||||
if (sections.length == 7) {
|
||||
recordData = new SOA(sections[0], sections[1],
|
||||
Long.valueOf(sections[2]), Integer.valueOf(sections[3]),
|
||||
Integer.valueOf(sections[4]), Integer.valueOf(sections[5]),
|
||||
Long.valueOf(sections[6]));
|
||||
}
|
||||
break;
|
||||
case DNAME:
|
||||
recordData = new DNAME(data);
|
||||
break;
|
||||
case NS:
|
||||
recordData = new NS(DnsName.from(data));
|
||||
break;
|
||||
case TXT:
|
||||
recordData = new TXT(data.getBytes());
|
||||
break;
|
||||
|
||||
}
|
||||
if (recordData != null) {
|
||||
msg.addAnswer(new Record<>(ans.get("name").getAsString(),
|
||||
type, 1,
|
||||
ans.get("TTL").getAsLong(),
|
||||
recordData));
|
||||
}
|
||||
}
|
||||
}
|
||||
result = msg.build().toArray();
|
||||
completed = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -36,6 +36,8 @@ import java.util.LinkedList;
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
abstract public class HttpsProvider extends Provider {
|
||||
protected static final String HTTPS_SUFFIX = "https://";
|
||||
|
||||
private static final String TAG = "HttpsProvider";
|
||||
|
||||
protected final WhqList whqList = new WhqList();
|
||||
@ -147,7 +149,8 @@ abstract public class HttpsProvider extends Provider {
|
||||
}
|
||||
|
||||
if (!resolve(parsedPacket, dnsMsg) && uri != null) {
|
||||
sendRequestToServer(parsedPacket, dnsMsg, uri);
|
||||
sendRequestToServer(parsedPacket, dnsMsg.asBuilder().setId(0).build(), uri);
|
||||
//SHOULD use a DNS ID of 0 in every DNS request (according to draft-ietf-doh-dns-over-https-11)
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,9 +169,6 @@ abstract public class HttpsProvider extends Provider {
|
||||
public abstract void doRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue of WaitingOnSocketPacket, bound on time and space.
|
||||
*/
|
||||
public static class WhqList implements Iterable<WaitingHttpsRequest> {
|
||||
private final LinkedList<WaitingHttpsRequest> list = new LinkedList<>();
|
||||
|
||||
|
@ -31,7 +31,7 @@ public class ProviderPicker {
|
||||
case DNS_QUERY_METHOD_HTTPS_IETF:
|
||||
return new HttpsIetfProvider(descriptor, service);
|
||||
case DNS_QUERY_METHOD_HTTPS_JSON:
|
||||
break;
|
||||
return new HttpsJsonProvider(descriptor, service);
|
||||
case DNS_QUERY_METHOD_TLS:
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user