2021-03-04 11:30:38 +00:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
# automated script for easy installing zapret
|
|
|
|
|
|
|
|
EXEDIR="$(dirname "$0")"
|
|
|
|
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
|
|
|
IPSET_DIR="$EXEDIR/ipset"
|
|
|
|
ZAPRET_CONFIG="$EXEDIR/config"
|
|
|
|
ZAPRET_BASE="$EXEDIR"
|
|
|
|
|
|
|
|
. "$ZAPRET_CONFIG"
|
2022-02-15 14:15:36 +00:00
|
|
|
. "$ZAPRET_BASE/common/base.sh"
|
|
|
|
. "$ZAPRET_BASE/common/elevate.sh"
|
|
|
|
. "$ZAPRET_BASE/common/fwtype.sh"
|
|
|
|
. "$ZAPRET_BASE/common/dialog.sh"
|
|
|
|
. "$ZAPRET_BASE/common/ipt.sh"
|
|
|
|
. "$ZAPRET_BASE/common/installer.sh"
|
2022-04-13 08:47:14 +00:00
|
|
|
. "$ZAPRET_BASE/common/virt.sh"
|
2021-03-04 11:30:38 +00:00
|
|
|
|
|
|
|
# install target
|
|
|
|
ZAPRET_TARGET=/opt/zapret
|
|
|
|
|
|
|
|
GET_LIST="$IPSET_DIR/get_config.sh"
|
|
|
|
|
2021-03-06 08:52:07 +00:00
|
|
|
[ -n "$TPPORT" ] || TPPORT=988
|
|
|
|
|
2021-11-16 08:46:40 +00:00
|
|
|
check_readonly_system()
|
|
|
|
{
|
|
|
|
local RO
|
|
|
|
echo \* checking readonly system
|
|
|
|
case $SYSTEM in
|
|
|
|
systemd)
|
|
|
|
[ -w "$SYSTEMD_SYSTEM_DIR" ] || RO=1
|
|
|
|
;;
|
|
|
|
openrc)
|
|
|
|
[ -w "$(dirname "$INIT_SCRIPT")" ] || RO=1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
[ -z "$RO" ] || {
|
|
|
|
echo '!!! READONLY SYSTEM DETECTED !!!'
|
|
|
|
echo '!!! WILL NOT BE ABLE TO CONFIGURE STARTUP !!!'
|
|
|
|
echo '!!! MANUAL STARTUP CONFIGURATION IS REQUIRED !!!'
|
|
|
|
ask_yes_no N "do you want to continue" || exitp 5
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-04 11:30:38 +00:00
|
|
|
check_bins()
|
|
|
|
{
|
|
|
|
echo \* checking executables
|
|
|
|
|
2023-11-19 14:27:02 +00:00
|
|
|
fix_perms_bin_test "$EXEDIR"
|
2024-05-04 13:01:09 +00:00
|
|
|
local arch="$(get_bin_arch)"
|
2021-03-04 11:30:38 +00:00
|
|
|
local make_target
|
|
|
|
[ "$FORCE_BUILD" = "1" ] && {
|
|
|
|
echo forced build mode
|
|
|
|
if [ "$arch" = "my" ]; then
|
|
|
|
echo already compiled
|
|
|
|
else
|
|
|
|
arch=""
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
if [ -n "$arch" ] ; then
|
|
|
|
echo found architecture "\"$arch\""
|
|
|
|
elif [ -f "$EXEDIR/Makefile" ] && exists make; then
|
|
|
|
echo trying to compile
|
|
|
|
[ "$SYSTEM" = "macos" ] && make_target=mac
|
|
|
|
make -C "$EXEDIR" $make_target || {
|
|
|
|
echo could not compile
|
|
|
|
make -C "$EXEDIR" clean
|
|
|
|
exitp 8
|
|
|
|
}
|
|
|
|
echo compiled
|
|
|
|
else
|
|
|
|
echo build tools not found
|
|
|
|
exitp 8
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
call_install_bin()
|
|
|
|
{
|
2023-11-18 18:28:20 +00:00
|
|
|
sh "$EXEDIR/install_bin.sh" $1
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
get_bin_arch()
|
|
|
|
{
|
|
|
|
call_install_bin getarch
|
|
|
|
}
|
|
|
|
|
|
|
|
install_binaries()
|
|
|
|
{
|
|
|
|
echo \* installing binaries
|
|
|
|
|
|
|
|
call_install_bin || {
|
|
|
|
echo compatible binaries not found
|
|
|
|
exitp 8
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
select_mode_mode()
|
|
|
|
{
|
2021-11-19 10:49:36 +00:00
|
|
|
local edited v vars MODES="tpws tpws-socks nfqws filter custom"
|
2021-03-04 18:03:26 +00:00
|
|
|
[ "$SYSTEM" = "macos" ] && MODES="tpws tpws-socks filter custom"
|
2021-03-04 11:30:38 +00:00
|
|
|
echo
|
|
|
|
echo select MODE :
|
|
|
|
ask_list MODE "$MODES" tpws && write_config_var MODE
|
2021-11-19 10:26:50 +00:00
|
|
|
|
2021-03-04 11:30:38 +00:00
|
|
|
case $MODE in
|
|
|
|
tpws)
|
2021-11-19 10:26:50 +00:00
|
|
|
vars="TPWS_OPT"
|
2021-03-04 11:30:38 +00:00
|
|
|
;;
|
|
|
|
nfqws)
|
2023-07-02 15:46:26 +00:00
|
|
|
vars="NFQWS_OPT_DESYNC NFQWS_OPT_DESYNC_HTTP NFQWS_OPT_DESYNC_HTTPS NFQWS_OPT_DESYNC_HTTP6 NFQWS_OPT_DESYNC_HTTPS6 NFQWS_OPT_DESYNC_QUIC NFQWS_OPT_DESYNC_QUIC6"
|
2021-03-04 11:30:38 +00:00
|
|
|
;;
|
|
|
|
esac
|
2021-11-19 10:26:50 +00:00
|
|
|
[ -n "$vars" ] && {
|
2021-11-19 10:38:49 +00:00
|
|
|
echo
|
2021-11-19 10:26:50 +00:00
|
|
|
while [ 1=1 ]; do
|
|
|
|
for var in $vars; do
|
|
|
|
eval v="\$$var"
|
|
|
|
echo $var=\"$v\"
|
|
|
|
done
|
|
|
|
ask_yes_no N "do you want to edit the options" || {
|
2021-11-19 10:49:36 +00:00
|
|
|
[ -n "$edited" ] && {
|
|
|
|
for var in $vars; do
|
|
|
|
write_config_var $var
|
|
|
|
done
|
|
|
|
}
|
2021-11-19 10:26:50 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
edit_vars $vars
|
2021-11-19 10:49:36 +00:00
|
|
|
edited=1
|
2021-11-19 10:26:50 +00:00
|
|
|
echo ..edited..
|
|
|
|
done
|
|
|
|
}
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
select_mode_http()
|
|
|
|
{
|
2021-03-04 18:03:26 +00:00
|
|
|
[ "$MODE" != "filter" ] && [ "$MODE" != "tpws-socks" ] && {
|
2021-03-04 11:30:38 +00:00
|
|
|
echo
|
|
|
|
ask_yes_no_var MODE_HTTP "enable http support"
|
|
|
|
write_config_var MODE_HTTP
|
|
|
|
}
|
|
|
|
}
|
|
|
|
select_mode_keepalive()
|
|
|
|
{
|
|
|
|
[ "$MODE" = "nfqws" ] && [ "$MODE_HTTP" = "1" ] && {
|
|
|
|
echo
|
|
|
|
echo enable keep alive support only if DPI checks every outgoing packet for http signature
|
|
|
|
echo dont enable otherwise because it consumes more cpu resources
|
|
|
|
ask_yes_no_var MODE_HTTP_KEEPALIVE "enable http keep alive support"
|
|
|
|
write_config_var MODE_HTTP_KEEPALIVE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
select_mode_https()
|
|
|
|
{
|
2021-03-04 18:03:26 +00:00
|
|
|
[ "$MODE" != "filter" ] && [ "$MODE" != "tpws-socks" ] && {
|
2021-03-04 11:30:38 +00:00
|
|
|
echo
|
|
|
|
ask_yes_no_var MODE_HTTPS "enable https support"
|
|
|
|
write_config_var MODE_HTTPS
|
|
|
|
}
|
|
|
|
}
|
2023-07-02 15:46:26 +00:00
|
|
|
select_mode_quic()
|
|
|
|
{
|
2024-03-22 15:26:00 +00:00
|
|
|
[ "$SUBSYS" = "keenetic" ] && {
|
|
|
|
echo
|
|
|
|
echo "WARNING ! Keenetic is not officially supported by zapret."
|
|
|
|
echo "WARNING ! This firmware requires additional manual iptables setup to support udp desync properly."
|
|
|
|
echo "WARNING ! Keenetic uses proprietary ndmmark to limit MASQUERADE."
|
|
|
|
echo "WARNING ! Desynced packets may go outside without MASQUERADE with LAN source ip."
|
|
|
|
echo "WARNING ! To fix this you need to add additional MASQUERADE rule to iptables nat table."
|
|
|
|
echo "WARNING ! Installer WILL NOT fix it for you automatically."
|
|
|
|
echo "WARNING ! If you cannot understand what it is all about - do not enable QUIC."
|
|
|
|
}
|
2023-07-02 15:46:26 +00:00
|
|
|
[ "$MODE" != "filter" ] && [ "$MODE" != "tpws-socks" ] && [ "$MODE" != "tpws" ] && {
|
|
|
|
echo
|
|
|
|
ask_yes_no_var MODE_QUIC "enable quic support"
|
|
|
|
write_config_var MODE_QUIC
|
|
|
|
}
|
|
|
|
}
|
2021-03-04 11:30:38 +00:00
|
|
|
select_mode_filter()
|
|
|
|
{
|
2023-10-26 12:12:32 +00:00
|
|
|
local filter="none ipset hostlist autohostlist"
|
|
|
|
[ "$MODE" = "tpws-socks" ] && filter="none hostlist autohostlist"
|
2021-03-04 11:30:38 +00:00
|
|
|
echo
|
|
|
|
echo select filtering :
|
2021-03-04 18:03:26 +00:00
|
|
|
ask_list MODE_FILTER "$filter" none && write_config_var MODE_FILTER
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
select_mode()
|
|
|
|
{
|
|
|
|
select_mode_mode
|
2021-03-06 08:52:07 +00:00
|
|
|
select_mode_iface
|
2021-03-04 11:30:38 +00:00
|
|
|
select_mode_http
|
|
|
|
select_mode_keepalive
|
|
|
|
select_mode_https
|
2023-07-02 15:46:26 +00:00
|
|
|
select_mode_quic
|
2021-03-04 11:30:38 +00:00
|
|
|
select_mode_filter
|
|
|
|
}
|
|
|
|
|
|
|
|
select_getlist()
|
|
|
|
{
|
|
|
|
if [ "$MODE_FILTER" = "ipset" -o "$MODE_FILTER" = "hostlist" ]; then
|
|
|
|
local D=N
|
|
|
|
[ -n "$GETLIST" ] && D=Y
|
|
|
|
echo
|
|
|
|
if ask_yes_no $D "do you want to auto download ip/host list"; then
|
|
|
|
if [ "$MODE_FILTER" = "hostlist" ] ; then
|
2023-01-07 16:35:29 +00:00
|
|
|
GETLISTS="get_antizapret_domains.sh get_reestr_resolvable_domains.sh get_reestr_hostlist.sh"
|
2022-03-17 11:13:21 +00:00
|
|
|
GETLIST_DEF="get_antizapret_domains.sh"
|
2021-03-04 11:30:38 +00:00
|
|
|
else
|
2022-12-14 08:13:55 +00:00
|
|
|
GETLISTS="get_user.sh get_antifilter_ip.sh get_antifilter_ipsmart.sh get_antifilter_ipsum.sh get_antifilter_ipresolve.sh get_antifilter_allyouneed.sh get_reestr_resolve.sh get_reestr_preresolved.sh get_reestr_preresolved_smart.sh"
|
2022-03-17 11:13:21 +00:00
|
|
|
GETLIST_DEF="get_antifilter_allyouneed.sh"
|
2021-03-04 11:30:38 +00:00
|
|
|
fi
|
2022-03-17 11:13:21 +00:00
|
|
|
ask_list GETLIST "$GETLISTS" "$GETLIST_DEF" && write_config_var GETLIST
|
2021-03-04 11:30:38 +00:00
|
|
|
return
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
GETLIST=""
|
|
|
|
write_config_var GETLIST
|
|
|
|
}
|
|
|
|
|
|
|
|
ask_config()
|
|
|
|
{
|
|
|
|
select_mode
|
|
|
|
select_getlist
|
|
|
|
}
|
|
|
|
|
|
|
|
ask_config_offload()
|
|
|
|
{
|
2022-02-15 14:15:36 +00:00
|
|
|
[ "$FWTYPE" = nftables ] || is_ipt_flow_offload_avail && {
|
2021-03-04 11:30:38 +00:00
|
|
|
echo
|
|
|
|
echo flow offloading can greatly increase speed on slow devices and high speed links \(usually 150+ mbits\)
|
2022-03-17 07:06:29 +00:00
|
|
|
if [ "$SYSTEM" = openwrt ]; then
|
|
|
|
echo unfortuantely its not compatible with most nfqws options. nfqws traffic must be exempted from flow offloading.
|
|
|
|
echo donttouch = disable system flow offloading setting if nfqws mode was selected, dont touch it otherwise and dont configure selective flow offloading
|
|
|
|
echo none = always disable system flow offloading setting and dont configure selective flow offloading
|
|
|
|
echo software = always disable system flow offloading setting and configure selective software flow offloading
|
|
|
|
echo hardware = always disable system flow offloading setting and configure selective hardware flow offloading
|
|
|
|
else
|
|
|
|
echo offloading is applicable only to forwarded traffic. it has no effect on outgoing traffic
|
|
|
|
echo hardware flow offloading is available only on specific supporting hardware. most likely will not work on a generic system
|
|
|
|
fi
|
|
|
|
echo offloading breaks traffic shaper
|
2021-03-04 11:30:38 +00:00
|
|
|
echo select flow offloading :
|
2022-03-17 07:06:29 +00:00
|
|
|
local options="none software hardware"
|
|
|
|
local default="none"
|
|
|
|
[ "$SYSTEM" = openwrt ] && {
|
|
|
|
options="donttouch none software hardware"
|
|
|
|
default="donttouch"
|
|
|
|
}
|
|
|
|
ask_list FLOWOFFLOAD "$options" $default && write_config_var FLOWOFFLOAD
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ask_config_tmpdir()
|
|
|
|
{
|
|
|
|
# ask tmpdir change for low ram systems with enough free disk space
|
|
|
|
[ -n "$GETLIST" ] && [ $(get_free_space_mb "$EXEDIR/tmp") -ge 128 ] && [ $(get_ram_mb) -le 400 ] && {
|
|
|
|
echo
|
|
|
|
echo /tmp in openwrt is tmpfs. on low RAM systems there may be not enough RAM to store downloaded files
|
|
|
|
echo default tmpfs has size of 50% RAM
|
|
|
|
echo "RAM : $(get_ram_mb) Mb"
|
|
|
|
echo "DISK : $(get_free_space_mb) Mb"
|
|
|
|
echo select temp file location
|
|
|
|
[ -z "$TMPDIR" ] && TMPDIR=/tmp
|
|
|
|
ask_list TMPDIR "/tmp $EXEDIR/tmp" && {
|
|
|
|
[ "$TMPDIR" = "/tmp" ] && TMPDIR=
|
|
|
|
write_config_var TMPDIR
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-17 07:06:29 +00:00
|
|
|
nft_flow_offload()
|
|
|
|
{
|
|
|
|
[ "$UNAME" = Linux -a "$FWTYPE" = nftables -a "$MODE" != "tpws-socks" ] && [ "$FLOWOFFLOAD" = software -o "$FLOWOFFLOAD" = hardware ]
|
|
|
|
}
|
|
|
|
|
2021-03-06 08:52:07 +00:00
|
|
|
ask_iface()
|
2021-03-04 11:30:38 +00:00
|
|
|
{
|
2021-03-06 08:52:07 +00:00
|
|
|
# $1 - var to ask
|
|
|
|
# $2 - additional name for empty string synonim
|
2021-03-04 11:30:38 +00:00
|
|
|
|
2021-03-06 08:52:07 +00:00
|
|
|
local ifs i0 def new
|
|
|
|
eval def="\$$1"
|
2021-03-04 11:30:38 +00:00
|
|
|
|
2021-03-06 08:52:07 +00:00
|
|
|
[ -n "$2" ] && i0="$2 "
|
|
|
|
case $SYSTEM in
|
|
|
|
macos)
|
|
|
|
ifs="$(ifconfig -l)"
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
ifs="$(ls /sys/class/net)"
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
[ -z "$def" ] && eval $1="$2"
|
|
|
|
ask_list $1 "$i0$ifs" && {
|
|
|
|
eval new="\$$1"
|
|
|
|
[ "$new" = "$2" ] && eval $1=""
|
|
|
|
write_config_var $1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ask_iface_lan()
|
|
|
|
{
|
|
|
|
echo LAN interface :
|
2022-03-17 07:06:29 +00:00
|
|
|
local opt
|
|
|
|
nft_flow_offload || opt=NONE
|
|
|
|
ask_iface IFACE_LAN $opt
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
2021-03-06 08:52:07 +00:00
|
|
|
ask_iface_wan()
|
2021-03-04 11:30:38 +00:00
|
|
|
{
|
2021-03-06 08:52:07 +00:00
|
|
|
echo WAN interface :
|
2022-03-17 07:06:29 +00:00
|
|
|
local opt
|
|
|
|
nft_flow_offload || opt=ANY
|
|
|
|
ask_iface IFACE_WAN $opt
|
2021-03-06 08:52:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
select_mode_iface()
|
|
|
|
{
|
|
|
|
# openwrt has its own interface management scheme
|
|
|
|
# filter just creates ip tables, no daemons involved
|
|
|
|
# nfqws sits in POSTROUTING chain and unable to filter by incoming interface
|
|
|
|
# tpws redirection works in PREROUTING chain
|
|
|
|
# in tpws-socks mode IFACE_LAN specifies additional bind interface for the socks listener
|
|
|
|
# it's not possible to instruct tpws to route outgoing connection to an interface (OS routing table decides)
|
|
|
|
# custom mode can also benefit from interface names (depends on custom script code)
|
|
|
|
|
|
|
|
if [ "$SYSTEM" = "openwrt" ] || [ "$MODE" = "filter" ]; then return; fi
|
|
|
|
|
|
|
|
case "$MODE" in
|
|
|
|
tpws-socks)
|
|
|
|
echo "select LAN interface to allow socks access from your LAN. select NONE for localhost only."
|
|
|
|
echo "expect socks on tcp port $TPPORT"
|
|
|
|
ask_iface_lan
|
|
|
|
;;
|
|
|
|
tpws)
|
|
|
|
echo "select LAN interface to operate in router mode. select NONE for local outgoing traffic only."
|
|
|
|
if [ "$SYSTEM" = "macos" ]; then
|
|
|
|
echo "WARNING ! OS feature \"internet sharing\" is not supported."
|
|
|
|
echo "Only manually configured PF router is supported."
|
|
|
|
else
|
|
|
|
echo "WARNING ! This installer will not configure routing, NAT, ... for you. Its your responsibility."
|
|
|
|
fi
|
|
|
|
ask_iface_lan
|
|
|
|
;;
|
|
|
|
custom)
|
|
|
|
echo "select LAN interface for your custom script (how it works depends on your code)"
|
|
|
|
ask_iface_lan
|
|
|
|
;;
|
2022-03-17 07:06:29 +00:00
|
|
|
*)
|
|
|
|
nft_flow_offload && {
|
|
|
|
echo "select LAN interface for nftables flow offloading"
|
|
|
|
ask_iface_lan
|
|
|
|
}
|
|
|
|
;;
|
2021-03-06 08:52:07 +00:00
|
|
|
esac
|
|
|
|
|
|
|
|
case "$MODE" in
|
|
|
|
tpws)
|
|
|
|
echo "select WAN interface for $MODE operations. select ANY to operate on any interface."
|
|
|
|
[ -n "$IFACE_LAN" ] && echo "WAN filtering works only for local outgoing traffic !"
|
|
|
|
ask_iface_wan
|
|
|
|
;;
|
|
|
|
nfqws)
|
|
|
|
echo "select WAN interface for $MODE operations. select ANY to operate on any interface."
|
|
|
|
ask_iface_wan
|
|
|
|
;;
|
|
|
|
custom)
|
|
|
|
echo "select WAN interface for your custom script (how it works depends on your code)"
|
|
|
|
ask_iface_wan
|
|
|
|
;;
|
2022-03-17 07:06:29 +00:00
|
|
|
*)
|
|
|
|
nft_flow_offload && {
|
|
|
|
echo "select WAN interface for nftables flow offloading"
|
|
|
|
ask_iface_wan
|
|
|
|
}
|
|
|
|
;;
|
2021-03-06 08:52:07 +00:00
|
|
|
esac
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
copy_all()
|
|
|
|
{
|
|
|
|
cp -R "$1" "$2"
|
|
|
|
[ -d "$2/tmp" ] || mkdir "$2/tmp"
|
|
|
|
}
|
|
|
|
copy_openwrt()
|
|
|
|
{
|
2024-05-04 13:01:09 +00:00
|
|
|
local ARCH="$(get_bin_arch)"
|
2021-03-04 11:30:38 +00:00
|
|
|
local BINDIR="$1/binaries/$ARCH"
|
|
|
|
|
|
|
|
[ -d "$2" ] || mkdir -p "$2"
|
2022-05-30 06:49:11 +00:00
|
|
|
|
|
|
|
mkdir "$2/tpws" "$2/nfq" "$2/ip2net" "$2/mdig" "$2/binaries" "$2/binaries/$ARCH" "$2/init.d" "$2/tmp" "$2/files"
|
|
|
|
cp -R "$1/files/fake" "$2/files"
|
2022-02-15 14:15:36 +00:00
|
|
|
cp -R "$1/common" "$1/ipset" "$2"
|
2021-03-04 11:30:38 +00:00
|
|
|
cp -R "$1/init.d/openwrt" "$2/init.d"
|
2024-01-23 10:40:34 +00:00
|
|
|
cp "$1/config" "$1/install_easy.sh" "$1/uninstall_easy.sh" "$1/install_bin.sh" "$1/install_prereq.sh" "$1/blockcheck.sh" "$2"
|
2021-03-04 11:30:38 +00:00
|
|
|
cp "$BINDIR/tpws" "$BINDIR/nfqws" "$BINDIR/ip2net" "$BINDIR/mdig" "$2/binaries/$ARCH"
|
|
|
|
}
|
|
|
|
|
2023-11-19 14:27:02 +00:00
|
|
|
fix_perms_bin_test()
|
|
|
|
{
|
|
|
|
[ -d "$1" ] || return
|
2023-11-20 13:54:23 +00:00
|
|
|
find "$1/binaries" -name ip2net ! -perm -111 -exec chmod +x {} \;
|
2023-11-19 14:27:02 +00:00
|
|
|
}
|
2023-11-16 16:31:39 +00:00
|
|
|
fix_perms()
|
|
|
|
{
|
|
|
|
[ -d "$1" ] || return
|
|
|
|
find "$1" -type d -exec chmod 755 {} \;
|
|
|
|
find "$1" -type f -exec chmod 644 {} \;
|
|
|
|
chown -R root:root "$1"
|
|
|
|
find "$1/binaries" '(' -name tpws -o -name dvtws -o -name nfqws -o -name ip2net -o -name mdig ')' -exec chmod 755 {} \;
|
|
|
|
for f in \
|
|
|
|
install_bin.sh \
|
|
|
|
blockcheck.sh \
|
|
|
|
install_easy.sh \
|
2024-01-23 10:42:12 +00:00
|
|
|
install_prereq.sh \
|
2023-11-16 16:31:39 +00:00
|
|
|
files/huawei/E8372/zapret-ip \
|
|
|
|
files/huawei/E8372/unzapret-ip \
|
|
|
|
files/huawei/E8372/run-zapret-hostlist \
|
|
|
|
files/huawei/E8372/unzapret \
|
|
|
|
files/huawei/E8372/zapret \
|
|
|
|
files/huawei/E8372/run-zapret-ip \
|
|
|
|
ipset/get_exclude.sh \
|
|
|
|
ipset/clear_lists.sh \
|
|
|
|
ipset/get_antifilter_ipresolve.sh \
|
|
|
|
ipset/get_reestr_resolvable_domains.sh \
|
|
|
|
ipset/get_config.sh \
|
|
|
|
ipset/get_reestr_preresolved.sh \
|
|
|
|
ipset/get_user.sh \
|
|
|
|
ipset/get_antifilter_allyouneed.sh \
|
|
|
|
ipset/get_reestr_resolve.sh \
|
|
|
|
ipset/create_ipset.sh \
|
|
|
|
ipset/get_reestr_hostlist.sh \
|
|
|
|
ipset/get_ipban.sh \
|
|
|
|
ipset/get_antifilter_ipsum.sh \
|
|
|
|
ipset/get_antifilter_ipsmart.sh \
|
|
|
|
ipset/get_antizapret_domains.sh \
|
|
|
|
ipset/get_reestr_preresolved_smart.sh \
|
|
|
|
ipset/get_antifilter_ip.sh \
|
|
|
|
init.d/pfsense/zapret.sh \
|
|
|
|
init.d/macos/zapret \
|
|
|
|
init.d/runit/zapret/run \
|
|
|
|
init.d/runit/zapret/finish \
|
|
|
|
init.d/openrc/zapret \
|
|
|
|
init.d/sysv/zapret \
|
|
|
|
init.d/openwrt/zapret \
|
|
|
|
uninstall_easy.sh \
|
|
|
|
; do chmod 755 "$1/$f" 2>/dev/null ; done
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-04 11:30:38 +00:00
|
|
|
_backup_settings()
|
|
|
|
{
|
|
|
|
local i=0
|
|
|
|
for f in "$@"; do
|
|
|
|
[ -f "$ZAPRET_TARGET/$f" ] && cp -f "$ZAPRET_TARGET/$f" "/tmp/zapret-bkp-$i"
|
|
|
|
i=$(($i+1))
|
|
|
|
done
|
|
|
|
}
|
|
|
|
_restore_settings()
|
|
|
|
{
|
|
|
|
local i=0
|
|
|
|
for f in "$@"; do
|
|
|
|
[ -f "/tmp/zapret-bkp-$i" ] && mv -f "/tmp/zapret-bkp-$i" "$ZAPRET_TARGET/$f" || rm -f "/tmp/zapret-bkp-$i"
|
|
|
|
i=$(($i+1))
|
|
|
|
done
|
|
|
|
}
|
|
|
|
backup_restore_settings()
|
|
|
|
{
|
|
|
|
# $1 - 1 - backup, 0 - restore
|
|
|
|
local mode=$1
|
2023-10-26 12:12:32 +00:00
|
|
|
on_off_function _backup_settings _restore_settings $mode "config" "init.d/sysv/custom" "init.d/openwrt/custom" "init.d/macos/custom" "ipset/zapret-hosts-user.txt" "ipset/zapret-hosts-user-exclude.txt" "ipset/zapret-hosts-user-ipban.txt" "ipset/zapret-hosts-auto.txt"
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
check_location()
|
|
|
|
{
|
|
|
|
# $1 - copy function
|
|
|
|
|
|
|
|
echo \* checking location
|
|
|
|
|
|
|
|
# use inodes in case something is linked
|
|
|
|
[ -d "$ZAPRET_TARGET" ] && [ $(get_dir_inode "$EXEDIR") = $(get_dir_inode "$ZAPRET_TARGET") ] || {
|
|
|
|
echo
|
|
|
|
echo easy install is supported only from default location : $ZAPRET_TARGET
|
|
|
|
echo currently its run from $EXEDIR
|
|
|
|
if ask_yes_no N "do you want the installer to copy it for you"; then
|
|
|
|
local keep=N
|
|
|
|
if [ -d "$ZAPRET_TARGET" ]; then
|
|
|
|
echo
|
|
|
|
echo installer found existing $ZAPRET_TARGET
|
|
|
|
echo directory needs to be replaced. config and custom scripts can be kept or replaced with clean version
|
|
|
|
if ask_yes_no N "do you want to delete all files there and copy this version"; then
|
|
|
|
echo
|
|
|
|
ask_yes_no Y "keep config, custom scripts and user lists" && keep=Y
|
|
|
|
[ "$keep" = "Y" ] && backup_restore_settings 1
|
|
|
|
rm -r "$ZAPRET_TARGET"
|
|
|
|
else
|
|
|
|
echo refused to overwrite $ZAPRET_TARGET. exiting
|
|
|
|
exitp 3
|
|
|
|
fi
|
|
|
|
fi
|
2024-05-04 13:01:09 +00:00
|
|
|
local B="$(dirname "$ZAPRET_TARGET")"
|
2021-03-04 11:30:38 +00:00
|
|
|
[ -d "$B" ] || mkdir -p "$B"
|
|
|
|
$1 "$EXEDIR" "$ZAPRET_TARGET"
|
2023-11-16 16:31:39 +00:00
|
|
|
fix_perms "$ZAPRET_TARGET"
|
2021-03-04 11:30:38 +00:00
|
|
|
[ "$keep" = "Y" ] && backup_restore_settings 0
|
|
|
|
echo relaunching itself from $ZAPRET_TARGET
|
|
|
|
exec $ZAPRET_TARGET/$(basename $0)
|
|
|
|
else
|
|
|
|
echo copying aborted. exiting
|
|
|
|
exitp 3
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
echo running from $EXEDIR
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
service_install_systemd()
|
|
|
|
{
|
|
|
|
echo \* installing zapret service
|
|
|
|
|
2021-11-16 08:46:40 +00:00
|
|
|
if [ -w "$SYSTEMD_SYSTEM_DIR" ] ; then
|
|
|
|
rm -f "$INIT_SCRIPT"
|
|
|
|
ln -fs "$EXEDIR/init.d/systemd/zapret.service" "$SYSTEMD_SYSTEM_DIR"
|
|
|
|
"$SYSTEMCTL" daemon-reload
|
|
|
|
"$SYSTEMCTL" enable zapret || {
|
|
|
|
echo could not enable systemd service
|
|
|
|
exitp 20
|
|
|
|
}
|
|
|
|
else
|
|
|
|
echo '!!! READONLY SYSTEM DETECTED !!! CANNOT INSTALL SYSTEMD UNITS !!!'
|
|
|
|
fi
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
timer_install_systemd()
|
|
|
|
{
|
|
|
|
echo \* installing zapret-list-update timer
|
|
|
|
|
2021-11-16 08:46:40 +00:00
|
|
|
if [ -w "$SYSTEMD_SYSTEM_DIR" ] ; then
|
|
|
|
"$SYSTEMCTL" disable zapret-list-update.timer
|
|
|
|
"$SYSTEMCTL" stop zapret-list-update.timer
|
|
|
|
ln -fs "$EXEDIR/init.d/systemd/zapret-list-update.service" "$SYSTEMD_SYSTEM_DIR"
|
|
|
|
ln -fs "$EXEDIR/init.d/systemd/zapret-list-update.timer" "$SYSTEMD_SYSTEM_DIR"
|
|
|
|
"$SYSTEMCTL" daemon-reload
|
|
|
|
"$SYSTEMCTL" enable zapret-list-update.timer || {
|
|
|
|
echo could not enable zapret-list-update.timer
|
|
|
|
exitp 20
|
|
|
|
}
|
|
|
|
"$SYSTEMCTL" start zapret-list-update.timer || {
|
|
|
|
echo could not start zapret-list-update.timer
|
|
|
|
exitp 30
|
|
|
|
}
|
|
|
|
else
|
|
|
|
echo '!!! READONLY SYSTEM DETECTED !!! CANNOT INSTALL SYSTEMD UNITS !!!'
|
|
|
|
fi
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
download_list()
|
|
|
|
{
|
2023-02-08 15:45:25 +00:00
|
|
|
[ -x "$GET_LIST" ] && {
|
2021-03-04 11:30:38 +00:00
|
|
|
echo \* downloading blocked ip/host list
|
|
|
|
|
2023-02-08 15:45:25 +00:00
|
|
|
# can be txt or txt.gz
|
|
|
|
"$IPSET_DIR/clear_lists.sh"
|
2022-03-22 10:10:44 +00:00
|
|
|
"$GET_LIST"
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-24 16:08:33 +00:00
|
|
|
dnstest()
|
|
|
|
{
|
|
|
|
# $1 - dns server. empty for system resolver
|
|
|
|
nslookup w3.org $1 >/dev/null 2>/dev/null
|
|
|
|
}
|
2021-03-04 11:30:38 +00:00
|
|
|
check_dns()
|
|
|
|
{
|
|
|
|
echo \* checking DNS
|
|
|
|
|
2021-11-24 16:08:33 +00:00
|
|
|
dnstest || {
|
|
|
|
echo -- DNS is not working. It's either misconfigured or blocked or you don't have inet access.
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
echo system DNS is working
|
2021-03-04 11:30:38 +00:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2022-04-13 06:18:36 +00:00
|
|
|
|
2021-03-04 11:30:38 +00:00
|
|
|
install_systemd()
|
|
|
|
{
|
|
|
|
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret"
|
|
|
|
|
|
|
|
check_bins
|
|
|
|
require_root
|
2021-11-16 08:46:40 +00:00
|
|
|
check_readonly_system
|
2021-03-04 11:30:38 +00:00
|
|
|
check_location copy_all
|
2022-02-15 14:15:36 +00:00
|
|
|
check_dns
|
2022-04-13 06:18:36 +00:00
|
|
|
check_virt
|
2021-03-04 11:30:38 +00:00
|
|
|
service_stop_systemd
|
2022-02-15 14:15:36 +00:00
|
|
|
select_fwtype
|
|
|
|
check_prerequisites_linux
|
2021-03-04 11:30:38 +00:00
|
|
|
install_binaries
|
|
|
|
select_ipv6
|
2022-03-17 07:06:29 +00:00
|
|
|
ask_config_offload
|
2021-03-04 11:30:38 +00:00
|
|
|
ask_config
|
|
|
|
service_install_systemd
|
|
|
|
download_list
|
|
|
|
# in case its left from old version of zapret
|
|
|
|
crontab_del_quiet
|
|
|
|
# now we use systemd timers
|
|
|
|
timer_install_systemd
|
|
|
|
service_start_systemd
|
|
|
|
}
|
|
|
|
|
2021-11-12 13:48:34 +00:00
|
|
|
_install_sysv()
|
|
|
|
{
|
|
|
|
# $1 - install init script
|
|
|
|
|
|
|
|
check_bins
|
|
|
|
require_root
|
2021-11-16 08:46:40 +00:00
|
|
|
check_readonly_system
|
2021-11-12 13:48:34 +00:00
|
|
|
check_location copy_all
|
2022-02-15 14:15:36 +00:00
|
|
|
check_dns
|
2022-04-13 06:18:36 +00:00
|
|
|
check_virt
|
2021-11-12 13:48:34 +00:00
|
|
|
service_stop_sysv
|
2022-02-15 14:15:36 +00:00
|
|
|
select_fwtype
|
|
|
|
check_prerequisites_linux
|
2021-11-12 13:48:34 +00:00
|
|
|
install_binaries
|
|
|
|
select_ipv6
|
2022-03-17 07:06:29 +00:00
|
|
|
ask_config_offload
|
2021-11-12 13:48:34 +00:00
|
|
|
ask_config
|
|
|
|
$1
|
|
|
|
download_list
|
|
|
|
crontab_del_quiet
|
|
|
|
# desktop system. more likely up at daytime
|
|
|
|
crontab_add 10 22
|
|
|
|
service_start_sysv
|
|
|
|
}
|
|
|
|
|
|
|
|
install_sysv()
|
|
|
|
{
|
2022-02-15 14:15:36 +00:00
|
|
|
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret"
|
2021-11-12 13:48:34 +00:00
|
|
|
_install_sysv install_sysv_init
|
|
|
|
}
|
|
|
|
|
|
|
|
install_openrc()
|
|
|
|
{
|
2022-02-15 14:15:36 +00:00
|
|
|
INIT_SCRIPT_SRC="$EXEDIR/init.d/openrc/zapret"
|
2021-11-12 13:48:34 +00:00
|
|
|
_install_sysv install_openrc_init
|
|
|
|
}
|
|
|
|
|
2021-03-04 11:30:38 +00:00
|
|
|
|
2021-11-15 15:09:08 +00:00
|
|
|
install_linux()
|
|
|
|
{
|
|
|
|
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret"
|
|
|
|
|
|
|
|
check_bins
|
|
|
|
require_root
|
|
|
|
check_location copy_all
|
2022-02-15 14:15:36 +00:00
|
|
|
check_dns
|
2022-04-13 06:18:36 +00:00
|
|
|
check_virt
|
2022-02-15 14:15:36 +00:00
|
|
|
select_fwtype
|
2021-11-15 15:09:08 +00:00
|
|
|
check_prerequisites_linux
|
|
|
|
install_binaries
|
|
|
|
select_ipv6
|
2022-03-17 07:06:29 +00:00
|
|
|
ask_config_offload
|
2021-11-15 15:09:08 +00:00
|
|
|
ask_config
|
|
|
|
download_list
|
|
|
|
crontab_del_quiet
|
|
|
|
# desktop system. more likely up at daytime
|
|
|
|
crontab_add 10 22
|
|
|
|
|
|
|
|
echo
|
|
|
|
echo '!!! WARNING. YOUR SETUP IS INCOMPLETE !!!'
|
|
|
|
echo you must manually add to auto start : $INIT_SCRIPT_SRC start
|
|
|
|
echo make sure it\'s executed after your custom/firewall iptables configuration
|
|
|
|
echo "if your system uses sysv init : ln -fs $INIT_SCRIPT_SRC /etc/init.d/zapret ; chkconfig zapret on"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-04 11:30:38 +00:00
|
|
|
deoffload_openwrt_firewall()
|
|
|
|
{
|
|
|
|
echo \* checking flow offloading
|
|
|
|
|
2022-02-15 14:15:36 +00:00
|
|
|
[ "$FWTYPE" = "nftables" ] || is_ipt_flow_offload_avail || {
|
2021-03-04 11:30:38 +00:00
|
|
|
echo unavailable
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
local fo=$(uci -q get firewall.@defaults[0].flow_offloading)
|
|
|
|
|
|
|
|
if [ "$fo" = "1" ] ; then
|
|
|
|
local mod=0
|
2022-02-15 14:15:36 +00:00
|
|
|
printf "system wide flow offloading detected. "
|
2021-03-04 11:30:38 +00:00
|
|
|
case $FLOWOFFLOAD in
|
|
|
|
donttouch)
|
|
|
|
if [ "$MODE" = "nfqws" ]; then
|
|
|
|
echo its incompatible with nfqws tcp data tampering. disabling
|
|
|
|
uci set firewall.@defaults[0].flow_offloading=0
|
|
|
|
mod=1
|
|
|
|
else
|
|
|
|
if [ "$MODE" = "custom" ] ; then
|
|
|
|
echo custom mode selected !!! only you can decide whether flow offloading is compatible
|
|
|
|
else
|
|
|
|
echo its compatible with selected options. not disabling
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
echo zapret will disable system wide offloading setting and add selective rules if required
|
|
|
|
uci set firewall.@defaults[0].flow_offloading=0
|
|
|
|
mod=1
|
|
|
|
esac
|
|
|
|
[ "$mod" = "1" ] && uci commit firewall
|
|
|
|
else
|
|
|
|
echo system wide software flow offloading disabled. ok
|
|
|
|
fi
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
install_openwrt()
|
|
|
|
{
|
|
|
|
INIT_SCRIPT_SRC="$EXEDIR/init.d/openwrt/zapret"
|
|
|
|
FW_SCRIPT_SRC="$EXEDIR/init.d/openwrt/firewall.zapret"
|
|
|
|
OPENWRT_FW_INCLUDE=/etc/firewall.zapret
|
|
|
|
OPENWRT_IFACE_HOOK="$EXEDIR/init.d/openwrt/90-zapret"
|
2022-03-02 08:47:27 +00:00
|
|
|
|
2021-03-04 11:30:38 +00:00
|
|
|
check_bins
|
|
|
|
require_root
|
|
|
|
check_location copy_openwrt
|
|
|
|
install_binaries
|
|
|
|
check_dns
|
2022-04-13 08:35:20 +00:00
|
|
|
check_virt
|
2022-02-15 14:15:36 +00:00
|
|
|
|
2022-03-02 08:50:33 +00:00
|
|
|
local FWTYPE_OLD=$FWTYPE
|
2022-03-02 08:47:27 +00:00
|
|
|
|
2022-02-15 14:15:36 +00:00
|
|
|
echo \* stopping current firewall rules/daemons
|
|
|
|
"$INIT_SCRIPT_SRC" stop_fw
|
|
|
|
"$INIT_SCRIPT_SRC" stop_daemons
|
|
|
|
|
|
|
|
select_fwtype
|
2021-03-04 11:30:38 +00:00
|
|
|
select_ipv6
|
|
|
|
check_prerequisites_openwrt
|
|
|
|
ask_config
|
|
|
|
ask_config_tmpdir
|
|
|
|
ask_config_offload
|
2022-02-15 14:15:36 +00:00
|
|
|
# stop and reinstall sysv init
|
2021-03-04 11:30:38 +00:00
|
|
|
install_sysv_init
|
2022-03-02 08:47:27 +00:00
|
|
|
[ "$FWTYPE_OLD" != "$FWTYPE" -a "$FWTYPE_OLD" = iptables -a -n "$OPENWRT_FW3" ] && remove_openwrt_firewall
|
2022-02-15 14:15:36 +00:00
|
|
|
# free some RAM
|
|
|
|
clear_ipset
|
2021-03-04 11:30:38 +00:00
|
|
|
download_list
|
|
|
|
crontab_del_quiet
|
|
|
|
# router system : works 24/7. night is the best time
|
|
|
|
crontab_add 0 6
|
|
|
|
cron_ensure_running
|
|
|
|
install_openwrt_iface_hook
|
2022-02-15 14:15:36 +00:00
|
|
|
# in case of nftables or iptables without fw3 sysv init script also controls firewall
|
|
|
|
[ -n "$OPENWRT_FW3" -a "$FWTYPE" = iptables ] && install_openwrt_firewall
|
|
|
|
service_start_sysv
|
2021-03-04 11:30:38 +00:00
|
|
|
deoffload_openwrt_firewall
|
|
|
|
restart_openwrt_firewall
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-03-04 14:48:26 +00:00
|
|
|
remove_pf_zapret_hooks()
|
2021-03-04 11:30:38 +00:00
|
|
|
{
|
|
|
|
echo \* removing zapret PF hooks
|
|
|
|
|
|
|
|
pf_anchors_clear
|
|
|
|
}
|
|
|
|
|
|
|
|
macos_fw_reload_trigger_clear()
|
|
|
|
{
|
2021-03-04 14:36:56 +00:00
|
|
|
case "$MODE" in
|
2021-03-04 18:03:26 +00:00
|
|
|
tpws|tpws-socks|custom)
|
2021-03-04 14:36:56 +00:00
|
|
|
LISTS_RELOAD=
|
|
|
|
write_config_var LISTS_RELOAD
|
|
|
|
;;
|
|
|
|
esac
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
macos_fw_reload_trigger_set()
|
|
|
|
{
|
2021-03-04 14:36:56 +00:00
|
|
|
case "$MODE" in
|
|
|
|
tpws|custom)
|
|
|
|
LISTS_RELOAD="$INIT_SCRIPT_SRC reload-fw-tables"
|
|
|
|
write_config_var LISTS_RELOAD
|
|
|
|
;;
|
|
|
|
esac
|
2021-03-04 11:30:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
install_macos()
|
|
|
|
{
|
|
|
|
INIT_SCRIPT_SRC="$EXEDIR/init.d/macos/zapret"
|
|
|
|
|
|
|
|
# compile before root
|
|
|
|
check_bins
|
|
|
|
require_root
|
|
|
|
check_location copy_all
|
2021-03-04 14:54:11 +00:00
|
|
|
service_stop_macos
|
2021-03-04 14:57:38 +00:00
|
|
|
remove_pf_zapret_hooks
|
2021-03-04 11:30:38 +00:00
|
|
|
install_binaries
|
|
|
|
check_dns
|
|
|
|
select_ipv6
|
|
|
|
ask_config
|
|
|
|
service_install_macos
|
|
|
|
macos_fw_reload_trigger_clear
|
|
|
|
# gzip lists are incompatible with PF
|
|
|
|
GZIP_LISTS=0 write_config_var GZIP_LISTS
|
|
|
|
download_list
|
|
|
|
macos_fw_reload_trigger_set
|
|
|
|
crontab_del_quiet
|
|
|
|
# desktop system. more likely up at daytime
|
|
|
|
crontab_add 10 22
|
|
|
|
service_start_macos
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# build binaries, do not use precompiled
|
|
|
|
[ "$1" = "make" ] && FORCE_BUILD=1
|
|
|
|
|
2023-11-15 07:42:10 +00:00
|
|
|
umask 0022
|
2022-03-27 15:58:47 +00:00
|
|
|
fix_sbin_path
|
2024-01-25 17:47:08 +00:00
|
|
|
fsleep_setup
|
2021-03-04 11:30:38 +00:00
|
|
|
check_system
|
|
|
|
|
|
|
|
[ "$SYSTEM" = "macos" ] && . "$EXEDIR/init.d/macos/functions"
|
|
|
|
|
|
|
|
case $SYSTEM in
|
|
|
|
systemd)
|
|
|
|
install_systemd
|
|
|
|
;;
|
2021-11-12 13:48:34 +00:00
|
|
|
openrc)
|
|
|
|
install_openrc
|
|
|
|
;;
|
2021-11-15 15:09:08 +00:00
|
|
|
linux)
|
|
|
|
install_linux
|
|
|
|
;;
|
2021-03-04 11:30:38 +00:00
|
|
|
openwrt)
|
|
|
|
install_openwrt
|
|
|
|
;;
|
|
|
|
macos)
|
|
|
|
install_macos
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
|
|
exitp 0
|