feat: keenetic support

This commit is contained in:
Roman 2023-01-13 17:37:09 +03:00
parent bac22bf9eb
commit f70d95966b
No known key found for this signature in database
GPG Key ID: 702817DDED8C6800
10 changed files with 481 additions and 8 deletions

View File

@ -107,14 +107,16 @@ check_system()
}
elif openrc_test; then
SYSTEM=openrc
elif [ -f "/bin/ndm" ]; then
SYSTEM=keenetic
else
echo system is not either systemd, openrc or openwrt based
echo easy installer can set up config settings but can\'t configure auto start
echo you have to do it manually. check readme.txt for manual setup info.
if ask_yes_no N "do you want to continue"; then
SYSTEM=linux
SYSTEM=linux
else
exitp 5
exitp 5
fi
fi
elif [ "$UNAME" = "Darwin" ]; then
@ -129,16 +131,16 @@ check_system()
get_free_space_mb()
{
df -m $PWD | awk '/[0-9]%/{print $(NF-2)}'
df -m $PWD | awk '/[0-9]%/{print $(NF-2)}'
}
get_ram_kb()
{
grep MemTotal /proc/meminfo | awk '{print $2}'
grep MemTotal /proc/meminfo | awk '{print $2}'
}
get_ram_mb()
{
local R=$(get_ram_kb)
echo $(($R/1024))
local R=$(get_ram_kb)
echo $(($R/1024))
}
crontab_del()
@ -202,6 +204,9 @@ cron_ensure_running()
/etc/init.d/cron enable
/etc/init.d/cron start
}
[ "$SYSTEM" = "keenetic" ] && {
/opt/etc/init.d/S10cron start
}
}
@ -347,8 +352,8 @@ openwrt_fw_section_find()
path=$(uci -q get firewall.@include[$i].path)
[ -n "$path" ] || break
[ "$path" = "$OPENWRT_FW_INCLUDE$1" ] && {
echo $i
return 0
echo $i
return 0
}
i=$(($i+1))
done
@ -462,3 +467,43 @@ remove_macos_firewall()
pf_anchor_root_del
pf_anchor_root_reload
}
install_keenetic_netfilter_hook()
{
echo \* installing netfilter hook
[ -n "MODE" ] || {
echo "should specify MODE in $ZAPRET_CONFIG"
exitp 7
}
echo "linking : $KEENETIC_NETFILTER_HOOK_SRC => $KEENETIC_NETFILTER_HOOK_DST"
ln -fs "$KEENETIC_NETFILTER_HOOK_SRC" "$KEENETIC_NETFILTER_HOOK_DST"
}
remove_keenetic_netfilter_hook()
{
rm -f "$KEENETIC_NETFILTER_HOOK_DST"
}
service_install_keenetic()
{
echo \* installing zapret service
ln -sf "$ZAPRET_BASE/init.d/keenetic/zapret" /opt/etc/init.d/S99zapret
}
service_start_keenetic()
{
echo \* starting zapret service
"$INIT_SCRIPT_SRC" start
}
service_remove_keenetic()
{
echo \* removing zapret service
rm -f /opt/etc/init.d/S99zapret
zapret_stop_daemons
}

34
init.d/keenetic/custom Normal file
View File

@ -0,0 +1,34 @@
# this script contain your special code to launch daemons and configure firewall
# use helpers from "functions" file
# in case of upgrade keep this file only, do not modify others
zapret_custom_daemons()
{
# $1 - 1 - run, 0 - stop
# PLACEHOLDER
echo !!! NEED ATTENTION !!!
echo Start daemon\(s\)
echo Study how other sections work
do_daemon $1 1 /bin/sleep 20
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
# PLACEHOLDER
echo !!! NEED ATTENTION !!!
echo Configure iptables for required actions
echo Study how other sections work
}
zapret_custom_firewall_nft()
{
# stop logic is not required
# PLACEHOLDER
echo !!! NEED ATTENTION !!!
echo Configure nftables for required actions
echo Study how other sections work
}

View File

@ -0,0 +1,51 @@
#!/bin/sh
# this custom script in addition to MODE=nfqws runs desync to all QUIC initial packets, without ipset/hostlist filtering
# need to add to config : NFQWS_OPT_DESYNC_QUIC="--dpi-desync=fake"
# russian TSPU version : NFQWS_OPT_DESYNC_QUIC="--dpi-desync=fake --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_short_header.bin"
# NOTE : do not use TTL fooling. chromium QUIC engine breaks sessions if TTL expired in transit received
QNUM2=$(($QNUM+10))
zapret_custom_daemons()
{
# $1 - 1 - run, 0 - stop
local MODE_OVERRIDE=nfqws
local opt
zapret_do_daemons $1
opt="--qnum=$QNUM2 $NFQWS_OPT_DESYNC_QUIC"
do_nfqws $1 100 "$opt"
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
local MODE_OVERRIDE=nfqws
local f
local first_packets_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:3"
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
zapret_do_firewall_rules_ipt $1
f="-p udp --dport 443"
fw_nfqws_post $1 "$f $desync $first_packets_only" "$f $desync $first_packets_only" $QNUM2
fw_nfqws_quic $1 "$f -m mark --mark $DESYNC_MARK/$DESYNC_MARK"
}
zapret_custom_firewall_nft()
{
# stop logic is not required
local MODE_OVERRIDE=nfqws
local f
local first_packets_only="ct original packets 1-3"
local desync="mark and $DESYNC_MARK == 0"
zapret_apply_firewall_rules_nft
f="udp dport 443"
nft_fw_nfqws_post "$f $desync $first_packets_only" "$f $desync $first_packets_only" $QNUM2
nft_fw_nfqws_quic "$f mark and $DESYNC_MARK == $DESYNC_MARK"
}

View File

@ -0,0 +1,49 @@
#!/bin/sh
# this custom script demonstrates how to reuse built-in modes and add something from yourself
MY_TPPORT=$(($TPPORT + 1))
MY_TPWS_OPT="--methodeol --hostcase"
MY_DPORT=81
zapret_custom_daemons()
{
# $1 - 1 - run, 0 - stop
local MODE_OVERRIDE=tpws
local opt
zapret_do_daemons $1
opt="--port=$MY_TPPORT $MY_TPWS_OPT"
filter_apply_hostlist_target opt
do_tpws $1 100 "$opt"
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
local MODE_OVERRIDE=tpws
local f4 f6
zapret_do_firewall_rules_ipt $1
f4="-p tcp --dport $MY_DPORT"
f6=$f4
filter_apply_ipset_target f4 f6
fw_tpws $1 "$f4" "$f6" $MY_TPPORT
}
zapret_custom_firewall_nft()
{
# stop logic is not required
local MODE_OVERRIDE=tpws
local f4 f6
zapret_apply_firewall_rules_nft
f4="tcp dport $MY_DPORT"
f6=$f4
nft_filter_apply_ipset_target f4 f6
nft_fw_tpws "$f4" "$f6" $MY_TPPORT
}

View File

@ -0,0 +1,69 @@
#!/bin/sh
# this custom script demonstrates how to apply tpws to http and nfqws to https
# it preserves config settings : MODE_HTTP, MODE_HTTPS, MODE_FILTER, TPWS_OPT, NFQWS_OPT_DESYNC, NFQWS_OPT_DESYNC_HTTPS
zapret_custom_daemons()
{
# $1 - 1 - run, 0 - stop
local opt
[ "$MODE_HTTP" = "1" ] && {
opt="--port=$TPPORT $TPWS_OPT"
filter_apply_hostlist_target opt
do_tpws $1 1 "$opt"
}
[ "$MODE_HTTPS" = "1" ] && {
opt="--qnum=$QNUM $NFQWS_OPT_DESYNC_HTTPS"
filter_apply_hostlist_target opt
do_nfqws $1 2 "$opt"
}
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
local f4 f6
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4"
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
[ "$MODE_HTTP" = "1" ] && {
f4="-p tcp --dport 80"
f6=$f4
filter_apply_ipset_target f4 f6
fw_tpws $1 "$f4" "$f6" $TPPORT
}
[ "$MODE_HTTPS" = "1" ] && {
f4="-p tcp --dport 443 $first_packet_only"
f6=$f4
filter_apply_ipset_target f4 f6
fw_nfqws_post $1 "$f4 $desync" "$f6 $desync" $QNUM
fw_nfqws_quic $1 "$f4 -m mark --mark $DESYNC_MARK/$DESYNC_MARK"
}
}
zapret_custom_firewall_nft()
{
# stop logic is not required
local f4 f6
local first_packet_only="ct original packets 1-4"
local desync="mark and $DESYNC_MARK == 0"
[ "$MODE_HTTP" = "1" ] && {
f4="tcp dport 80"
f6=$f4
nft_filter_apply_ipset_target f4 f6
nft_fw_tpws "$f4" "$f6" $TPPORT
}
[ "$MODE_HTTPS" = "1" ] && {
f4="tcp dport 443 $first_packet_only"
f6=$f4
nft_filter_apply_ipset_target f4 f6
nft_fw_nfqws_post "$f4 $desync" "$f6 $desync" $QNUM
nft_fw_nfqws_quic $1 "$f4 mark and $DESYNC_MARK == $DESYNC_MARK"
}
}

46
init.d/keenetic/functions Normal file
View File

@ -0,0 +1,46 @@
#!/bin/sh
SCRIPT=$(readlink -f "$0")
EXEDIR=$(dirname "$SCRIPT")
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
. "$ZAPRET_BASE/init.d/sysv/functions"
CUSTOM_SCRIPT="$ZAPRET_BASE/init.d/keenetic/custom"
[ -f "$CUSTOM_SCRIPT" ] && . "$CUSTOM_SCRIPT"
load_kmod()
{
if lsmod | grep "$1" &> /dev/null ; then
echo "$1.ko is already loaded"
else
if insmod "/lib/modules/$(uname -r)/$1.ko" &> /dev/null; then
echo "$1.ko loaded"
else
echo "Cannot find $1.ko kernel module, aborting"
exit 1
fi
fi
}
# Fix local source ip issue when quic packets were sent with raw sockets (no Keenetic-specific iptable marks were applied)
fw_nfqws_quic()
{
# $1 - 1 - add, 0 - del
# $2 - iptable filter
ipt_print_op $1 "$2" "nfqws quic masquerade"
rule="$2 -d 0/0 -j MASQUERADE"
if [ -n "$IFACE_WAN" ] ; then
for wan in $IFACE_WAN; do
ipt_add_del $1 POSTROUTING -t nat -o $wan $rule
done
else
ipt_add_del $1 POSTROUTING -t nat $rule
fi
}
nft_fw_nfqws_quic()
{
echo "Quic through nft is not supported"
}

View File

@ -0,0 +1,20 @@
#!/bin/sh
[ "$type" == "ip6tables" ] && exit 0
[ "$table" != "mangle" ] && exit 0
SCRIPT=$(readlink /opt/etc/init.d/S99zapret)
if [ -n "$SCRIPT" ]; then
EXEDIR=$(dirname "$SCRIPT")
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
else
ZAPRET_BASE=/opt/zapret
fi
. "$EXEDIR/functions"
case $MODE in
nfqws|twps|custom)
zapret_apply_firewall
;;
esac

43
init.d/keenetic/zapret Executable file
View File

@ -0,0 +1,43 @@
#!/bin/sh
SCRIPT=$(readlink -f "$0")
EXEDIR=$(dirname "$SCRIPT")
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
. "$EXEDIR/functions"
do_start()
{
sysctl -w "net.netfilter.nf_conntrack_checksum=0"
load_kmod xt_string
load_kmod xt_NFQUEUE
load_kmod xt_multiport
load_kmod xt_owner
load_kmod xt_connbytes
zapret_run_daemons
[ "$INIT_APPLY_FW" != "1" ] || { zapret_apply_firewall; }
}
do_stop()
{
sysctl -w "net.netfilter.nf_conntrack_checksum=1"
zapret_stop_daemons
[ "$INIT_APPLY_FW" != "1" ] || zapret_unapply_firewall
}
case $1 in
start)
do_start
;;
stop|kill)
do_stop
;;
restart)
"$0" stop
"$0" start
;;
*)
echo -e "Usage: $0 (start|stop|restart)" >&2
exit 1
;;
esac
exit 0

View File

@ -964,6 +964,105 @@ install_macos()
service_start_macos
}
check_prerequisites_keenetic()
{
echo \* checking prerequisites
local PKGS="curl" PKGS UPD=0
case "$FWTYPE" in
iptables)
PKGS="$PKGS"
[ "$DISABLE_IPV6" != "1" ] && PKGS="$PKGS"
;;
nftables)
PKGS="$PKGS"
[ "$DISABLE_IPV6" != "1" ] && PKGS="$PKGS"
;;
esac
if check_packages_openwrt $PKGS ; then
echo everything is present
else
echo \* installing prerequisites
opkg update
UPD=1
opkg install $PKGS || {
echo could not install prerequisites
exitp 6
}
fi
is_linked_to_busybox gzip && {
echo
echo your system uses default busybox gzip. its several times slower than GNU gzip.
echo ip/host list scripts will run much faster with GNU gzip
echo installer can install GNU gzip but it requires about 100 Kb space
if ask_yes_no N "do you want to install GNU gzip"; then
[ "$UPD" = "0" ] && {
opkg update
UPD=1
}
opkg install --force-overwrite gzip
fi
}
is_linked_to_busybox sort && {
echo
echo your system uses default busybox sort. its much slower and consumes much more RAM than GNU sort
echo ip/host list scripts will run much faster with GNU sort
echo installer can install GNU sort but it requires about 100 Kb space
if ask_yes_no N "do you want to install GNU sort"; then
[ "$UPD" = "0" ] && {
opkg update
UPD=1
}
opkg install --force-overwrite coreutils-sort
fi
}
is_linked_to_busybox grep && {
echo
echo your system uses default busybox grep. its damn infinite slow with -f option
echo get_combined.sh will be severely impacted
echo installer can install GNU grep but it requires about 0.5 Mb space
if ask_yes_no N "do you want to install GNU grep"; then
[ "$UPD" = "0" ] && {
opkg update
UPD=1
}
opkg install --force-overwrite grep
# someone reported device partially fail if /bin/grep is absent
# grep package deletes /bin/grep
[ -f /bin/grep ] || ln -s busybox /bin/grep
fi
}
}
install_keenetic()
{
INIT_SCRIPT_SRC="$EXEDIR/init.d/keenetic/zapret"
KEENETIC_NETFILTER_HOOK_SRC="$EXEDIR/init.d/keenetic/netfilter.hook.sh"
KEENETIC_NETFILTER_HOOK_DST=/opt/etc/ndm/netfilter.d/zapret.sh
check_bins
require_root
check_location copy_all
install_binaries
check_dns
select_fwtype
check_prerequisites_keenetic
select_ipv6
ask_config
ask_config_offload
service_install_keenetic
download_list
crontab_del_quiet
crontab_add 0 6
cron_ensure_running
install_keenetic_netfilter_hook
service_start_keenetic
}
# build binaries, do not use precompiled
[ "$1" = "make" ] && FORCE_BUILD=1
@ -986,6 +1085,9 @@ case $SYSTEM in
openwrt)
install_openwrt
;;
keenetic)
install_keenetic
;;
macos)
install_macos
;;

View File

@ -73,6 +73,17 @@ remove_macos()
crontab_del
}
remove_keenetic()
{
KEENETIC_NETFILTER_HOOK_DST=/opt/etc/ndm/netfilter.d/zapret.sh
clear_ipset
remove_keenetic_netfilter_hook
service_remove_keenetic
nft_del_table
crontab_del
}
fix_sbin_path
check_system
@ -96,6 +107,9 @@ case $SYSTEM in
macos)
remove_macos
;;
keenetic)
remove_keenetic
;;
esac