diff --git a/binaries/aarch64/mdig b/binaries/aarch64/mdig new file mode 100755 index 0000000..29f108d Binary files /dev/null and b/binaries/aarch64/mdig differ diff --git a/binaries/armhf/mdig b/binaries/armhf/mdig new file mode 100755 index 0000000..ce7abcb Binary files /dev/null and b/binaries/armhf/mdig differ diff --git a/binaries/mips32r1-lsb/mdig b/binaries/mips32r1-lsb/mdig new file mode 100755 index 0000000..e9fae27 Binary files /dev/null and b/binaries/mips32r1-lsb/mdig differ diff --git a/binaries/mips32r1-msb/mdig b/binaries/mips32r1-msb/mdig new file mode 100755 index 0000000..cf09ef6 Binary files /dev/null and b/binaries/mips32r1-msb/mdig differ diff --git a/binaries/x86/mdig b/binaries/x86/mdig new file mode 100755 index 0000000..2ad4f47 Binary files /dev/null and b/binaries/x86/mdig differ diff --git a/binaries/x86_64/mdig b/binaries/x86_64/mdig new file mode 100755 index 0000000..17c0c05 Binary files /dev/null and b/binaries/x86_64/mdig differ diff --git a/changes.txt b/changes.txt index 3967670..bbadab6 100644 --- a/changes.txt +++ b/changes.txt @@ -99,3 +99,6 @@ tpws : added hostlist option v20 added ip2net. ip2net groups ips from iplist into subnets and reduces ipset size twice + +v21 +added mdig. get_reestr.sh is *real* again diff --git a/compile/openwrt/package/zapret/mdig/Makefile b/compile/openwrt/package/zapret/mdig/Makefile new file mode 100644 index 0000000..55d55d2 --- /dev/null +++ b/compile/openwrt/package/zapret/mdig/Makefile @@ -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)) + diff --git a/compile/openwrt/package/zapret/mdig/readme.txt b/compile/openwrt/package/zapret/mdig/readme.txt new file mode 100644 index 0000000..14e5c14 --- /dev/null +++ b/compile/openwrt/package/zapret/mdig/readme.txt @@ -0,0 +1 @@ +Copy "mdig" folder here ! diff --git a/ipset/get_reestr.sh b/ipset/get_reestr.sh index 2d2e00d..9c9cc1b 100755 --- a/ipset/get_reestr.sh +++ b/ipset/get_reestr.sh @@ -12,6 +12,18 @@ ZIPLISTTMP=$TMPDIR/zapret-ip.txt #ZURL=https://reestr.rublacklist.net/api/current 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 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 rm -f $ZREESTR 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 exit 1 } rm -f $ZDIG $ZIPLIST -sort $ZIPLISTTMP | uniq >$ZIPLIST +sort -u $ZIPLISTTMP >$ZIPLIST rm -f $ZIPLISTTMP "$EXEDIR/create_ipset.sh" diff --git a/mdig/Makefile b/mdig/Makefile new file mode 100644 index 0000000..588344d --- /dev/null +++ b/mdig/Makefile @@ -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 diff --git a/mdig/mdig.c b/mdig/mdig.c new file mode 100644 index 0000000..9c5767f --- /dev/null +++ b/mdig/mdig.c @@ -0,0 +1,243 @@ +// multi thread dns resolver +// domain list stdout +// errors, verbose >stderr + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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=\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(); +} diff --git a/readme.txt b/readme.txt index d8cd293..3df3522 100644 --- a/readme.txt +++ b/readme.txt @@ -1,4 +1,4 @@ -zapret v.20 +zapret v.21 Для чего это надо ----------------- @@ -194,6 +194,11 @@ tiera : Требуется сплит http запросов в течение в несколько Мб и продолжает расти. На роутерах openwrt /tmp представляет собой tmpfs , то есть ramdisk. В случае роутера с 32 мб памяти ее не хватит, и будут проблемы. В этом случае используйте следующий скрипт. +get_reestr.sh может использовать мультипоточный ресолвер mdig (собственная разработка) или +стандартный однопоточный dig от bind. При наличии скомпилированного mdig или скопированного в zapret/mdig бинарика +используется он, в противном случае dig. +Реестр РКН уже настолько огромен, что однопоточный ресолв займет вечность, а многопоточный хоть и тоже много времени, +но хотя бы оно конечно. В скрипте можно настроить количество потоков. 3) ipset/get_anizapret.sh. быстро и без нагрузки на роутер получает лист с antizapret.prostovpn.org. @@ -252,6 +257,9 @@ Debian 7 изначально содержит ядро 3.2. Оно не уме Собрать ip2net : cd /opt/zapret/ip2net make +Собрать mdig : + cd /opt/zapret/mdig + make Скопировать /opt/zapret/init.d/debian7/zapret в /etc/init.d. В /etc/init.d/zapret выбрать пераметр "ISP". В зависимости от него будут применены нужные правила. Там же выбрать параметр SLAVE_ETH, соответствующий названию внутреннего сетевого интерфейса. @@ -331,7 +339,7 @@ opkg install iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptable Скорее всего таковой найдется. Если нет - вам придется собирать самостоятельно. Скопировать директорию "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. В /etc/init.d/zapret выбрать пераметр "ISP". В зависимости от него будут применены нужные правила. /etc/init.d/zapret enable