mirror of
https://github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker.git
synced 2025-09-01 18:19:55 +00:00
add a setup script to insert the required includes
the script will try to insert the new configuration below any existing includes in your config files. If the search string is not found the inserts are made at the end of the start search range: * for vhost files this is below the server_* directives. * for nginx.conf this is below http{ The search ranges & search string can be changed in main(). usage instructions can be found by running: setup-ngxblocker -h or --help by default running the script with no command line switches does a "dry run" & prints to stdout the files & includes it would change: setup-ngxblocker to actually make changes you need to run with -x: setup-ngxblocker -x
This commit is contained in:
parent
9ad7bb8a3c
commit
82282b5284
1 changed files with 246 additions and 0 deletions
246
setup-ngxblocker
Executable file
246
setup-ngxblocker
Executable file
|
@ -0,0 +1,246 @@
|
|||
#!/bin/sh
|
||||
|
||||
### NGINX Bad Bot Blocker: setup script #################
|
||||
### Copyright (C) 2017 Stuart Cardall ###
|
||||
### https://github.com/itoffshore ###
|
||||
### Licensed under the terms of the GPL2 ###
|
||||
##########################################################
|
||||
|
||||
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
|
||||
# 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"
|
||||
|
||||
####### end user configuration ###########################
|
||||
|
||||
usage() {
|
||||
local script=$(basename $0)
|
||||
cat <<EOF
|
||||
$script: add Nginx Bad Bot Blocker configuration [ in $MAIN_CONF ] [ $VHOST_DIR/* ]
|
||||
|
||||
Usage: $script [OPTIONS]
|
||||
[ -w | --www ] : WWW path (default: $WWW)
|
||||
[ -e | --ext ] : Vhost file extension (default: .$VHOST_EXT)
|
||||
[ -v | --vhost ] : Vhost directory (default: $VHOST_DIR)
|
||||
[ -b | --bots ] : Bot rules directory (default: $BOTS_DIR)
|
||||
[ -c | --conf ] : NGINX conf directory (default: $CONF_DIR)
|
||||
[ -m | --main ] : NGINX main configuration (default: $MAIN_CONF)
|
||||
[ -n | --names ] : NO whitelist of .names only (default: $DOT_NAMES)
|
||||
[ -d | --ddos ] : NO insert of DDOS rule (default: $INC_DDOS)
|
||||
[ -x | --exec ] : Actually change the files (default: don't change anything)
|
||||
[ -h | --help ] : this help message
|
||||
|
||||
Examples:
|
||||
$script -n (Whitelist all directory names in $WWW as domains: not just dot.name directories)
|
||||
$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
|
||||
return 0
|
||||
}
|
||||
|
||||
check_config() {
|
||||
local files=$@
|
||||
|
||||
if [ -z "$files" ]; then
|
||||
echo "no vhost files in: $VHOST_DIR/*.$VHOST_EXT => exiting."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
find_vhosts() {
|
||||
find $VHOST_DIR -type f -name "*.$VHOST_EXT"
|
||||
}
|
||||
|
||||
whitelist_ips() {
|
||||
local ip= conf=$BOTS_DIR/whitelist-ips.conf
|
||||
|
||||
mkdir -p $BOTS_DIR
|
||||
|
||||
if [ -n "$(which dig)" ]; then
|
||||
ip=$(dig +short myip.opendns.com @resolver1.opendns.com)
|
||||
if ! grep "$ip" $conf &>/dev/null; then
|
||||
printf "%-17s %-15s %-s\n" "Whitelisting ip:" "$ip" "=> $conf"
|
||||
if [ "$DRY_RUN" = "N" ]; then
|
||||
printf "%-23s %-s\n" "$ip" "0;" >> $conf
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "WARN: dig binary missing => install bind-tools to whitelist external ip address"
|
||||
fi
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
domain_len=$(find $WWW -mindepth 1 -maxdepth 1 -type d -exec basename {} \; \
|
||||
| awk '{ print length ($0) }' | sort -nr | head -1)
|
||||
|
||||
for domain in $domain_list; do
|
||||
if ! grep "$domain" $conf &>/dev/null; then
|
||||
printf "%-s %-$(( $domain_len +2))s %s\n" "Whitelisting domain:" "$domain" "=> $conf"
|
||||
if [ "$DRY_RUN" = "N" ]; then
|
||||
printf "%-$(( $domain_len +8))s %s\n" "\"~*$domain\"" "0;" >> $conf
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
longest_str() {
|
||||
echo $@ | tr " " "\n" | awk '{print length ($0)}' | sort -nr | head -n1
|
||||
}
|
||||
|
||||
add_includes() {
|
||||
local ph='<<!!>>' line=$1 file=$2 conf_dir=$3 text= update=
|
||||
local include_list=$(echo $@ | awk '{$1=$2=$3=""}sub("^"OFS"+","")')
|
||||
local col_size=$(( $(longest_str $include_list) + $(echo $conf_dir | wc -m) ))
|
||||
|
||||
for text in $include_list; do
|
||||
if ! grep "$text" $file 1>/dev/null; then
|
||||
update='true'
|
||||
text="include $conf_dir/$text;"
|
||||
printf "%-10s %-$(( $col_size +10 ))s %s\n" "inserting:" "$text" "=> $file"
|
||||
if [ "$DRY_RUN" = "N" ]; then
|
||||
# $ph is just a placeholder so sed inserts a \t (tab)
|
||||
sed -i "$line i $ph \t$text $ph" $file
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$DRY_RUN" = "N" ]; then
|
||||
if [ -n "$update" ]; then
|
||||
#add blank line below inserts
|
||||
line=$(( $line + $(echo $include_list | wc -w) ))
|
||||
if ! sed -n "${line}p" $file | grep ^'}' 1>/dev/null; then
|
||||
text="include $conf_dir/$(echo $include_list | awk '{print $1}');"
|
||||
sed -i "s|$text|$text\n|" $file
|
||||
fi
|
||||
|
||||
#add comment above inserts
|
||||
text="include $conf_dir/$(echo $include_list | awk '{print $NF}');"
|
||||
sed -i "s|$text|# Bad Bot Blocker\n\t$text|" $file
|
||||
|
||||
# remove placeholders
|
||||
sed -i "s|$ph||g" $file
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
find_line() {
|
||||
local file=$1 find_str=$2 first_last=$3
|
||||
|
||||
case "$first_last" in
|
||||
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)
|
||||
|
||||
sed -n ${start},${end}p ${file} > $tmp
|
||||
line=$(find_line $tmp $search $search_first_last)
|
||||
rm -f $tmp
|
||||
|
||||
# search string not found
|
||||
if [ -z "$line" ]; then
|
||||
line=1
|
||||
fi
|
||||
|
||||
case "$search_first_last" in
|
||||
first) line=$(( $line + $start -1 ));;
|
||||
last) line=$(( $line + $start +1 ));;
|
||||
esac
|
||||
|
||||
# if inserting beyond the end of the file
|
||||
if [ $line -gt $(wc -l < $file) ]; then
|
||||
# insert blank line
|
||||
sed -i "$end i \ " $file
|
||||
fi
|
||||
|
||||
echo $line
|
||||
}
|
||||
|
||||
get_options() {
|
||||
local options=$(getopt -o w:e:v:b:c:m:ndhx --long \
|
||||
www:,ext:,vhost:,bots:,conf:,main:,names,ddos,help,exec -- "$@" 2>/dev/null)
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
eval set -- "$options"
|
||||
|
||||
while :; do
|
||||
case "$1" in
|
||||
-h | --help) usage && exit 1;;
|
||||
-x | --exec) DRY_RUN=N; shift;;
|
||||
-w | --www) WWW=$2; shift 2;;
|
||||
-e | --ext) VHOST_EXT=$2; shift 2;;
|
||||
-v | --vhost) VHOST_DIR=$2; shift 2;;
|
||||
-b | --bots) BOTS_DIR=$2; shift 2;;
|
||||
-c | --conf) CONF_DIR=$2; shift 2;;
|
||||
-m | --main) MAIN_CONF=$2; shift 2;;
|
||||
-n | --names) DOT_NAMES=N; shift;;
|
||||
-d | --ddos) INC_DDOS=N; shift;;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
local file= line= vhost_includes= main_includes= file_list=
|
||||
main_includes="botblocker-nginx-settings.conf globalblacklist.conf"
|
||||
vhost_includes="blockbots.conf"
|
||||
|
||||
# parse command line
|
||||
get_options $@
|
||||
|
||||
case "$INC_DDOS" in
|
||||
y*|Y*) vhost_includes="$vhost_includes ddos.conf"
|
||||
esac
|
||||
|
||||
file_list=$(find_vhosts)
|
||||
check_config $file_list
|
||||
|
||||
if [ -z "$DRY_RUN" ]; then
|
||||
printf "\n** Dry Run ** | not updating files | -x or --exec to change files\n\n"
|
||||
fi
|
||||
|
||||
# update vhosts
|
||||
for file in $file_list; do
|
||||
line=$(find_includes $file include last server_ last location first )
|
||||
add_includes $line $file $BOTS_DIR $vhost_includes
|
||||
done
|
||||
|
||||
# update main config
|
||||
line=$(find_includes $MAIN_CONF include last http first '\}' last )
|
||||
add_includes $line $MAIN_CONF $CONF_DIR botblocker-nginx-settings.conf globalblacklist.conf
|
||||
|
||||
whitelist_ips
|
||||
whitelist_domains
|
||||
}
|
||||
|
||||
## START ##
|
||||
main $@
|
||||
exit $?
|
||||
|
Loading…
Add table
Reference in a new issue