Compare commits

...

17 Commits

Author SHA1 Message Date
bol-van
2db1ebafe3 tpws systemd unit fix comment 2025-03-12 18:14:43 +03:00
bol-van
33bcf6f7b4 systemd improve cheat sheet 2025-03-12 17:47:17 +03:00
bol-van
f037f1acb2 update docs 2025-03-12 17:45:19 +03:00
bol-van
cdd9b32b27 update docs 2025-03-12 17:44:04 +03:00
bol-van
7934125c09 init.d: systemd unit examples for tpws and nfqws 2025-03-12 17:27:55 +03:00
bol-van
6493d55977 tpws: move systemd notify deeper 2025-03-12 14:45:52 +03:00
bol-van
cafbb17e70 install_easy: make systemd if systemd detected 2025-03-12 14:32:00 +03:00
bol-van
9ac73f7d2f readme.eng: hostlist ^ note 2025-03-12 13:07:29 +03:00
bol-van
08a6e8e069 nfqws,tpws : rename function 2025-03-12 13:03:33 +03:00
bol-van
644a934099 nfqws.service : add special compile warning 2025-03-12 12:58:36 +03:00
bol-van
0eec445af0
Merge pull request #1237 from tie/systemd
nfqws: add support for systemd readiness notifications
2025-03-12 12:50:02 +03:00
bol-van
b8acc1b979 Revert "Revert "Revert "nfqws,tpws: fflush stdin,stdout"""
This reverts commit 123eb057aecbeca0d2e52e771a2f2bb4f45fa6cd.
2025-03-12 12:49:06 +03:00
bol-van
123eb057ae Revert "Revert "nfqws,tpws: fflush stdin,stdout""
This reverts commit 56d06456fb1eb010a46b7bb50508daa1ac6cbf31.
2025-03-12 12:48:32 +03:00
bol-van
56d06456fb Revert "nfqws,tpws: fflush stdin,stdout"
This reverts commit a6efe05aa610b0791bbc5e0364f37e4b170cbea4.
2025-03-12 12:48:18 +03:00
bol-van
a6efe05aa6 nfqws,tpws: fflush stdin,stdout 2025-03-12 12:13:53 +03:00
Ivan Trubach
a1d29b0c3a nfqws,tpws: always use line buffering for console IO
Forces stdout and stderr to always use line buffering. Note that glibc
does automatically flush on newline iff connected to a terminal, but
that is not the case when running under systemd. See also
https://www.gnu.org/software/libc/manual/html_node/Buffering-Concepts.html
https://www.gnu.org/software/libc/manual/html_node/Controlling-Buffering.html
2025-03-12 12:00:28 +03:00
Ivan Trubach
756603338b nfqws,tpws: add support for systemd readiness notifications 2025-03-12 11:39:03 +03:00
20 changed files with 222 additions and 15 deletions

View File

@ -15,6 +15,19 @@ all: clean
done \
done
systemd: clean
@mkdir -p "$(TGT)"; \
for dir in $(DIRS); do \
find "$$dir" -type f \( -name "*.c" -o -name "*.h" -o -name "*akefile" \) -exec chmod -x {} \; ; \
$(MAKE) -C "$$dir" systemd || exit; \
for exe in "$$dir/"*; do \
if [ -f "$$exe" ] && [ -x "$$exe" ]; then \
mv -f "$$exe" "${TGT}" ; \
ln -fs "../${TGT}/$$(basename "$$exe")" "$$exe" ; \
fi \
done \
done
android: clean
@mkdir -p "$(TGT)"; \
for dir in $(DIRS); do \

View File

@ -462,3 +462,5 @@ nfqws,tpws: --version
v70.4
nfqws,tpws: ^ prefix in hostlist to disable subdomain matches
nfqws,tpws: optional systemd notify support. compile using 'make systemd'
nfqws,tpws: systemd instance templates for nfqws and tpws

View File

@ -703,9 +703,9 @@ tpws is transparent proxy.
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
--hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply if not prefixed with '^', gzip supported, multiple hostlists allowed)
--hostlist-domains=<domain_list> ; comma separated fixed domain list
--hostlist-exclude=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-exclude=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply if not prefixed with '^', gzip supported, multiple hostlists allowed)
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)

View File

@ -57,6 +57,7 @@ zapret является свободным и open source.
- [Прикручивание к системе управления фаерволом или своей системе запуска](#прикручивание-к-системе-управления-фаерволом-или-своей-системе-запуска)
- [Вариант custom](#вариант-custom)
- [Простая установка](#простая-установка)
- [Установка под systemd](#установка-под-systemd)
- [Простая установка на openwrt](#простая-установка-на-openwrt)
- [Установка на openwrt в режиме острой нехватки места на диске](#установка-на-openwrt-в-режиме-острой-нехватки-места-на-диске)
- [Android](#android)
@ -2002,6 +2003,15 @@ zapret_custom_firewall_nft поднимает правила nftables.
Деинсталляция выполняется через `uninstall_easy.sh`. После выполнения деинсталляции можно удалить каталог `/opt/zapret`.
## Установка под systemd
Если вам нравится systemd и хочется максимально под него заточиться, можно отказаться от скриптов запуска zapret
и поднимать инстансы `tpws` и `nfqws` как отдельные юниты systemd. При этом вам придется вручную написать правила iptables/nftables
и каким-то образом их поднимать. Например, написать дополнительный systemd unit для этого.
Так же требуется собрать бинарники особым образом через `make systemd`.
В комплекте zapret есть шаблоны `init.d/systemd/{nfqws@.service,tpws@.service}`.
Краткий перечень команд для их использования приведен в комментариях в этих файлах.
## Простая установка на openwrt

View File

@ -0,0 +1,65 @@
# Example systemd service unit for nfqws. Adjust for your installation.
# WARNING ! This unit requires to compile nfqws using `make systemd`
# WARNING ! This makefile target enabled special systemd notify support.
# PREPARE
# install build depends
# make -C /opt/zapret systemd
# cp nfqws@service /lib/systemd/system
# systemctl daemon-reload
# MANAGE INSTANCE
# prepare /etc/zapret/nfqws1.conf with nfqws parameters
# systemctl start nfqws@nfqws1
# systemctl status nfqws@nfqws1
# systemctl restart nfqws@nfqws1
# systemctl enable nfqws@nfqws1
# systemctl disable nfqws@nfqws1
# systemctl stop nfqws@nfqws1
# DELETE
# rm /lib/systemd/system/nfqws@.service
# systemctl daemon-reload
[Unit]
After=network.target
[Service]
Type=notify
Restart=on-failure
ExecSearchPath=/opt/zapret/binaries/my
ExecStart=nfqws @${CONFIG_DIR}/${INSTANCE}.conf
Environment=CONFIG_DIR=/etc/zapret
Environment=INSTANCE=%i
RestrictAddressFamilies=AF_NETLINK AF_UNIX AF_INET6 AF_INET
LockPersonality=true
MemoryDenyWriteExecute=true
PrivateDevices=true
PrivateMounts=true
PrivateTmp=true
ProcSubset=pid
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectProc=invisible
ProtectSystem=full
RemoveIPC=true
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@resources
UMask=0077
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,63 @@
# Example systemd service unit for tpws. Adjust for your installation.
# WARNING ! This unit requires to compile tpws using `make systemd`
# WARNING ! This makefile target enabled special systemd notify support.
# PREPARE
# install build depends
# make -C /opt/zapret systemd
# cp tpws@service /lib/systemd/system
# systemctl daemon-reload
# MANAGE INSTANCE
# prepare /etc/zapret/tpws1.conf with tpws parameters
# systemctl start tpws@tpws1
# systemctl status tpws@tpws1
# systemctl restart tpws@tpws1
# systemctl enable tpws@tpws1
# systemctl disable tpws@tpws1
# systemctl stop tpws@tpws1
# DELETE
# rm /lib/systemd/system/tpws@.service
# systemctl daemon-reload
[Unit]
After=network.target
[Service]
Type=notify
Restart=on-failure
ExecSearchPath=/opt/zapret/binaries/my
ExecStart=tpws @${CONFIG_DIR}/${INSTANCE}.conf
Environment=CONFIG_DIR=/etc/zapret
Environment=INSTANCE=%i
RestrictAddressFamilies=AF_NETLINK AF_UNIX AF_INET6 AF_INET
LockPersonality=true
MemoryDenyWriteExecute=true
PrivateDevices=true
PrivateMounts=true
PrivateTmp=true
ProcSubset=pid
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectProc=invisible
ProtectSystem=full
RemoveIPC=true
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
SystemCallFilter=@system-service
UMask=0077
[Install]
WantedBy=multi-user.target

View File

@ -69,7 +69,14 @@ check_bins()
echo found architecture "\"$arch\""
elif [ -f "$EXEDIR/Makefile" ] && exists make; then
echo trying to compile
[ "$SYSTEM" = "macos" ] && make_target=mac
case $SYSTEM in
macos)
make_target=mac
;;
systemd)
make_target=systemd
;;
esac
CFLAGS="-march=native ${CFLAGS}" make -C "$EXEDIR" $make_target || {
echo could not compile
make -C "$EXEDIR" clean

View File

@ -11,6 +11,8 @@ all: ip2net
ip2net: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o ip2net $(SRC_FILES) $(LIBS) $(LDFLAGS)
systemd: ip2net
android: ip2net
bsd: $(SRC_FILES)

View File

@ -12,6 +12,8 @@ all: mdig
mdig: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS) $(LDFLAGS)
systemd: mdig
android: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS_ANDROID) $(LDFLAGS)

View File

@ -1,8 +1,10 @@
CC ?= gcc
CFLAGS += -std=gnu99 -Os -flto=auto
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
LIBS_SYSTEMD = -lsystemd
LIBS_BSD = -lz
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32
LIBS_CYGWIN32 = -lwindivert32
@ -16,6 +18,9 @@ all: nfqws
nfqws: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o nfqws $(SRC_FILES) $(LIBS_LINUX) $(LDFLAGS)
systemd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_SYSTEMD) -o nfqws $(SRC_FILES) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)
android: nfqws
bsd: $(SRC_FILES)

BIN
nfq/WinDivert.dll Normal file

Binary file not shown.

BIN
nfq/WinDivert64.sys Normal file

Binary file not shown.

View File

@ -391,6 +391,12 @@ void fill_random_az09(uint8_t *p,size_t sz)
}
}
void set_console_io_buffering(void)
{
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);
}
bool set_env_exedir(const char *argv0)
{
char *s,*d;

View File

@ -92,6 +92,7 @@ void fill_random_bytes(uint8_t *p,size_t sz);
void fill_random_az(uint8_t *p,size_t sz);
void fill_random_az09(uint8_t *p,size_t sz);
void set_console_io_buffering(void);
bool set_env_exedir(const char *argv0);

View File

@ -35,6 +35,10 @@
#include "win.h"
#endif
#ifdef USE_SYSTEMD
#include <systemd/sd-daemon.h>
#endif
#ifdef __linux__
#include <libnetfilter_queue/libnetfilter_queue.h>
#define NF_DROP 0
@ -271,6 +275,15 @@ exiterr:
return false;
}
static void notify_ready(void)
{
#ifdef USE_SYSTEMD
int r = sd_notify(0, "READY=1");
if (r < 0)
DLOG_ERR("sd_notify: %s\n", strerror(-r));
#endif
}
static int nfq_main(void)
{
uint8_t buf[16384] __attribute__((aligned));
@ -291,6 +304,8 @@ static int nfq_main(void)
if (!nfq_init(&h,&qh))
return 1;
notify_ready();
fd = nfq_fd(h);
do
{
@ -484,7 +499,6 @@ static int win_main(const char *windivert_filter)
if (!logical_net_filter_match())
{
DLOG_CONDUP("logical network is not present. waiting it to appear.\n");
fflush(stdout);
do
{
if (bQuit)
@ -497,7 +511,6 @@ static int win_main(const char *windivert_filter)
}
while (!logical_net_filter_match());
DLOG_CONDUP("logical network now present\n");
fflush(stdout);
}
if (!windivert_init(windivert_filter))
@ -508,10 +521,6 @@ static int win_main(const char *windivert_filter)
DLOG_CONDUP("windivert initialized. capture is started.\n");
// cygwin auto flush fails when piping
fflush(stdout);
fflush(stderr);
for (id=0;;id++)
{
len = sizeof(packet);
@ -574,10 +583,6 @@ static int win_main(const char *windivert_filter)
default:
DLOG("packet: id=%u drop\n", id);
}
// cygwin auto flush fails when piping
fflush(stdout);
fflush(stderr);
}
}
win_dark_deinit();
@ -1409,6 +1414,7 @@ void check_dp(const struct desync_profile *dp)
int main(int argc, char **argv)
{
set_console_io_buffering();
set_env_exedir(argv[0]);
#ifdef __CYGWIN__

View File

@ -1,7 +1,9 @@
CC ?= gcc
CFLAGS += -std=gnu99 -Os -flto=auto
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
CFLAGS_BSD = -Wno-address-of-packed-member
LIBS = -lz -lpthread
LIBS_SYSTEMD = -lz -lsystemd
LIBS_ANDROID = -lz
SRC_FILES = *.c
SRC_FILES_ANDROID = $(SRC_FILES) andr/*.c
@ -11,6 +13,9 @@ all: tpws
tpws: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES) $(LIBS) $(LDFLAGS)
systemd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_SYSTEMD) -o tpws $(SRC_FILES) $(LIBS_SYSTEMD) $(LDFLAGS)
android: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES_ANDROID) $(LIBS_ANDROID) $(LDFLAGS)

View File

@ -383,6 +383,11 @@ bool pf_is_empty(const port_filter *pf)
return !pf->neg && !pf->from && !pf->to;
}
void set_console_io_buffering(void)
{
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);
}
bool set_env_exedir(const char *argv0)
{

View File

@ -82,6 +82,7 @@ bool pf_in_range(uint16_t port, const port_filter *pf);
bool pf_parse(const char *s, port_filter *pf);
bool pf_is_empty(const port_filter *pf);
void set_console_io_buffering(void);
bool set_env_exedir(const char *argv0);
#ifndef IN_LOOPBACK

View File

@ -1694,6 +1694,7 @@ int main(int argc, char *argv[])
struct salisten_s list[MAX_BINDS];
char ip_port[48];
set_console_io_buffering();
set_env_exedir(argv[0]);
srand(time(NULL));
mask_from_preflen6_prepare();

View File

@ -16,6 +16,10 @@
#include <fcntl.h>
#include <netdb.h>
#ifdef USE_SYSTEMD
#include <systemd/sd-daemon.h>
#endif
#include "tpws.h"
#include "tpws_conn.h"
#include "redirect.h"
@ -25,6 +29,15 @@
#include "hostlist.h"
#include "linux_compat.h"
static void notify_ready(void)
{
#ifdef USE_SYSTEMD
int r = sd_notify(0, "READY=1");
if (r < 0)
DLOG_ERR("sd_notify: %s\n", strerror(-r));
#endif
}
// keep separate legs counter. counting every time thousands of legs can consume cpu
static int legs_local, legs_remote;
/*
@ -1542,6 +1555,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
VPRINT("initialized multi threaded resolver with %d threads\n",resolver_thread_count());
}
notify_ready();
for(;;)
{
ReloadCheck();
@ -1755,8 +1770,6 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
// at least one leg was removed. recount legs
print_legs();
}
fflush(stderr); fflush(stdout); // for console messages
}
ex: