Setup Ngxblocker
Setup Ngxblocker
/bin/sh
WWW=/var/www
VHOST_EXT="vhost"
VHOST_DIR=/etc/nginx/sites-available
BOTS_DIR=/etc/nginx/bots.d
CONF_DIR=/etc/nginx/conf.d
MAIN_CONF=/etc/nginx/nginx.conf
INSTALLER=/usr/local/sbin/install-ngxblocker
# setting Y / yes will whitelist only directories in $www
# that look like domain.names
DOT_NAMES="Y"
# if you already set 'limit_conn addr' you may want to set
# this to N / no.
INC_DDOS="Y"
BOLDGREEN="\033[1m\033[32m"
BOLDMAGENTA="\033[1m\033[35m"
BOLDRED="\033[1m\033[31m"
BOLDYELLOW="\033[1m\033[33m"
BOLDWHITE="\033[1m\033[37m"
RESET="\033[0m"
OS=$(uname -s)
usage() {
local script=$(basename $0)
cat <<EOF
$script: SETUP Nginx Bad Bot Blocker configuration in [ $MAIN_CONF ] [ $VHOST_DIR/*
]
Examples:
$script -n (Whitelist all directory names in $WWW as domains: not just dot.name
directories)
$script -l domain1.com -l domain2.com (Whitelist these manual domain name args)
$script -d (Do not insert DDOS rule: these may clash with existing 'limit_conn
addr' rules)
$script (Don't change anything: display results on stdout)
$script -x (Change / update config files)
EOF
exit 0
}
update_paths() {
# variables in nginx include files not currently possible
# updates hard coded bots.d path in globalblacklist.conf
local blacklist=$1 include_paths= dir= x=
for x in $include_paths; do
dir=$(dirname $x)
${SED_CMD} -i "s|$dir|$BOTS_DIR|" $blacklist
done
else
printf "${BOLDRED}ERROR${RESET}: '$BOTS_DIR' does not exist => $
{BOLDWHITE}running $INSTALLER${RESET}.\n"
$INSTALL_INC
update_paths $blacklist
fi
fi
}
check_config() {
if [ -z "$FILE_LIST" ]; then
printf "${BOLDGREEN}using a file extension for vhost files allows
multiple domains to be included with a single directive in nginx.conf:\n\n"
printf "${BOLDWHITE}include /etc/nginx/sites-enabled/*.$VHOST_EXT;\n\n"
printf "${BOLDYELLOW}see command line switches below: ${BOLDGREEN}-e $
{RESET}to customise the vhost file extension\n\n"
printf "${BOLDMAGENTA}no vhost files in:${RESET} [ $VHOST_DIR/*.
$VHOST_EXT ] ${BOLDWHITE}=> exiting${RESET}.\n\n"
usage
fi
if [ ! -f "$MAIN_CONF" ]; then
printf "${BOLDYELLOW}see command line switches below: ${BOLDGREEN}-m $
{RESET}to customise the location of ${BOLDWHITE}nginx.conf${RESET}\n\n"
printf "${BOLDWHITE}NGINX main configuration${RESET} [ $MAIN_CONF ] $
{BOLDMAGENTA}not found ${BOLDWHITE}=> exiting${RESET}.\n\n"
usage
fi
}
find_vhosts() {
local ans=
FILE_LIST=$(find $VHOST_DIR \( -type f -or -type l \) -name "*.$VHOST_EXT")
whitelist_ips() {
local ip= conf=$BOTS_DIR/whitelist-ips.conf
mkdir -p $BOTS_DIR
whitelist_domains() {
local domain_list= domain= domain_len=
local conf=$BOTS_DIR/whitelist-domains.conf
case "$DOT_NAMES" in
y*|Y*) domain_list=$(find $WWW -mindepth 1 -maxdepth 1 -type d -name
'*\.*' -exec basename {} \;);;
*) domain_list=$(find $WWW -mindepth 1 -maxdepth 1 -type d -exec
basename {} \;);;
esac
whitelist_manual_domains() {
local x= domain= domain_len=0
local conf=$BOTS_DIR/whitelist-domains.conf
longest_str() {
echo $@ | tr " " "\n" | awk '{print length ($0)}' | sort -nr | head -n1
}
check_wildcard() {
local file=$1 dir=$(basename $2)
local check="$(grep -E "^[^#]+include[[:alnum:] /]+$dir/\*" $file)"
echo $check
}
add_includes() {
local ph='<<!!>>' line=$1 file=$2 conf_dir=$3 col_size=$4 text= update=
local include_list="$(echo $@ | awk '{$1=$2=$3=$4=""}sub("^"OFS"+","")')"
# remove placeholders
${SED_CMD} -i "s|$ph||g" $file
fi
fi
}
find_line() {
local file=$1 find_str=$2 first_last=$3
case "$first_last" in
# ignore file #comments
first) awk "/$find_str/{ print NR; exit }" $file;;
last) awk "/$find_str/{ print NR }" $file | tail -n1;;
esac
}
find_includes() {
local file=$1 search=$2 search_first_last=$3 line= tmp=$(mktemp)
local start_range=$4 start_first_last=$5
local end_range=$6 end_first_last=$7
local start=$(find_line $file $start_range $start_first_last)
local end=$(find_line $file $end_range $end_first_last)
case "$search_first_last" in
first) line=$(( $line + $start -1 ));;
last) line=$(( $line + $start +1 ));;
esac
echo $line
}
sanitize_path() {
echo $1 |tr -cd '[:alnum:] [=@=] [=.=] [=-=] [=/=] [=_=]' \
|tr -s '@.-/_' |awk '{print tolower($0)}'
}
sanitize_ext() {
echo $1 |tr -cd '[:alnum:]' |awk '{print tolower($0)}'
}
check_args() {
local option=$1 type=$2 arg=$3
local msg="ERROR: option '-$option' argument '$arg' requires:"
case "$type" in
path) if ! echo $arg | grep ^/ 1>/dev/null; then
printf "$msg absolute path.\n"
exit 1
fi
;;
script) if [ ! -x $arg ]; then
printf "$msg '$arg' is not executable / does not exist.\n"
exit 1
fi
;;
none) printf "$msg argument.\n"; exit 1;;
esac
}
find_binary() {
local x= path= binary=$1 bin_paths='/bin /usr/bin /usr/local/bin /sbin
/usr/sbin /usr/local/sbin /root/bin /root/.bin'
for x in $bin_paths; do
path="$x/$binary"
if [ -x $path ]; then
echo $path
return
fi
done
}
check_depends() {
# centos does not have which by default
if [ -z $(find_binary curl) ]; then
printf "${BOLDRED}ERROR${RESET}: $0 requires: 'curl' => $
{BOLDWHITE}cannot check remote version.${RESET}\n"
exit 1
fi
case $OS in
Linux)
SED_CMD=$(find_binary sed)
if [ -z ${SED_CMD} ]; then
printf "${BOLDRED}ERROR${RESET}: $0 requires: 'sed' => $
{BOLDWHITE}please install sed.${RESET}\n"
exit 1
fi
;;
*BSD)
SED_CMD=$(find_binary gsed)
if [ -z ${SED_CMD} ]; then
printf "${BOLDRED}ERROR${RESET}: $0 requires: 'gsed' => $
{BOLDWHITE}please install textproc/gsed.${RESET}\n"
exit 1
fi
;;
esac
check_nginx_directives() {
# avoid directive conflicts with nginx.conf
local x= bot_config="$CONF_DIR"/botblocker-nginx-settings.conf
get_options() {
local arg= opts=
case "$opts" in
w) WWW=$arg; check_args $opts path $arg ;;
l) DOMAINS="$DOMAINS $arg" ;;
e) VHOST_EXT=$arg;;
v) VHOST_DIR=$arg; check_args $opts path $arg ;;
b) BOTS_DIR=$arg; check_args $opts path $arg ;;
c) CONF_DIR=$arg; check_args $opts path $arg ;;
m) MAIN_CONF=$arg; check_args $opts path $arg ;;
i) INSTALLER=$arg; check_args $opts script $arg ;;
n) DOT_NAMES=N ;;
d) INC_DDOS=N ;;
x) DRY_RUN=N ;;
z) SETUP_VHOST=N ;;
h) usage ;;
\?) usage ;;
:) check_args $OPTARG none none ;;
esac
done
check_online() {
local url=$1
local response_code=$(curl -o /dev/null --silent --head --write-out '%
{http_code}' $url)
main() {
local include_url= file= line= col_size= blacklist=
local CONF_FILES= VHOST_INCLUDES=
local REPO=https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-
bad-bot-blocker/master
# require root
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
# check vhosts
find_vhosts
check_config
# update vhosts
for file in $FILE_LIST; do
line=$(find_includes $file include last server_ last location first )
# whitelisting
whitelist_ips
if [ -d $WWW ]; then
whitelist_domains
else
printf "\nWeb directory not found ('$WWW'): not automatically
whitelisting domains.\n"
fi
if [ -n "$DOMAINS" ]; then
whitelist_manual_domains
fi
## START ##
main $@
exit $?