mdig : multithread digger

This commit is contained in:
bolvan 2019-04-17 14:12:14 +03:00
parent 7b15029279
commit 0d58f6171e
13 changed files with 315 additions and 4 deletions

BIN
binaries/aarch64/mdig Executable file

Binary file not shown.

BIN
binaries/armhf/mdig Executable file

Binary file not shown.

BIN
binaries/mips32r1-lsb/mdig Executable file

Binary file not shown.

BIN
binaries/mips32r1-msb/mdig Executable file

Binary file not shown.

BIN
binaries/x86/mdig Executable file

Binary file not shown.

BIN
binaries/x86_64/mdig Executable file

Binary file not shown.

View File

@ -99,3 +99,6 @@ tpws : added hostlist option
v20 v20
added ip2net. ip2net groups ips from iplist into subnets and reduces ipset size twice added ip2net. ip2net groups ips from iplist into subnets and reduces ipset size twice
v21
added mdig. get_reestr.sh is *real* again

View File

@ -0,0 +1,32 @@
#
include $(TOPDIR)/rules.mk
PKG_NAME:=mdig
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/mdig
SECTION:=net
CATEGORY:=Network
TITLE:=mdig
SUBMENU:=Zapret
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./mdig/* $(PKG_BUILD_DIR)/
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
endef
define Package/mdig/install
$(INSTALL_DIR) $(1)/opt/zapret/mdig
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret/mdig
endef
$(eval $(call BuildPackage,mdig))

View File

@ -0,0 +1 @@
Copy "mdig" folder here !

View File

@ -12,6 +12,18 @@ ZIPLISTTMP=$TMPDIR/zapret-ip.txt
#ZURL=https://reestr.rublacklist.net/api/current #ZURL=https://reestr.rublacklist.net/api/current
ZURL=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv ZURL=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv
MDIG=$EXEDIR/../mdig/mdig
MDIG_THREADS=30
digger()
{
if [ -x $MDIG ]; then
$MDIG --family=4 --threads=$MDIG_THREADS <$1
else
dig A +short +time=8 +tries=2 -f $1
fi
}
getuser getuser
curl -k --fail --max-time 300 --max-filesize 41943040 "$ZURL" >$ZREESTR || curl -k --fail --max-time 300 --max-filesize 41943040 "$ZURL" >$ZREESTR ||
@ -30,12 +42,12 @@ echo preparing dig list ..
cut -f2 -d';' $ZREESTR | grep -avE '^$|\*|:' >$ZDIG cut -f2 -d';' $ZREESTR | grep -avE '^$|\*|:' >$ZDIG
rm -f $ZREESTR rm -f $ZREESTR
echo digging started ... echo digging started ...
dig A +short +time=8 +tries=2 -f $ZDIG | grep -E '^[^;].*[^\.]$' | grep -vE '^192\.168\.[0-9]+\.[0-9]+$' | grep -vE '^127\.[0-9]+\.[0-9]+\.[0-9]+$' | grep -vE '^10\.[0-9]+\.[0-9]+\.[0-9]+$' >$ZIPLISTTMP || { digger $ZDIG | grep -E '^[^;].*[^\.]$' | grep -vE '^192\.168\.[0-9]+\.[0-9]+$' | grep -vE '^127\.[0-9]+\.[0-9]+\.[0-9]+$' | grep -vE '^10\.[0-9]+\.[0-9]+\.[0-9]+$' >$ZIPLISTTMP || {
rm -f $ZDIG rm -f $ZDIG
exit 1 exit 1
} }
rm -f $ZDIG $ZIPLIST rm -f $ZDIG $ZIPLIST
sort $ZIPLISTTMP | uniq >$ZIPLIST sort -u $ZIPLISTTMP >$ZIPLIST
rm -f $ZIPLISTTMP rm -f $ZIPLISTTMP
"$EXEDIR/create_ipset.sh" "$EXEDIR/create_ipset.sh"

12
mdig/Makefile Normal file
View File

@ -0,0 +1,12 @@
CC ?= gcc
CFLAGS += -s -O3
LIBS =
SRC_FILES = *.c
all: mdig
mdig: $(SRC_FILES)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
clean:
rm -f mdig *.o

243
mdig/mdig.c Normal file
View File

@ -0,0 +1,243 @@
// multi thread dns resolver
// domain list <stdin
// ip list >stdout
// errors, verbose >stderr
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <getopt.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#define RESOLVER_EAGAIN_ATTEMPTS 3
void trimstr(char *s)
{
char *p;
for (p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--) *p = '\0';
}
const char* eai_str(int r)
{
switch (r)
{
case EAI_NONAME:
return "EAI_NONAME";
case EAI_AGAIN:
return "EAI_AGAIN";
case EAI_ADDRFAMILY:
return "EAI_ADDRFAMILY";
case EAI_BADFLAGS:
return "EAI_BADFLAGS";
case EAI_FAIL:
return "EAI_FAIL";
case EAI_MEMORY:
return "EAI_MEMORY";
case EAI_FAMILY:
return "EAI_FAMILY";
case EAI_NODATA:
return "EAI_NODATA";
case EAI_SERVICE:
return "EAI_SERVICE";
case EAI_SOCKTYPE:
return "EAI_SOCKTYPE";
case EAI_SYSTEM:
return "EAI_SYSTEM";
default:
return "UNKNOWN";
}
}
#define FAMILY4 1
#define FAMILY6 2
static struct
{
char verbose;
char family;
int threads;
pthread_mutex_t flock;
} glob;
// get next domain. return 0 if failure
static char interlocked_get_dom(char *dom, size_t size)
{
char *s;
pthread_mutex_lock(&glob.flock);
s = fgets(dom, size, stdin);
pthread_mutex_unlock(&glob.flock);
if (!s) return 0;
trimstr(s);
return 1;
}
static void interlocked_fprintf(FILE *stream, const char * format, ...)
{
va_list args;
va_start(args, format);
pthread_mutex_lock(&glob.flock);
vfprintf(stream, format, args);
pthread_mutex_unlock(&glob.flock);
va_end(args);
}
#define ELOG(format, ...) interlocked_fprintf(stderr, "[%d] " format "\n", tid, ##__VA_ARGS__)
#define VLOG(format, ...) {if (glob.verbose) ELOG(format, ##__VA_ARGS__);}
static void print_addrinfo(struct addrinfo *ai, char family)
{
char str[64];
while (ai)
{
switch (ai->ai_family)
{
case AF_INET:
if (inet_ntop(ai->ai_family, &((struct sockaddr_in*)ai->ai_addr)->sin_addr, str, sizeof(str)))
interlocked_fprintf(stdout, "%s\n", str);
break;
case AF_INET6:
if (inet_ntop(ai->ai_family, &((struct sockaddr_in6*)ai->ai_addr)->sin6_addr, str, sizeof(str)))
interlocked_fprintf(stdout, "%s\n", str);
break;
}
ai = ai->ai_next;
}
}
static void *t_resolver(void *arg)
{
int tid = (int)(size_t)arg;
int i,r;
char dom[256];
struct addrinfo hints;
struct addrinfo *result;
VLOG("started");
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = (glob.family == FAMILY4) ? AF_INET : (glob.family == FAMILY6) ? AF_INET6 : AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
while (interlocked_get_dom(dom, sizeof(dom)))
{
if (*dom)
{
VLOG("resolving %s", dom);
for (i = 0; i < RESOLVER_EAGAIN_ATTEMPTS; i++)
{
if (r = getaddrinfo(dom, NULL, &hints, &result))
{
ELOG("failed to resolve %s : result %d (%s)", dom, r, eai_str(r));
if (r == EAI_AGAIN) continue; // temporary failure. should retry
}
else
{
print_addrinfo(result, glob.family);
freeaddrinfo(result);
}
break;
}
}
}
VLOG("ended");
return NULL;
}
static int run_threads()
{
int i, thread;
pthread_t *t;
if (pthread_mutex_init(&glob.flock, NULL) != 0)
{
fprintf(stderr, "mutex init failed\n");
return 10;
}
t = (pthread_t*)malloc(sizeof(pthread_t)*glob.threads);
if (!t)
{
fprintf(stderr, "out of memory\n");
pthread_mutex_destroy(&glob.flock);
return 11;
}
for (thread = 0; thread < glob.threads; thread++)
{
if (pthread_create(t + thread, NULL, t_resolver, (void*)(size_t)thread))
{
interlocked_fprintf(stderr, "failed to create thread #%d\n", thread);
break;
}
}
for (i = 0; i < thread; i++)
{
pthread_join(t[i], NULL);
}
free(t);
pthread_mutex_destroy(&glob.flock);
return thread ? 0 : 12;
}
static void exithelp()
{
printf(
" --threads=<threads_number>\n"
" --family=<4|6|46>\t; ipv4, ipv6, ipv4+ipv6\n"
" --verbose\t\t; print query progress to stderr\n"
);
exit(1);
}
int main(int argc, char **argv)
{
int ret, v, option_index = 0;
static const struct option long_options[] = {
{"threads",required_argument,0,0}, // optidx=0
{"family",required_argument,0,0}, // optidx=1
{"verbose",no_argument,0,0}, // optidx=2
{"help",no_argument,0,0}, // optidx=3
{NULL,0,NULL,0}
};
glob.verbose = '\0';
glob.family = FAMILY4;
glob.threads = 1;
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{
if (v) exithelp();
switch (option_index)
{
case 0: /* threads */
glob.threads = optarg ? atoi(optarg) : 0;
if (glob.threads <= 0 || glob.threads > 100)
{
fprintf(stderr, "thread number must be within 1..100\n");
return 1;
}
break;
case 1: /* family */
if (!strcmp(optarg, "4"))
glob.family = FAMILY4;
else if (!strcmp(optarg, "6"))
glob.family = FAMILY6;
else if (!strcmp(optarg, "46"))
glob.family = FAMILY4 | FAMILY6;
else
{
fprintf(stderr, "ip family must be 4,6 or 46\n");
return 1;;
}
break;
case 2: /* verbose */
glob.verbose = '\1';
break;
case 3: /* help */
exithelp();
break;
}
}
return run_threads();
}

View File

@ -1,4 +1,4 @@
zapret v.20 zapret v.21
Для чего это надо Для чего это надо
----------------- -----------------
@ -194,6 +194,11 @@ tiera : Требуется сплит http запросов в течение в
несколько Мб и продолжает расти. На роутерах openwrt /tmp представляет собой tmpfs , то есть ramdisk. несколько Мб и продолжает расти. На роутерах openwrt /tmp представляет собой tmpfs , то есть ramdisk.
В случае роутера с 32 мб памяти ее не хватит, и будут проблемы. В этом случае используйте В случае роутера с 32 мб памяти ее не хватит, и будут проблемы. В этом случае используйте
следующий скрипт. следующий скрипт.
get_reestr.sh может использовать мультипоточный ресолвер mdig (собственная разработка) или
стандартный однопоточный dig от bind. При наличии скомпилированного mdig или скопированного в zapret/mdig бинарика
используется он, в противном случае dig.
Реестр РКН уже настолько огромен, что однопоточный ресолв займет вечность, а многопоточный хоть и тоже много времени,
но хотя бы оно конечно. В скрипте можно настроить количество потоков.
3) ipset/get_anizapret.sh. быстро и без нагрузки на роутер получает лист с antizapret.prostovpn.org. 3) ipset/get_anizapret.sh. быстро и без нагрузки на роутер получает лист с antizapret.prostovpn.org.
@ -252,6 +257,9 @@ Debian 7 изначально содержит ядро 3.2. Оно не уме
Собрать ip2net : Собрать ip2net :
cd /opt/zapret/ip2net cd /opt/zapret/ip2net
make make
Собрать mdig :
cd /opt/zapret/mdig
make
Скопировать /opt/zapret/init.d/debian7/zapret в /etc/init.d. Скопировать /opt/zapret/init.d/debian7/zapret в /etc/init.d.
В /etc/init.d/zapret выбрать пераметр "ISP". В зависимости от него будут применены нужные правила. В /etc/init.d/zapret выбрать пераметр "ISP". В зависимости от него будут применены нужные правила.
Там же выбрать параметр SLAVE_ETH, соответствующий названию внутреннего сетевого интерфейса. Там же выбрать параметр SLAVE_ETH, соответствующий названию внутреннего сетевого интерфейса.
@ -331,7 +339,7 @@ opkg install iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptable
Скорее всего таковой найдется. Если нет - вам придется собирать самостоятельно. Скорее всего таковой найдется. Если нет - вам придется собирать самостоятельно.
Скопировать директорию "zapret" в /opt на роутер. Скопировать директорию "zapret" в /opt на роутер.
Скопировать работающий бинарик nfqws в /opt/zapret/nfq, tpws в /opt/zapret/tpws, ip2net в /opt/zapret/ip2net. Скопировать работающий бинарик nfqws в /opt/zapret/nfq, tpws в /opt/zapret/tpws, ip2net в /opt/zapret/ip2net, mdig в /opt/zapret/mdig.
Скопировать /opt/zapret/init.d/zapret в /etc/init.d. Скопировать /opt/zapret/init.d/zapret в /etc/init.d.
В /etc/init.d/zapret выбрать пераметр "ISP". В зависимости от него будут применены нужные правила. В /etc/init.d/zapret выбрать пераметр "ISP". В зависимости от него будут применены нужные правила.
/etc/init.d/zapret enable /etc/init.d/zapret enable