mirror of
https://github.com/bol-van/zapret.git
synced 2025-04-19 13:32:58 +03:00
nfqws: works without root now
This commit is contained in:
parent
0127713829
commit
40b1c7b903
@ -12,7 +12,7 @@ define Package/nfqws
|
|||||||
CATEGORY:=Network
|
CATEGORY:=Network
|
||||||
TITLE:=nfqws
|
TITLE:=nfqws
|
||||||
SUBMENU:=Zapret
|
SUBMENU:=Zapret
|
||||||
DEPENDS:=+libnetfilter-queue
|
DEPENDS:=+libnetfilter-queue +libcap
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Build/Prepare
|
define Build/Prepare
|
||||||
|
@ -136,6 +136,8 @@ It takes the following parameters:
|
|||||||
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
|
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
|
||||||
--daemon ; daemonize
|
--daemon ; daemonize
|
||||||
--pidfile=<filename> ; write pid to file
|
--pidfile=<filename> ; write pid to file
|
||||||
|
--user=<username> ; drop root privs
|
||||||
|
--uid=uid[:gid] ; drop root privs
|
||||||
|
|
||||||
The manipulation parameters can be combined in any way.
|
The manipulation parameters can be combined in any way.
|
||||||
|
|
||||||
@ -173,7 +175,7 @@ tpws is transparent proxy.
|
|||||||
--daemon ; daemonize
|
--daemon ; daemonize
|
||||||
--pidfile=<filename> ; write pid to file
|
--pidfile=<filename> ; write pid to file
|
||||||
--user=<username> ; drop root privs
|
--user=<username> ; drop root privs
|
||||||
--uid=uid[:gid] ; менять uid процесса
|
--uid=uid[:gid] ; drop root privs
|
||||||
|
|
||||||
The manipulation parameters can be combined in any way.
|
The manipulation parameters can be combined in any way.
|
||||||
There are exceptions: split-pos replaces split-http-req. hostdot and hosttab are mutually exclusive.
|
There are exceptions: split-pos replaces split-http-req. hostdot and hosttab are mutually exclusive.
|
||||||
|
@ -137,6 +137,8 @@ nfqws
|
|||||||
Она берет следующие параметры :
|
Она берет следующие параметры :
|
||||||
--daemon ; демонизировать прогу
|
--daemon ; демонизировать прогу
|
||||||
--pidfile=<file> ; сохранить PID в файл
|
--pidfile=<file> ; сохранить PID в файл
|
||||||
|
--user=<username> ; менять uid процесса
|
||||||
|
--uid=uid[:gid] ; менять uid процесса
|
||||||
--qnum=200 ; номер очереди
|
--qnum=200 ; номер очереди
|
||||||
--wsize=4 ; менять tcp window size на указанный размер
|
--wsize=4 ; менять tcp window size на указанный размер
|
||||||
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
|
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
|
||||||
|
@ -14,8 +14,9 @@ ZAPRET_BASE=/opt/zapret
|
|||||||
PIDDIR=/var/run
|
PIDDIR=/var/run
|
||||||
|
|
||||||
QNUM=200
|
QNUM=200
|
||||||
|
NFQWS_USER=daemon
|
||||||
NFQWS=$ZAPRET_BASE/nfq/nfqws
|
NFQWS=$ZAPRET_BASE/nfq/nfqws
|
||||||
NFQWS_OPT_BASE="--qnum=$QNUM"
|
NFQWS_OPT_BASE="--qnum=$QNUM --user=$NFQWS_USER"
|
||||||
|
|
||||||
TPWS_USER=daemon
|
TPWS_USER=daemon
|
||||||
TPPORT_HTTP=1188
|
TPPORT_HTTP=1188
|
||||||
|
@ -8,20 +8,21 @@ PIDDIR=/var/run
|
|||||||
|
|
||||||
IPSET_CR=$ZAPRET_BASE/ipset/create_ipset.sh
|
IPSET_CR=$ZAPRET_BASE/ipset/create_ipset.sh
|
||||||
|
|
||||||
|
WS_USER=tpws
|
||||||
|
|
||||||
QNUM=200
|
QNUM=200
|
||||||
NFQWS=$ZAPRET_BASE/nfq/nfqws
|
NFQWS=$ZAPRET_BASE/nfq/nfqws
|
||||||
NFQWS_OPT_BASE="--qnum=$QNUM"
|
NFQWS_OPT_BASE="--qnum=$QNUM --user=$WS_USER"
|
||||||
|
|
||||||
TPWS_USER=tpws
|
|
||||||
TPPORT_HTTP=1188
|
TPPORT_HTTP=1188
|
||||||
TPPORT_HTTPS=1189
|
TPPORT_HTTPS=1189
|
||||||
TPWS=$ZAPRET_BASE/tpws/tpws
|
TPWS=$ZAPRET_BASE/tpws/tpws
|
||||||
TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts.txt.gz
|
TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts.txt.gz
|
||||||
[ -f "$TPWS_HOSTLIST" ] || TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts-user.txt
|
[ -f "$TPWS_HOSTLIST" ] || TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts-user.txt
|
||||||
TPWS_OPT_BASE="--user=$TPWS_USER --bind-addr=127.0.0.1"
|
TPWS_OPT_BASE="--user=$WS_USER --bind-addr=127.0.0.1"
|
||||||
TPWS_OPT_BASE6="--user=$TPWS_USER --bind-addr=::1"
|
TPWS_OPT_BASE6="--user=$WS_USER --bind-addr=::1"
|
||||||
# first wait for lan to ifup, then wait for bind-wait-ip-linklocal seconds for link local address and bind-wait-ip for any ipv6 as the worst case
|
# first wait for lan to ifup, then wait for bind-wait-ip-linklocal seconds for link local address and bind-wait-ip for any ipv6 as the worst case
|
||||||
TPWS_OPT_BASE6_PRE="--user=$TPWS_USER --bind-linklocal=prefer --bind-wait-ifup=30 --bind-wait-ip=30 --bind-wait-ip-linklocal=3"
|
TPWS_OPT_BASE6_PRE="--user=$WS_USER --bind-linklocal=prefer --bind-wait-ifup=30 --bind-wait-ip=30 --bind-wait-ip-linklocal=3"
|
||||||
TPWS_OPT_BASE_HTTP="--port=$TPPORT_HTTP"
|
TPWS_OPT_BASE_HTTP="--port=$TPPORT_HTTP"
|
||||||
TPWS_OPT_BASE_HTTPS="--port=$TPPORT_HTTPS"
|
TPWS_OPT_BASE_HTTPS="--port=$TPPORT_HTTPS"
|
||||||
|
|
||||||
@ -169,7 +170,7 @@ fw_tpws()
|
|||||||
[ -n "$IFACE_LAN" ] && {
|
[ -n "$IFACE_LAN" ] && {
|
||||||
ipt_add_del $1 PREROUTING -t nat $IPT_ILAN -p tcp $2 -j DNAT --to 127.0.0.1:$4
|
ipt_add_del $1 PREROUTING -t nat $IPT_ILAN -p tcp $2 -j DNAT --to 127.0.0.1:$4
|
||||||
}
|
}
|
||||||
ipt_add_del $1 OUTPUT -t nat $IPT_OWAN -m owner ! --uid-owner $TPWS_USER -p tcp $2 -j DNAT --to 127.0.0.1:$4
|
ipt_add_del $1 OUTPUT -t nat $IPT_OWAN -m owner ! --uid-owner $WS_USER -p tcp $2 -j DNAT --to 127.0.0.1:$4
|
||||||
}
|
}
|
||||||
[ "$DISABLE_IPV6" = "1" ] || {
|
[ "$DISABLE_IPV6" = "1" ] || {
|
||||||
print_op $1 "$3" "tpws" 6
|
print_op $1 "$3" "tpws" 6
|
||||||
@ -177,7 +178,7 @@ fw_tpws()
|
|||||||
dnat6_target
|
dnat6_target
|
||||||
[ "$DNAT6_TARGET" != "-" ] && ipt6_add_del $1 PREROUTING -t nat $IPT_ILAN -p tcp $3 -j DNAT --to [$DNAT6_TARGET]:$4
|
[ "$DNAT6_TARGET" != "-" ] && ipt6_add_del $1 PREROUTING -t nat $IPT_ILAN -p tcp $3 -j DNAT --to [$DNAT6_TARGET]:$4
|
||||||
}
|
}
|
||||||
ipt6_add_del $1 OUTPUT -t nat $IPT_OWAN -m owner ! --uid-owner $TPWS_USER -p tcp $3 -j DNAT --to [::1]:$4
|
ipt6_add_del $1 OUTPUT -t nat $IPT_OWAN -m owner ! --uid-owner $WS_USER -p tcp $3 -j DNAT --to [::1]:$4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fw_nfqws_pre()
|
fw_nfqws_pre()
|
||||||
@ -266,16 +267,25 @@ do_daemon()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
prepare_tpws()
|
prepare_user()
|
||||||
{
|
{
|
||||||
# $TPWS_USER is required to prevent redirection of the traffic originating from TPWS itself
|
# $WS_USER is required to prevent redirection of the traffic originating from TPWS itself
|
||||||
# otherwise infinite loop will occur
|
# otherwise infinite loop will occur
|
||||||
# also its good idea not to run tpws as root
|
# also its good idea not to run tpws as root
|
||||||
id -u $TPWS_USER >/dev/null 2>/dev/null || useradd --no-create-home --system --shell /bin/false $TPWS_USER
|
id -u $WS_USER >/dev/null 2>/dev/null || useradd --no-create-home --system --shell /bin/false $WS_USER
|
||||||
|
}
|
||||||
|
prepare_tpws()
|
||||||
|
{
|
||||||
|
prepare_user
|
||||||
|
|
||||||
# otherwise linux kernel will treat 127.0.0.1 as "martian" ip and refuse routing to it
|
# otherwise linux kernel will treat 127.0.0.1 as "martian" ip and refuse routing to it
|
||||||
# NOTE : kernels <3.6 do not have this feature. consider upgrading or change DNAT to REDIRECT and do not bind to 127.0.0.1
|
# NOTE : kernels <3.6 do not have this feature. consider upgrading or change DNAT to REDIRECT and do not bind to 127.0.0.1
|
||||||
[ -n "$IFACE_LAN" ] && sysctl -qw net.ipv4.conf.$IFACE_LAN.route_localnet=1
|
[ -n "$IFACE_LAN" ] && sysctl -qw net.ipv4.conf.$IFACE_LAN.route_localnet=1
|
||||||
}
|
}
|
||||||
|
prepare_nfqws()
|
||||||
|
{
|
||||||
|
prepare_user
|
||||||
|
}
|
||||||
do_tpws()
|
do_tpws()
|
||||||
{
|
{
|
||||||
# $1 : 1 - run, 0 - stop
|
# $1 : 1 - run, 0 - stop
|
||||||
@ -289,6 +299,15 @@ do_tpws()
|
|||||||
[ -n "$IFACE_LAN" ] && do_daemon $1 $((660+$2)) $TPWS "$TPWS_OPT_BASE6_PRE --bind-iface6=$IFACE_LAN $3"
|
[ -n "$IFACE_LAN" ] && do_daemon $1 $((660+$2)) $TPWS "$TPWS_OPT_BASE6_PRE --bind-iface6=$IFACE_LAN $3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
do_nfqws()
|
||||||
|
{
|
||||||
|
# $1 : 1 - run, 0 - stop
|
||||||
|
# $2 : daemon number
|
||||||
|
# $3 : daemon args
|
||||||
|
|
||||||
|
[ "$1" = "1" ] && prepare_nfqws
|
||||||
|
do_daemon $1 $2 $NFQWS "$NFQWS_OPT_BASE $3"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
create_ipset()
|
create_ipset()
|
||||||
@ -385,7 +404,7 @@ zapret_do_daemons()
|
|||||||
do_tpws $1 1 "$TPWS_OPT_BASE_HTTP $TPWS_OPT_HTTP"
|
do_tpws $1 1 "$TPWS_OPT_BASE_HTTP $TPWS_OPT_HTTP"
|
||||||
;;
|
;;
|
||||||
nfqws_ipset|nfqws_ipset_https|nfqws_all|nfqws_all_https)
|
nfqws_ipset|nfqws_ipset_https|nfqws_all|nfqws_all_https)
|
||||||
do_daemon $1 1 $NFQWS "$NFQWS_OPT_BASE $NFQWS_OPT"
|
do_nfqws $1 1 "$NFQWS_OPT"
|
||||||
;;
|
;;
|
||||||
custom)
|
custom)
|
||||||
# PLACEHOLDER
|
# PLACEHOLDER
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CFLAGS ?= -s -O3
|
CFLAGS += -s -O3
|
||||||
LIBS = -lnetfilter_queue -lnfnetlink
|
LIBS = -lnetfilter_queue -lnfnetlink -lcap
|
||||||
SRC_FILES = *.c
|
SRC_FILES = *.c
|
||||||
|
|
||||||
all: nfqws
|
all: nfqws
|
||||||
|
68
nfq/nfqws.c
68
nfq/nfqws.c
@ -13,6 +13,8 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <sys/capability.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
bool proto_check_ipv4(unsigned char *data,int len)
|
bool proto_check_ipv4(unsigned char *data,int len)
|
||||||
{
|
{
|
||||||
@ -363,10 +365,40 @@ static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
|
|||||||
return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
|
return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dropcaps()
|
||||||
|
{
|
||||||
|
cap_value_t cap_values[] = {CAP_NET_ADMIN};
|
||||||
|
cap_t capabilities;
|
||||||
|
if (!(capabilities = cap_init()))
|
||||||
|
{
|
||||||
|
perror("cap_init");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (cap_set_flag(capabilities, CAP_PERMITTED, sizeof(cap_values)/sizeof(*cap_values), cap_values, CAP_SET) ||
|
||||||
|
cap_set_flag(capabilities, CAP_EFFECTIVE, sizeof(cap_values)/sizeof(*cap_values), cap_values, CAP_SET))
|
||||||
|
{
|
||||||
|
perror("cap_set_flag");
|
||||||
|
cap_free(capabilities);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (cap_set_proc(capabilities))
|
||||||
|
{
|
||||||
|
perror("cap_set_proc");
|
||||||
|
cap_free(capabilities);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cap_free(capabilities);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
bool droproot(uid_t uid, gid_t gid)
|
bool droproot(uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
if (uid)
|
if (uid || gid)
|
||||||
{
|
{
|
||||||
|
if (prctl(PR_SET_KEEPCAPS, 1L))
|
||||||
|
{
|
||||||
|
perror("prctl(PR_SET_KEEPCAPS): ");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (setgid(gid))
|
if (setgid(gid))
|
||||||
{
|
{
|
||||||
perror("setgid: ");
|
perror("setgid: ");
|
||||||
@ -378,7 +410,7 @@ bool droproot(uid_t uid, gid_t gid)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return dropcaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
void daemonize()
|
void daemonize()
|
||||||
@ -431,6 +463,8 @@ void exithelp()
|
|||||||
" --hostnospace\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
|
" --hostnospace\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
|
||||||
" --daemon\t\t; daemonize\n"
|
" --daemon\t\t; daemonize\n"
|
||||||
" --pidfile=<filename>\t; write pid to file\n"
|
" --pidfile=<filename>\t; write pid to file\n"
|
||||||
|
" --user=<username>\t; drop root privs\n"
|
||||||
|
" --uid=uid[:gid]\t; drop root privs\n"
|
||||||
);
|
);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -447,7 +481,7 @@ int main(int argc, char **argv)
|
|||||||
int v;
|
int v;
|
||||||
bool daemon=false;
|
bool daemon=false;
|
||||||
uid_t uid=0;
|
uid_t uid=0;
|
||||||
gid_t gid;
|
gid_t gid=0;
|
||||||
char pidfile[256];
|
char pidfile[256];
|
||||||
|
|
||||||
memset(&cbdata,0,sizeof(cbdata));
|
memset(&cbdata,0,sizeof(cbdata));
|
||||||
@ -461,8 +495,9 @@ int main(int argc, char **argv)
|
|||||||
{"hostcase",no_argument,0,0}, // optidx=3
|
{"hostcase",no_argument,0,0}, // optidx=3
|
||||||
{"hostspell",required_argument,0,0}, // optidx=4
|
{"hostspell",required_argument,0,0}, // optidx=4
|
||||||
{"hostnospace",no_argument,0,0}, // optidx=5
|
{"hostnospace",no_argument,0,0}, // optidx=5
|
||||||
{"user",required_argument,0,0}, // optidx=6
|
{"pidfile",required_argument,0,0}, // optidx=6
|
||||||
{"pidfile",required_argument,0,0}, // optidx=7
|
{"user",required_argument,0,0 },// optidx=7
|
||||||
|
{"uid",required_argument,0,0 },// optidx=8
|
||||||
{NULL,0,NULL,0}
|
{NULL,0,NULL,0}
|
||||||
};
|
};
|
||||||
if (argc<2) exithelp();
|
if (argc<2) exithelp();
|
||||||
@ -505,7 +540,11 @@ int main(int argc, char **argv)
|
|||||||
case 5: /* hostnospace */
|
case 5: /* hostnospace */
|
||||||
cbdata.hostnospace = true;
|
cbdata.hostnospace = true;
|
||||||
break;
|
break;
|
||||||
case 6: /* user */
|
case 6: /* pidfile */
|
||||||
|
strncpy(pidfile,optarg,sizeof(pidfile));
|
||||||
|
pidfile[sizeof(pidfile)-1]='\0';
|
||||||
|
break;
|
||||||
|
case 7: /* user */
|
||||||
{
|
{
|
||||||
struct passwd *pwd = getpwnam(optarg);
|
struct passwd *pwd = getpwnam(optarg);
|
||||||
if (!pwd)
|
if (!pwd)
|
||||||
@ -517,9 +556,13 @@ int main(int argc, char **argv)
|
|||||||
gid = pwd->pw_gid;
|
gid = pwd->pw_gid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 7: /* pidfile */
|
case 8: /* uid */
|
||||||
strncpy(pidfile,optarg,sizeof(pidfile));
|
gid=0x7FFFFFFF; // default git. drop gid=0
|
||||||
pidfile[sizeof(pidfile)-1]='\0';
|
if (!sscanf(optarg,"%u:%u",&uid,&gid))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "--uid should be : uid[:gid]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -567,16 +610,15 @@ int main(int argc, char **argv)
|
|||||||
goto exiterr;
|
goto exiterr;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = nfq_fd(h);
|
if (!droproot(uid,gid)) goto exiterr;
|
||||||
|
fprintf(stderr,"Running as UID=%u GID=%u\n",getuid(),getgid());
|
||||||
|
|
||||||
if (droproot(uid,gid))
|
fd = nfq_fd(h);
|
||||||
{
|
|
||||||
while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0)
|
while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0)
|
||||||
{
|
{
|
||||||
int r=nfq_handle_packet(h, buf, rv);
|
int r=nfq_handle_packet(h, buf, rv);
|
||||||
if (r) fprintf(stderr,"nfq_handle_packet error %d\n",r);
|
if (r) fprintf(stderr,"nfq_handle_packet error %d\n",r);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
printf("unbinding from queue 0\n");
|
printf("unbinding from queue 0\n");
|
||||||
nfq_destroy_queue(qh);
|
nfq_destroy_queue(qh);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user