mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-29 21:40:52 +03:00
mdig: --dns-make-query,--dns-parse-query
This commit is contained in:
parent
d59c77a899
commit
6be62d775b
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.
@ -341,3 +341,7 @@ 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)
|
||||||
|
@ -1098,6 +1098,26 @@ 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
|
||||||
|
|
||||||
|
|
||||||
Фильтрация по именам доменов
|
Фильтрация по именам доменов
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
143
mdig/mdig.c
143
mdig/mdig.c
@ -319,15 +319,135 @@ 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; ipv4, ipv6, ipv4+ipv6\n"
|
" --family=<4|6|46>\t\t; ipv4, ipv6, ipv4+ipv6\n"
|
||||||
" --verbose\t\t; print query progress to stderr\n"
|
" --verbose\t\t\t; print query progress to stderr\n"
|
||||||
" --stats=N\t\t; print resolve stats to stderr every N domains\n"
|
" --stats=N\t\t\t; print resolve stats to stderr every N domains\n"
|
||||||
" --log-resolved=<file>\t; log successfully resolved domains to a file\n"
|
" --log-resolved=<file>\t\t; log successfully resolved domains to a file\n"
|
||||||
" --log-failed=<file>\t; log failed domains to a file\n"
|
" --log-failed=<file>\t\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);
|
||||||
}
|
}
|
||||||
@ -335,6 +455,7 @@ 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
|
||||||
@ -344,11 +465,13 @@ 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 = 0;
|
*fn1 = *fn2 = *dom = 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)
|
||||||
@ -394,6 +517,12 @@ 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,6 +535,8 @@ 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");
|
||||||
|
Loading…
Reference in New Issue
Block a user