mirror of https://github.com/M66B/NetGuard.git
Native experiment: route DNS traffic into dnscrypt-proxy
Setup: - download dnscrypt-proxy compiled for Android from https://dnscrypt.org/ - copy the following files to /system/xbin using recovery: -rwxr-xr-x root root 224320 2016-02-03 14:44 dnscrypt-proxy -rwxr-xr-x root root 130432 2016-02-03 14:40 hostip -rwxr-xr-x root root 268196 2016-02-03 14:40 libsodium.so - make these files executable (chmod 755) - copy dnscrypt-resolvers.csv to /sdcard//Download/dnscrypt/ - run this script from the shell: export LD_LIBRARY_PATH="/system/xbin" dnscrypt-proxy -a127.0.0.1:5353 --loglevel=7 --resolver-name="dnscrypt.org-fr" --resolvers-list=/sdcard//Download/dnscrypt/dnscrypt-resolvers.csv - make sure you set an IPv4 DNS server in NetGuard - note that Android caches DNS responses for 10 minutes - profit! Refs #272
This commit is contained in:
parent
2834f1e555
commit
0d61d804d8
|
@ -35,7 +35,7 @@
|
|||
void logPacket(eu.faircode.netguard.Packet);
|
||||
void dnsResolved(eu.faircode.netguard.ResourceRecord);
|
||||
boolean isDomainBlocked(java.lang.String);
|
||||
boolean isAddressAllowed(eu.faircode.netguard.Packet);
|
||||
int isAddressAllowed(eu.faircode.netguard.Packet);
|
||||
}
|
||||
|
||||
#Support library
|
||||
|
|
|
@ -1084,12 +1084,12 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
}
|
||||
|
||||
// Called from native code
|
||||
private boolean isAddressAllowed(Packet packet) {
|
||||
private int isAddressAllowed(Packet packet) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
// Allow name resolving
|
||||
if (packet.uid == Process.myUid())
|
||||
return true;
|
||||
return -1;
|
||||
|
||||
packet.allowed = false;
|
||||
if (packet.protocol == 6 /* TCP */ || packet.protocol == 17 /* UDP */
|
||||
|
@ -1123,7 +1123,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
if (prefs.getBoolean("log", false) || prefs.getBoolean("log_app", false))
|
||||
logPacket(packet);
|
||||
|
||||
return packet.allowed;
|
||||
return packet.allowed ? -1 : 0;
|
||||
}
|
||||
|
||||
private BroadcastReceiver interactiveStateReceiver = new BroadcastReceiver() {
|
||||
|
|
|
@ -875,7 +875,7 @@ void check_icmp_sockets(const struct arguments *args, fd_set *rfds, fd_set *wfds
|
|||
0, (uint8_t *) &pseudo, sizeof(struct ip6_hdr_pseudo));
|
||||
}
|
||||
icmp->icmp_cksum = 0;
|
||||
icmp->icmp_cksum = ~calc_checksum(csum, buffer, bytes);
|
||||
icmp->icmp_cksum = ~calc_checksum(csum, buffer, (size_t) bytes);
|
||||
|
||||
// Forward to tun
|
||||
if (write_icmp(args, cur, buffer, (size_t) bytes) < 0)
|
||||
|
@ -913,7 +913,7 @@ void check_udp_sockets(const struct arguments *args, fd_set *rfds, fd_set *wfds,
|
|||
if (FD_ISSET(cur->socket, rfds)) {
|
||||
cur->time = time(NULL);
|
||||
|
||||
uint16_t blen = cur->version == 4 ? UDP4_MAXMSG : UDP6_MAXMSG;
|
||||
uint16_t blen = (uint16_t) (cur->version == 4 ? UDP4_MAXMSG : UDP6_MAXMSG);
|
||||
uint8_t *buffer = malloc(blen);
|
||||
ssize_t bytes = recv(cur->socket, buffer, blen, 0);
|
||||
if (bytes < 0) {
|
||||
|
@ -1413,14 +1413,14 @@ void handle_ip(const struct arguments *args, const uint8_t *pkt, const size_t le
|
|||
#endif
|
||||
|
||||
// Check if allowed
|
||||
jboolean allowed = 0;
|
||||
int32_t allowed = 0;
|
||||
if (protocol == IPPROTO_UDP && dport == 53)
|
||||
allowed = 1; // allow DNS
|
||||
allowed = 5353; // allow DNS
|
||||
else if (protocol == IPPROTO_UDP && has_udp_session(args, pkt, payload)) {
|
||||
allowed = 1;
|
||||
allowed = -1;
|
||||
log_android(ANDROID_LOG_INFO, "UDP existing session allowed");
|
||||
} else if (protocol == IPPROTO_TCP && !syn)
|
||||
allowed = 1; // assume session
|
||||
allowed = -1; // assume session
|
||||
else {
|
||||
jobject objPacket = create_packet(
|
||||
args, version, protocol, flags, source, sport, dest, dport, "", uid, 0);
|
||||
|
@ -1432,7 +1432,7 @@ void handle_ip(const struct arguments *args, const uint8_t *pkt, const size_t le
|
|||
if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6)
|
||||
handle_icmp(args, pkt, length, payload, uid);
|
||||
else if (protocol == IPPROTO_UDP)
|
||||
handle_udp(args, pkt, length, payload, uid);
|
||||
handle_udp(args, pkt, length, payload, uid, allowed);
|
||||
else if (protocol == IPPROTO_TCP)
|
||||
handle_tcp(args, pkt, length, payload, uid);
|
||||
}
|
||||
|
@ -1536,7 +1536,7 @@ jboolean handle_icmp(const struct arguments *args,
|
|||
csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ip6_hdr_pseudo));
|
||||
}
|
||||
icmp->icmp_cksum = 0;
|
||||
icmp->icmp_cksum = ~calc_checksum(csum, icmp, icmplen);
|
||||
icmp->icmp_cksum = ~calc_checksum(csum, (uint8_t *) icmp, icmplen);
|
||||
|
||||
log_android(ANDROID_LOG_INFO,
|
||||
"ICMP forward from tun %s to %s type %d code %d id %x seq %d data %d",
|
||||
|
@ -1594,7 +1594,7 @@ int has_udp_session(const struct arguments *args, const uint8_t *pkt, const uint
|
|||
|
||||
jboolean handle_udp(const struct arguments *args,
|
||||
const uint8_t *pkt, size_t length, const uint8_t *payload,
|
||||
int uid) {
|
||||
int uid, int32_t lport) {
|
||||
// Get headers
|
||||
const uint8_t version = (*pkt) >> 4;
|
||||
const struct iphdr *ip4 = (struct iphdr *) pkt;
|
||||
|
@ -1629,8 +1629,8 @@ jboolean handle_udp(const struct arguments *args,
|
|||
|
||||
// Create new session if needed
|
||||
if (cur == NULL) {
|
||||
log_android(ANDROID_LOG_INFO, "UDP new session from %s/%u to %s/%u",
|
||||
source, ntohs(udphdr->source), dest, ntohs(udphdr->dest));
|
||||
log_android(ANDROID_LOG_INFO, "UDP new session from %s/%u to %s/%u lport %d",
|
||||
source, ntohs(udphdr->source), dest, ntohs(udphdr->dest), lport);
|
||||
|
||||
// Register session
|
||||
struct udp_session *u = malloc(sizeof(struct udp_session));
|
||||
|
@ -1652,6 +1652,7 @@ jboolean handle_udp(const struct arguments *args,
|
|||
u->next = NULL;
|
||||
|
||||
// Open UDP socket
|
||||
u->lport = lport;
|
||||
u->socket = open_udp_socket(args, u);
|
||||
if (u->socket < 0) {
|
||||
free(u);
|
||||
|
@ -1710,12 +1711,26 @@ jboolean handle_udp(const struct arguments *args,
|
|||
struct sockaddr_in6 server6;
|
||||
if (version == 4) {
|
||||
server4.sin_family = AF_INET;
|
||||
server4.sin_addr.s_addr = (__be32) ip4->daddr;
|
||||
server4.sin_port = udphdr->dest;
|
||||
if (cur->lport < 0 || cur->uid == 2000) {
|
||||
server4.sin_addr.s_addr = (__be32) ip4->daddr;
|
||||
server4.sin_port = udphdr->dest;
|
||||
}
|
||||
else {
|
||||
inet_pton(AF_INET, "127.0.0.1", &server4.sin_addr.s_addr);
|
||||
server4.sin_port = htons(cur->lport);
|
||||
log_android(ANDROID_LOG_WARN, "Redirecting to local IP4 port %d", cur->lport);
|
||||
}
|
||||
} else {
|
||||
server6.sin6_family = AF_INET6;
|
||||
memcpy(&server6.sin6_addr, &ip6->ip6_dst, 16);
|
||||
server6.sin6_port = udphdr->dest;
|
||||
if (cur->lport < 0 || cur->uid == 2000) {
|
||||
memcpy(&server6.sin6_addr, &ip6->ip6_dst, 16);
|
||||
server6.sin6_port = udphdr->dest;
|
||||
}
|
||||
else {
|
||||
inet_pton(AF_INET6, "::1", &ip6->ip6_dst);
|
||||
server4.sin_port = htons(cur->lport);
|
||||
log_android(ANDROID_LOG_WARN, "Redirecting to local IP6 port %d", cur->lport);
|
||||
}
|
||||
}
|
||||
|
||||
if (sendto(cur->socket, data, (socklen_t) datalen, MSG_NOSIGNAL,
|
||||
|
@ -3175,7 +3190,7 @@ jboolean is_domain_blocked(const struct arguments *args, const char *name) {
|
|||
|
||||
static jmethodID midIsAddressAllowed = NULL;
|
||||
|
||||
jboolean is_address_allowed(const struct arguments *args, jobject jpacket) {
|
||||
jint is_address_allowed(const struct arguments *args, jobject jpacket) {
|
||||
#ifdef PROFILE_JNI
|
||||
float mselapsed;
|
||||
struct timeval start, end;
|
||||
|
@ -3184,11 +3199,11 @@ jboolean is_address_allowed(const struct arguments *args, jobject jpacket) {
|
|||
|
||||
jclass clsService = (*args->env)->GetObjectClass(args->env, args->instance);
|
||||
|
||||
const char *signature = "(Leu/faircode/netguard/Packet;)Z";
|
||||
const char *signature = "(Leu/faircode/netguard/Packet;)I";
|
||||
if (midIsAddressAllowed == NULL)
|
||||
midIsAddressAllowed = jniGetMethodID(args->env, clsService, "isAddressAllowed", signature);
|
||||
|
||||
jboolean jallowed = (*args->env)->CallBooleanMethod(
|
||||
jint jallowed = (*args->env)->CallIntMethod(
|
||||
args->env, args->instance, midIsAddressAllowed, jpacket);
|
||||
jniCheckException(args->env);
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ struct udp_session {
|
|||
__be16 dest; // network notation
|
||||
|
||||
uint8_t stop;
|
||||
int32_t lport; // host notation
|
||||
jint socket;
|
||||
|
||||
struct udp_session *next;
|
||||
|
@ -270,7 +271,7 @@ int has_udp_session(const struct arguments *args, const uint8_t *pkt, const uint
|
|||
jboolean handle_udp(const struct arguments *args,
|
||||
const uint8_t *pkt, size_t length,
|
||||
const uint8_t *payload,
|
||||
int uid);
|
||||
int uid, int32_t lport);
|
||||
|
||||
int get_dns_query(const struct arguments *args, const struct udp_session *u,
|
||||
const uint8_t *data, const size_t datalen,
|
||||
|
@ -290,6 +291,8 @@ jboolean handle_tcp(const struct arguments *args,
|
|||
const uint8_t *payload,
|
||||
int uid);
|
||||
|
||||
int open_icmp_socket(const struct arguments *args, const struct icmp_session *cur);
|
||||
|
||||
int open_udp_socket(const struct arguments *args, const struct udp_session *cur);
|
||||
|
||||
int open_tcp_socket(const struct arguments *args, const struct tcp_session *cur);
|
||||
|
@ -353,7 +356,7 @@ void dns_resolved(const struct arguments *args,
|
|||
|
||||
jboolean is_domain_blocked(const struct arguments *args, const char *name);
|
||||
|
||||
jboolean is_address_allowed(const struct arguments *args, jobject objPacket);
|
||||
jint is_address_allowed(const struct arguments *args, jobject objPacket);
|
||||
|
||||
jobject create_packet(const struct arguments *args,
|
||||
jint version,
|
||||
|
|
Loading…
Reference in New Issue