Implemented DNS over TLS (alpha)

This commit is contained in:
PeratX 2018-06-22 12:51:57 +08:00
parent 1db66012ea
commit b794722a5b
4 changed files with 76 additions and 7 deletions

View File

@ -21,6 +21,7 @@ public class ProviderPicker {
public static final int DNS_QUERY_METHOD_TLS = 2;
public static final int DNS_QUERY_METHOD_HTTPS_IETF = 3;
public static final int DNS_QUERY_METHOD_HTTPS_JSON = 4;
//This section mush be the same as the one in arrays.xml
public static Provider getProvider(ParcelFileDescriptor descriptor, DaedalusVpnService service) {
switch (Integer.valueOf(Daedalus.getPrefs().getString("settings_dns_query_method", "0"))) {
@ -33,7 +34,7 @@ public class ProviderPicker {
case DNS_QUERY_METHOD_HTTPS_JSON:
return new HttpsJsonProvider(descriptor, service);
case DNS_QUERY_METHOD_TLS:
break;
return new TlsProvider(descriptor, service);
}
return new UdpProvider(descriptor, service);
}

View File

@ -38,7 +38,7 @@ public class TcpProvider extends UdpProvider {
private static final String TAG = "TcpProvider";
private final TcpProvider.WospList dnsIn = new TcpProvider.WospList();
protected final TcpProvider.WospList dnsIn = new TcpProvider.WospList();
public TcpProvider(ParcelFileDescriptor descriptor, DaedalusVpnService service) {
super(descriptor, service);
@ -118,14 +118,15 @@ public class TcpProvider extends UdpProvider {
}
}
private byte[] processUdpPacket(DatagramPacket outPacket, IpPacket parsedPacket) {
protected byte[] processUdpPacket(DatagramPacket outPacket, IpPacket parsedPacket) {
if (parsedPacket == null) {
return new byte[0];
}
return outPacket.getData();
}
void forwardPacket(DatagramPacket outPacket, IpPacket parsedPacket) throws DaedalusVpnService.VpnNetworkException {
@Override
protected void forwardPacket(DatagramPacket outPacket, IpPacket parsedPacket) throws DaedalusVpnService.VpnNetworkException {
Socket dnsSocket;
try {
// Packets to be sent to the real DNS server will need to be protected from the VPN
@ -176,7 +177,7 @@ public class TcpProvider extends UdpProvider {
/**
* Helper class holding a socket, the packet we are waiting the answer for, and a time
*/
private static class WaitingOnSocketPacket {
public static class WaitingOnSocketPacket {
final Socket socket;
final IpPacket packet;
private final long time;
@ -195,7 +196,7 @@ public class TcpProvider extends UdpProvider {
/**
* Queue of WaitingOnSocketPacket, bound on time and space.
*/
private static class WospList implements Iterable<TcpProvider.WaitingOnSocketPacket> {
public static class WospList implements Iterable<TcpProvider.WaitingOnSocketPacket> {
private final LinkedList<TcpProvider.WaitingOnSocketPacket> list = new LinkedList<>();
void add(TcpProvider.WaitingOnSocketPacket wosp) {

View File

@ -0,0 +1,67 @@
package org.itxtech.daedalus.provider;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.OsConstants;
import org.itxtech.daedalus.service.DaedalusVpnService;
import org.itxtech.daedalus.util.Logger;
import org.itxtech.daedalus.util.server.DNSServerHelper;
import org.pcap4j.packet.IpPacket;
import javax.net.ssl.SSLContext;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
/**
* 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 TlsProvider extends TcpProvider{
public TlsProvider(ParcelFileDescriptor descriptor, DaedalusVpnService service) {
super(descriptor, service);
}
@Override
protected void forwardPacket(DatagramPacket outPacket, IpPacket parsedPacket) throws DaedalusVpnService.VpnNetworkException {
Socket dnsSocket;
try {
dnsSocket = SSLContext.getInstance("TLSv1.2").getSocketFactory()
.createSocket(outPacket.getAddress(),
DNSServerHelper.getPortOrDefault(outPacket.getAddress(), outPacket.getPort()));
//Create TLS v1.2 socket
service.protect(dnsSocket);
DataOutputStream dos = new DataOutputStream(dnsSocket.getOutputStream());
byte[] packet = processUdpPacket(outPacket, parsedPacket);
dos.writeShort(packet.length);
dos.write(packet);
dos.flush();
if (parsedPacket != null) {
dnsIn.add(new WaitingOnSocketPacket(dnsSocket, parsedPacket));
} else {
dnsSocket.close();
}
} catch (NoSuchAlgorithmException e){
Logger.logException(e);
} catch (IOException e) {
if (e.getCause() instanceof ErrnoException) {
ErrnoException errnoExc = (ErrnoException) e.getCause();
if ((errnoExc.errno == OsConstants.ENETUNREACH) || (errnoExc.errno == OsConstants.EPERM)) {
throw new DaedalusVpnService.VpnNetworkException("Cannot send message:", e);
}
}
}
}
}

View File

@ -121,7 +121,7 @@ public class UdpProvider extends Provider {
}
}
void forwardPacket(DatagramPacket outPacket, IpPacket parsedPacket) throws DaedalusVpnService.VpnNetworkException {
protected void forwardPacket(DatagramPacket outPacket, IpPacket parsedPacket) throws DaedalusVpnService.VpnNetworkException {
DatagramSocket dnsSocket;
try {
// Packets to be sent to the real DNS server will need to be protected from the VPN