Compare commits

..

No commits in common. "862ae72fd3f6df85b7035031ab746a8f0b9e1188" and "c0cb2c43bf067d4ee8ad4dbdac3ac6d4a949db04" have entirely different histories.

15 changed files with 17 additions and 216 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -53,7 +53,6 @@ NFT_TABLE=blockcheck
DNSCHECK_DNS=${DNSCHECK_DNS:-8.8.8.8 1.1.1.1 77.88.8.1} DNSCHECK_DNS=${DNSCHECK_DNS:-8.8.8.8 1.1.1.1 77.88.8.1}
DNSCHECK_DOM=${DNSCHECK_DOM:-pornhub.com ntc.party rutracker.org www.torproject.org bbc.com} DNSCHECK_DOM=${DNSCHECK_DOM:-pornhub.com ntc.party rutracker.org www.torproject.org bbc.com}
DOH_SERVERS=${DOH_SERVERS:-"https://cloudflare-dns.com/dns-query https://dns.google/dns-query https://dns.quad9.net/dns-query https://dns.adguard.com/dns-query https://common.dot.dns.yandex.net/dns-query"}
DNSCHECK_DIG1=/tmp/dig1.txt DNSCHECK_DIG1=/tmp/dig1.txt
DNSCHECK_DIG2=/tmp/dig2.txt DNSCHECK_DIG2=/tmp/dig2.txt
DNSCHECK_DIGS=/tmp/digs.txt DNSCHECK_DIGS=/tmp/digs.txt
@ -202,35 +201,6 @@ nft_has_nfq()
} }
return $res return $res
} }
doh_resolve()
{
# $1 - ip version 4/6
# $2 - hostname
# $3 - doh server URL. use $DOH_SERVER if empty
$MDIG --family=$1 --dns-make-query=$2 | curl -s --data-binary @- -H "Content-Type: application/dns-message" "${3:-$DOH_SERVER}" | $MDIG --dns-parse-query
}
doh_find_working()
{
local doh
[ -n "$DOH_SERVER" ] && return 0
echo "* searching working DoH server"
DOH_SERVER=
for doh in $DOH_SERVERS; do
echo -n "$doh : "
if doh_resolve 4 iana.org $doh >/dev/null 2>/dev/null; then
echo OK
DOH_SERVER="$doh"
return 0
else
echo FAIL
fi
done
echo all DoH servers failed
return 1
}
mdig_vars() mdig_vars()
{ {
# $1 - ip version 4/6 # $1 - ip version 4/6
@ -249,11 +219,7 @@ mdig_cache()
mdig_vars "$@" mdig_vars "$@"
[ -n "$count" ] || { [ -n "$count" ] || {
# windows version of mdig outputs 0D0A line ending. remove 0D. # windows version of mdig outputs 0D0A line ending. remove 0D.
if [ "$SECURE_DNS" = 1 ]; then
ips="$(echo $2 | doh_resolve $1 $2 | tr -d '\r' | xargs)"
else
ips="$(echo $2 | "$MDIG" --family=$1 | tr -d '\r' | xargs)" ips="$(echo $2 | "$MDIG" --family=$1 | tr -d '\r' | xargs)"
fi
[ -n "$ips" ] || return 1 [ -n "$ips" ] || return 1
count=0 count=0
for ip in $ips; do for ip in $ips; do
@ -552,7 +518,7 @@ curl_supports_tls13()
[ $? = 2 ] && return 1 [ $? = 2 ] && return 1
# curl can have tlsv1.3 key present but ssl library without TLS 1.3 support # curl can have tlsv1.3 key present but ssl library without TLS 1.3 support
# this is online test because there's no other way to trigger library incompatibility case # this is online test because there's no other way to trigger library incompatibility case
$CURL --tlsv1.3 --max-time $CURL_MAX_TIME -Is -o /dev/null https://iana.org 2>/dev/null $CURL --tlsv1.3 --max-time $CURL_MAX_TIME -Is -o /dev/null https://w3.org 2>/dev/null
r=$? r=$?
[ $r != 4 -a $r != 35 ] [ $r != 4 -a $r != 35 ]
} }
@ -1711,7 +1677,7 @@ pingtest()
dnstest() dnstest()
{ {
# $1 - dns server. empty for system resolver # $1 - dns server. empty for system resolver
"$LOOKUP" iana.org $1 >/dev/null 2>/dev/null "$LOOKUP" w3.org $1 >/dev/null 2>/dev/null
} }
find_working_public_dns() find_working_public_dns()
{ {
@ -1760,10 +1726,6 @@ check_dns()
{ {
local C1 C2 dom local C1 C2 dom
DNS_IS_SPOOFED=0
[ "$SKIP_DNSCHECK" = 1 ] && return 0
echo \* checking DNS echo \* checking DNS
[ -f "$DNSCHECK_DIGS" ] && rm -f "$DNSCHECK_DIGS" [ -f "$DNSCHECK_DIGS" ] && rm -f "$DNSCHECK_DIGS"
@ -1786,8 +1748,6 @@ check_dns()
check_dns_cleanup check_dns_cleanup
echo -- POSSIBLE DNS HIJACK DETECTED. ZAPRET WILL NOT HELP YOU IN CASE DNS IS SPOOFED !!! echo -- POSSIBLE DNS HIJACK DETECTED. ZAPRET WILL NOT HELP YOU IN CASE DNS IS SPOOFED !!!
echo -- DNS CHANGE OR DNSCRYPT MAY BE REQUIRED echo -- DNS CHANGE OR DNSCRYPT MAY BE REQUIRED
DNS_IS_SPOOFED=1
USE_SECURE_DNS=${USE_SECURE_DNS:-1}
return 1 return 1
else else
echo $dom : OK echo $dom : OK
@ -1817,8 +1777,6 @@ check_dns()
echo -- POSSIBLE DNS HIJACK DETECTED. ZAPRET WILL NOT HELP YOU IN CASE DNS IS SPOOFED !!! echo -- POSSIBLE DNS HIJACK DETECTED. ZAPRET WILL NOT HELP YOU IN CASE DNS IS SPOOFED !!!
echo -- DNSCRYPT MAY BE REQUIRED echo -- DNSCRYPT MAY BE REQUIRED
check_dns_cleanup check_dns_cleanup
DNS_IS_SPOOFED=1
USE_SECURE_DNS=${USE_SECURE_DNS:-1}
return 1 return 1
} }
echo all resolved IPs are unique echo all resolved IPs are unique
@ -1867,8 +1825,7 @@ check_already
[ "$UNAME" = CYGWIN ] || require_root [ "$UNAME" = CYGWIN ] || require_root
check_prerequisites check_prerequisites
trap sigint_cleanup INT trap sigint_cleanup INT
check_dns [ "$SKIP_DNSCHECK" = 1 ] || check_dns
[ "$SECURE_DNS" = 1 ] && doh_find_working
check_virt check_virt
ask_params ask_params
trap - INT trap - INT

View File

@ -341,8 +341,3 @@ v66:
init.d: rewrite traffic interception and daemon launch parameters in config file. this break compatibility with old versions. init.d: rewrite traffic interception and daemon launch parameters in config file. this break compatibility with old versions.
init.d: openwrt-minimal : tpws launch for low storage openwrt devices init.d: openwrt-minimal : tpws launch for low storage openwrt devices
v67:
mdig: --dns-make-query, --dns-parse-query for side-channel resolving (DoH)
blockcheck: use DoH resolvers if DNS spoof is detected

View File

@ -1098,26 +1098,6 @@ ip2net фильтрует входные данные, выкидывая неп
Не надо делать такое : 5000000/10000000. 1/2 - гораздо лучше. Не надо делать такое : 5000000/10000000. 1/2 - гораздо лучше.
mdig
----
Программа предназначена для многопоточного ресолвинга больших листов через системный DNS.
Она берет из stdin список доменов и выводит в stdout результат ресолвинга. Ошибки выводятся в stderr.
--threads=<threads_number> ; количество потоков. по умолчанию 1.
--family=<4|6|46> ; выбор семейства IP адресов : ipv4, ipv6, ipv4+ipv6
--verbose ; дебаг-лог на консоль
--stats=N ; выводить статистику каждые N доменов
--log-resolved=<file> ; сохранять успешно отресолвленные домены в файл
--log-failed=<file> ; сохранять неудачно отресолвленные домены в файл
--dns-make-query=<domain> ; вывести в stdout бинарный DNS запрос по домену. если --family=6, запрос будет AAAA, иначе A.
--dns-parse-query ; распарсить бинарный DNS ответ и выдать все ivp4 и ipv6 адреса из него в stdout
Параметры --dns-make-query и --dns-parse-query позволяют провести ресолвинг одного домена через произвольный канал.
Например, следующим образом можно выполнить DoH запрос, используя лишь mdig и curl :
mdig --family=6 --dns-make-query=rutracker.org | curl --data-binary @- -H "Content-Type: application/dns-message" https://cloudflare-dns.com/dns-query | mdig --dns-parse-query
Фильтрация по именам доменов Фильтрация по именам доменов
---------------------------- ----------------------------

View File

@ -319,135 +319,15 @@ static int run_threads(void)
return thread ? 0 : 12; return thread ? 0 : 12;
} }
// slightly patched musl code
size_t dns_mk_query_blob(uint8_t op, const char *dname, uint8_t class, uint8_t type, uint8_t *buf, size_t buflen)
{
int i, j;
uint16_t id;
struct timespec ts;
size_t l = strnlen(dname, 255);
size_t n;
if (l && dname[l-1]=='.') l--;
if (l && dname[l-1]=='.') return 0;
n = 17+l+!!l;
if (l>253 || buflen<n || op>15u) return 0;
/* Construct query template - ID will be filled later */
memset(buf, 0, n);
buf[2] = (op<<3) | 1;
buf[5] = 1;
memcpy((char *)buf+13, dname, l);
for (i=13; buf[i]; i=j+1)
{
for (j=i; buf[j] && buf[j] != '.'; j++);
if (j-i-1u > 62u) return 0;
buf[i-1] = j-i;
}
buf[i+1] = type;
buf[i+3] = class;
/* Make a reasonably unpredictable id */
clock_gettime(CLOCK_REALTIME, &ts);
id = (uint16_t)ts.tv_nsec + (uint16_t)(ts.tv_nsec>>16);
buf[0] = id>>8;
buf[1] = id;
return n;
}
int dns_make_query(const char *dom, char family)
{
uint8_t q[280];
size_t l = dns_mk_query_blob(0, dom, 1, family == FAMILY6 ? 28 : 1, q, sizeof(q));
if (!l)
{
fprintf(stderr, "could not make DNS query\n");
return 1;
}
if (fwrite(q,l,1,stdout)!=1)
{
fprintf(stderr, "could not write DNS query blob to stdout\n");
return 10;
}
return 0;
}
bool dns_parse_print(const uint8_t *a, size_t len)
{
// check of minimum header length and response flag
uint16_t k, dlen, qcount = a[4]<<8 | a[5], acount = a[6]<<8 | a[7];
char s_ip[40];
if (len<12 || !(a[2]&0x80)) return false;
a+=12; len-=12;
for(k=0;k<qcount;k++)
{
while (len && *a)
{
if ((*a+1)>len) return false;
// skip to next label
len -= *a+1; a += *a+1;
}
if (len<5) return false;
// skip zero length label, type, class
a+=5; len-=5;
}
for(k=0;k<acount;k++)
{
// 11 higher bits indicate pointer
if (len<12 || (*a & 0xC0)!=0xC0) return false;
dlen = a[10]<<8 | a[11];
if (len<(dlen+12)) return false;
if (a[4]==0 && a[5]==1 && a[2]==0) // IN class and higher byte of type = 0
{
switch(a[3])
{
case 1: // A
if (dlen!=4) break;
if (inet_ntop(AF_INET, a+12, s_ip, sizeof(s_ip)))
printf("%s\n", s_ip);
break;
case 28: // AAAA
if (dlen!=16) break;
if (inet_ntop(AF_INET6, a+12, s_ip, sizeof(s_ip)))
printf("%s\n", s_ip);
break;
}
}
len -= 12+dlen; a += 12+dlen;
}
return true;
}
int dns_parse_query()
{
uint8_t a[1500];
size_t l;
l = fread(a,1,sizeof(a),stdin);
if (!l || !feof(stdin))
{
fprintf(stderr, "could not read DNS reply blob from stdin\n");
return 10;
}
if (!dns_parse_print(a,l))
{
fprintf(stderr, "could not parse DNS reply blob\n");
return 11;
}
return 0;
}
static void exithelp(void) static void exithelp(void)
{ {
printf( printf(
" --threads=<threads_number>\n" " --threads=<threads_number>\n"
" --family=<4|6|46>\t\t; ipv4, ipv6, ipv4+ipv6\n" " --family=<4|6|46>\t; ipv4, ipv6, ipv4+ipv6\n"
" --verbose\t\t\t; print query progress to stderr\n" " --verbose\t\t; print query progress to stderr\n"
" --stats=N\t\t\t; print resolve stats to stderr every N domains\n" " --stats=N\t\t; print resolve stats to stderr every N domains\n"
" --log-resolved=<file>\t\t; log successfully resolved domains to a file\n" " --log-resolved=<file>\t; log successfully resolved domains to a file\n"
" --log-failed=<file>\t\t; log failed domains to a file\n" " --log-failed=<file>\t; log failed domains to a file\n"
" --dns-make-query=<domain>\t; output to stdout binary blob with DNS query. use --family to specify ip version.\n"
" --dns-parse-query\t\t; read from stdin binary DNS answer blob and parse it to ipv4/ipv6 addresses\n"
); );
exit(1); exit(1);
} }
@ -455,7 +335,6 @@ int main(int argc, char **argv)
{ {
int r, v, option_index = 0; int r, v, option_index = 0;
char fn1[256],fn2[256]; char fn1[256],fn2[256];
char dom[256];
static const struct option long_options[] = { static const struct option long_options[] = {
{"help",no_argument,0,0}, // optidx=0 {"help",no_argument,0,0}, // optidx=0
@ -465,13 +344,11 @@ int main(int argc, char **argv)
{"stats",required_argument,0,0}, // optidx=4 {"stats",required_argument,0,0}, // optidx=4
{"log-resolved",required_argument,0,0}, // optidx=5 {"log-resolved",required_argument,0,0}, // optidx=5
{"log-failed",required_argument,0,0}, // optidx=6 {"log-failed",required_argument,0,0}, // optidx=6
{"dns-make-query",required_argument,0,0}, // optidx=7
{"dns-parse-query",no_argument,0,0}, // optidx=8
{NULL,0,NULL,0} {NULL,0,NULL,0}
}; };
memset(&glob, 0, sizeof(glob)); memset(&glob, 0, sizeof(glob));
*fn1 = *fn2 = *dom = 0; *fn1 = *fn2 = 0;
glob.family = FAMILY4; glob.family = FAMILY4;
glob.threads = 1; glob.threads = 1;
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
@ -517,12 +394,6 @@ int main(int argc, char **argv)
strncpy(fn2,optarg,sizeof(fn2)); strncpy(fn2,optarg,sizeof(fn2));
fn2[sizeof(fn2)-1] = 0; fn2[sizeof(fn2)-1] = 0;
break; break;
case 7: /* dns-make-query */
strncpy(dom,optarg,sizeof(dom));
dom[sizeof(dom)-1] = 0;
break;
case 8: /* dns-parse-query */
return dns_parse_query();
} }
} }
@ -535,8 +406,6 @@ int main(int argc, char **argv)
} }
#endif #endif
if (*dom) return dns_make_query(dom, glob.family);
if (*fn1) if (*fn1)
{ {
glob.F_log_resolved = fopen(fn1,"wt"); glob.F_log_resolved = fopen(fn1,"wt");