forked from mariogrip/notrack
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
notrack.sh
1650 lines (1454 loc) · 52.5 KB
/
notrack.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
#Title : NoTrack
#Description : This script will download latest Adblock Domain block files from quidsup.net, then parse them into Dnsmasq.
#Author : QuidsUp
#Date : 2015-01-14
#Usage : sudo bash notrack.sh
#User Configerable Settings (in case config file is missing)---------
#Set NetDev to the name of network device e.g. "eth0" IF you have multiple network cards
NetDev=$(ip -o link show | awk '{print $2,$9}' | grep ": UP" | cut -d ":" -f 1)
#If NetDev fails to recognise a Local Area Network IP Address, then you can use IPVersion to assign a custom IP Address in /etc/notrack/notrack.conf
#e.g. IPVersion = 192.168.1.2
IPVersion="IPv4"
declare -A Config #Config array for Block Lists
Config[bl_custom]=""
Config[bl_notrack]=1
Config[bl_tld]=1
Config[bl_qmalware]=1
Config[bl_cedia]=0
Config[bl_cedia_immortal]=1
Config[bl_hexxium]=1
Config[bl_disconnectmalvertising]=0
Config[bl_easylist]=0
Config[bl_easyprivacy]=0
Config[bl_fbannoyance]=0
Config[bl_fbenhanced]=0
Config[bl_fbsocial]=0
Config[bl_hphosts]=0
Config[bl_malwaredomainlist]=0
Config[bl_malwaredomains]=0
Config[bl_pglyoyo]=0
Config[bl_someonewhocares]=0
Config[bl_spam404]=0
Config[bl_swissransom]=0
Config[bl_swisszeus]=0
Config[bl_winhelp2002]=0
Config[bl_areasy]=0 #Arab
Config[bl_chneasy]=0 #China
Config[bl_deueasy]=0 #Germany
Config[bl_dnkeasy]=0 #Denmark
Config[bl_ruseasy]=0 #Russia
Config[bl_fblatin]=0 #Portugal/Spain (Latin Countries)
Config[bl_yhosts]=0 #China yhosts
#######################################
# Constants
#######################################
readonly VERSION="0.8.4"
readonly MAIN_BLOCKLIST="/etc/dnsmasq.d/notrack.list"
readonly FILE_BLACKLIST="/etc/notrack/blacklist.txt"
readonly FILE_WHITELIST="/etc/notrack/whitelist.txt"
readonly FILE_DOMAINBLACK="/etc/notrack/domain-blacklist.txt"
readonly FILE_DOMAINWHITE="/etc/notrack/domain-whitelist.txt"
readonly CSV_DOMAIN="/var/www/html/admin/include/tld.csv"
readonly FILE_CONFIG="/etc/notrack/notrack.conf"
readonly CHECKTIME=343800 #Time in Seconds between downloading lists (4 days - 30mins)
readonly USER="ntrk"
readonly PASSWORD="ntrkpass"
readonly DBNAME="ntrkdb"
declare -A URLList #Array of URL's
URLList[notrack]="https://raw.githubusercontent.com/quidsup/notrack/master/trackers.txt"
URLList[qmalware]="https://raw.githubusercontent.com/quidsup/notrack/master/malicious-sites.txt"
URLList[cedia]="http://mirror.cedia.org.ec/malwaredomains/domains.zip"
URLList[cedia_immortal]="http://mirror.cedia.org.ec/malwaredomains/immortal_domains.zip"
URLList[hexxium]="https://hexxiumcreations.github.io/threat-list/hexxiumthreatlist.txt"
URLList[disconnectmalvertising]="https://s3.amazonaws.com/lists.disconnect.me/simple_malvertising.txt"
URLList[easylist]="https://easylist-downloads.adblockplus.org/easylist_noelemhide.txt"
URLList[easyprivacy]="https://easylist-downloads.adblockplus.org/easyprivacy.txt"
URLList[fbannoyance]="https://easylist-downloads.adblockplus.org/fanboy-annoyance.txt"
URLList[fbenhanced]="https://www.fanboy.co.nz/enhancedstats.txt"
URLList[fbsocial]="https://secure.fanboy.co.nz/fanboy-social.txt"
URLList[hphosts]="http://hosts-file.net/ad_servers.txt"
URLList[malwaredomainlist]="http://www.malwaredomainlist.com/hostslist/hosts.txt"
URLList[malwaredomains]="http://mirror1.malwaredomains.com/files/justdomains"
#URLList[securemecca]="http://securemecca.com/Downloads/hosts.txt"
URLList[spam404]="https://raw.githubusercontent.com/Dawsey21/Lists/master/adblock-list.txt"
URLList[swissransom]="https://ransomwaretracker.abuse.ch/downloads/RW_DOMBL.txt"
URLList[swisszeus]="https://zeustracker.abuse.ch/blocklist.php?download=domainblocklist"
URLList[pglyoyo]="http://pgl.yoyo.org/adservers/serverlist.php?hostformat=;mimetype=plaintext"
URLList[someonewhocares]="http://someonewhocares.org/hosts/hosts"
URLList[winhelp2002]="http://winhelp2002.mvps.org/hosts.txt"
URLList[areasy]="https://easylist-downloads.adblockplus.org/Liste_AR.txt"
URLList[chneasy]="https://easylist-downloads.adblockplus.org/easylistchina.txt"
URLList[deueasy]="https://easylist-downloads.adblockplus.org/easylistgermany.txt"
URLList[dnkeasy]="https://adblock.dk/block.csv"
URLList[ruseasy]="https://easylist-downloads.adblockplus.org/ruadlist+easylist.txt"
URLList[fblatin]="https://www.fanboy.co.nz/fanboy-espanol.txt"
URLList[yhosts]="https://raw.githubusercontent.com/vokins/yhosts/master/hosts"
#######################################
# Global Variables
#######################################
FileTime=0 #Return value from get_filetime
Force=0 #Force update block list
OldLatestVersion="$VERSION"
EXECTIME=$(date +%s) #Time at Execution
JumpPoint=0 #Percentage increment
PercentPoint=0 #Number of lines to loop through before a percentage increment is hit
declare -A WhiteList #associative array for referencing sites in White List
declare -a SQLList #Array to store each list for entering into MariaDB
declare -A DomainList #Array to check if TLD blocked
declare -A SiteList #Array to store sites being blocked
declare -i Dedup=0 #Count of Deduplication
#--------------------------------------------------------------------
# Error Exit
#
# Globals:
# None
# Arguments:
# $1 = Error Message
# $2 = Exit Code
# Returns:
# None
#--------------------------------------------------------------------
function error_exit() {
echo "Error. $1"
echo "Aborting"
exit "$2"
}
#######################################
# Restart service
# with either systemd or sysvinit
#
# Globals:
# None
# Arguments:
# None
# Returns:
# None
#######################################
service_restart() {
if [[ -n $1 ]]; then
echo "Restarting $1"
if [ "$(command -v systemctl)" ]; then #systemd
sudo systemctl restart $1
elif [ "$(command -v service)" ]; then #sysvinit
sudo service $1 restart
else
error_exit "Unable to restart services. Unknown service supervisor" "21"
fi
fi
}
#--------------------------------------------------------------------
# Create File
# Checks if a file exists and creates it
#
# Globals:
# None
# Arguments:
# #$1 File to create
# Returns:
# None
#--------------------------------------------------------------------
function create_file() {
if [ ! -e "$1" ]; then #Does file already exist?
echo "Creating file: $1"
touch "$1" #If not then create it
fi
}
#--------------------------------------------------------------------
# Create SQL Tables
# Create SQL tables, in case they have been deleted
#
# Globals:
# USER, PASSWORD, DBNAME
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function create_sqltables {
mysql --user="$USER" --password="$PASSWORD" -D "$DBNAME" -e "CREATE TABLE IF NOT EXISTS live (id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, log_time DATETIME, sys TINYTEXT, dns_request TINYTEXT, dns_result CHAR(1));"
mysql --user="$USER" --password="$PASSWORD" -D "$DBNAME" -e "CREATE TABLE IF NOT EXISTS historic (id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, log_time DATETIME, sys TINYTEXT, dns_request TINYTEXT, dns_result CHAR(1));"
mysql --user="$USER" --password="$PASSWORD" -D "$DBNAME" -e "CREATE TABLE IF NOT EXISTS users (id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, user TINYTEXT, pass TEXT, level CHAR(1));"
mysql --user="$USER" --password="$PASSWORD" -D "$DBNAME" -e "CREATE TABLE IF NOT EXISTS blocklist (id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, bl_source TINYTEXT, site TINYTEXT, site_status BOOLEAN, comment TEXT);"
mysql --user="$USER" --password="$PASSWORD" -D "$DBNAME" -e "CREATE TABLE IF NOT EXISTS lightyaccess (id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, log_time DATETIME, site TINYTEXT, http_method CHAR(4), uri_path TEXT, referrer TEXT, user_agent TEXT, remote_host TEXT);"
if [ -e "/var/log/lighttpd/access.log" ]; then
sudo chmod 775 /var/log/lighttpd/access.log #Not SQL related, but my system was causing ntrk-parse to fail because of permissions
fi
}
#--------------------------------------------------------------------
# Delete Old File
# Checks if a file exists and then deletes it
#
# Globals:
# None
# Arguments:
# #$1 File to delete
# Returns:
# None
#--------------------------------------------------------------------
function delete_file() {
if [ -e "$1" ]; then #Does file exist?
echo "Deleting file $1"
rm "$1" #If yes then delete it
fi
}
#--------------------------------------------------------------------
# Add Site to List
# Checks whether a Site is in the Users whitelist or has previously been added
#
# Globals:
# DomainList
# WhiteList
# Dedup
# Arguments:
# $1 site to Add
# $2 Comment
# Returns:
# None
#--------------------------------------------------------------------
function addsite() {
local site="$1"
if [[ $site =~ ^www\. ]]; then #Drop www.
site="${site:4}"
fi
#Ignore Sub domain
#Group 1 Domain: A-Z,a-z,0-9,- one or more
# .
#Group 2 (Double-barrelled TLD's) : org. | co. | com. optional
#Group 3 TLD: A-Z,a-z,0-9,- one or more
if [[ $site =~ ([A-Za-z0-9\-]+)\.(org\.|co\.|com\.)?([A-Za-z0-9\-]+)$ ]]; then
if [ "${DomainList[.${BASH_REMATCH[3]}]}" ]; then #Drop if .domain is in TLD
#echo "Dedup TLD $site" #Uncomment for debugging
((Dedup++))
return 0
fi
if [ "${SiteList[${BASH_REMATCH[1]}.${BASH_REMATCH[2]}${BASH_REMATCH[3]}]}" ]; then #Drop if sub.site.domain has been added
#echo "Dedup Domain $site" #Uncomment for debugging
((Dedup++))
return 0
fi
if [ "${SiteList[$site]}" ]; then #Drop if sub.site.domain has been added
#echo "Dedup Duplicate Sub $site" #Uncomment for debugging
((Dedup++))
return 0
fi
if [ "${WhiteList[$site]}" ] || [ "${WhiteList[${BASH_REMATCH[1]}.${BASH_REMATCH[2]}${BASH_REMATCH[3]}]}" ]; then #Is sub.site.domain or site.domain in whitelist?
SQLList+=("\"$site\",\"0\",\"$2\"") #Add to SQL as Disabled
else #No match in whitelist
SQLList+=("\"$site\",\"1\",\"$2\"") #Add to SQL as Active
SiteList[$site]=true #Add site into SiteList array
fi
#else
#echo "Invalid site $site"
fi
}
#--------------------------------------------------------------------
# Calculate Percent Point in list files
# 1. Count number of lines in file with "wc"
# 2. Calculate Percentage Point (number of for loop passes for 1%)
# 3. Calculate Jump Point (increment of 1 percent point on for loop)
# E.g.1 20 lines = 1 for loop pass to increment percentage by 5%
# E.g.2 200 lines = 2 for loop passes to increment percentage by 1%
#
# Globals:
# PercentPoint
# JumpPoint
# Arguments:
# $1 = File to Calculate
# Returns:
# None
#--------------------------------------------------------------------
function CalculatePercentPoint() {
local NumLines=0
NumLines=$(wc -l "$1" | cut -d " " -f 1) #Count number of lines
if [ "$NumLines" -ge 100 ]; then
PercentPoint=$((NumLines/100))
JumpPoint=1
else
PercentPoint=1
JumpPoint=$((100/NumLines))
fi
}
#--------------------------------------------------------------------
# Check Version of Dnsmasq
#
# Globals:
# None
# Arguments:
# None
# Returns:
# 50. Dnsmasq Missing
# 51. Dnsmasq Version Unknown
# 52. Dnsmasq doesn't support whitelisting (below 2.75)
# 53. Dnsmasq supports whitelisting (2.75 and above)#
#--------------------------------------------------------------------
function CheckDnsmasqVer() {
if [ -z "$(command -v dnsmasq)" ]; then
return 50
fi
local VerStr=""
VerStr="$(dnsmasq --version)" #Get version from dnsmasq
#The return is very wordy, so we need to extract the relevent info
[[ $VerStr =~ ^Dnsmasq[[:space:]]version[[:space:]]([0-9]\.[0-9]{1,2}) ]]
local VerNo="${BASH_REMATCH[1]}" #Extract version number from string
if [[ -z $VerNo ]]; then #Was anything extracted?
return 51
else
[[ $VerNo =~ ([0-9])\.([0-9]{1,2}) ]]
if [ "${BASH_REMATCH[1]}" -eq 2 ] && [ "${BASH_REMATCH[2]}" -ge 75 ]; then #Version 2.75 onwards
return 53
elif [ "${BASH_REMATCH[1]}" -ge 3 ]; then #Version 3 onwards
return 53
else #2.74 or below
return 52
fi
fi
}
#--------------------------------------------------------------------
# Check If Running as Root and if Script is already running
#
# Globals:
# None
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function check_root() {
local Pid=""
Pid=$(pgrep notrack | head -n 1) #Get PID of first notrack process
if [[ "$(id -u)" != "0" ]]; then
error_exit "This script must be run as root" "5"
fi
#Check if another copy of notrack is running
if [[ $Pid != "$$" ]] && [[ -n $Pid ]] ; then #$$ = This PID
error_exit "NoTrack already running under Pid $Pid" "8"
fi
}
#--------------------------------------------------------------------
# Count number of lines in /etc/dnsmasq.d block lists
#
# Globals:
# None
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function CountLines() {
local ListFile=""
local LineCount=0
for ListFile in /etc/dnsmasq.d/*.list; do
let "LineCount += $(wc -l "$ListFile" | cut -d\ -f 1)"
done
echo "$LineCount"
}
#--------------------------------------------------------------------
# Delete Blocklist table
# 1. Delete all rows in Table
# 2. Reset Counter
#
# Globals:
# USER, PASSWORD, DBNAME
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function delete_table() {
echo "Clearing Blocklist Table"
echo "DELETE FROM blocklist;" | mysql --user="$USER" --password="$PASSWORD" -D "$DBNAME"
echo "ALTER TABLE blocklist AUTO_INCREMENT = 1;" | mysql --user="$USER" --password="$PASSWORD" -D "$DBNAME"
}
#--------------------------------------------------------------------
# Generate Example Black List File
#
# Globals:
# None
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function generate_blacklist() {
local -a tmp #Local array to build contents of file
echo "Creating blacklist"
touch "$FILE_BLACKLIST"
tmp+=("#Use this file to create your own custom block list")
tmp+=("#Run notrack script (sudo notrack) after you make any changes to this file")
tmp+=("#doubleclick.net")
tmp+=("#googletagmanager.com")
tmp+=("#googletagservices.com")
printf "%s\n" "${tmp[@]}" > $FILE_BLACKLIST #Write Array to file with line seperator
}
#--------------------------------------------------------------------
# Generate Example White List File
#
# Globals:
# None
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function generate_whitelist() {
local -a tmp #Local array to build contents of file
echo "Creating whitelist"
touch "$FILE_WHITELIST"
tmp+=("#Use this file to remove sites from block list")
tmp+=("#Run notrack script (sudo notrack) after you make any changes to this file")
tmp+=("#doubleclick.net")
tmp+=("#google-analytics.com")
printf "%s\n" "${tmp[@]}" > $FILE_WHITELIST #Write Array to file with line seperator
}
#--------------------------------------------------------------------
# Get IP Address
# Reads IP address of System or uses custom IP assigned by IPVersion
#
# Globals:
# IPAddr, IPVersion
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function get_ip() {
#A manual IP address can be assigned using IPVersion
if [ "$IPVersion" == "IPv4" ]; then
echo "Internet Protocol Version 4 (IPv4)"
echo "Reading IPv4 Address from $NetDev"
IPAddr=$(ip addr list "$NetDev" | grep inet | head -n 1 | cut -d ' ' -f6 | cut -d/ -f1)
elif [ "$IPVersion" == "IPv6" ]; then
echo "Internet Protocol Version 6 (IPv6)"
echo "Reading IPv6 Address"
IPAddr=$(ip addr list "$NetDev" | grep inet6 | head -n 1 | cut -d ' ' -f6 | cut -d/ -f1)
else
echo "Custom IP Address used"
IPAddr="$IPVersion"; #Use IPVersion to assign a manual IP Address
fi
echo "System IP Address: $IPAddr"
echo
}
#--------------------------------------------------------------------
# Get File Time
# Gets file time of a file if it exists
#
# Globals:
# FileTime
# Arguments:
# None
# Returns:
# Via FileTime
#--------------------------------------------------------------------
function get_filetime() {
#$1 = File to be checked
if [ -e "$1" ]; then #Does file exist?
FileTime=$(stat -c %Z "$1") #Return time of last status change, seconds since Epoch
else
FileTime=0 #Otherwise retrun 0
fi
}
#--------------------------------------------------------------------
# Get Blacklist
# Get Users Custom Blacklist
#
# Globals:
# FILE_BLACKLIST, SQLList
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function get_blacklist() {
echo "Processing Custom Black List"
SQLList=()
process_plainlist "$FILE_BLACKLIST"
if [ ${#SQLList[@]} -gt 0 ]; then #Are there any URL's in the block list?
insert_data "custom"
else
delete_file "/etc/notrack/custom.csv"
fi
echo "Finished processing Custom Black List"
echo
}
#Get Custom List-----------------------------------------------------
function get_custom() {
local -A CustomListArray
local dlfile=""
local dlfile_time=0 #Downloaded File Time
local CustomCount=1 #For displaying count of custom list
local FileName=""
if [[ ${Config[bl_custom]} == "" ]]; then #Are there any custom block lists?
echo "No Custom Block Lists in use"
echo
for FileName in /etc/notrack/custom_*; do #Clean up old custom lists
FileName=${FileName##*/} #Get filename from path
FileName=${FileName%.*} #Remove file extension
delete_file "/etc/dnsmasq.d/$FileName.list"
delete_file "/etc/notrack/$FileName.csv"
delete_file "/tmp/$FileName.txt"
done
return
fi
echo "Processing Custom Block Lists"
#Split comma seperated list into individual URL's
IFS=',' read -ra CustomList <<< "${Config[bl_custom]}"
for ListUrl in "${CustomList[@]}"; do
echo "$CustomCount: $ListUrl"
FileName=${ListUrl##*/} #Get filename from URL
FileName=${FileName%.*} #Remove file extension
dlfile="/tmp/custom_$FileName.txt"
CustomListArray[$FileName]="$FileName" #Used later to find old custom lists
get_filetime "$dlfile" #When was file last downloaded / copied?
dlfile_time="$FileTime"
#Determine whether we are dealing with a download or local file
if [[ $ListUrl =~ ^(https?|ftp):// ]]; then #Is URL a http(s) or ftp?
if [ $dlfile_time -lt $((EXECTIME-CHECKTIME)) ]; then #Is list older than 4 days
echo "Downloading $FileName"
wget -qO "$dlfile" "$ListUrl" #Yes, download it
else
echo "File in date, not downloading"
fi
elif [ -e "$ListUrl" ]; then #Is it a file on the server?
echo "$ListUrl File Found on system"
get_filetime "$ListUrl" #Get date of file
if [ $FileTime -gt $dlfile_time ]; then #Is the original file newer than file in /tmp?
echo "Copying to $dlfile" #Yes, copy file
cp "$ListUrl" "$dlfile"
else
echo "File in date, not copying"
fi
else #Don't know what to do, skip to next file
echo "Unable to identify what $ListUrl is"
echo
continue
fi
if [ -s "$dlfile" ]; then #Only process if filesize > 0
SQLList=() #Zero Array
#Adblock EasyList can be identified by first line of file
Line=$(head -n1 "$dlfile") #What is on the first line?
if [[ ${Line:0:13} == "[Adblock Plus" ]]; then #First line identified as EasyList
echo "Block list identified as Adblock Plus EasyList"
process_easylist "$dlfile"
else #Other, lets grab URL from each line
echo "Processing as Custom List"
process_customlist "$dlfile"
fi
if [ ${#SQLList[@]} -gt 0 ]; then #Are there any URL's in the block list?
insert_data "custom_$FileName"
echo "Finished processing $FileName"
else #No URL's in block list
echo "No URL's extracted from Block list"
fi
else #File not downloaded
echo "Error $dlfile not found"
fi
echo
((CustomCount++)) #Increase count of custom lists
done
for FileName in /etc/dnsmasq.d/custom_*; do #Clean up old custom lists
FileName=${FileName##*/} #Get filename from path
FileName=${FileName%.*} #Remove file extension
FileName=${FileName:7} #Remove custom_
if [ ! "${CustomListArray[$FileName]}" ]; then
delete_file "/etc/dnsmasq.d/custom_$FileName.list"
delete_file "/etc/notrack/custom_$FileName.csv"
fi
done
unset IFS
}
#--------------------------------------------------------------------
# Get List
# Downloads a blocklist and prepares it for processing
#
# Globals:
# Config, FileTime, SQLList
# Arguments:
# $1 = List Name to be Processed
# $2 = Process Method
# $3 = List file to use within zip file
# Returns:
# None
#--------------------------------------------------------------------
function get_list() {
local list="$1"
local dlfile="/tmp/$1.txt"
local zipfile=false
#Should we process this list according to the Config settings?
if [ "${Config[bl_$list]}" == 0 ]; then
delete_file "$dlfile" #If not delete the old file, then leave the function
return 0
fi
if [[ ${URLList[$list]} =~ \.zip$ ]]; then #Is the download a zip file?
dlfile="/tmp/$1.zip"
zipfile=true
fi
get_filetime "$dlfile" #Is the download in date?
if [ $FileTime -gt $((EXECTIME-CHECKTIME)) ]; then
echo "$list in date. Not downloading"
else
echo "Downloading $list"
wget -qO "$dlfile" "${URLList[$list]}" #Download out of date
fi
if [ ! -s "$dlfile" ]; then #Check if list has been downloaded
echo "File not downloaded"
return 1
fi
if [[ $zipfile == true ]]; then #Do we need to unzip?
unzip -o "$dlfile" -d "/tmp/" #Unzip not quietly (-q)
dlfile="/tmp/$3" #dlfile is now the expected unziped file
if [ ! -e "$dlfile" ]; then #Check if expected file is there
echo "Warning: Can't find file $dlfile"
return 0
fi
fi
SQLList=() #Zero Arrays
echo "Processing list $list" #Inform user
case $2 in #What type of processing is required?
"csv") process_csv "$dlfile" ;;
"easylist") process_easylist "$dlfile" ;;
"plain") process_plainlist "$dlfile" ;;
"notrack") process_notracklist "$dlfile" ;;
"tldlist") process_tldlist ;;
"unix") process_unixlist "$dlfile" ;;
*) error_exit "Unknown option $2" "7"
esac
if [ ${#SQLList[@]} -gt 0 ]; then #Are there any URL's in the block list?
insert_data "bl_$list" #Add data to SQL table
echo "Finished processing $list"
else #No URL's in block list
echo "No URL's extracted from Block list"
fi
echo
}
#--------------------------------------------------------------------
# Insert Data into SQL Table
# 1. Save SQLList array to .csv file
# 2. Bulk write csv file into MariaDB
#
# Globals:
# SQLList
# Arguments:
# $1 - Blocklist
# Returns:
# None
#--------------------------------------------------------------------
function insert_data() {
#echo "Inserting data into MariaDB"
printf "%s\n" "${SQLList[@]}" > "/tmp/$1.csv" #Output arrays to file
mysql --user="$USER" --password="$PASSWORD" -D "$DBNAME" -e "LOAD DATA INFILE '/tmp/$1.csv' INTO TABLE blocklist FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\n' (@var1, @var2, @var3) SET id='NULL', bl_source = '$1', site = @var1, site_status=@var2, comment=@var3;"
rm "/tmp/$1.csv"
}
#--------------------------------------------------------------------
# Check If mysql or MariaDB is installed
# exits if not installed
# Globals:
# None
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function is_sql_installed() {
if [ -z "$(command -v mysql)" ]; then
echo "NoTrack requires MySql or MariaDB to be installed"
echo "Run install.sh -sql"
exit 60
fi
}
#--------------------------------------------------------------------
# Check if an update is required
# Triggers for Update being required:
# 1. -f or --forced
# 2 Block list older than 4 days
# 3 White list recently modified
# 4 Black list recently modified
# 5 Config recently modified
# 6 Domain White list recently modified
# 7 Domain Black list recently modified
# 8 Domain CSV recently modified
# Globals:
# Force
# FILE_BLACKLIST, FILE_WHITELIST, FILE_CONFIG, FILE_DOMAINBLACK, FILE_DOMAINWHITE
# CSV_DOMAIN
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function is_update_required() {
get_filetime "$MAIN_BLOCKLIST"
local ListFileTime="$FileTime"
if [ $Force == 1 ]; then
echo "Forced Update"
return 0
fi
if [ $ListFileTime -lt $((EXECTIME-CHECKTIME)) ]; then
echo "Block List out of date"
return 0
fi
get_filetime "$FILE_WHITELIST"
if [ $FileTime -gt $ListFileTime ]; then
echo "White List recently modified"
return 0
fi
get_filetime "$FILE_BLACKLIST"
if [ $FileTime -gt $ListFileTime ]; then
echo "Black List recently modified"
return 0
fi
get_filetime "$FILE_CONFIG"
if [ $FileTime -gt $ListFileTime ]; then
echo "Config recently modified"
return 0
fi
get_filetime "$FILE_DOMAINWHITE"
if [ $FileTime -gt $ListFileTime ]; then
echo "Domain White List recently modified"
return 0
fi
get_filetime "$FILE_DOMAINBLACK"
if [ $FileTime -gt $ListFileTime ]; then
echo "Domain White List recently modified"
return 0
fi
get_filetime "$CSV_DOMAIN"
if [ $FileTime -gt $ListFileTime ]; then
echo "Domain Master List recently modified"
return 0
fi
echo "No update required"
exit 0
}
#--------------------------------------------------------------------
# Load Config File
# Default values are set at top of this script
# Config File contains Key & Value on each line for some/none/or all items
# If the Key is found in the case, then we write the value to the Variable
#
# Globals:
# Config
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function load_config() {
local key=""
local value=""
if [ ! -e "$FILE_CONFIG" ]; then
echo "Config $FILE_CONFIG missing"
return
fi
echo "Reading Config File"
while IFS='= ' read -r key value #Seperator '= '
do
if [[ ! $key =~ ^\ *# ]] && [[ -n $key ]]; then
value="${value%%\#*}" #Del in line right comments
value="${value%%*( )}" #Del trailing spaces
value="${value%\"*}" #Del opening string quotes
value="${value#\"*}" #Del closing string quotes
if [ "${Config[$key]}" ]; then #Does key exist in Config array?
Config[$key]="$value" #Yes - replace value
else
case "$key" in
IPVersion) IPVersion="$value";;
NetDev) NetDev="$value";;
LatestVersion) OldLatestVersion="$value";;
esac
fi
fi
done < $FILE_CONFIG
unset IFS
}
#--------------------------------------------------------------------
# Load White List
#
# Globals:
# FILE_WHITELIST, WhiteList
# Arguments:
# None
# Returns:
# None
#--------------------------------------------------------------------
function load_whitelist() {
while IFS=$'\n' read -r Line
do
if [[ $Line =~ ^([A-Za-z0-9\-]+)\.([A-Za-z0-9\.\-]+)[[:space:]]?#?(.*)$ ]]; then
WhiteList["${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"]=true #Add site to associative array
fi
done < $FILE_WHITELIST
unset IFS
}
#--------------------------------------------------------------------
# Process CSV
# Process CSV List Tab seperated with Col1 = site, Col2 = comments
# Globals:
# JumpPoint
# PercentPoint
# Arguments:
# $1 List file to process
# Returns:
# None
# Regex:
# Group 1: Subdomain or Domain
# .
# Group 2: Domain or TLD
#--------------------------------------------------------------------
function process_csv() {
local csvsite=""
local csvcomment=""
local i=0
local j=0
CalculatePercentPoint "$1"
i=1 #Progress counter
j=$JumpPoint #Jump in percent
while IFS=$'\t\n' read -r csvsite csvcomment _
do
if [[ $csvsite =~ ^([A-Za-z0-9\-]+)\.([A-Za-z0-9\.\-]+)$ ]]; then
addsite "$csvsite" "$csvcomment"
fi
if [ $i -ge $PercentPoint ]; then #Display progress
echo -ne " $j% \r" #Echo without return
j=$((j + JumpPoint))
i=0
fi
((i++))
done < "$1"
echo " 100%"
unset IFS
}
#--------------------------------------------------------------------
# Process Custom List
#
# Globals:
# JumpPoint
# PercentPoint
# Arguments:
# #$1 List file to process
# Returns:
# None
#--------------------------------------------------------------------
function process_customlist() {
local i=0
local j=0
CalculatePercentPoint "$1"
i=1 #Progress counter
j=$JumpPoint #Jump in percent
while IFS=$'#\n\r' read -r Line Comment _
do
if [[ ! $Line =~ ^\ *# ]] && [[ -n $Line ]]; then
Line="${Line%%\#*}" #Delete comments
Line="${Line%%*( )}" #Delete trailing spaces
if [[ $Line =~ ([A-Za-z0-9\-]*\.)?([A-Za-z0-9\-]*\.)?[A-Za-z0-9\-]*\.[A-Za-z0-9\-]*$ ]]; then
addsite "${BASH_REMATCH[0]}" "$Comment"
fi
fi
if [ $i -ge $PercentPoint ]; then #Display progress
echo -ne " $j% \r" #Echo without return
j=$((j + JumpPoint))
i=0
fi
((i++))
done < "$1"
echo " 100%"
unset IFS
}
#--------------------------------------------------------------------
# Process Easy List
# EasyLists contain a mixture of Element hiding rules and third party sites to block.
# DNS is only capable of blocking sites, therefore NoTrack can only use the lines with $third party or popup in
# Globals:
# JumpPoint
# PercentPoint
# Arguments:
# $1 List file to process
# Returns:
# None
# Regex:
# ||
# Group 1: IPv4 address optional
# Group 2: Site A-Z, a-z, 0-9, -, . one or more
# Group 3: ^ | / | $ once
# Group 4: $third-party | $popup | $popup,third-party
#--------------------------------------------------------------------
function process_easylist() {
local i=0
local j=0
CalculatePercentPoint "$1"
i=1 #Progress counter
j=$JumpPoint #Jump in percent
while IFS=$'\n' read -r Line
do
if [[ $Line =~ ^\|\|([[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3})?([A-Za-z0-9\.\-]+)(\^|\/|$)(\$third-party|\$popup|\$popup\,third\-party)?$ ]]; then
addsite "${BASH_REMATCH[2]}" ""
fi
if [ $i -ge $PercentPoint ]; then #Display progress