Skip to content

Commit cbb03e2

Browse files
add setup-ngxblocker into the equation
1 parent 10e4972 commit cbb03e2

File tree

2 files changed

+358
-9
lines changed

2 files changed

+358
-9
lines changed

setup-ngxblocker

Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
#!/bin/sh
2+
3+
### NGINX Bad Bot Blocker: setup script #################
4+
### Copyright (C) 2017 Stuart Cardall ###
5+
### https://github.com/itoffshore ###
6+
### Licensed under the terms of the GPL2 ###
7+
##########################################################
8+
9+
WWW=/var/www
10+
VHOST_EXT="vhost"
11+
VHOST_DIR=/etc/nginx/sites-available
12+
BOTS_DIR=/etc/nginx/bots.d
13+
CONF_DIR=/etc/nginx/conf.d
14+
MAIN_CONF=/etc/nginx/nginx.conf
15+
# setting Y / yes will whitelist only directories in $www
16+
# that look like domain.names
17+
DOT_NAMES="Y"
18+
# if you already set 'limit_conn addr' you may want to set
19+
# this to N / no.
20+
INC_DDOS="Y"
21+
22+
####### end user configuration ###########################
23+
24+
usage() {
25+
local script=$(basename $0)
26+
cat <<EOF
27+
$script: SETUP Nginx Bad Bot Blocker configuration in [ $MAIN_CONF ] [ $VHOST_DIR/* ]
28+
29+
Usage: $script [OPTIONS]
30+
[ -w ] : WWW path (default: $WWW)
31+
[ -e ] : Vhost file extension (default: .$VHOST_EXT)
32+
[ -v ] : Vhost directory (default: $VHOST_DIR)
33+
[ -b ] : Bot rules directory (default: $BOTS_DIR)
34+
[ -c ] : NGINX conf directory (default: $CONF_DIR)
35+
[ -m ] : NGINX main configuration (default: $MAIN_CONF)
36+
[ -n ] : NO whitelist of .names only (default: $DOT_NAMES)
37+
[ -d ] : NO insert of DDOS rule (default: $INC_DDOS)
38+
[ -x ] : Actually change the files (default: don't change anything)
39+
[ -h ] : this help message
40+
41+
Examples:
42+
$script -n (Whitelist all directory names in $WWW as domains: not just dot.name directories)
43+
$script -d (Do not insert DDOS rule: these may clash with existing 'limit_conn addr' rules)
44+
$script (Don't change anything: display results on stdout)
45+
$script -x (Change / update config files)
46+
EOF
47+
exit 0
48+
}
49+
50+
check_config() {
51+
local files="$*"
52+
53+
if [ -z "$files" ]; then
54+
echo "no vhost files in: $VHOST_DIR/*.$VHOST_EXT => exiting."
55+
exit 1
56+
fi
57+
58+
if [ ! -f "$MAIN_CONF" ]; then
59+
echo "NGINX main configuration ('$MAIN_CONF') not found => exiting."
60+
exit 1
61+
fi
62+
}
63+
64+
find_vhosts() {
65+
find $VHOST_DIR -type f -name "*.$VHOST_EXT"
66+
}
67+
68+
whitelist_ips() {
69+
local ip= conf=$BOTS_DIR/whitelist-ips.conf
70+
71+
mkdir -p $BOTS_DIR
72+
73+
if [ -n "$(which dig)" ]; then
74+
ip=$(dig +short myip.opendns.com @resolver1.opendns.com)
75+
if ! grep "$ip" $conf >/dev/null 2>&1; then
76+
printf "\n%-17s %-15s %-s\n" "Whitelisting ip:" "$ip" "=> $conf"
77+
if [ "$DRY_RUN" = "N" ]; then
78+
printf "%-23s %-s\n" "$ip" "0;" >> $conf
79+
fi
80+
fi
81+
else
82+
echo "WARN: dig binary missing => install bind-tools to whitelist external ip address"
83+
fi
84+
}
85+
86+
whitelist_domains() {
87+
local domain_list= domain= domain_len=
88+
local conf=$BOTS_DIR/whitelist-domains.conf
89+
90+
case "$DOT_NAMES" in
91+
y*|Y*) domain_list=$(find $WWW -mindepth 1 -maxdepth 1 -type d -name '*\.*' -exec basename {} \;);;
92+
*) domain_list=$(find $WWW -mindepth 1 -maxdepth 1 -type d -exec basename {} \;);;
93+
esac
94+
95+
domain_len=$(find $WWW -mindepth 1 -maxdepth 1 -type d -exec basename {} \; \
96+
| awk '{ print length ($0) }' | sort -nr | head -1)
97+
98+
for domain in $domain_list; do
99+
if ! grep "$domain" $conf >/dev/null 2>&1; then
100+
printf "%-s %-$(( $domain_len +2))s %s\n" "Whitelisting domain:" "$domain" "=> $conf"
101+
if [ "$DRY_RUN" = "N" ]; then
102+
printf "%-$(( $domain_len +8))s %s\n" "\"~*$domain\"" "0;" >> $conf
103+
fi
104+
fi
105+
done
106+
}
107+
108+
longest_str() {
109+
echo $@ | tr " " "\n" | awk '{print length ($0)}' | sort -nr | head -n1
110+
}
111+
112+
check_wildcard() {
113+
local file=$1 dir=$(basename $2)
114+
local check=$(grep -E "include[[:alnum:] /]+$dir/\*;" $file)
115+
echo $check
116+
}
117+
118+
add_includes() {
119+
local ph='<<!!>>' line=$1 file=$2 conf_dir=$3 text= update=
120+
local include_list="$(echo $@ | awk '{$1=$2=$3=""}sub("^"OFS"+","")')"
121+
local col_size=$(( $(longest_str $include_list) + $(echo $conf_dir | wc -m) ))
122+
123+
for text in $include_list; do
124+
if ! grep "$text" $file 1>/dev/null; then
125+
update='true'
126+
text="include $conf_dir/$text;"
127+
printf "%-10s %-$(( $col_size +10 ))s %s\n" "inserting:" "$text" "=> $file"
128+
if [ "$DRY_RUN" = "N" ]; then
129+
# $ph is just a placeholder so sed inserts a \t (tab)
130+
sed -i "$line i $ph \t$text $ph" $file
131+
fi
132+
fi
133+
done
134+
135+
if [ "$DRY_RUN" = "N" ]; then
136+
if [ -n "$update" ]; then
137+
#add blank line below inserts
138+
line=$(( $line + $(echo $include_list | wc -w) ))
139+
if ! sed -n "${line}p" $file | grep ^'}' 1>/dev/null; then
140+
text="include $conf_dir/$(echo $include_list | awk '{print $1}');"
141+
sed -i "s|$text|$text\n|" $file
142+
fi
143+
144+
#add comment above inserts
145+
text="include $conf_dir/$(echo $include_list | awk '{print $NF}');"
146+
sed -i "s|$text|# Bad Bot Blocker\n\t$text|" $file
147+
148+
# remove placeholders
149+
sed -i "s|$ph||g" $file
150+
fi
151+
fi
152+
}
153+
154+
find_line() {
155+
local file=$1 find_str=$2 first_last=$3
156+
157+
case "$first_last" in
158+
first) awk "/$find_str/{ print NR; exit }" $file;;
159+
last) awk "/$find_str/{ print NR }" $file | tail -n1;;
160+
esac
161+
}
162+
163+
find_includes() {
164+
local file=$1 search=$2 search_first_last=$3 line= tmp=$(mktemp)
165+
local start_range=$4 start_first_last=$5
166+
local end_range=$6 end_first_last=$7
167+
local start=$(find_line $file $start_range $start_first_last)
168+
local end=$(find_line $file $end_range $end_first_last)
169+
170+
sed -n ${start},${end}p ${file} > $tmp
171+
line=$(find_line $tmp $search $search_first_last)
172+
rm -f $tmp
173+
174+
# search string not found
175+
if [ -z "$line" ]; then
176+
line=1
177+
fi
178+
179+
case "$search_first_last" in
180+
first) line=$(( $line + $start -1 ));;
181+
last) line=$(( $line + $start +1 ));;
182+
esac
183+
184+
# if inserting beyond the end of the stanza
185+
if [ "$(sed -n $(( $line - 1))p $file | grep ^})" = "}" ]; then
186+
# insert blank line
187+
sed -i "$(( line - 1)) i \ " $file
188+
fi
189+
190+
echo $line
191+
}
192+
193+
sanitize_path() {
194+
echo $1 |tr -cd '[:alnum:] [=@=] [=.=] [=-=] [=/=] [=_=]' \
195+
|tr -s '@.-/_' |awk '{print tolower($0)}'
196+
}
197+
198+
sanitize_ext() {
199+
echo $1 |tr -cd '[:alnum:]' |awk '{print tolower($0)}'
200+
}
201+
202+
check_args() {
203+
local option=$1 type=$2 arg=$3
204+
local msg="ERROR: option '-$option' argument '$arg' requires:"
205+
206+
case "$type" in
207+
path) if ! echo $arg | grep ^/ 1>/dev/null; then
208+
printf "$msg absolute path.\n"
209+
exit 1
210+
fi
211+
;;
212+
none) printf "$msg argument.\n"; exit 1;;
213+
esac
214+
}
215+
216+
get_options() {
217+
local arg= opts=
218+
219+
while getopts :w:e:v:b:c:m:ndxh opts "$@"
220+
do
221+
if [ -n "${OPTARG}" ]; then
222+
case "$opts" in
223+
e) arg=$(sanitize_ext ${OPTARG});;
224+
*) arg=$(sanitize_path ${OPTARG});;
225+
esac
226+
fi
227+
228+
case "$opts" in
229+
w) WWW=$arg; check_args $opts path $arg ;;
230+
e) VHOST_EXT=$arg;;
231+
v) VHOST_DIR=$arg; check_args $opts path $arg ;;
232+
b) BOTS_DIR=$arg; check_args $opts path $arg ;;
233+
c) CONF_DIR=$arg; check_args $opts path $arg ;;
234+
m) MAIN_CONF=$arg; check_args $opts path $arg ;;
235+
n) DOT_NAMES=N ;;
236+
d) INC_DDOS=N ;;
237+
x) DRY_RUN=N ;;
238+
h) usage ;;
239+
\?) usage ;;
240+
:) check_args $OPTARG none none ;;
241+
esac
242+
done
243+
}
244+
245+
wget_opts() {
246+
local opts=
247+
248+
# GNU wget / Busybox 1.26.2
249+
if wget --help 2>&1 | grep "\--spider" >/dev/null 2>&1; then
250+
opts="--spider"
251+
else # Busybox wget < 1.26.2
252+
opts="-s"
253+
fi
254+
255+
echo $opts
256+
}
257+
258+
check_online() {
259+
local url=$1 options=$(wget_opts)
260+
261+
if wget $options $url >/dev/null 2>&1; then
262+
echo "true"
263+
fi
264+
}
265+
266+
main() {
267+
local include_url= file= line= file_list=
268+
local CONF_FILES= VHOST_INCLUDES=
269+
local REPO=https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master
270+
271+
# require root
272+
if [ "$(id -u)" != "0" ]; then
273+
echo "This script must be run as root" 1>&2
274+
exit 1
275+
fi
276+
277+
# parse command line
278+
get_options $@
279+
include_url=$REPO/include_filelist.txt
280+
281+
# check repo is online & source includes
282+
printf "Checking url: $include_url\n"
283+
if [ -n "$(check_online $include_url)" ]; then
284+
local tmp=$(mktemp)
285+
wget -q $include_url -O $tmp
286+
# use period not source in POSIX shell
287+
. $tmp 2>/dev/null
288+
rm -f $tmp
289+
else
290+
printf "Repo down or missing: $include_url\n"
291+
exit 1
292+
fi
293+
294+
# double check we have some files sourced
295+
if [ -z "$CONF_FILES" ] || [ -z "$VHOST_INCLUDES" ]; then
296+
printf "Error sourcing variables from: $include_url\n"
297+
exit 1
298+
fi
299+
300+
# configure ddos include
301+
case "$INC_DDOS" in
302+
n*|N*) VHOST_INCLUDES=$(echo $VHOST_INCLUDES | sed 's|ddos.conf||');;
303+
esac
304+
305+
# gather vhosts
306+
file_list=$(find_vhosts)
307+
check_config $file_list
308+
309+
# by default do not change any files
310+
if [ -z "$DRY_RUN" ]; then
311+
printf "\n** Dry Run ** | not updating files | -x or --exec to change files\n\n"
312+
else
313+
printf "\n"
314+
fi
315+
316+
# update vhosts
317+
for file in $file_list; do
318+
line=$(find_includes $file include last server_ last location first )
319+
if [ -n "$(check_wildcard $file $BOTS_DIR)" ]; then
320+
local col_size=$(( $(longest_str $file_list) + $(echo $BOTS_DIR | wc -m) ))
321+
printf "%-10s %-$(( $col_size -19 ))s %s\n" "WARN:" "$BOTS_DIR/* detected" "=> $file"
322+
else # don't use wildcards in vhost files
323+
add_includes $line $file $BOTS_DIR $VHOST_INCLUDES
324+
fi
325+
done
326+
327+
# update main config
328+
line=$(find_includes $MAIN_CONF include last http first '\}' last )
329+
if [ -n "$(check_wildcard $MAIN_CONF $CONF_DIR)" ]; then
330+
local col_size=$(( $(longest_str $file_list) + $(echo $CONF_DIR | wc -m) ))
331+
printf "%-10s %-$(( $col_size -19 ))s %s\n" "INFO:" "$CONF_DIR/* detected" "=> $MAIN_CONF"
332+
else # wildcard conf.d ok in nginx.conf
333+
add_includes $line $MAIN_CONF $CONF_DIR $CONF_FILES
334+
fi
335+
336+
whitelist_ips
337+
338+
if [ -d $WWW ]; then
339+
whitelist_domains
340+
else
341+
printf "\nWeb directory not found ('$WWW'): not whitelisting domains.\n"
342+
fi
343+
}
344+
345+
## START ##
346+
main $@
347+
exit $?

travis-ci/install-nginx2.sh

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,21 +59,23 @@ set -x
5959

6060
# Start nginx.
6161
#nginx -c "$DIR/nginx/nginx.conf"
62-
echo $TRAVIS_BUILD_DIR
62+
#echo $TRAVIS_BUILD_DIR
6363
sudo chmod +x $TRAVIS_BUILD_DIR/install-ngxblocker
64+
sudo chmod +x $TRAVIS_BUILD_DIR/setup-ngxblocker
6465
sudo $TRAVIS_BUILD_DIR/install-ngxblocker -x
65-
ls -la /etc/nginx/conf.d
66-
ls -la /etc/nginx/bots.d
67-
ls -la /etc/nginx/sites-available
66+
#ls -la /etc/nginx/conf.d
67+
#ls -la /etc/nginx/bots.d
68+
#ls -la /etc/nginx/sites-available
6869
#sudo rm /etc/nginx/sites-available/default
69-
sudo rm /etc/nginx/sites-enabled/default
70+
#sudo rm /etc/nginx/sites-enabled/default
7071
sudo cp $TRAVIS_BUILD_DIR/travis-ci/defaultsite.vhost /etc/nginx/sites-available/default.vhost
7172
sudo ln -s /etc/nginx/sites-available/default.vhost /etc/nginx/sites-enabled/default.vhost
7273
#sudo mv $TRAVIS_BUILD_DIR/travis-ci/nginx.conf /etc/nginx/nginx.conf
74+
sudo $TRAVIS_BUILD_DIR/setup-ngxblocker -x
7375
cat /etc/nginx/nginx.conf
7476
sudo nginx -c /etc/nginx/nginx.conf
7577
sudo nginx -t
76-
sudo nginx -V
77-
sudo netstat -peanut
78-
ls -la /etc/nginx/sites-available/
79-
ls -la /etc/nginx/sites-enabled/
78+
#sudo nginx -V
79+
#sudo netstat -peanut
80+
#ls -la /etc/nginx/sites-available/
81+
#ls -la /etc/nginx/sites-enabled/

0 commit comments

Comments
 (0)