Compare commits

...

180 Commits

Author SHA1 Message Date
DL6ER
4922ed2aeb Recommend to disable logging to pihole.log on new installs/during reconfigure.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-07-10 19:05:00 +02:00
Mark Drobnak
5a6763f90d Merge pull request #2833 from bcambl/fedora30_tests
Fedora 30 tests
2019-07-06 19:27:02 -04:00
bcambl
218476fab0 ensure installation dependencies for FTL tests which rely on /etc/init.d
Signed-off-by: bcambl <blayne@blaynecampbell.com>
2019-07-06 11:06:08 -06:00
bcambl
ec850dc820 add chkconfig to INSTALLER_DEPS (CentOS/Fedora)
chkconfig is a dependency of spawn-fcgi which is a dependency of lighttpd which is installed via PIHOLE_WEB_DEPS in phase 2
adding chkconfig to INSTALLER_DEPS to ensure /etc/init.d is present during the installation prompts (phase 1)

Signed-off-by: bcambl <blayne@blaynecampbell.com>
2019-07-06 10:58:19 -06:00
bcambl
c48b03584f update Fedora Dockerfile to 30
Signed-off-by: bcambl <blayne@blaynecampbell.com>
2019-07-06 10:57:57 -06:00
Mark Drobnak
6bb213e56f Merge pull request #2826 from Forceflow/development
Fix for 404 error when browsing to pi.hole (without /admin)
2019-07-05 17:18:50 -04:00
Mark Drobnak
92c3c86be4 Merge pull request #2769 from pi-hole/new/arp-flush
Add new "pihole arpflush" command
2019-07-04 14:00:16 -04:00
Mark Drobnak
ada8b53423 Merge pull request #2803 from pi-hole/new/gravity.db_domain_groups
Implement groups for lists
2019-07-04 13:52:52 -04:00
DL6ER
7a1b6fd205 Merge branch 'development' into new/gravity.db_domain_groups 2019-07-03 19:21:55 +02:00
DL6ER
b78cbb98d8 Merge pull request #2830 from mmotti/fix/regexp_query
Fix potential invalid result for pihole -q
2019-07-03 19:16:04 +02:00
MMotti
04abcb71f6 Fix potential invalid result for pihole -q
Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-07-03 13:04:57 +01:00
DL6ER
1fe3507bc5 Adlists table was renamed to Adlist. Adapt further places in the code to match the new name.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-07-03 07:56:10 +02:00
Jeroen Baert
9fedafed15 Fix 404 error when browsing to pi.hole (without /admin) (for fedora)
Signed-off-by: Jeroen Baert <3607063+Forceflow@users.noreply.github.com>
2019-07-03 04:28:44 +02:00
DL6ER
23b3a9a650 Add DISTINCT to the view\'s SELECT queries to avoid domain duplication in case they are enabled in multiple groups at the same time.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-07-01 09:44:20 +02:00
Jeroen Baert
7b2ac25a52 Fix for 404 error when browsing to pi.hole (without /admin)
Signed-off-by: Jeroen Baert <3607063+Forceflow@users.noreply.github.com>
2019-07-01 03:42:02 +02:00
DL6ER
f91421418a Rename adlists -> adlist table.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-30 23:21:10 +02:00
DL6ER
3a14e8b013 Check whitelist_by_group.group_id instead of group.enabled against NULL.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-30 23:20:13 +02:00
DL6ER
ad97e95f2f Add required name column in group table.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-30 23:06:15 +02:00
DL6ER
5b01facd73 Fix logix on the views: AND ( OR )
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-30 20:03:22 +02:00
DL6ER
6fe637b9ee Rename groups -> group
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-30 19:43:18 +02:00
DL6ER
94d83dbb2d Unify the two group tables into a single "groups" table. This allows managing adlists and domains together.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-30 19:33:02 +02:00
Mark Drobnak
c9a843b417 Merge pull request #2823 from pi-hole/fix/lighttpd-mime
Update with v4.3.1 changes
2019-06-30 13:27:55 -04:00
Mark Drobnak
b986c5585d Merge pull request #2822 from akurth/development
Fix pihole manpage to match code.
2019-06-30 13:11:20 -04:00
DL6ER
87c115fc86 Change implementation to use linking tables (domain_groups, adlists_groups). This allows adding domains to multiple lists conveniently.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-30 19:04:38 +02:00
Andreas Kurth
acee97916e Fix pihole manpage to match code.
The dry-run argument to pihole -up is "--check-only", not "--checkonly".

Signed-off-by: Andreas Kurth <github@akurth.de>
2019-06-30 08:02:51 +02:00
Mark Drobnak
06134d3ffc Merge pull request #2817 from pi-hole/tweak/gravity_db_timeout
Add timeout to sqlite3 command
2019-06-27 17:34:34 -04:00
Mark Drobnak
092957c14a Merge pull request #2808 from pi-hole/fix/uninstall
Fix uninstall causing 403 errors and not removing packages
2019-06-27 12:51:07 -04:00
DL6ER
d5e8f1a781 Add 10 seconds timeout to the sqlite3 command that writes tables to the gravity database. This prevents gravity from failing when the database file is locked for a short time.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-26 18:20:36 +02:00
Mcat12
974bba4a45 Fix PKG_REMOVE array usage
Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-06-17 16:30:26 -07:00
Mcat12
951732fc1b Use an array for PKG_REMOVE
Fixes shellcheck warning.

Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-06-17 16:28:55 -07:00
Mcat12
b6700924b2 Fix uninstall causing 403 errors and not removing packages
The 403 lighttpd errors were caused by removing the lighttpd config
directory and not removing lighttpd itself. This caused a subsequent
Pi-hole reinstall to not have all of the required lighttpd config files.

The error while removing packages was caused by combining arguments into
a string instead of listing each argument.

Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-06-17 16:13:31 -07:00
DL6ER
5d43639e93 Merge branch 'development' into new/arp-flush 2019-06-16 20:21:03 +02:00
DL6ER
27e4208631 Merge branch 'development' into new/gravity.db_domain_groups 2019-06-16 20:20:27 +02:00
DL6ER
b505ad22e6 Merge pull request #2806 from pi-hole/fix/fedora-ci-tests
Pin the Fedora test docker container to 29
2019-06-16 20:19:44 +02:00
Mcat12
d67122dffc Pin the Fedora test docker container to 29
The tests are currently failing due to a change in Fedora 30, which we
are not currently supporting.

Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-06-16 11:13:23 -07:00
DL6ER
0774c4e5ca vw_gravity should actually filter using vw_whitelist.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-16 18:52:23 +02:00
DL6ER
01850c2128 Automatically recreate standard group after deletion to avoid violating foreign key constraints even if foreign key enforcing is disabled (SQLite's default behavior)
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-16 17:15:36 +02:00
DL6ER
cbc210b014 Add adlist_groups and mark group_id columns as NOT NULL.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-16 17:05:33 +02:00
DL6ER
c53ee4202b Add filtering by domain groups to gravity database.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-16 16:50:51 +02:00
DL6ER
f2be12f97b Merge pull request #2796 from pi-hole/tweak/opendns-ipv6
Use the filtered IPv6 OpenDNS servers
2019-06-16 14:56:00 +02:00
DL6ER
6996ffa451 Also flush network_addresses table
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-15 09:15:12 +02:00
DL6ER
435a5fb3ad Add pihole arpflush to man page.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-15 09:12:44 +02:00
DL6ER
4947350ca5 Add arpflush to help and bash autocompletion
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-06-15 09:08:33 +02:00
DL6ER
c1495b0fa8 Merge branch 'development' into new/arp-flush 2019-06-15 09:04:30 +02:00
Mark Drobnak
67dda9c8bb Merge pull request #2790 from mmotti/tidy/query
Small changes to regexp querying
2019-06-13 20:32:42 -04:00
Mcat12
c8987e20c2 Use the filtered IPv6 OpenDNS servers
The ones we were using previously were not filtered. See
https://support.opendns.com/hc/en-us/articles/227986667-Does-OpenDNS-Support-IPv6-

Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-06-12 19:13:29 -07:00
MMotti
bcf03647ef Add comment and remove blankspace
Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-06-12 16:02:59 +01:00
MMotti
a9d0690f4d Change the case of some variables
Just for consistency

Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-06-10 18:50:52 +01:00
MMotti
10fbed50f3 Shellcheck
Suggesting to use parameter expansion but we need to be able to identify the start of each line

Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-06-10 18:10:25 +01:00
MMotti
785f1fedd9 Tidy regexp queries
Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-06-10 17:52:58 +01:00
Mark Drobnak
b0c5dcf42f Merge pull request #2780 from mmotti/fix/regexp_query
Fix for regexp queries through pihole -q
2019-06-05 13:19:39 -04:00
MMotti
cf21efa103 Minor grammar changes
Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-06-05 14:36:43 +01:00
MMotti
7613e94ef6 Minor tweaks
Mainly for consistency

Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-06-04 06:06:17 +01:00
MMotti
b49c702f33 Consistency tweak
Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-06-04 00:03:37 +01:00
MMotti
09532638d5 Read from DB instead of regex.list
Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-06-04 00:00:25 +01:00
MMotti
97df6d7415 Stickler fix
Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-06-03 19:56:10 +01:00
MMotti
54bfaa28c1 Fix for regexp queries through pihole -q
Taking inspiration from: https://github.com/pi-hole/pi-hole/pull/2346

We will use awk to iterate through each regexp and print any that match the domain query.

Signed-off-by: MMotti <matthew.w.motti@gmail.com>
2019-06-03 19:32:59 +01:00
Mark Drobnak
afd28fab03 Merge pull request #2767 from pi-hole/fix/multiple_pihole-FTL_PIDs
Improve PID detection in pihole-FTL.service
2019-06-01 01:03:55 -04:00
Mark Drobnak
d92ced6fb6 Merge pull request #2734 from pi-hole/fix/query_black_and_whitelists_database
Query black and whitelists database
2019-06-01 00:55:05 -04:00
DL6ER
ae98fde321 Try to obtain PID from PIDFILE. If this fails (file does not exist or is empty), fall back to using pidof + awk
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-31 09:18:12 +02:00
DL6ER
9ddce88092 Review comments
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-31 08:42:22 +02:00
DL6ER
44f8fcb600 We can print the table name without any extra check as we already returned early in case there are no results.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-31 08:39:18 +02:00
Mark Drobnak
814fdcf9b6 Merge pull request #2768 from pi-hole/fix/dhcp-ignore-names
Add dhcp-ignore-names option when enabling DHCP service
2019-05-30 22:35:52 -04:00
DL6ER
5060605626 Print table name before entering the loop for the sake of simplicity
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-30 21:44:59 +02:00
DL6ER
453ba14cbd Merge pull request #2758 from pi-hole/fix/debug-log-gravity-database
Update debug script with gravity DB changes
2019-05-30 21:37:49 +02:00
DL6ER
285e6fe090 Address lint complaints
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-30 21:32:35 +02:00
DL6ER
c3023fe681 Add new "pihole arpflush" command to flush both the ARP cache as well as the network table in pihole-FTL.db
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-30 21:25:10 +02:00
DL6ER
c5df104a66 Add dhcp-ignore-names option when enabling DHCP service. We currently remove anything that starts with "dhcp-" to have a clean configuration and removed these lines without noticing when enabling the DHCP server.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-30 16:41:37 +02:00
DL6ER
f6213d4f4d Use last PID in case pidof returns multiple PIDs for pihole-FTL
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-30 15:26:27 +02:00
Mark Drobnak
ca2ea388b7 Merge pull request #2763 from chrisys/development
Handle an empty local.list
2019-05-27 16:06:25 -04:00
Chris Crocker-White
69dba022c4 Handle an empty local.list
Handle the case of an empty local.list file which would otherwise prevent the system from starting

Change-type: patch
Signed-off-by: Chris Crocker-White <chriscw@balena.io>
2019-05-27 10:27:28 -07:00
Mcat12
bfb99c361c Note that the gravity size does not include the blacklist entries
Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-05-21 17:12:47 -07:00
Mcat12
5796054305 Increase ID column width to 4
Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-05-20 21:59:18 -07:00
Mcat12
a3e1473ac1 Set explicit column widths to prevent text from getting cut off
Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-05-20 21:33:09 -07:00
Mcat12
7b5fc60e00 Improve table formatting
Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-05-20 21:20:38 -07:00
Mcat12
807ce0af4e Show whitelist, blacklist, and regexlist details
Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-05-20 21:15:22 -07:00
Mcat12
3f05efd60f Add extra newline
Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-05-20 21:02:31 -07:00
Mcat12
03d93aa19a Update debug script with gravity DB changes
Signed-off-by: Mcat12 <newtoncat12@yahoo.com>
2019-05-20 20:58:57 -07:00
DL6ER
cad9386ff6 Merge pull request #2750 from pi-hole/release/v4.3
Update Dev with v4.3 fixes
2019-05-19 19:42:29 +02:00
Dan Schaper
7de6bbca61 Merge branch 'development' into release/v4.3 2019-05-18 13:18:14 -07:00
Mark Drobnak
c8d32e0dd3 Merge pull request #2743 from haguenau/fix/shellcheck-install-script
Clean up basic install script
2019-05-16 23:22:01 -04:00
David Haguenauer
be3a21ae07 Put quotes at ends of strings
Signed-off-by: David Haguenauer <ml@kurokatta.org>
2019-05-14 15:20:28 -04:00
David Haguenauer
69081a9175 Drop indirection from install_dependent_packages
Previously, install_dependent_packages would receive an array variable
name as its single parameter, and would use variable indirection to
access it; this change simplifies that function so that it instead
receives the expanded array.

Signed-off-by: David Haguenauer <ml@kurokatta.org>
2019-05-14 15:20:28 -04:00
David Haguenauer
ab2f8a0c09 Quote variables in basic-install.sh
This greatly reduces the number of warnings emitted by ShellCheck, and
in turn should make it more likely that errors are caught in the
future.

Signed-off-by: David Haguenauer <ml@kurokatta.org>
2019-05-14 15:20:28 -04:00
Mark Drobnak
b961a501bb Merge pull request #2611 from pi-hole/new/gravitydb
Store blocking domains in a database
2019-05-12 18:46:47 -04:00
Mcat12
8e1bf6e3d4 Merge branch 'development' into new/gravitydb
# Conflicts:
#	advanced/Scripts/list.sh
#	gravity.sh
#	pihole
2019-05-12 15:20:52 -07:00
Mark Drobnak
d6756eb46b Merge pull request #2730 from pvogt09/development
Adds world readable attribute to files created by Pi-hole to circumve…
2019-05-12 15:44:20 -04:00
pvogt09
efbd42f7b5 Moves creation of pihole user before FTL installation
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-12 11:27:25 +02:00
pvogt09
3f90261520 Moves chmod after every creation of ${destination} instead of end of function
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-12 11:25:48 +02:00
pvogt09
225285cb97 Removes chmod for ${source} and superfluous chmod for ${destination}
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-11 11:14:07 +02:00
pvogt09
e076db5a4e Changes ownership of macvendor.db to pihole
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-10 11:19:28 +02:00
pvogt09
a3d2a1062f Makes blocklists world readable
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-10 11:13:19 +02:00
pvogt09
2e6198077d chmod 644 adlists.list
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-09 12:23:44 +02:00
pvogt09
4d23b3267f Adds X to chmod for git operations
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-07 10:46:16 +02:00
pvogt09
e19adccd9c Moves chmod for /var/www/html into INSTALL_WEB_SERVER block
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-05 22:34:13 +02:00
pvogt09
a25f331e83 Adds chmod 644 for /var/www and /var/www/html
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-05 09:20:49 +02:00
pvogt09
69c06ba6fe Sets permissions for dnsmaq.conf
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-05 00:32:10 +02:00
DL6ER
a904c183df Use printf to escape domain content. This prevents possible SQL injection issues
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-04 18:25:11 +02:00
DL6ER
5246b3e496 Explicitly escape backslash in ESCAPE clause. This has been suggested by Stickler bot.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-04 13:24:36 +02:00
DL6ER
f80fdd7e83 Improve comments
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-04 13:19:50 +02:00
DL6ER
6ba58896d2 Simplify code
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-04 13:15:30 +02:00
DL6ER
3aa838bbe4 Implement black- and whitelist searching with SQL statements. We use the ESCAPE clause in the LIKE query as the underscore "_" wildcard matches any single character but we want to suppress this behavior (underscores can be legitimate part of domains)
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-04 13:02:14 +02:00
pvogt09
2c3a27e9c7 Replaces cp chmod with install and add read permission to repository files after checkout and pull
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-03 12:27:56 +02:00
DL6ER
0bc112ce52 Query only those columns we actually use when showing domains on the CLI. Show date of last modification instead of addition date for domains.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-02 17:11:39 +02:00
DL6ER
d46ff1d2d7 Remove UNIQUE on gravity table as the only column is already PRIMARY KEY. Primary keys must contain UNIQUE values, and cannot contain NULL values
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 22:08:30 +02:00
DL6ER
0cfecd31d3 Invert logic to reduce nesting
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 22:07:14 +02:00
DL6ER
008e88b84b Only migrate legacy list files when we create gravity.db in the same gravity run
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 18:04:31 +02:00
DL6ER
2f698904e4 Use PRIMARY KEY instead of NOT NULL also in gravity and info tables
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 18:03:35 +02:00
DL6ER
106f079afc Improve indentation (single tab) in SQLite template
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 17:57:23 +02:00
DL6ER
6c1e3a17f7 Remove NOT NULL constraint on list ids as this is implied by PRIMARY KEY (even though most, if not all, examples on the web still use both attributes at the same time)
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 17:54:29 +02:00
DL6ER
540c57f755 Add comment for automigrated list entries
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 17:51:25 +02:00
DL6ER
5e26e8245b Order results of queries to list views by id key
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 17:51:10 +02:00
DL6ER
983117d788 Add id (primary key, autoincrement) field to lists tables
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 17:47:15 +02:00
DL6ER
b372f808dd Fix lint errors
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 17:06:14 +02:00
DL6ER
bc9b623638 Modify query.sh to use the gravity database
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 16:56:16 +02:00
DL6ER
d5781fb110 Fix extra space in front on END statement in CREATE TRIGGER commands
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 16:38:41 +02:00
DL6ER
487718512d Remove DISTINCT attribute from views. They are not needed as the corresponding data is obtained from fields with UNIQUE attribute so duplications are already prevented at domain insertion. The elimination of the duplication check on imort through the views slightly reduces the load during import (I observed about 8 percent time saved on my NanoPi NEO).
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-05-01 16:37:23 +02:00
pvogt09
8a92fb24c4 Incorporates changes requested by @Mcat12
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-05-01 11:20:26 +02:00
pvogt09
5c575e73c7 Adds world readable attribute to files created by Pi-hole to circumvent #2724
Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com>
2019-04-30 22:41:12 +02:00
DL6ER
2180531a84 Add trigger for automatic updates of the date_modified column and improve formating in the gravity.db template
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-29 19:43:35 +02:00
DL6ER
a932209143 Set default for date_modified to be the current time
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-29 17:21:59 +02:00
DL6ER
4946b5907b Move migrated files to backup directory instead of deleting them. This has the benefit that gravity.db can be recreated at any time by: 1. deleting gravity.db, 2. copying all files from the migration_backup directory back to /etc/pihole, 3. running pihole -g again.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-28 22:15:47 +02:00
DL6ER
efeba594ae Add support for manipulating adlists from the CLI
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-28 21:39:06 +02:00
DL6ER
5e1241acd2 Merge branch 'new/gravitydb' of github.com:pi-hole/pi-hole into new/gravitydb 2019-04-28 14:44:34 +02:00
DL6ER
126f7101ff Add (optional) date_modified field and use vw_whitelist view in vw_blacklist
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-28 14:44:03 +02:00
Mark Drobnak
4596d9a577 Merge branch 'development' into new/gravitydb 2019-04-26 23:40:28 -04:00
DL6ER
b4ae142149 Remove printf escaping (we will realize it differently) and ensure we're using single quotes for strings (although double quotes are possible, too)
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 20:54:01 +02:00
DL6ER
3fe43ce1d9 Rely on default value (database provided) for date_added when adding a new domain
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 18:16:04 +02:00
DL6ER
8524aecfed Don't set gravity database permissions
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 17:56:11 +02:00
DL6ER
e04dc9d2bb Remove sqlitekey variable as the first column of the regex table is now called domain as well
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 17:44:42 +02:00
DL6ER
3dcb9722d3 Remove global haveSourceUrls variable and just skip downloading and processing adlists if there aren't any to be downloaded
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 17:39:35 +02:00
DL6ER
bd0215524b Add vw_adlists view which returns only enabled adlists
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 17:36:00 +02:00
DL6ER
53e3ff2b24 Only add non-empty lines when moving file content into database tables
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 17:32:05 +02:00
DL6ER
5bb8163674 Change type of whitelist, blacklist, regex, and adlists time column to INTEGER and insert a DEFAULT clause that returns the current Unix time as such an integer
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 17:26:15 +02:00
DL6ER
a891d64395 We should always exit after displaying a list, even if it is empty
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 17:13:36 +02:00
DL6ER
6b1d2523e8 Also print datetime a domain was added when listing the domains on the CLI
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 17:07:16 +02:00
DL6ER
08ee9526ad Review comments
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 17:06:01 +02:00
DL6ER
0efc46260f Use both old and new strings for detecting whether this is a Pi-hole dnsmasq config file
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-26 16:16:30 +02:00
DL6ER
6a01a1257f Merge pull request #2597 from xCh12i5/RegEx-Fix
Solves RegEx issue.
2019-04-25 15:27:35 +02:00
DL6ER
a2a7e80007 Add --web for sending a confirmation string when executed from the web interface. This is necessary as the "Reloading DNS service" message does not always propagate through to the web interface when reloading pihole-FTL takes a while.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-25 15:01:13 +02:00
DL6ER
cce66a13b6 Fix output in list.sh when adding a domain that is already present in the target list
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-25 14:54:41 +02:00
DL6ER
43bced7997 Add more comments
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-25 12:45:08 +02:00
DL6ER
788cd78321 Reduce code duplication and add special handling of | character as it might appear in regex filter string
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-25 12:30:38 +02:00
DL6ER
e5d1cb5a2e Rewrite list.sh to operate on database-based lists
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-25 12:10:42 +02:00
DL6ER
d94bbfca7f Finish migrating gravity.db to using our new gravity database. This removes the --skip-download, --blacklist-only, --whitelist-only, and --wildcard-only options as it is not necessary to run gravity when modifying them from now on (gravity really only builds the gravity database and the local.list file).
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-25 11:23:06 +02:00
DL6ER
465a39427b Source adlists from gravity database
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-25 10:46:18 +02:00
DL6ER
2664ac0efc Improve error reporting
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-25 10:18:37 +02:00
DL6ER
c1277705d8 Copy existing whitelist.txt, blacklist.txt, regex.list, and adlists.list to the database. We remove the files afterwards as the content lives in the database now
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-25 10:14:45 +02:00
DL6ER
61cfd2f9f9 Add adlists table
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-24 19:48:06 +02:00
DL6ER
ee4dabeca6 Merge branch 'development' into new/gravitydb
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-24 19:12:19 +02:00
DL6ER
e57d0fb93c Remove the empty templates gravity.list, white.list, black.list. The old source files whitelist.txt, blacklist.txt, and regex.list still exist and need to be removed in a follow-up commit
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-24 19:05:08 +02:00
DL6ER
ee20164207 Remove detect_pihole_blocking_status() as we can modify the database at any time
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-24 19:01:31 +02:00
DL6ER
d7ee44960e Remove moving around of the gravity and blacklist files as we do not use them any longer
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-24 18:57:38 +02:00
DL6ER
c13ebd3a9d Replace Pi-hole ID string with another line we intend to keep
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-24 18:55:25 +02:00
DL6ER
6594a0a6e7 Fix detection of blocked query in pihole -t
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-24 18:53:20 +02:00
DL6ER
de44563301 Remove addn-hosts from 01-pihole.conf
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-04-24 18:51:38 +02:00
Dan Schaper
54ae9d83b0 Stickler-lints
Signed-off-by: Dan Schaper <dan.schaper@pi-hole.net>
2019-02-23 13:42:15 -08:00
DL6ER
0e14d11a20 Merge branch 'development' into new/gravitydb 2019-02-22 23:06:17 +01:00
DL6ER
bbc392caeb More review comments
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-22 22:49:02 +01:00
DL6ER
61840edb30 Fill comment field with NULL (default) instead of empty string and use a variable for the timestamp instead of periodically calling date
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-22 22:46:19 +01:00
DL6ER
f9250d91a5 Explictly escape the escape.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-06 19:17:13 +01:00
DL6ER
491c828661 Improved code, ensure that gravity.sh passes shellcheck as a whole
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-06 19:09:09 +01:00
DL6ER
644ec36e64 Review comments
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-06 18:57:48 +01:00
DL6ER
9984647ebb After renaming column in regex, it also needs to be renamed in vw_regex
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-05 19:41:11 +01:00
DL6ER
ec5b16ef85 Fix incomplete comment
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-05 19:08:08 +01:00
DL6ER
c3c60e10f1 Rename regex field from domain to filter because this described better what it is
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-05 19:07:12 +01:00
DL6ER
8a2363621d Rename fields from DateAdded to dateadded
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-05 19:06:46 +01:00
DL6ER
dbbf21071b Invert logic to use ENABLED instead of DISABLED. We make sure to set "enabled = 1 WHERE enabled IS NULL" in gravity_store_in_database()
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-05 19:05:11 +01:00
DL6ER
b2f4385232 Avoid infinity loop if gravity optimization fails
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-03 17:05:00 +01:00
DL6ER
1f9a7d0b0c Only run VACUUM on "pihole -g -o"
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-03 17:01:38 +01:00
DL6ER
d5feffa117 Do not backup the database
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-03 16:45:19 +01:00
DL6ER
fc62cf7e2f Only run VACUUM on "full" gravity runs
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-03 16:45:06 +01:00
DL6ER
93f1859bab Store regex in gravity.db as well
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-03 15:13:18 +01:00
DL6ER
dcf0a605cf Use views for all tables and set disabled column to false for those tables that support it
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-03 14:14:14 +01:00
DL6ER
710036adae Add DISABLED field to white- and blacklist defaulting to false. The two views respect the DISABLED fields for both lists.
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-03 13:34:08 +01:00
DL6ER
8a91fe6992 Store domains in gravit tables: gravity, whitelist, blacklist
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-03 13:21:26 +01:00
DL6ER
09c4c88a6d Create and fill gravity.db during pihole -g
Signed-off-by: DL6ER <dl6er@dl6er.de>
2019-02-03 13:04:31 +01:00
xch12i5
cd8a423b32 Solves RegEx issue and updates documentation.
Signed-off-by: xch12i5 <40517505+xCh12i5@users.noreply.github.com>
2019-01-20 16:09:25 +01:00
xch12i5
e02da90faa Replaces double quotes by single quotes and updates documentation.
Signed-off-by: xch12i5 <40517505+xCh12i5@users.noreply.github.com>
2019-01-19 17:52:28 +01:00
xch12i5
0de5132e2b Solves RegEx issue.
Signed-off-by: xch12i5 <40517505+xCh12i5@users.noreply.github.com>
2019-01-19 17:07:27 +01:00
21 changed files with 884 additions and 575 deletions

View File

@@ -18,8 +18,6 @@
# WITHIN /etc/dnsmasq.d/yourname.conf #
###############################################################################
addn-hosts=/etc/pihole/gravity.list
addn-hosts=/etc/pihole/black.list
addn-hosts=/etc/pihole/local.list
domain-needed
@@ -43,8 +41,3 @@ log-facility=/var/log/pihole.log
local-ttl=2
log-async
# If a DHCP client claims that its name is "wpad", ignore that.
# This fixes a security hole. see CERT Vulnerability VU#598349
dhcp-name-match=set:wpad-ignore,wpad
dhcp-ignore-names=tag:wpad-ignore

View File

@@ -11,46 +11,45 @@
# Globals
basename=pihole
piholeDir=/etc/"${basename}"
whitelist="${piholeDir}"/whitelist.txt
blacklist="${piholeDir}"/blacklist.txt
gravityDBfile="${piholeDir}/gravity.db"
readonly regexlist="/etc/pihole/regex.list"
reload=false
addmode=true
verbose=true
wildcard=false
web=false
domList=()
listMain=""
listAlt=""
listType=""
listname=""
colfile="/opt/pihole/COL_TABLE"
source ${colfile}
helpFunc() {
if [[ "${listMain}" == "${whitelist}" ]]; then
if [[ "${listType}" == "whitelist" ]]; then
param="w"
type="white"
elif [[ "${listMain}" == "${regexlist}" && "${wildcard}" == true ]]; then
type="whitelist"
elif [[ "${listType}" == "regex" && "${wildcard}" == true ]]; then
param="-wild"
type="wildcard black"
elif [[ "${listMain}" == "${regexlist}" ]]; then
type="wildcard blacklist"
elif [[ "${listType}" == "regex" ]]; then
param="-regex"
type="regex black"
type="regex filter"
else
param="b"
type="black"
type="blacklist"
fi
echo "Usage: pihole -${param} [options] <domain> <domain2 ...>
Example: 'pihole -${param} site.com', or 'pihole -${param} site1.com site2.com'
${type^}list one or more domains
${type^} one or more domains
Options:
-d, --delmode Remove domain(s) from the ${type}list
-nr, --noreload Update ${type}list without refreshing dnsmasq
-d, --delmode Remove domain(s) from the ${type}
-nr, --noreload Update ${type} without reloading the DNS server
-q, --quiet Make output less verbose
-h, --help Show this help dialog
-l, --list Display all your ${type}listed domains
@@ -73,7 +72,7 @@ HandleOther() {
# Check validity of domain (don't check for regex entries)
if [[ "${#domain}" -le 253 ]]; then
if [[ "${listMain}" == "${regexlist}" && "${wildcard}" == false ]]; then
if [[ "${listType}" == "regex" && "${wildcard}" == false ]]; then
validDomain="${domain}"
else
validDomain=$(grep -P "^((-|_)*[a-z\\d]((-|_)*[a-z\\d])*(-|_)*)(\\.(-|_)*([a-z\\d]((-|_)*[a-z\\d])*))*$" <<< "${domain}") # Valid chars check
@@ -88,175 +87,143 @@ HandleOther() {
fi
}
PoplistFile() {
# Check whitelist file exists, and if not, create it
if [[ ! -f "${whitelist}" ]]; then
touch "${whitelist}"
fi
# Check blacklist file exists, and if not, create it
if [[ ! -f "${blacklist}" ]]; then
touch "${blacklist}"
ProcessDomainList() {
if [[ "${listType}" == "regex" ]]; then
# Regex filter list
listname="regex filters"
else
# Whitelist / Blacklist
listname="${listType}"
fi
for dom in "${domList[@]}"; do
# Logic: If addmode then add to desired list and remove from the other; if delmode then remove from desired list but do not add to the other
# Format domain into regex filter if requested
if [[ "${wildcard}" == true ]]; then
dom="(^|\\.)${dom//\./\\.}$"
fi
# Logic: If addmode then add to desired list and remove from the other;
# if delmode then remove from desired list but do not add to the other
if ${addmode}; then
AddDomain "${dom}" "${listMain}"
RemoveDomain "${dom}" "${listAlt}"
AddDomain "${dom}" "${listType}"
if [[ ! "${listType}" == "regex" ]]; then
RemoveDomain "${dom}" "${listAlt}"
fi
else
RemoveDomain "${dom}" "${listMain}"
RemoveDomain "${dom}" "${listType}"
fi
done
}
AddDomain() {
local domain list num
# Use printf to escape domain. %q prints the argument in a form that can be reused as shell input
domain="$1"
list="$2"
domain=$(EscapeRegexp "$1")
[[ "${list}" == "${whitelist}" ]] && listname="whitelist"
[[ "${list}" == "${blacklist}" ]] && listname="blacklist"
# Is the domain in the list we want to add it to?
num="$(sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM ${list} WHERE domain = '${domain}';")"
if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then
[[ "${list}" == "${whitelist}" && -z "${type}" ]] && type="--whitelist-only"
[[ "${list}" == "${blacklist}" && -z "${type}" ]] && type="--blacklist-only"
bool=true
# Is the domain in the list we want to add it to?
grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == false ]]; then
# Domain not found in the whitelist file, add it!
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} Adding ${1} to ${listname}..."
fi
reload=true
# Add it to the list we want to add it to
echo "$1" >> "${list}"
else
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${1} already exists in ${listname}, no need to add!"
fi
fi
elif [[ "${list}" == "${regexlist}" ]]; then
[[ -z "${type}" ]] && type="--wildcard-only"
bool=true
domain="${1}"
[[ "${wildcard}" == true ]] && domain="(^|\\.)${domain//\./\\.}$"
# Is the domain in the list?
# Search only for exactly matching lines
grep -Fx "${domain}" "${regexlist}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == false ]]; then
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} Adding ${domain} to regex list..."
fi
reload="restart"
echo "$domain" >> "${regexlist}"
else
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${domain} already exists in regex list, no need to add!"
fi
fi
if [[ "${num}" -ne 0 ]]; then
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${1} already exists in ${listname}, no need to add!"
fi
return
fi
# Domain not found in the table, add it!
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} Adding ${1} to the ${listname}..."
fi
reload=true
# Insert only the domain here. The enabled and date_added fields will be filled
# with their default values (enabled = true, date_added = current timestamp)
sqlite3 "${gravityDBfile}" "INSERT INTO ${list} (domain) VALUES ('${domain}');"
}
RemoveDomain() {
local domain list num
# Use printf to escape domain. %q prints the argument in a form that can be reused as shell input
domain="$1"
list="$2"
domain=$(EscapeRegexp "$1")
[[ "${list}" == "${whitelist}" ]] && listname="whitelist"
[[ "${list}" == "${blacklist}" ]] && listname="blacklist"
# Is the domain in the list we want to remove it from?
num="$(sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM ${list} WHERE domain = '${domain}';")"
if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then
bool=true
[[ "${list}" == "${whitelist}" && -z "${type}" ]] && type="--whitelist-only"
[[ "${list}" == "${blacklist}" && -z "${type}" ]] && type="--blacklist-only"
# Is it in the list? Logic follows that if its whitelisted it should not be blacklisted and vice versa
grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == true ]]; then
# Remove it from the other one
echo -e " ${INFO} Removing $1 from ${listname}..."
# /I flag: search case-insensitive
sed -i "/${domain}/Id" "${list}"
reload=true
else
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${1} does not exist in ${listname}, no need to remove!"
fi
fi
elif [[ "${list}" == "${regexlist}" ]]; then
[[ -z "${type}" ]] && type="--wildcard-only"
domain="${1}"
[[ "${wildcard}" == true ]] && domain="(^|\\.)${domain//\./\\.}$"
bool=true
# Is it in the list?
grep -Fx "${domain}" "${regexlist}" > /dev/null 2>&1 || bool=false
if [[ "${bool}" == true ]]; then
# Remove it from the other one
echo -e " ${INFO} Removing $domain from regex list..."
local lineNumber
lineNumber=$(grep -Fnx "$domain" "${list}" | cut -f1 -d:)
sed -i "${lineNumber}d" "${list}"
reload=true
else
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${domain} does not exist in regex list, no need to remove!"
fi
fi
if [[ "${num}" -eq 0 ]]; then
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} ${1} does not exist in ${list}, no need to remove!"
fi
return
fi
}
# Update Gravity
Reload() {
echo ""
pihole -g --skip-download "${type:-}"
# Domain found in the table, remove it!
if [[ "${verbose}" == true ]]; then
echo -e " ${INFO} Removing ${1} from the ${listname}..."
fi
reload=true
# Remove it from the current list
sqlite3 "${gravityDBfile}" "DELETE FROM ${list} WHERE domain = '${domain}';"
}
Displaylist() {
if [[ -f ${listMain} ]]; then
if [[ "${listMain}" == "${whitelist}" ]]; then
string="gravity resistant domains"
else
string="domains caught in the sinkhole"
fi
verbose=false
echo -e "Displaying $string:\n"
count=1
while IFS= read -r RD || [ -n "${RD}" ]; do
echo " ${count}: ${RD}"
count=$((count+1))
done < "${listMain}"
local list listname count num_pipes domain enabled status nicedate
listname="${listType}"
data="$(sqlite3 "${gravityDBfile}" "SELECT domain,enabled,date_modified FROM ${listType};" 2> /dev/null)"
if [[ -z $data ]]; then
echo -e "Not showing empty ${listname}"
else
echo -e " ${COL_LIGHT_RED}${listMain} does not exist!${COL_NC}"
echo -e "Displaying ${listname}:"
count=1
while IFS= read -r line
do
# Count number of pipes seen in this line
# This is necessary because we can only detect the pipe separating the fields
# from the end backwards as the domain (which is the first field) may contain
# pipe symbols as they are perfectly valid regex filter control characters
num_pipes="$(grep -c "^" <<< "$(grep -o "|" <<< "${line}")")"
# Extract domain and enabled status based on the obtained number of pipe characters
domain="$(cut -d'|' -f"-$((num_pipes-1))" <<< "${line}")"
enabled="$(cut -d'|' -f"$((num_pipes))" <<< "${line}")"
datemod="$(cut -d'|' -f"$((num_pipes+1))" <<< "${line}")"
# Translate boolean status into human readable string
if [[ "${enabled}" -eq 1 ]]; then
status="enabled"
else
status="disabled"
fi
# Get nice representation of numerical date stored in database
nicedate=$(date --rfc-2822 -d "@${datemod}")
echo " ${count}: ${domain} (${status}, last modified ${nicedate})"
count=$((count+1))
done <<< "${data}"
fi
exit 0;
}
NukeList() {
if [[ -f "${listMain}" ]]; then
# Back up original list
cp "${listMain}" "${listMain}.bck~"
# Empty out file
echo "" > "${listMain}"
fi
sqlite3 "${gravityDBfile}" "DELETE FROM ${listType};"
}
for var in "$@"; do
case "${var}" in
"-w" | "whitelist" ) listMain="${whitelist}"; listAlt="${blacklist}";;
"-b" | "blacklist" ) listMain="${blacklist}"; listAlt="${whitelist}";;
"--wild" | "wildcard" ) listMain="${regexlist}"; wildcard=true;;
"--regex" | "regex" ) listMain="${regexlist}";;
"-w" | "whitelist" ) listType="whitelist"; listAlt="blacklist";;
"-b" | "blacklist" ) listType="blacklist"; listAlt="whitelist";;
"--wild" | "wildcard" ) listType="regex"; wildcard=true;;
"--regex" | "regex" ) listType="regex";;
"-nr"| "--noreload" ) reload=false;;
"-d" | "--delmode" ) addmode=false;;
"-q" | "--quiet" ) verbose=false;;
"-h" | "--help" ) helpFunc;;
"-l" | "--list" ) Displaylist;;
"--nuke" ) NukeList;;
"--web" ) web=true;;
* ) HandleOther "${var}";;
esac
done
@@ -267,9 +234,13 @@ if [[ $# = 0 ]]; then
helpFunc
fi
PoplistFile
ProcessDomainList
# Used on web interface
if $web; then
echo "DONE"
fi
if [[ "${reload}" != false ]]; then
# Ensure that "restart" is used for Wildcard updates
Reload "${reload}"
pihole restartdns reload
fi

View File

@@ -0,0 +1,73 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090
# Pi-hole: A black hole for Internet advertisements
# (c) 2019 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware.
#
# ARP table interaction
#
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
coltable="/opt/pihole/COL_TABLE"
if [[ -f ${coltable} ]]; then
source ${coltable}
fi
# Determine database location
# Obtain DBFILE=... setting from pihole-FTL.db
# Constructed to return nothing when
# a) the setting is not present in the config file, or
# b) the setting is commented out (e.g. "#DBFILE=...")
FTLconf="/etc/pihole/pihole-FTL.conf"
if [ -e "$FTLconf" ]; then
DBFILE="$(sed -n -e 's/^\s*DBFILE\s*=\s*//p' ${FTLconf})"
fi
# Test for empty string. Use standard path in this case.
if [ -z "$DBFILE" ]; then
DBFILE="/etc/pihole/pihole-FTL.db"
fi
flushARP(){
local output
if [[ "${args[1]}" != "quiet" ]]; then
echo -ne " ${INFO} Flushing network table ..."
fi
# Flush ARP cache to avoid re-adding of dead entries
if ! output=$(ip neigh flush all 2>&1); then
echo -e "${OVER} ${CROSS} Failed to clear ARP cache"
echo " Output: ${output}"
return 1
fi
# Truncate network_addresses table in pihole-FTL.db
# This needs to be done before we can truncate the network table due to
# foreign key contraints
if ! output=$(sqlite3 "${DBFILE}" "DELETE FROM network_addresses" 2>&1); then
echo -e "${OVER} ${CROSS} Failed to truncate network_addresses table"
echo " Database location: ${DBFILE}"
echo " Output: ${output}"
return 1
fi
# Truncate network table in pihole-FTL.db
if ! output=$(sqlite3 "${DBFILE}" "DELETE FROM network" 2>&1); then
echo -e "${OVER} ${CROSS} Failed to truncate network table"
echo " Database location: ${DBFILE}"
echo " Output: ${output}"
return 1
fi
if [[ "${args[1]}" != "quiet" ]]; then
echo -e "${OVER} ${TICK} Flushed network table"
fi
}
args=("$@")
case "${args[0]}" in
"arpflush" ) flushARP;;
esac

View File

@@ -90,6 +90,7 @@ checkout() {
local path
path="development/${binary}"
echo "development" > /etc/pihole/ftlbranch
chmod 644 /etc/pihole/ftlbranch
elif [[ "${1}" == "master" ]] ; then
# Shortcut to check out master branches
echo -e " ${INFO} Shortcut \"master\" detected - checking out master branches..."
@@ -104,6 +105,7 @@ checkout() {
local path
path="master/${binary}"
echo "master" > /etc/pihole/ftlbranch
chmod 644 /etc/pihole/ftlbranch
elif [[ "${1}" == "core" ]] ; then
str="Fetching branches from ${piholeGitUrl}"
echo -ne " ${INFO} $str"
@@ -166,6 +168,7 @@ checkout() {
if check_download_exists "$path"; then
echo " ${TICK} Branch ${2} exists"
echo "${2}" > /etc/pihole/ftlbranch
chmod 644 /etc/pihole/ftlbranch
FTLinstall "${binary}"
restart_service pihole-FTL
enable_service pihole-FTL

View File

@@ -89,16 +89,12 @@ PIHOLE_WILDCARD_CONFIG_FILE="${DNSMASQ_D_DIRECTORY}/03-wildcard.conf"
WEB_SERVER_CONFIG_FILE="${WEB_SERVER_CONFIG_DIRECTORY}/lighttpd.conf"
#WEB_SERVER_CUSTOM_CONFIG_FILE="${WEB_SERVER_CONFIG_DIRECTORY}/external.conf"
PIHOLE_DEFAULT_AD_LISTS="${PIHOLE_DIRECTORY}/adlists.default"
PIHOLE_USER_DEFINED_AD_LISTS="${PIHOLE_DIRECTORY}/adlists.list"
PIHOLE_BLACKLIST_FILE="${PIHOLE_DIRECTORY}/blacklist.txt"
PIHOLE_BLOCKLIST_FILE="${PIHOLE_DIRECTORY}/gravity.list"
PIHOLE_INSTALL_LOG_FILE="${PIHOLE_DIRECTORY}/install.log"
PIHOLE_RAW_BLOCKLIST_FILES="${PIHOLE_DIRECTORY}/list.*"
PIHOLE_LOCAL_HOSTS_FILE="${PIHOLE_DIRECTORY}/local.list"
PIHOLE_LOGROTATE_FILE="${PIHOLE_DIRECTORY}/logrotate"
PIHOLE_SETUP_VARS_FILE="${PIHOLE_DIRECTORY}/setupVars.conf"
PIHOLE_WHITELIST_FILE="${PIHOLE_DIRECTORY}/whitelist.txt"
PIHOLE_GRAVITY_DB_FILE="${PIHOLE_DIRECTORY}/gravity.db"
PIHOLE_COMMAND="${BIN_DIRECTORY}/pihole"
PIHOLE_COLTABLE_FILE="${BIN_DIRECTORY}/COL_TABLE"
@@ -142,16 +138,11 @@ REQUIRED_FILES=("${PIHOLE_CRON_FILE}"
"${PIHOLE_DHCP_CONFIG_FILE}"
"${PIHOLE_WILDCARD_CONFIG_FILE}"
"${WEB_SERVER_CONFIG_FILE}"
"${PIHOLE_DEFAULT_AD_LISTS}"
"${PIHOLE_USER_DEFINED_AD_LISTS}"
"${PIHOLE_BLACKLIST_FILE}"
"${PIHOLE_BLOCKLIST_FILE}"
"${PIHOLE_INSTALL_LOG_FILE}"
"${PIHOLE_RAW_BLOCKLIST_FILES}"
"${PIHOLE_LOCAL_HOSTS_FILE}"
"${PIHOLE_LOGROTATE_FILE}"
"${PIHOLE_SETUP_VARS_FILE}"
"${PIHOLE_WHITELIST_FILE}"
"${PIHOLE_COMMAND}"
"${PIHOLE_COLTABLE_FILE}"
"${FTL_PID}"
@@ -793,7 +784,7 @@ dig_at() {
# This helps emulate queries to different domains that a user might query
# It will also give extra assurance that Pi-hole is correctly resolving and blocking domains
local random_url
random_url=$(shuf -n 1 "${PIHOLE_BLOCKLIST_FILE}")
random_url=$(sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" "SELECT domain FROM vw_gravity ORDER BY RANDOM() LIMIT 1")
# First, do a dig on localhost to see if Pi-hole can use itself to block a domain
if local_dig=$(dig +tries=1 +time=2 -"${protocol}" "${random_url}" @${local_address} +short "${record_type}"); then
@@ -975,8 +966,7 @@ list_files_in_dir() {
if [[ -d "${dir_to_parse}/${each_file}" ]]; then
# If it's a directoy, do nothing
:
elif [[ "${dir_to_parse}/${each_file}" == "${PIHOLE_BLOCKLIST_FILE}" ]] || \
[[ "${dir_to_parse}/${each_file}" == "${PIHOLE_DEBUG_LOG}" ]] || \
elif [[ "${dir_to_parse}/${each_file}" == "${PIHOLE_DEBUG_LOG}" ]] || \
[[ "${dir_to_parse}/${each_file}" == "${PIHOLE_RAW_BLOCKLIST_FILES}" ]] || \
[[ "${dir_to_parse}/${each_file}" == "${PIHOLE_INSTALL_LOG_FILE}" ]] || \
[[ "${dir_to_parse}/${each_file}" == "${PIHOLE_SETUP_VARS_FILE}" ]] || \
@@ -1061,31 +1051,70 @@ head_tail_log() {
IFS="$OLD_IFS"
}
analyze_gravity_list() {
echo_current_diagnostic "Gravity list"
local head_line
local tail_line
# Put the current Internal Field Separator into another variable so it can be restored later
show_db_entries() {
local title="${1}"
local query="${2}"
local widths="${3}"
echo_current_diagnostic "${title}"
OLD_IFS="$IFS"
# Get the lines that are in the file(s) and store them in an array for parsing later
IFS=$'\r\n'
local entries=()
mapfile -t entries < <(\
sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" \
-cmd ".headers on" \
-cmd ".mode column" \
-cmd ".width ${widths}" \
"${query}"\
)
for line in "${entries[@]}"; do
log_write " ${line}"
done
IFS="$OLD_IFS"
}
show_adlists() {
show_db_entries "Adlists" "SELECT * FROM adlist" "4 100 7 10 13 50"
}
show_whitelist() {
show_db_entries "Whitelist" "SELECT * FROM whitelist" "4 100 7 10 13 50"
}
show_blacklist() {
show_db_entries "Blacklist" "SELECT * FROM blacklist" "4 100 7 10 13 50"
}
show_regexlist() {
show_db_entries "Regexlist" "SELECT * FROM regex" "4 100 7 10 13 50"
}
analyze_gravity_list() {
echo_current_diagnostic "Gravity List and Database"
local gravity_permissions
gravity_permissions=$(ls -ld "${PIHOLE_BLOCKLIST_FILE}")
gravity_permissions=$(ls -ld "${PIHOLE_GRAVITY_DB_FILE}")
log_write "${COL_GREEN}${gravity_permissions}${COL_NC}"
local gravity_head=()
mapfile -t gravity_head < <(head -n 4 ${PIHOLE_BLOCKLIST_FILE})
log_write " ${COL_CYAN}-----head of $(basename ${PIHOLE_BLOCKLIST_FILE})------${COL_NC}"
for head_line in "${gravity_head[@]}"; do
log_write " ${head_line}"
done
local gravity_size
gravity_size=$(sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" "SELECT COUNT(*) FROM vw_gravity")
log_write " Size (excluding blacklist): ${COL_CYAN}${gravity_size}${COL_NC} entries"
log_write ""
local gravity_tail=()
mapfile -t gravity_tail < <(tail -n 4 ${PIHOLE_BLOCKLIST_FILE})
log_write " ${COL_CYAN}-----tail of $(basename ${PIHOLE_BLOCKLIST_FILE})------${COL_NC}"
for tail_line in "${gravity_tail[@]}"; do
log_write " ${tail_line}"
OLD_IFS="$IFS"
IFS=$'\r\n'
local gravity_sample=()
mapfile -t gravity_sample < <(sqlite3 "${PIHOLE_GRAVITY_DB_FILE}" "SELECT domain FROM vw_gravity LIMIT 10")
log_write " ${COL_CYAN}----- First 10 Domains -----${COL_NC}"
for line in "${gravity_sample[@]}"; do
log_write " ${line}"
done
# Set the IFS back to what it was
log_write ""
IFS="$OLD_IFS"
}
@@ -1236,6 +1265,10 @@ process_status
parse_setup_vars
check_x_headers
analyze_gravity_list
show_adlists
show_whitelist
show_blacklist
show_regexlist
show_content_of_pihole_files
parse_locale
analyze_pihole_log

View File

@@ -39,8 +39,9 @@ if [[ "$@" == *"once"* ]]; then
# Note that moving the file is not an option, as
# dnsmasq would happily continue writing into the
# moved file (it will have the same file handler)
cp /var/log/pihole.log /var/log/pihole.log.1
cp -p /var/log/pihole.log /var/log/pihole.log.1
echo " " > /var/log/pihole.log
chmod 644 /var/log/pihole.log
fi
else
# Manual flushing
@@ -53,6 +54,7 @@ else
echo " " > /var/log/pihole.log
if [ -f /var/log/pihole.log.1 ]; then
echo " " > /var/log/pihole.log.1
chmod 644 /var/log/pihole.log.1
fi
fi
# Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history)

145
advanced/Scripts/query.sh Normal file → Executable file
View File

@@ -11,8 +11,7 @@
# Globals
piholeDir="/etc/pihole"
adListsList="$piholeDir/adlists.list"
wildcardlist="/etc/dnsmasq.d/03-pihole-wildcard.conf"
gravityDBfile="${piholeDir}/gravity.db"
options="$*"
adlist=""
all=""
@@ -23,27 +22,10 @@ matchType="match"
colfile="/opt/pihole/COL_TABLE"
source "${colfile}"
# Print each subdomain
# e.g: foo.bar.baz.com = "foo.bar.baz.com bar.baz.com baz.com com"
processWildcards() {
IFS="." read -r -a array <<< "${1}"
for (( i=${#array[@]}-1; i>=0; i-- )); do
ar=""
for (( j=${#array[@]}-1; j>${#array[@]}-i-2; j-- )); do
if [[ $j == $((${#array[@]}-1)) ]]; then
ar="${array[$j]}"
else
ar="${array[$j]}.${ar}"
fi
done
echo "${ar}"
done
}
# Scan an array of files for matching strings
scanList(){
# Escape full stops
local domain="${1//./\\.}" lists="${2}" type="${3:-}"
local domain="${1}" esc_domain="${1//./\\.}" lists="${2}" type="${3:-}"
# Prevent grep from printing file path
cd "$piholeDir" || exit 1
@@ -54,9 +36,14 @@ scanList(){
# /dev/null forces filename to be printed when only one list has been generated
# shellcheck disable=SC2086
case "${type}" in
"exact" ) grep -i -E -l "(^|(?<!#)\\s)${domain}($|\\s|#)" ${lists} /dev/null 2>/dev/null;;
"wc" ) grep -i -o -m 1 "/${domain}/" ${lists} 2>/dev/null;;
* ) grep -i "${domain}" ${lists} /dev/null 2>/dev/null;;
"exact" ) grep -i -E -l "(^|(?<!#)\\s)${esc_domain}($|\\s|#)" ${lists} /dev/null 2>/dev/null;;
# Create array of regexps
# Iterate through each regexp and check whether it matches the domainQuery
# If it does, print the matching regexp and continue looping
# Input 1 - regexps | Input 2 - domainQuery
"regex" ) awk 'NR==FNR{regexps[$0];next}{for (r in regexps)if($0 ~ r)print r}' \
<(echo "${lists}") <(echo "${domain}") 2>/dev/null;;
* ) grep -i "${esc_domain}" ${lists} /dev/null 2>/dev/null;;
esac
}
@@ -73,11 +60,6 @@ Options:
exit 0
fi
if [[ ! -e "$adListsList" ]]; then
echo -e "${COL_LIGHT_RED}The file $adListsList was not found${COL_NC}"
exit 1
fi
# Handle valid options
if [[ "${options}" == *"-bp"* ]]; then
exact="exact"; blockpage=true
@@ -107,48 +89,80 @@ if [[ -n "${str:-}" ]]; then
exit 1
fi
# Scan Whitelist and Blacklist
lists="whitelist.txt blacklist.txt"
mapfile -t results <<< "$(scanList "${domainQuery}" "${lists}" "${exact}")"
if [[ -n "${results[*]}" ]]; then
scanDatabaseTable() {
local domain table type querystr result
domain="$(printf "%q" "${1}")"
table="${2}"
type="${3:-}"
# As underscores are legitimate parts of domains, we escape them when using the LIKE operator.
# Underscores are SQLite wildcards matching exactly one character. We obviously want to suppress this
# behavior. The "ESCAPE '\'" clause specifies that an underscore preceded by an '\' should be matched
# as a literal underscore character. We pretreat the $domain variable accordingly to escape underscores.
case "${type}" in
"exact" ) querystr="SELECT domain FROM vw_${table} WHERE domain = '${domain}'";;
* ) querystr="SELECT domain FROM vw_${table} WHERE domain LIKE '%${domain//_/\\_}%' ESCAPE '\\'";;
esac
# Send prepared query to gravity database
result="$(sqlite3 "${gravityDBfile}" "${querystr}")" 2> /dev/null
if [[ -z "${result}" ]]; then
# Return early when there are no matches in this table
return
fi
# Mark domain as having been white-/blacklist matched (global variable)
wbMatch=true
# Loop through each result in order to print unique file title once
# Print table name
echo " ${matchType^} found in ${COL_BOLD}${table^}${COL_NC}"
# Loop over results and print them
mapfile -t results <<< "${result}"
for result in "${results[@]}"; do
fileName="${result%%.*}"
if [[ -n "${blockpage}" ]]; then
echo "π ${result}"
exit 0
elif [[ -n "${exact}" ]]; then
echo " ${matchType^} found in ${COL_BOLD}${fileName^}${COL_NC}"
else
# Only print filename title once per file
if [[ ! "${fileName}" == "${fileName_prev:-}" ]]; then
echo " ${matchType^} found in ${COL_BOLD}${fileName^}${COL_NC}"
fileName_prev="${fileName}"
fi
echo " ${result#*:}"
fi
echo " ${result}"
done
fi
}
# Scan Wildcards
if [[ -e "${wildcardlist}" ]]; then
# Determine all subdomains, domain and TLDs
mapfile -t wildcards <<< "$(processWildcards "${domainQuery}")"
for match in "${wildcards[@]}"; do
# Search wildcard list for matches
mapfile -t results <<< "$(scanList "${match}" "${wildcardlist}" "wc")"
if [[ -n "${results[*]}" ]]; then
if [[ -z "${wcMatch:-}" ]] && [[ -z "${blockpage}" ]]; then
wcMatch=true
echo " ${matchType^} found in ${COL_BOLD}Wildcards${COL_NC}:"
fi
case "${blockpage}" in
true ) echo "π ${wildcardlist##*/}"; exit 0;;
* ) echo " *.${match}";;
esac
fi
done
# Scan Whitelist and Blacklist
scanDatabaseTable "${domainQuery}" "whitelist" "${exact}"
scanDatabaseTable "${domainQuery}" "blacklist" "${exact}"
# Scan Regex table
mapfile -t regexList < <(sqlite3 "${gravityDBfile}" "SELECT domain FROM vw_regex" 2> /dev/null)
# If we have regexps to process
if [[ "${#regexList[@]}" -ne 0 ]]; then
# Split regexps over a new line
str_regexList=$(printf '%s\n' "${regexList[@]}")
# Check domainQuery against regexps
mapfile -t regexMatches < <(scanList "${domainQuery}" "${str_regexList}" "regex")
# If there were regex matches
if [[ "${#regexMatches[@]}" -ne 0 ]]; then
# Split matching regexps over a new line
str_regexMatches=$(printf '%s\n' "${regexMatches[@]}")
# Form a "matched" message
str_message="${matchType^} found in ${COL_BOLD}Regex list${COL_NC}"
# Form a "results" message
str_result="${COL_BOLD}${str_regexMatches}${COL_NC}"
# If we are displaying more than just the source of the block
if [[ -z "${blockpage}" ]]; then
# Set the wildcard match flag
wcMatch=true
# Echo the "matched" message, indented by one space
echo " ${str_message}"
# Echo the "results" message, each line indented by three spaces
# shellcheck disable=SC2001
echo "${str_result}" | sed 's/^/ /'
else
echo "π Regex list"
exit 0
fi
fi
fi
# Get version sorted *.domains filenames (without dir path)
@@ -186,11 +200,8 @@ fi
# Get adlist file content as array
if [[ -n "${adlist}" ]] || [[ -n "${blockpage}" ]]; then
for adlistUrl in $(< "${adListsList}"); do
if [[ "${adlistUrl:0:4}" =~ (http|www.) ]]; then
adlists+=("${adlistUrl}")
fi
done
# Retrieve source URLs from gravity database
mapfile -t adlists <<< "$(sqlite3 "${gravityDBfile}" "SELECT address FROM vw_adlist;" 2> /dev/null)"
fi
# Print "Exact matches for" title

View File

@@ -51,6 +51,7 @@ if [[ "$2" == "remote" ]]; then
GITHUB_CORE_VERSION="$(json_extract tag_name "$(curl -s 'https://api.github.com/repos/pi-hole/pi-hole/releases/latest' 2> /dev/null)")"
echo -n "${GITHUB_CORE_VERSION}" > "${GITHUB_VERSION_FILE}"
chmod 644 "${GITHUB_VERSION_FILE}"
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
GITHUB_WEB_VERSION="$(json_extract tag_name "$(curl -s 'https://api.github.com/repos/pi-hole/AdminLTE/releases/latest' 2> /dev/null)")"
@@ -66,6 +67,7 @@ else
CORE_BRANCH="$(get_local_branch /etc/.pihole)"
echo -n "${CORE_BRANCH}" > "${LOCAL_BRANCH_FILE}"
chmod 644 "${LOCAL_BRANCH_FILE}"
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
WEB_BRANCH="$(get_local_branch /var/www/html/admin)"
@@ -79,6 +81,7 @@ else
CORE_VERSION="$(get_local_version /etc/.pihole)"
echo -n "${CORE_VERSION}" > "${LOCAL_VERSION_FILE}"
chmod 644 "${LOCAL_VERSION_FILE}"
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
WEB_VERSION="$(get_local_version /var/www/html/admin)"

View File

@@ -17,6 +17,8 @@ readonly FTLconf="/etc/pihole/pihole-FTL.conf"
# 03 -> wildcards
readonly dhcpstaticconfig="/etc/dnsmasq.d/04-pihole-static-dhcp.conf"
readonly gravityDBfile="/etc/pihole/gravity.db"
coltable="/opt/pihole/COL_TABLE"
if [[ -f ${coltable} ]]; then
source ${coltable}
@@ -322,6 +324,7 @@ dhcp-option=option:router,${DHCP_ROUTER}
dhcp-leasefile=/etc/pihole/dhcp.leases
#quiet-dhcp
" > "${dhcpconfig}"
chmod 644 "${dhcpconfig}"
if [[ "${PIHOLE_DOMAIN}" != "none" ]]; then
echo "domain=${PIHOLE_DOMAIN}" >> "${dhcpconfig}"
@@ -363,6 +366,14 @@ EnableDHCP() {
delete_dnsmasq_setting "dhcp-"
delete_dnsmasq_setting "quiet-dhcp"
# If a DHCP client claims that its name is "wpad", ignore that.
# This fixes a security hole. see CERT Vulnerability VU#598349
# We also ignore "localhost" as Windows behaves strangely if a
# device claims this host name
add_dnsmasq_setting "dhcp-name-match=set:hostname-ignore,wpad
dhcp-name-match=set:hostname-ignore,localhost
dhcp-ignore-names=tag:hostname-ignore"
ProcessDHCPSettings
RestartDNS
@@ -385,19 +396,17 @@ SetWebUILayout() {
}
CustomizeAdLists() {
list="/etc/pihole/adlists.list"
local address
address="${args[3]}"
if [[ "${args[2]}" == "enable" ]]; then
sed -i "\\@${args[3]}@s/^#http/http/g" "${list}"
sqlite3 "${gravityDBfile}" "UPDATE adlist SET enabled = 1 WHERE address = '${address}'"
elif [[ "${args[2]}" == "disable" ]]; then
sed -i "\\@${args[3]}@s/^http/#http/g" "${list}"
sqlite3 "${gravityDBfile}" "UPDATE adlist SET enabled = 0 WHERE address = '${address}'"
elif [[ "${args[2]}" == "add" ]]; then
if [[ $(grep -c "^${args[3]}$" "${list}") -eq 0 ]] ; then
echo "${args[3]}" >> ${list}
fi
sqlite3 "${gravityDBfile}" "INSERT OR IGNORE INTO adlist (address) VALUES ('${address}')"
elif [[ "${args[2]}" == "del" ]]; then
var=$(echo "${args[3]}" | sed 's/\//\\\//g')
sed -i "/${var}/Id" "${list}"
sqlite3 "${gravityDBfile}" "DELETE FROM adlist WHERE address = '${address}'"
else
echo "Not permitted"
return 1
@@ -541,11 +550,13 @@ addAudit()
do
echo "${var}" >> /etc/pihole/auditlog.list
done
chmod 644 /etc/pihole/auditlog.list
}
clearAudit()
{
echo -n "" > /etc/pihole/auditlog.list
chmod 644 /etc/pihole/auditlog.list
}
SetPrivacyLevel() {

View File

@@ -0,0 +1,142 @@
PRAGMA FOREIGN_KEYS=ON;
CREATE TABLE "group"
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
enabled BOOLEAN NOT NULL DEFAULT 1,
name TEXT NOT NULL,
description TEXT
);
CREATE TABLE whitelist
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
domain TEXT UNIQUE NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT 1,
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
comment TEXT
);
CREATE TABLE whitelist_by_group
(
whitelist_id INTEGER NOT NULL REFERENCES whitelist (id),
group_id INTEGER NOT NULL REFERENCES "group" (id),
PRIMARY KEY (whitelist_id, group_id)
);
CREATE TABLE blacklist
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
domain TEXT UNIQUE NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT 1,
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
comment TEXT
);
CREATE TABLE blacklist_by_group
(
blacklist_id INTEGER NOT NULL REFERENCES blacklist (id),
group_id INTEGER NOT NULL REFERENCES "group" (id),
PRIMARY KEY (blacklist_id, group_id)
);
CREATE TABLE regex
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
domain TEXT UNIQUE NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT 1,
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
comment TEXT
);
CREATE TABLE regex_by_group
(
regex_id INTEGER NOT NULL REFERENCES regex (id),
group_id INTEGER NOT NULL REFERENCES "group" (id),
PRIMARY KEY (regex_id, group_id)
);
CREATE TABLE adlist
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
address TEXT UNIQUE NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT 1,
date_added INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
date_modified INTEGER NOT NULL DEFAULT (cast(strftime('%s', 'now') as int)),
comment TEXT
);
CREATE TABLE adlist_by_group
(
adlist_id INTEGER NOT NULL REFERENCES adlist (id),
group_id INTEGER NOT NULL REFERENCES "group" (id),
PRIMARY KEY (adlist_id, group_id)
);
CREATE TABLE gravity
(
domain TEXT PRIMARY KEY
);
CREATE TABLE info
(
property TEXT PRIMARY KEY,
value TEXT NOT NULL
);
INSERT INTO info VALUES("version","1");
CREATE VIEW vw_gravity AS SELECT domain
FROM gravity
WHERE domain NOT IN (SELECT domain from vw_whitelist);
CREATE VIEW vw_whitelist AS SELECT DISTINCT domain
FROM whitelist
LEFT JOIN whitelist_by_group ON whitelist_by_group.whitelist_id = whitelist.id
LEFT JOIN "group" ON "group".id = whitelist_by_group.group_id
WHERE whitelist.enabled = 1 AND (whitelist_by_group.group_id IS NULL OR "group".enabled = 1)
ORDER BY whitelist.id;
CREATE TRIGGER tr_whitelist_update AFTER UPDATE ON whitelist
BEGIN
UPDATE whitelist SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE domain = NEW.domain;
END;
CREATE VIEW vw_blacklist AS SELECT DISTINCT domain
FROM blacklist
LEFT JOIN blacklist_by_group ON blacklist_by_group.blacklist_id = blacklist.id
LEFT JOIN "group" ON "group".id = blacklist_by_group.group_id
WHERE blacklist.enabled = 1 AND (blacklist_by_group.group_id IS NULL OR "group".enabled = 1)
ORDER BY blacklist.id;
CREATE TRIGGER tr_blacklist_update AFTER UPDATE ON blacklist
BEGIN
UPDATE blacklist SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE domain = NEW.domain;
END;
CREATE VIEW vw_regex AS SELECT DISTINCT domain
FROM regex
LEFT JOIN regex_by_group ON regex_by_group.regex_id = regex.id
LEFT JOIN "group" ON "group".id = regex_by_group.group_id
WHERE regex.enabled = 1 AND (regex_by_group.group_id IS NULL OR "group".enabled = 1)
ORDER BY regex.id;
CREATE TRIGGER tr_regex_update AFTER UPDATE ON regex
BEGIN
UPDATE regex SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE domain = NEW.domain;
END;
CREATE VIEW vw_adlist AS SELECT DISTINCT address
FROM adlist
LEFT JOIN adlist_by_group ON adlist_by_group.adlist_id = adlist.id
LEFT JOIN "group" ON "group".id = adlist_by_group.group_id
WHERE adlist.enabled = 1 AND (adlist_by_group.group_id IS NULL OR "group".enabled = 1)
ORDER BY adlist.id;
CREATE TRIGGER tr_adlist_update AFTER UPDATE ON adlist
BEGIN
UPDATE adlist SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE address = NEW.address;
END;

View File

@@ -13,7 +13,14 @@ FTLUSER=pihole
PIDFILE=/var/run/pihole-FTL.pid
get_pid() {
pidof "pihole-FTL"
# First, try to obtain PID from PIDFILE
if [ -s "${PIDFILE}" ]; then
cat "${PIDFILE}"
return
fi
# If the PIDFILE is empty or not available, obtain the PID using pidof
pidof "pihole-FTL" | awk '{print $(NF)}'
}
is_running() {

View File

@@ -7,7 +7,7 @@ _pihole() {
case "${prev}" in
"pihole")
opts="admin blacklist checkout chronometer debug disable enable flush help logging query reconfigure regex restartdns status tail uninstall updateGravity updatePihole version wildcard whitelist"
opts="admin blacklist checkout chronometer debug disable enable flush help logging query reconfigure regex restartdns status tail uninstall updateGravity updatePihole version wildcard whitelist arpflush"
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
;;
"whitelist"|"blacklist"|"wildcard"|"regex")

View File

@@ -27,7 +27,7 @@ server.modules = (
)
server.document-root = "/var/www/html"
server.error-handler-404 = "pihole/index.php"
server.error-handler-404 = "/pihole/index.php"
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
server.errorlog = "/var/log/lighttpd/error.log"
server.pid-file = "/var/run/lighttpd.pid"

View File

@@ -28,7 +28,7 @@ server.modules = (
)
server.document-root = "/var/www/html"
server.error-handler-404 = "pihole/index.php"
server.error-handler-404 = "/pihole/index.php"
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
server.errorlog = "/var/log/lighttpd/error.log"
server.pid-file = "/var/run/lighttpd.pid"

View File

@@ -31,7 +31,7 @@ set -e
# List of supported DNS servers
DNS_SERVERS=$(cat << EOM
Google (ECS);8.8.8.8;8.8.4.4;2001:4860:4860:0:0:0:0:8888;2001:4860:4860:0:0:0:0:8844
OpenDNS (ECS);208.67.222.222;208.67.220.220;2620:0:ccc::2;2620:0:ccd::2
OpenDNS (ECS);208.67.222.222;208.67.220.220;2620:119:35::35;2620:119:53::53
Level3;4.2.2.1;4.2.2.2;;
Comodo;8.26.56.26;8.20.247.20;;
DNS.WATCH;84.200.69.80;84.200.70.40;2001:1608:10:25:0:0:1c04:b12f;2001:1608:10:25:0:0:9249:d69b
@@ -74,8 +74,8 @@ regexFile="/etc/pihole/regex.list"
# this script can run
IPV4_ADDRESS=""
IPV6_ADDRESS=""
# By default, query logging is enabled and the dashboard is set to be installed
QUERY_LOGGING=true
# By default, query logging is disabled and the dashboard is set to be installed
QUERY_LOGGING=false
INSTALL_WEB_INTERFACE=true
PRIVACY_LEVEL=0
@@ -118,7 +118,7 @@ done
# If the color table file exists,
if [[ -f "${coltable}" ]]; then
# source it
source ${coltable}
source "${coltable}"
# Otherwise,
else
# Set these values so the installer can still run in color
@@ -182,26 +182,26 @@ if is_command apt-get ; then
# A variable to store the command used to update the package cache
UPDATE_PKG_CACHE="${PKG_MANAGER} update"
# An array for something...
PKG_INSTALL=(${PKG_MANAGER} --yes --no-install-recommends install)
PKG_INSTALL=("${PKG_MANAGER}" --yes --no-install-recommends install)
# grep -c will return 1 retVal on 0 matches, block this throwing the set -e with an OR TRUE
PKG_COUNT="${PKG_MANAGER} -s -o Debug::NoLocking=true upgrade | grep -c ^Inst || true"
# Some distros vary slightly so these fixes for dependencies may apply
# on Ubuntu 18.04.1 LTS we need to add the universe repository to gain access to dialog and dhcpcd5
APT_SOURCES="/etc/apt/sources.list"
if awk 'BEGIN{a=1;b=0}/bionic main/{a=0}/bionic.*universe/{b=1}END{exit a + b}' ${APT_SOURCES}; then
if ! whiptail --defaultno --title "Dependencies Require Update to Allowed Repositories" --yesno "Would you like to enable 'universe' repository?\\n\\nThis repository is required by the following packages:\\n\\n- dhcpcd5\\n- dialog" ${r} ${c}; then
if ! whiptail --defaultno --title "Dependencies Require Update to Allowed Repositories" --yesno "Would you like to enable 'universe' repository?\\n\\nThis repository is required by the following packages:\\n\\n- dhcpcd5\\n- dialog" "${r}" "${c}"; then
printf " %b Aborting installation: dependencies could not be installed.\\n" "${CROSS}"
exit # exit the installer
else
printf " %b Enabling universe package repository for Ubuntu Bionic\\n" "${INFO}"
cp ${APT_SOURCES} ${APT_SOURCES}.backup # Backup current repo list
cp -p ${APT_SOURCES} ${APT_SOURCES}.backup # Backup current repo list
printf " %b Backed up current configuration to %s\\n" "${TICK}" "${APT_SOURCES}.backup"
add-apt-repository universe
printf " %b Enabled %s\\n" "${TICK}" "'universe' repository"
fi
fi
# Debian 7 doesn't have iproute2 so if the dry run install is successful,
if ${PKG_MANAGER} install --dry-run iproute2 > /dev/null 2>&1; then
if "${PKG_MANAGER}" install --dry-run iproute2 > /dev/null 2>&1; then
# we can install it
iproute_pkg="iproute2"
# Otherwise,
@@ -222,7 +222,7 @@ if is_command apt-get ; then
# Check if installed php is v 7.0, or newer to determine packages to install
if [[ "$phpInsNewer" != true ]]; then
# Prefer the php metapackage if it's there
if ${PKG_MANAGER} install --dry-run php > /dev/null 2>&1; then
if "${PKG_MANAGER}" install --dry-run php > /dev/null 2>&1; then
phpVer="php"
# fall back on the php5 packages
else
@@ -233,19 +233,19 @@ if is_command apt-get ; then
phpVer="php$phpInsMajor.$phpInsMinor"
fi
# We also need the correct version for `php-sqlite` (which differs across distros)
if ${PKG_MANAGER} install --dry-run ${phpVer}-sqlite3 > /dev/null 2>&1; then
if "${PKG_MANAGER}" install --dry-run "${phpVer}-sqlite3" > /dev/null 2>&1; then
phpSqlite="sqlite3"
else
phpSqlite="sqlite"
fi
# Since our install script is so large, we need several other programs to successfully get a machine provisioned
# These programs are stored in an array so they can be looped through later
INSTALLER_DEPS=(apt-utils dialog debconf dhcpcd5 git ${iproute_pkg} whiptail)
INSTALLER_DEPS=(apt-utils dialog debconf dhcpcd5 git "${iproute_pkg}" whiptail)
# Pi-hole itself has several dependencies that also need to be installed
PIHOLE_DEPS=(cron curl dnsutils iputils-ping lsof netcat psmisc sudo unzip wget idn2 sqlite3 libcap2-bin dns-root-data resolvconf libcap2)
# The Web dashboard has some that also need to be installed
# It's useful to separate the two since our repos are also setup as "Core" code and "Web" code
PIHOLE_WEB_DEPS=(lighttpd ${phpVer}-common ${phpVer}-cgi ${phpVer}-${phpSqlite})
PIHOLE_WEB_DEPS=(lighttpd "${phpVer}-common" "${phpVer}-cgi" "${phpVer}-${phpSqlite}")
# The Web server user,
LIGHTTPD_USER="www-data"
# group,
@@ -281,9 +281,9 @@ elif is_command rpm ; then
# Fedora and family update cache on every PKG_INSTALL call, no need for a separate update.
UPDATE_PKG_CACHE=":"
PKG_INSTALL=(${PKG_MANAGER} install -y)
PKG_INSTALL=("${PKG_MANAGER}" install -y)
PKG_COUNT="${PKG_MANAGER} check-update | egrep '(.i686|.x86|.noarch|.arm|.src)' | wc -l"
INSTALLER_DEPS=(dialog git iproute newt procps-ng which)
INSTALLER_DEPS=(dialog git iproute newt procps-ng which chkconfig)
PIHOLE_DEPS=(bind-utils cronie curl findutils nmap-ncat sudo unzip wget libidn2 psmisc sqlite libcap)
PIHOLE_WEB_DEPS=(lighttpd lighttpd-fastcgi php-common php-cli php-pdo)
LIGHTTPD_USER="lighttpd"
@@ -319,7 +319,7 @@ elif is_command rpm ; then
# The default php on CentOS 7.x is 5.4 which is EOL
# Check if the version of PHP available via installed repositories is >= to PHP 7
AVAILABLE_PHP_VERSION=$(${PKG_MANAGER} info php | grep -i version | grep -o '[0-9]\+' | head -1)
AVAILABLE_PHP_VERSION=$("${PKG_MANAGER}" info php | grep -i version | grep -o '[0-9]\+' | head -1)
if [[ $AVAILABLE_PHP_VERSION -ge $SUPPORTED_CENTOS_PHP_VERSION ]]; then
# Since PHP 7 is available by default, install via default PHP package names
: # do nothing as PHP is current
@@ -329,7 +329,7 @@ elif is_command rpm ; then
rpm -q ${REMI_PKG} &> /dev/null || rc=$?
if [[ $rc -ne 0 ]]; then
# The PHP version available via default repositories is older than version 7
if ! whiptail --defaultno --title "PHP 7 Update (recommended)" --yesno "PHP 7.x is recommended for both security and language features.\\nWould you like to install PHP7 via Remi's RPM repository?\\n\\nSee: https://rpms.remirepo.net for more information" ${r} ${c}; then
if ! whiptail --defaultno --title "PHP 7 Update (recommended)" --yesno "PHP 7.x is recommended for both security and language features.\\nWould you like to install PHP7 via Remi's RPM repository?\\n\\nSee: https://rpms.remirepo.net for more information" "${r}" "${c}"; then
# User decided to NOT update PHP from REMI, attempt to install the default available PHP version
printf " %b User opt-out of PHP 7 upgrade on CentOS. Deprecated PHP may be in use.\\n" "${INFO}"
: # continue with unsupported php version
@@ -352,7 +352,7 @@ elif is_command rpm ; then
fi
else
# Warn user of unsupported version of Fedora or CentOS
if ! whiptail --defaultno --title "Unsupported RPM based distribution" --yesno "Would you like to continue installation on an unsupported RPM based distribution?\\n\\nPlease ensure the following packages have been installed manually:\\n\\n- lighttpd\\n- lighttpd-fastcgi\\n- PHP version 7+" ${r} ${c}; then
if ! whiptail --defaultno --title "Unsupported RPM based distribution" --yesno "Would you like to continue installation on an unsupported RPM based distribution?\\n\\nPlease ensure the following packages have been installed manually:\\n\\n- lighttpd\\n- lighttpd-fastcgi\\n- PHP version 7+" "${r}" "${c}"; then
printf " %b Aborting installation due to unsupported RPM based distribution\\n" "${CROSS}"
exit # exit the installer
else
@@ -414,6 +414,9 @@ make_repo() {
fi
# Clone the repo and return the return code from this command
git clone -q --depth 20 "${remoteRepo}" "${directory}" &> /dev/null || return $?
# Data in the repositories is public anyway so we can make it readable by everyone (+r to keep executable permission if already set by git)
chmod -R a+rX "${directory}"
# Show a colored message showing it's status
printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
# Always return 0? Not sure this is correct
@@ -447,6 +450,8 @@ update_repo() {
git pull --quiet &> /dev/null || return $?
# Show a completion message
printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
# Data in the repositories is public anyway so we can make it readable by everyone (+r to keep executable permission if already set by git)
chmod -R a+rX "${directory}"
# Move back into the original directory
cd "${curdir}" &> /dev/null || return 1
return 0
@@ -494,6 +499,8 @@ resetRepo() {
printf " %b %s..." "${INFO}" "${str}"
# Use git to remove the local changes
git reset --hard &> /dev/null || return $?
# Data in the repositories is public anyway so we can make it readable by everyone (+r to keep executable permission if already set by git)
chmod -R a+rX "${directory}"
# And show the status
printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
# Returning success anyway?
@@ -537,15 +544,15 @@ get_available_interfaces() {
# A function for displaying the dialogs the user sees when first running the installer
welcomeDialogs() {
# Display the welcome dialog using an appropriately sized window via the calculation conducted earlier in the script
whiptail --msgbox --backtitle "Welcome" --title "Pi-hole automated installer" "\\n\\nThis installer will transform your device into a network-wide ad blocker!" ${r} ${c}
whiptail --msgbox --backtitle "Welcome" --title "Pi-hole automated installer" "\\n\\nThis installer will transform your device into a network-wide ad blocker!" "${r}" "${c}"
# Request that users donate if they enjoy the software since we all work on it in our free time
whiptail --msgbox --backtitle "Plea" --title "Free and open source" "\\n\\nThe Pi-hole is free, but powered by your donations: http://pi-hole.net/donate" ${r} ${c}
whiptail --msgbox --backtitle "Plea" --title "Free and open source" "\\n\\nThe Pi-hole is free, but powered by your donations: http://pi-hole.net/donate" "${r}" "${c}"
# Explain the need for a static address
whiptail --msgbox --backtitle "Initiating network interface" --title "Static IP Needed" "\\n\\nThe Pi-hole is a SERVER so it needs a STATIC IP ADDRESS to function properly.
In the next section, you can choose to use your current network settings (DHCP) or to manually edit them." ${r} ${c}
In the next section, you can choose to use your current network settings (DHCP) or to manually edit them." "${r}" "${c}"
}
# We need to make sure there is enough space before installing, so there is a function to check this
@@ -632,7 +639,7 @@ chooseInterface() {
# Feed the available interfaces into this while loop
done <<< "${availableInterfaces}"
# The whiptail command that will be run, stored in a variable
chooseInterfaceCmd=(whiptail --separate-output --radiolist "Choose An Interface (press space to select)" ${r} ${c} ${interfaceCount})
chooseInterfaceCmd=(whiptail --separate-output --radiolist "Choose An Interface (press space to select)" "${r}" "${c}" "${interfaceCount}")
# Now run the command using the interfaces saved into the array
chooseInterfaceOptions=$("${chooseInterfaceCmd[@]}" "${interfacesArray[@]}" 2>&1 >/dev/tty) || \
# If the user chooses Cancel, exit
@@ -713,7 +720,7 @@ useIPv6dialog() {
# If the IPV6_ADDRESS contains a value
if [[ ! -z "${IPV6_ADDRESS}" ]]; then
# Display that IPv6 is supported and will be used
whiptail --msgbox --backtitle "IPv6..." --title "IPv6 Supported" "$IPV6_ADDRESS will be used to block ads." ${r} ${c}
whiptail --msgbox --backtitle "IPv6..." --title "IPv6 Supported" "$IPV6_ADDRESS will be used to block ads." "${r}" "${c}"
fi
}
@@ -723,7 +730,7 @@ use4andor6() {
local useIPv4
local useIPv6
# Let use select IPv4 and/or IPv6 via a checklist
cmd=(whiptail --separate-output --checklist "Select Protocols (press space to select)" ${r} ${c} 2)
cmd=(whiptail --separate-output --checklist "Select Protocols (press space to select)" "${r}" "${c}" 2)
# In an array, show the options available:
# IPv4 (on by default)
options=(IPv4 "Block ads over IPv4" on
@@ -772,11 +779,11 @@ getStaticIPv4Settings() {
# This is useful for users that are using DHCP reservations; then we can just use the information gathered via our functions
if whiptail --backtitle "Calibrating network interface" --title "Static IP Address" --yesno "Do you want to use your current network settings as a static address?
IP address: ${IPV4_ADDRESS}
Gateway: ${IPv4gw}" ${r} ${c}; then
Gateway: ${IPv4gw}" "${r}" "${c}"; then
# If they choose yes, let the user know that the IP address will not be available via DHCP and may cause a conflict.
whiptail --msgbox --backtitle "IP information" --title "FYI: IP Conflict" "It is possible your router could still try to assign this IP to a device, which would cause a conflict. But in most cases the router is smart enough to not do that.
If you are worried, either manually set the address, or modify the DHCP reservation pool so it does not include the IP you want.
It is also possible to use a DHCP reservation, but if you are going to do that, you might as well set a static address." ${r} ${c}
It is also possible to use a DHCP reservation, but if you are going to do that, you might as well set a static address." "${r}" "${c}"
# Nothing else to do since the variables are already set above
else
# Otherwise, we need to ask the user to input their desired settings.
@@ -785,13 +792,13 @@ It is also possible to use a DHCP reservation, but if you are going to do that,
until [[ "${ipSettingsCorrect}" = True ]]; do
# Ask for the IPv4 address
IPV4_ADDRESS=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 address" --inputbox "Enter your desired IPv4 address" ${r} ${c} "${IPV4_ADDRESS}" 3>&1 1>&2 2>&3) || \
IPV4_ADDRESS=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 address" --inputbox "Enter your desired IPv4 address" "${r}" "${c}" "${IPV4_ADDRESS}" 3>&1 1>&2 2>&3) || \
# Cancelling IPv4 settings window
{ ipSettingsCorrect=False; echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
printf " %b Your static IPv4 address: %s\\n" "${INFO}" "${IPV4_ADDRESS}"
# Ask for the gateway
IPv4gw=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 gateway (router)" --inputbox "Enter your desired IPv4 default gateway" ${r} ${c} "${IPv4gw}" 3>&1 1>&2 2>&3) || \
IPv4gw=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 gateway (router)" --inputbox "Enter your desired IPv4 default gateway" "${r}" "${c}" "${IPv4gw}" 3>&1 1>&2 2>&3) || \
# Cancelling gateway settings window
{ ipSettingsCorrect=False; echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
printf " %b Your static IPv4 gateway: %s\\n" "${INFO}" "${IPv4gw}"
@@ -799,7 +806,7 @@ It is also possible to use a DHCP reservation, but if you are going to do that,
# Give the user a chance to review their settings before moving on
if whiptail --backtitle "Calibrating network interface" --title "Static IP Address" --yesno "Are these settings correct?
IP address: ${IPV4_ADDRESS}
Gateway: ${IPv4gw}" ${r} ${c}; then
Gateway: ${IPv4gw}" "${r}" "${c}"; then
# After that's done, the loop ends and we move on
ipSettingsCorrect=True
else
@@ -847,7 +854,7 @@ setIFCFG() {
# Put the IP in variables without the CIDR notation
printf -v CIDR "%s" "${IPV4_ADDRESS##*/}"
# Backup existing interface configuration:
cp "${IFCFG_FILE}" "${IFCFG_FILE}".pihole.orig
cp -p "${IFCFG_FILE}" "${IFCFG_FILE}".pihole.orig
# Build Interface configuration file using the GLOBAL variables we have
{
echo "# Configured via Pi-hole installer"
@@ -861,6 +868,8 @@ setIFCFG() {
echo "DNS2=$PIHOLE_DNS_2"
echo "USERCTL=no"
}> "${IFCFG_FILE}"
chmod 644 "${IFCFG_FILE}"
chown root:root "${IFCFG_FILE}"
# Use ip to immediately set the new address
ip addr replace dev "${PIHOLE_INTERFACE}" "${IPV4_ADDRESS}"
# If NetworkMangler command line interface exists and ready to mangle,
@@ -925,7 +934,7 @@ valid_ip() {
# and set the new one to a dot (period)
IFS='.'
# Put the IP into an array
ip=(${ip})
ip=("${ip}")
# Restore the IFS to what it was
IFS=${OIFS}
## Evaluate each octet by checking if it's less than or equal to 255 (the max for each octet)
@@ -935,7 +944,7 @@ valid_ip() {
stat=$?
fi
# Return the exit code
return ${stat}
return "${stat}"
}
# A function to choose the upstream DNS provider(s)
@@ -965,7 +974,7 @@ setDNS() {
# Restore the IFS to what it was
IFS=${OIFS}
# In a whiptail dialog, show the options
DNSchoices=$(whiptail --separate-output --menu "Select Upstream DNS Provider. To use your own, select Custom." ${r} ${c} 7 \
DNSchoices=$(whiptail --separate-output --menu "Select Upstream DNS Provider. To use your own, select Custom." "${r}" "${c}" 7 \
"${DNSChooseOptions[@]}" 2>&1 >/dev/tty) || \
# exit if Cancel is selected
{ printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
@@ -995,7 +1004,7 @@ setDNS() {
fi
# Dialog for the user to enter custom upstream servers
piholeDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), separated by a comma.\\n\\nFor example '8.8.8.8, 8.8.4.4'" ${r} ${c} "${prePopulate}" 3>&1 1>&2 2>&3) || \
piholeDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), separated by a comma.\\n\\nFor example '8.8.8.8, 8.8.4.4'" "${r}" "${c}" "${prePopulate}" 3>&1 1>&2 2>&3) || \
{ printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
# Clean user input and replace whitespace with comma.
piholeDNS=$(sed 's/[, \t]\+/,/g' <<< "${piholeDNS}")
@@ -1028,7 +1037,7 @@ setDNS() {
# Otherwise,
else
# Show the settings
if (whiptail --backtitle "Specify Upstream DNS Provider(s)" --title "Upstream DNS Provider(s)" --yesno "Are these settings correct?\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c}); then
if (whiptail --backtitle "Specify Upstream DNS Provider(s)" --title "Upstream DNS Provider(s)" --yesno "Are these settings correct?\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" "${r}" "${c}"); then
# and break from the loop since the servers are valid
DNSSettingsCorrect=True
# Otherwise,
@@ -1067,21 +1076,21 @@ setLogging() {
local LogChoices
# Ask if the user wants to log queries
LogToggleCommand=(whiptail --separate-output --radiolist "Do you want to log queries?" "${r}" "${c}" 6)
# The default selection is on
LogChooseOptions=("On (Recommended)" "" on
Off "" off)
LogToggleCommand=(whiptail --separate-output --radiolist "Do you want to log queries to pihole.log?" "${r}" "${c}" 6)
# The default selection is off to reduce stressing the SD card
LogChooseOptions=("Off (Recommended)" "" on
"On" "" off)
# Get the user's choice
LogChoices=$("${LogToggleCommand[@]}" "${LogChooseOptions[@]}" 2>&1 >/dev/tty) || (printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" && exit 1)
case ${LogChoices} in
# If it's on
"On (Recommended)")
"On")
printf " %b Logging On.\\n" "${INFO}"
# Set the GLOBAL variable to true so we know what they selected
QUERY_LOGGING=true
;;
# Otherwise, it's off,
Off)
"Off (Recommended)")
printf " %b Logging Off.\\n" "${INFO}"
# So set it to false
QUERY_LOGGING=false
@@ -1119,7 +1128,7 @@ setAdminFlag() {
local WebChoices
# Similar to the logging function, ask what the user wants
WebToggleCommand=(whiptail --separate-output --radiolist "Do you wish to install the web admin interface?" ${r} ${c} 6)
WebToggleCommand=(whiptail --separate-output --radiolist "Do you wish to install the web admin interface?" "${r}" "${c}" 6)
# with the default being enabled
WebChooseOptions=("On (Recommended)" "" on
Off "" off)
@@ -1185,6 +1194,7 @@ chooseBlocklists() {
do
appendToListsFile "${choice}"
done
chmod 644 "${adlistFile}"
}
# Accept a string parameter, it must be one of the default lists
@@ -1225,6 +1235,7 @@ version_check_dnsmasq() {
local dnsmasq_conf="/etc/dnsmasq.conf"
local dnsmasq_conf_orig="/etc/dnsmasq.conf.orig"
local dnsmasq_pihole_id_string="addn-hosts=/etc/pihole/gravity.list"
local dnsmasq_pihole_id_string2="# Dnsmasq config for Pi-hole's FTLDNS"
local dnsmasq_original_config="${PI_HOLE_LOCAL_REPO}/advanced/dnsmasq.conf.original"
local dnsmasq_pihole_01_snippet="${PI_HOLE_LOCAL_REPO}/advanced/01-pihole.conf"
local dnsmasq_pihole_01_location="/etc/dnsmasq.d/01-pihole.conf"
@@ -1232,16 +1243,17 @@ version_check_dnsmasq() {
# If the dnsmasq config file exists
if [[ -f "${dnsmasq_conf}" ]]; then
printf " %b Existing dnsmasq.conf found..." "${INFO}"
# If gravity.list is found within this file, we presume it's from older versions on Pi-hole,
if grep -q ${dnsmasq_pihole_id_string} ${dnsmasq_conf}; then
# If a specific string is found within this file, we presume it's from older versions on Pi-hole,
if grep -q "${dnsmasq_pihole_id_string}" "${dnsmasq_conf}" ||
grep -q "${dnsmasq_pihole_id_string2}" "${dnsmasq_conf}"; then
printf " it is from a previous Pi-hole install.\\n"
printf " %b Backing up dnsmasq.conf to dnsmasq.conf.orig..." "${INFO}"
# so backup the original file
mv -f ${dnsmasq_conf} ${dnsmasq_conf_orig}
mv -f "${dnsmasq_conf}" "${dnsmasq_conf_orig}"
printf "%b %b Backing up dnsmasq.conf to dnsmasq.conf.orig...\\n" "${OVER}" "${TICK}"
printf " %b Restoring default dnsmasq.conf..." "${INFO}"
# and replace it with the default
cp ${dnsmasq_original_config} ${dnsmasq_conf}
install -D -m 644 -T "${dnsmasq_original_config}" "${dnsmasq_conf}"
printf "%b %b Restoring default dnsmasq.conf...\\n" "${OVER}" "${TICK}"
# Otherwise,
else
@@ -1252,47 +1264,47 @@ version_check_dnsmasq() {
# If a file cannot be found,
printf " %b No dnsmasq.conf found... restoring default dnsmasq.conf..." "${INFO}"
# restore the default one
cp ${dnsmasq_original_config} ${dnsmasq_conf}
install -D -m 644 -T "${dnsmasq_original_config}" "${dnsmasq_conf}"
printf "%b %b No dnsmasq.conf found... restoring default dnsmasq.conf...\\n" "${OVER}" "${TICK}"
fi
printf " %b Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf..." "${INFO}"
# Check to see if dnsmasq directory exists (it may not due to being a fresh install and dnsmasq no longer being a dependency)
if [[ ! -d "/etc/dnsmasq.d" ]];then
mkdir "/etc/dnsmasq.d"
install -d -m 755 "/etc/dnsmasq.d"
fi
# Copy the new Pi-hole DNS config file into the dnsmasq.d directory
cp ${dnsmasq_pihole_01_snippet} ${dnsmasq_pihole_01_location}
install -D -m 644 -T "${dnsmasq_pihole_01_snippet}" "${dnsmasq_pihole_01_location}"
printf "%b %b Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf\\n" "${OVER}" "${TICK}"
# Replace our placeholder values with the GLOBAL DNS variables that we populated earlier
# First, swap in the interface to listen on
sed -i "s/@INT@/$PIHOLE_INTERFACE/" ${dnsmasq_pihole_01_location}
sed -i "s/@INT@/$PIHOLE_INTERFACE/" "${dnsmasq_pihole_01_location}"
if [[ "${PIHOLE_DNS_1}" != "" ]]; then
# Then swap in the primary DNS server
sed -i "s/@DNS1@/$PIHOLE_DNS_1/" ${dnsmasq_pihole_01_location}
sed -i "s/@DNS1@/$PIHOLE_DNS_1/" "${dnsmasq_pihole_01_location}"
else
#
sed -i '/^server=@DNS1@/d' ${dnsmasq_pihole_01_location}
sed -i '/^server=@DNS1@/d' "${dnsmasq_pihole_01_location}"
fi
if [[ "${PIHOLE_DNS_2}" != "" ]]; then
# Then swap in the primary DNS server
sed -i "s/@DNS2@/$PIHOLE_DNS_2/" ${dnsmasq_pihole_01_location}
sed -i "s/@DNS2@/$PIHOLE_DNS_2/" "${dnsmasq_pihole_01_location}"
else
#
sed -i '/^server=@DNS2@/d' ${dnsmasq_pihole_01_location}
sed -i '/^server=@DNS2@/d' "${dnsmasq_pihole_01_location}"
fi
#
sed -i 's/^#conf-dir=\/etc\/dnsmasq.d$/conf-dir=\/etc\/dnsmasq.d/' ${dnsmasq_conf}
sed -i 's/^#conf-dir=\/etc\/dnsmasq.d$/conf-dir=\/etc\/dnsmasq.d/' "${dnsmasq_conf}"
# If the user does not want to enable logging,
if [[ "${QUERY_LOGGING}" == false ]] ; then
# Disable it by commenting out the directive in the DNS config file
sed -i 's/^log-queries/#log-queries/' ${dnsmasq_pihole_01_location}
sed -i 's/^log-queries/#log-queries/' "${dnsmasq_pihole_01_location}"
# Otherwise,
else
# enable it by uncommenting the directive in the DNS config file
sed -i 's/^#log-queries/log-queries/' ${dnsmasq_pihole_01_location}
sed -i 's/^#log-queries/log-queries/' "${dnsmasq_pihole_01_location}"
fi
}
@@ -1360,6 +1372,7 @@ installConfigs() {
# Format: Name;Primary IPv4;Secondary IPv4;Primary IPv6;Secondary IPv6
# Some values may be empty (for example: DNS servers without IPv6 support)
echo "${DNS_SERVERS}" > "${PI_HOLE_CONFIG_DIR}/dns-servers.conf"
chmod 644 "${PI_HOLE_CONFIG_DIR}/dns-servers.conf"
# Install empty file if it does not exist
if [[ ! -r "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf" ]]; then
@@ -1378,19 +1391,18 @@ installConfigs() {
if [[ "${INSTALL_WEB_SERVER}" == true ]]; then
# and if the Web server conf directory does not exist,
if [[ ! -d "/etc/lighttpd" ]]; then
# make it
mkdir /etc/lighttpd
# and set the owners
chown "${USER}":root /etc/lighttpd
# make it and set the owners
install -d -m 755 -o "${USER}" -g root /etc/lighttpd
# Otherwise, if the config file already exists
elif [[ -f "/etc/lighttpd/lighttpd.conf" ]]; then
# back up the original
mv /etc/lighttpd/lighttpd.conf /etc/lighttpd/lighttpd.conf.orig
fi
# and copy in the config file Pi-hole needs
cp ${PI_HOLE_LOCAL_REPO}/advanced/${LIGHTTPD_CFG} /etc/lighttpd/lighttpd.conf
install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/${LIGHTTPD_CFG} /etc/lighttpd/lighttpd.conf
# Make sure the external.conf file exists, as lighttpd v1.4.50 crashes without it
touch /etc/lighttpd/external.conf
chmod 644 /etc/lighttpd/external.conf
# if there is a custom block page in the html/pihole directory, replace 404 handler in lighttpd config
if [[ -f "${PI_HOLE_BLOCKPAGE_DIR}/custom.php" ]]; then
sed -i 's/^\(server\.error-handler-404\s*=\s*\).*$/\1"pihole\/custom\.php"/' /etc/lighttpd/lighttpd.conf
@@ -1421,16 +1433,16 @@ install_manpage() {
fi
if [[ ! -d "/usr/local/share/man/man8" ]]; then
# if not present, create man8 directory
mkdir /usr/local/share/man/man8
install -d -m 755 /usr/local/share/man/man8
fi
if [[ ! -d "/usr/local/share/man/man5" ]]; then
# if not present, create man8 directory
mkdir /usr/local/share/man/man5
# if not present, create man5 directory
install -d -m 755 /usr/local/share/man/man5
fi
# Testing complete, copy the files & update the man db
cp ${PI_HOLE_LOCAL_REPO}/manpages/pihole.8 /usr/local/share/man/man8/pihole.8
cp ${PI_HOLE_LOCAL_REPO}/manpages/pihole-FTL.8 /usr/local/share/man/man8/pihole-FTL.8
cp ${PI_HOLE_LOCAL_REPO}/manpages/pihole-FTL.conf.5 /usr/local/share/man/man5/pihole-FTL.conf.5
install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/manpages/pihole.8 /usr/local/share/man/man8/pihole.8
install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/manpages/pihole-FTL.8 /usr/local/share/man/man8/pihole-FTL.8
install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/manpages/pihole-FTL.conf.5 /usr/local/share/man/man5/pihole-FTL.conf.5
if mandb -q &>/dev/null; then
# Updated successfully
printf "%b %b man pages installed and database updated\\n" "${OVER}" "${TICK}"
@@ -1605,7 +1617,6 @@ install_dependent_packages() {
# Install packages passed in via argument array
# No spinner - conflicts with set -e
declare -a argArray1=("${!1}")
declare -a installArray
# Debian based package install - debconf will download the entire package list
@@ -1615,7 +1626,7 @@ install_dependent_packages() {
# installed by us, and remove only the installed packages, and not the entire list.
if is_command debconf-apt-progress ; then
# For each package,
for i in "${argArray1[@]}"; do
for i in "$@"; do
printf " %b Checking for %s..." "${INFO}" "${i}"
if dpkg-query -W -f='${Status}' "${i}" 2>/dev/null | grep "ok installed" &> /dev/null; then
printf "%b %b Checking for %s\\n" "${OVER}" "${TICK}" "${i}"
@@ -1634,9 +1645,9 @@ install_dependent_packages() {
fi
# Install Fedora/CentOS packages
for i in "${argArray1[@]}"; do
for i in "$@"; do
printf " %b Checking for %s..." "${INFO}" "${i}"
if ${PKG_MANAGER} -q list installed "${i}" &> /dev/null; then
if "${PKG_MANAGER}" -q list installed "${i}" &> /dev/null; then
printf "%b %b Checking for %s" "${OVER}" "${TICK}" "${i}"
else
printf "%b %b Checking for %s (will be installed)" "${OVER}" "${INFO}" "${i}"
@@ -1660,7 +1671,7 @@ installPiholeWeb() {
# Install the directory
install -d -m 0755 ${PI_HOLE_BLOCKPAGE_DIR}
# and the blockpage
install -D ${PI_HOLE_LOCAL_REPO}/advanced/{index,blockingpage}.* ${PI_HOLE_BLOCKPAGE_DIR}/
install -D -m 644 ${PI_HOLE_LOCAL_REPO}/advanced/{index,blockingpage}.* ${PI_HOLE_BLOCKPAGE_DIR}/
# Remove superseded file
if [[ -e "${PI_HOLE_BLOCKPAGE_DIR}/index.js" ]]; then
@@ -1687,7 +1698,7 @@ installPiholeWeb() {
local str="Installing sudoer file"
printf "\\n %b %s..." "${INFO}" "${str}"
# Make the .d directory if it doesn't exist
mkdir -p /etc/sudoers.d/
install -d -m 755 /etc/sudoers.d/
# and copy in the pihole sudoers file
install -m 0640 ${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole.sudo /etc/sudoers.d/pihole
# Add lighttpd user (OS dependent) to sudoers file
@@ -1710,7 +1721,8 @@ installCron() {
local str="Installing latest Cron script"
printf "\\n %b %s..." "${INFO}" "${str}"
# Copy the cron file over from the local repo
cp ${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole.cron /etc/cron.d/pihole
# File must not be world or group writeable and must be owned by root
install -D -m 644 -T -o root -g root ${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole.cron /etc/cron.d/pihole
# Randomize gravity update time
sed -i "s/59 1 /$((1 + RANDOM % 58)) $((3 + RANDOM % 2))/" /etc/cron.d/pihole
# Randomize update checker time
@@ -1753,7 +1765,7 @@ configureFirewall() {
# If a firewall is running,
if firewall-cmd --state &> /dev/null; then
# ask if the user wants to install Pi-hole's default firewall rules
whiptail --title "Firewall in use" --yesno "We have detected a running firewall\\n\\nPi-hole currently requires HTTP and DNS port access.\\n\\n\\n\\nInstall Pi-hole default firewall rules?" ${r} ${c} || \
whiptail --title "Firewall in use" --yesno "We have detected a running firewall\\n\\nPi-hole currently requires HTTP and DNS port access.\\n\\n\\n\\nInstall Pi-hole default firewall rules?" "${r}" "${c}" || \
{ printf " %b Not installing firewall rulesets.\\n" "${INFO}"; return 0; }
printf " %b Configuring FirewallD for httpd and pihole-FTL\\n" "${TICK}"
# Allow HTTP and DNS traffic
@@ -1766,7 +1778,7 @@ configureFirewall() {
# If chain Policy is not ACCEPT or last Rule is not ACCEPT
# then check and insert our Rules above the DROP/REJECT Rule.
if iptables -S INPUT | head -n1 | grep -qv '^-P.*ACCEPT$' || iptables -S INPUT | tail -n1 | grep -qv '^-\(A\|P\).*ACCEPT$'; then
whiptail --title "Firewall in use" --yesno "We have detected a running firewall\\n\\nPi-hole currently requires HTTP and DNS port access.\\n\\n\\n\\nInstall Pi-hole default firewall rules?" ${r} ${c} || \
whiptail --title "Firewall in use" --yesno "We have detected a running firewall\\n\\nPi-hole currently requires HTTP and DNS port access.\\n\\n\\n\\nInstall Pi-hole default firewall rules?" "${r}" "${c}" || \
{ printf " %b Not installing firewall rulesets.\\n" "${INFO}"; return 0; }
printf " %b Installing new IPTables firewall rulesets\\n" "${TICK}"
# Check chain first, otherwise a new rule will duplicate old ones
@@ -1818,6 +1830,7 @@ finalExports() {
echo "INSTALL_WEB_INTERFACE=${INSTALL_WEB_INTERFACE}"
echo "LIGHTTPD_ENABLED=${LIGHTTPD_ENABLED}"
}>> "${setupVars}"
chmod 644 "${setupVars}"
# Set the privacy level
sed -i '/PRIVACYLEVEL/d' "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf"
@@ -1840,7 +1853,7 @@ installLogrotate() {
local str="Installing latest logrotate script"
printf "\\n %b %s..." "${INFO}" "${str}"
# Copy the file over from the local repo
cp ${PI_HOLE_LOCAL_REPO}/advanced/Templates/logrotate /etc/pihole/logrotate
install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/advanced/Templates/logrotate /etc/pihole/logrotate
# Different operating systems have different user / group
# settings for logrotate that makes it impossible to create
# a static logrotate file that will work with e.g.
@@ -1859,29 +1872,26 @@ installLogrotate() {
# At some point in the future this list can be pruned, for now we'll need it to ensure updates don't break.
# Refactoring of install script has changed the name of a couple of variables. Sort them out here.
accountForRefactor() {
sed -i 's/piholeInterface/PIHOLE_INTERFACE/g' ${setupVars}
sed -i 's/IPv4_address/IPV4_ADDRESS/g' ${setupVars}
sed -i 's/IPv4addr/IPV4_ADDRESS/g' ${setupVars}
sed -i 's/IPv6_address/IPV6_ADDRESS/g' ${setupVars}
sed -i 's/piholeIPv6/IPV6_ADDRESS/g' ${setupVars}
sed -i 's/piholeDNS1/PIHOLE_DNS_1/g' ${setupVars}
sed -i 's/piholeDNS2/PIHOLE_DNS_2/g' ${setupVars}
sed -i 's/^INSTALL_WEB=/INSTALL_WEB_INTERFACE=/' ${setupVars}
sed -i 's/piholeInterface/PIHOLE_INTERFACE/g' "${setupVars}"
sed -i 's/IPv4_address/IPV4_ADDRESS/g' "${setupVars}"
sed -i 's/IPv4addr/IPV4_ADDRESS/g' "${setupVars}"
sed -i 's/IPv6_address/IPV6_ADDRESS/g' "${setupVars}"
sed -i 's/piholeIPv6/IPV6_ADDRESS/g' "${setupVars}"
sed -i 's/piholeDNS1/PIHOLE_DNS_1/g' "${setupVars}"
sed -i 's/piholeDNS2/PIHOLE_DNS_2/g' "${setupVars}"
sed -i 's/^INSTALL_WEB=/INSTALL_WEB_INTERFACE=/' "${setupVars}"
# Add 'INSTALL_WEB_SERVER', if its not been applied already: https://github.com/pi-hole/pi-hole/pull/2115
if ! grep -q '^INSTALL_WEB_SERVER=' ${setupVars}; then
local webserver_installed=false
if grep -q '^INSTALL_WEB_INTERFACE=true' ${setupVars}; then
webserver_installed=true
fi
echo -e "INSTALL_WEB_SERVER=$webserver_installed" >> ${setupVars}
echo -e "INSTALL_WEB_SERVER=$webserver_installed" >> "${setupVars}"
fi
}
# Install base files and web interface
installPihole() {
# Create the pihole user
create_pihole_user
# If the user wants to install the Web interface,
if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then
if [[ ! -d "${webroot}" ]]; then
@@ -1893,6 +1903,9 @@ installPihole() {
# Set the owner and permissions
chown ${LIGHTTPD_USER}:${LIGHTTPD_GROUP} ${webroot}
chmod 0775 ${webroot}
# Repair permissions if /var/www/html is not world readable
chmod a+rx /var/www
chmod a+rx /var/www/html
# Give pihole access to the Web server group
usermod -a -G ${LIGHTTPD_GROUP} pihole
# If the lighttpd command is executable,
@@ -1955,7 +1968,7 @@ checkSelinux() {
# If it's enforcing,
if [[ "${enforceMode}" == "Enforcing" ]]; then
# Explain Pi-hole does not support it yet
whiptail --defaultno --title "SELinux Enforcing Detected" --yesno "SELinux is being ENFORCED on your system! \\n\\nPi-hole currently does not support SELinux, but you may still continue with the installation.\\n\\nNote: Web Admin will not be fully functional unless you set your policies correctly\\n\\nContinue installing Pi-hole?" ${r} ${c} || \
whiptail --defaultno --title "SELinux Enforcing Detected" --yesno "SELinux is being ENFORCED on your system! \\n\\nPi-hole currently does not support SELinux, but you may still continue with the installation.\\n\\nNote: Web Admin will not be fully functional unless you set your policies correctly\\n\\nContinue installing Pi-hole?" "${r}" "${c}" || \
{ printf "\\n %bSELinux Enforcing detected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
printf " %b Continuing installation with SELinux Enforcing\\n" "${INFO}"
printf " %b Please refer to official SELinux documentation to create a custom policy\\n" "${INFO}"
@@ -1994,7 +2007,7 @@ If you set a new IP address, you should restart the Pi.
The install log is in /etc/pihole.
${additional}" ${r} ${c}
${additional}" "${r}" "${c}"
}
update_dialogs() {
@@ -2015,7 +2028,7 @@ update_dialogs() {
opt2b="This will reset your Pi-hole and allow you to enter new settings."
# Display the information to the user
UpdateCmd=$(whiptail --title "Existing Install Detected!" --menu "\\n\\nWe have detected an existing install.\\n\\nPlease choose from the following options: \\n($strAdd)" ${r} ${c} 2 \
UpdateCmd=$(whiptail --title "Existing Install Detected!" --menu "\\n\\nWe have detected an existing install.\\n\\nPlease choose from the following options: \\n($strAdd)" "${r}" "${c}" 2 \
"${opt1a}" "${opt1b}" \
"${opt2a}" "${opt2b}" 3>&2 2>&1 1>&3) || \
{ printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; }
@@ -2104,6 +2117,8 @@ checkout_pull_branch() {
printf " %b %s" "${INFO}" "$str"
git checkout "${branch}" --quiet || return 1
printf "%b %b %s\\n" "${OVER}" "${TICK}" "$str"
# Data in the repositories is public anyway so we can make it readable by everyone (+r to keep executable permission if already set by git)
chmod -R a+rX "${directory}"
git_pull=$(git pull || return 1)
@@ -2200,6 +2215,8 @@ FTLinstall() {
# Before stopping FTL, we download the macvendor database
curl -sSL "https://ftl.pi-hole.net/macvendor.db" -o "${PI_HOLE_CONFIG_DIR}/macvendor.db" || true
chmod 644 "${PI_HOLE_CONFIG_DIR}/macvendor.db"
chown pihole:pihole "${PI_HOLE_CONFIG_DIR}/macvendor.db"
# Stop pihole-FTL service if available
stop_service pihole-FTL &> /dev/null
@@ -2250,6 +2267,7 @@ disable_dnsmasq() {
fi
# Create /etc/dnsmasq.conf
echo "conf-dir=/etc/dnsmasq.d" > "${conffile}"
chmod 644 "${conffile}"
}
get_binary_name() {
@@ -2431,6 +2449,7 @@ copy_to_install_log() {
# Copy the contents of file descriptor 3 into the install log
# Since we use color codes such as '\e[1;33m', they should be removed
sed 's/\[[0-9;]\{1,5\}m//g' < /proc/$$/fd/3 > "${installLogLoc}"
chmod 644 "${installLogLoc}"
}
main() {
@@ -2506,7 +2525,7 @@ main() {
notify_package_updates_available
# Install packages used by this installation script
install_dependent_packages INSTALLER_DEPS[@]
install_dependent_packages "${INSTALLER_DEPS[@]}"
# Check if SELinux is Enforcing
checkSelinux
@@ -2515,7 +2534,7 @@ main() {
# Display welcome dialogs
welcomeDialogs
# Create directory for Pi-hole storage
mkdir -p /etc/pihole/
install -d -m 755 /etc/pihole/
# Determine available interfaces
get_available_interfaces
# Find interfaces and let the user choose one
@@ -2537,7 +2556,7 @@ main() {
installDefaultBlocklists
# Source ${setupVars} to use predefined user variables in the functions
source ${setupVars}
source "${setupVars}"
# Get the privacy level if it exists (default is 0)
if [[ -f "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf" ]]; then
@@ -2557,7 +2576,7 @@ main() {
dep_install_list+=("${PIHOLE_WEB_DEPS[@]}")
fi
install_dependent_packages dep_install_list[@]
install_dependent_packages "${dep_install_list[@]}"
unset dep_install_list
# On some systems, lighttpd is not enabled on first install. We need to enable it here if the user
@@ -2571,6 +2590,8 @@ main() {
else
LIGHTTPD_ENABLED=false
fi
# Create the pihole user
create_pihole_user
# Check if FTL is installed - do this early on as FTL is a hard dependency for Pi-hole
if ! FTLdetect; then
printf " %b FTL Engine not installed\\n" "${CROSS}"
@@ -2592,7 +2613,7 @@ main() {
pw=$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 8)
# shellcheck disable=SC1091
. /opt/pihole/webpage.sh
echo "WEBPASSWORD=$(HashPassword ${pw})" >> ${setupVars}
echo "WEBPASSWORD=$(HashPassword "${pw}")" >> "${setupVars}"
fi
fi

View File

@@ -55,13 +55,13 @@ fi
# Compatability
if [ -x "$(command -v apt-get)" ]; then
# Debian Family
PKG_REMOVE="${PKG_MANAGER} -y remove --purge"
PKG_REMOVE=("${PKG_MANAGER}" -y remove --purge)
package_check() {
dpkg-query -W -f='${Status}' "$1" 2>/dev/null | grep -c "ok installed"
}
elif [ -x "$(command -v rpm)" ]; then
# Fedora Family
PKG_REMOVE="${PKG_MANAGER} remove -y"
PKG_REMOVE=("${PKG_MANAGER}" remove -y)
package_check() {
rpm -qa | grep "^$1-" > /dev/null
}
@@ -80,7 +80,7 @@ removeAndPurge() {
case ${yn} in
[Yy]* )
echo -ne " ${INFO} Removing ${i}...";
${SUDO} "${PKG_REMOVE} ${i}" &> /dev/null;
${SUDO} "${PKG_REMOVE[@]}" "${i}" &> /dev/null;
echo -e "${OVER} ${INFO} Removed ${i}";
break;;
[Nn]* ) echo -e " ${INFO} Skipped ${i}"; break;;
@@ -132,12 +132,15 @@ removeNoPurge() {
fi
if package_check lighttpd > /dev/null; then
${SUDO} rm -rf /etc/lighttpd/ &> /dev/null
echo -e " ${TICK} Removed lighttpd"
else
if [ -f /etc/lighttpd/lighttpd.conf.orig ]; then
if [[ -f /etc/lighttpd/lighttpd.conf.orig ]]; then
${SUDO} mv /etc/lighttpd/lighttpd.conf.orig /etc/lighttpd/lighttpd.conf
fi
if [[ -f /etc/lighttpd/external.conf ]]; then
${SUDO} rm /etc/lighttpd/external.conf
fi
echo -e " ${TICK} Removed lighttpd configs"
fi
${SUDO} rm -f /etc/dnsmasq.d/adList.conf &> /dev/null
@@ -153,7 +156,7 @@ removeNoPurge() {
# Restore Resolved
if [[ -e /etc/systemd/resolved.conf.orig ]]; then
${SUDO} cp /etc/systemd/resolved.conf.orig /etc/systemd/resolved.conf
${SUDO} cp -p /etc/systemd/resolved.conf.orig /etc/systemd/resolved.conf
systemctl reload-or-restart systemd-resolved
fi

View File

@@ -23,31 +23,27 @@ PIHOLE_COMMAND="/usr/local/bin/${basename}"
piholeDir="/etc/${basename}"
adListFile="${piholeDir}/adlists.list"
adListDefault="${piholeDir}/adlists.default"
# Legacy (pre v5.0) list file locations
whitelistFile="${piholeDir}/whitelist.txt"
blacklistFile="${piholeDir}/blacklist.txt"
regexFile="${piholeDir}/regex.list"
adListFile="${piholeDir}/adlists.list"
adList="${piholeDir}/gravity.list"
blackList="${piholeDir}/black.list"
localList="${piholeDir}/local.list"
VPNList="/etc/openvpn/ipp.txt"
piholeGitDir="/etc/.pihole"
gravityDBfile="${piholeDir}/gravity.db"
gravityDBschema="${piholeGitDir}/advanced/Templates/gravity.db.sql"
optimize_database=false
domainsExtension="domains"
matterAndLight="${basename}.0.matterandlight.txt"
parsedMatter="${basename}.1.parsedmatter.txt"
whitelistMatter="${basename}.2.whitelistmatter.txt"
accretionDisc="${basename}.3.accretionDisc.txt"
preEventHorizon="list.preEventHorizon"
skipDownload="false"
resolver="pihole-FTL"
haveSourceUrls=true
# Source setupVars from install script
setupVars="${piholeDir}/setupVars.conf"
if [[ -f "${setupVars}" ]];then
@@ -83,17 +79,104 @@ if [[ -r "${piholeDir}/pihole.conf" ]]; then
echo -e " ${COL_LIGHT_RED}Ignoring overrides specified within pihole.conf! ${COL_NC}"
fi
# Determine if Pi-hole blocking is disabled
# If this is the case, we want to update
# gravity.list.bck and black.list.bck instead of
# gravity.list and black.list
detect_pihole_blocking_status() {
if [[ "${BLOCKING_ENABLED}" == false ]]; then
echo -e " ${INFO} Pi-hole blocking is disabled"
adList="${adList}.bck"
blackList="${blackList}.bck"
# Generate new sqlite3 file from schema template
generate_gravity_database() {
sqlite3 "${gravityDBfile}" < "${gravityDBschema}"
}
# Import domains from file and store them in the specified database table
database_table_from_file() {
# Define locals
local table source backup_path backup_file
table="${1}"
source="${2}"
backup_path="${piholeDir}/migration_backup"
backup_file="${backup_path}/$(basename "${2}")"
# Truncate table
output=$( { sqlite3 "${gravityDBfile}" <<< "DELETE FROM ${table};"; } 2>&1 )
status="$?"
if [[ "${status}" -ne 0 ]]; then
echo -e "\\n ${CROSS} Unable to truncate ${table} database ${gravityDBfile}\\n ${output}"
gravity_Cleanup "error"
fi
local tmpFile
tmpFile="$(mktemp -p "/tmp" --suffix=".gravity")"
local timestamp
timestamp="$(date --utc +'%s')"
local inputfile
if [[ "${table}" == "gravity" ]]; then
# No need to modify the input data for the gravity table
inputfile="${source}"
else
echo -e " ${INFO} Pi-hole blocking is enabled"
# Apply format for white-, blacklist, regex, and adlist tables
local rowid
declare -i rowid
rowid=1
# Read file line by line
grep -v '^ *#' < "${source}" | while IFS= read -r domain
do
# Only add non-empty lines
if [[ ! -z "${domain}" ]]; then
echo "${rowid},\"${domain}\",1,${timestamp},${timestamp},\"Migrated from ${source}\"" >> "${tmpFile}"
rowid+=1
fi
done
inputfile="${tmpFile}"
fi
# Store domains in database table specified by ${table}
# Use printf as .mode and .import need to be on separate lines
# see https://unix.stackexchange.com/a/445615/83260
output=$( { printf ".timeout 10000\\n.mode csv\\n.import \"%s\" %s\\n" "${inputfile}" "${table}" | sqlite3 "${gravityDBfile}"; } 2>&1 )
status="$?"
if [[ "${status}" -ne 0 ]]; then
echo -e "\\n ${CROSS} Unable to fill table ${table} in database ${gravityDBfile}\\n ${output}"
gravity_Cleanup "error"
fi
# Delete tmpfile
rm "${tmpFile}" > /dev/null 2>&1 || \
echo -e " ${CROSS} Unable to remove ${tmpFile}"
# Move source file to backup directory, create directory if not existing
mkdir -p "${backup_path}"
mv "${source}" "${backup_file}" 2> /dev/null || \
echo -e " ${CROSS} Unable to backup ${source} to ${backup_path}"
}
# Migrate pre-v5.0 list files to database-based Pi-hole versions
migrate_to_database() {
# Create database file only if not present
if [ -e "${gravityDBfile}" ]; then
return 0
fi
echo -e " ${INFO} Creating new gravity database"
generate_gravity_database
# Migrate list files to new database
if [[ -e "${adListFile}" ]]; then
# Store adlist domains in database
echo -e " ${INFO} Migrating content of ${adListFile} into new database"
database_table_from_file "adlist" "${adListFile}"
fi
if [[ -e "${blacklistFile}" ]]; then
# Store blacklisted domains in database
echo -e " ${INFO} Migrating content of ${blacklistFile} into new database"
database_table_from_file "blacklist" "${blacklistFile}"
fi
if [[ -e "${whitelistFile}" ]]; then
# Store whitelisted domains in database
echo -e " ${INFO} Migrating content of ${whitelistFile} into new database"
database_table_from_file "whitelist" "${whitelistFile}"
fi
if [[ -e "${regexFile}" ]]; then
# Store regex domains in database
echo -e " ${INFO} Migrating content of ${regexFile} into new database"
database_table_from_file "regex" "${regexFile}"
fi
}
@@ -101,8 +184,8 @@ detect_pihole_blocking_status() {
gravity_CheckDNSResolutionAvailable() {
local lookupDomain="pi.hole"
# Determine if $localList does not exist
if [[ ! -e "${localList}" ]]; then
# Determine if $localList does not exist, and ensure it is not empty
if [[ ! -e "${localList}" ]] || [[ -s "${localList}" ]]; then
lookupDomain="raw.githubusercontent.com"
fi
@@ -153,19 +236,13 @@ gravity_CheckDNSResolutionAvailable() {
gravity_CheckDNSResolutionAvailable
}
# Retrieve blocklist URLs and parse domains from adlists.list
# Retrieve blocklist URLs and parse domains from adlist.list
gravity_GetBlocklistUrls() {
echo -e " ${INFO} ${COL_BOLD}Neutrino emissions detected${COL_NC}..."
if [[ -f "${adListDefault}" ]] && [[ -f "${adListFile}" ]]; then
# Remove superceded $adListDefault file
rm "${adListDefault}" 2> /dev/null || \
echo -e " ${CROSS} Unable to remove ${adListDefault}"
fi
# Retrieve source URLs from $adListFile
# Logic: Remove comments and empty lines
mapfile -t sources <<< "$(grep -v -E "^(#|$)" "${adListFile}" 2> /dev/null)"
# Retrieve source URLs from gravity database
# We source only enabled adlists, sqlite3 stores boolean values as 0 (false) or 1 (true)
mapfile -t sources <<< "$(sqlite3 "${gravityDBfile}" "SELECT address FROM vw_adlist;" 2> /dev/null)"
# Parse source domains from $sources
mapfile -t sourceDomains <<< "$(
@@ -182,11 +259,12 @@ gravity_GetBlocklistUrls() {
if [[ -n "${sources[*]}" ]] && [[ -n "${sourceDomains[*]}" ]]; then
echo -e "${OVER} ${TICK} ${str}"
return 0
else
echo -e "${OVER} ${CROSS} ${str}"
echo -e " ${INFO} No source list found, or it is empty"
echo ""
haveSourceUrls=false
return 1
fi
}
@@ -214,11 +292,9 @@ gravity_SetDownloadOptions() {
*) cmd_ext="";;
esac
if [[ "${skipDownload}" == false ]]; then
echo -e " ${INFO} Target: ${domain} (${url##*/})"
gravity_DownloadBlocklistFromUrl "${url}" "${cmd_ext}" "${agent}"
echo ""
fi
echo -e " ${INFO} Target: ${domain} (${url##*/})"
gravity_DownloadBlocklistFromUrl "${url}" "${cmd_ext}" "${agent}"
echo ""
done
gravity_Blackbody=true
}
@@ -335,14 +411,17 @@ gravity_ParseFileIntoDomains() {
# Most of the lists downloaded are already in hosts file format but the spacing/formating is not contigious
# This helps with that and makes it easier to read
# It also helps with debugging so each stage of the script can be researched more in depth
# Awk -F splits on given IFS, we grab the right hand side (chops trailing #coments and /'s to grab the domain only.
# Last awk command takes non-commented lines and if they have 2 fields, take the right field (the domain) and leave
# the left (IP address), otherwise grab the single field.
< ${source} awk -F '#' '{print $1}' | \
awk -F '/' '{print $1}' | \
awk '($1 !~ /^#/) { if (NF>1) {print $2} else {print $1}}' | \
sed -nr -e 's/\.{2,}/./g' -e '/\./p' > ${destination}
# 1) Remove carriage returns
# 2) Convert all characters to lowercase
# 3) Remove lines containing "#" or "/"
# 4) Remove leading tabs, spaces, etc.
# 5) Delete lines not matching domain names
< "${source}" tr -d '\r' | \
tr '[:upper:]' '[:lower:]' | \
sed -r '/(\/|#).*$/d' | \
sed -r 's/^.*\s+//g' | \
sed -r '/([^\.]+\.)+[^\.]{2,}/!d' > "${destination}"
chmod 644 "${destination}"
return 0
fi
@@ -373,6 +452,7 @@ gravity_ParseFileIntoDomains() {
if($0 ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) { $0="" }
if($0) { print $0 }
}' "${source}" > "${destination}"
chmod 644 "${destination}"
# Determine if there are Adblock exception rules
# https://adblockplus.org/filters
@@ -390,6 +470,7 @@ gravity_ParseFileIntoDomains() {
# Remove exceptions
comm -23 "${destination}" <(sort "${destination}.exceptionsFile.tmp") > "${source}"
mv "${source}" "${destination}"
chmod 644 "${destination}"
fi
echo -e "${OVER} ${TICK} Format: Adblock"
@@ -413,11 +494,13 @@ gravity_ParseFileIntoDomains() {
# Print if nonempty
length { print }
' "${source}" 2> /dev/null > "${destination}"
chmod 644 "${destination}"
echo -e "${OVER} ${TICK} Format: URL"
else
# Default: Keep hosts/domains file in same format as it was downloaded
output=$( { mv "${source}" "${destination}"; } 2>&1 )
chmod 644 "${destination}"
if [[ ! -e "${destination}" ]]; then
echo -e "\\n ${CROSS} Unable to move tmp file to ${piholeDir}
@@ -432,12 +515,11 @@ gravity_ConsolidateDownloadedBlocklists() {
local str lastLine
str="Consolidating blocklists"
if [[ "${haveSourceUrls}" == true ]]; then
echo -ne " ${INFO} ${str}..."
fi
echo -ne " ${INFO} ${str}..."
# Empty $matterAndLight if it already exists, otherwise, create it
: > "${piholeDir}/${matterAndLight}"
chmod 644 "${piholeDir}/${matterAndLight}"
# Loop through each *.domains file
for i in "${activeDomains[@]}"; do
@@ -453,9 +535,8 @@ gravity_ConsolidateDownloadedBlocklists() {
fi
fi
done
if [[ "${haveSourceUrls}" == true ]]; then
echo -e "${OVER} ${TICK} ${str}"
fi
echo -e "${OVER} ${TICK} ${str}"
}
# Parse consolidated list into (filtered, unique) domains-only format
@@ -463,67 +544,45 @@ gravity_SortAndFilterConsolidatedList() {
local str num
str="Extracting domains from blocklists"
if [[ "${haveSourceUrls}" == true ]]; then
echo -ne " ${INFO} ${str}..."
fi
echo -ne " ${INFO} ${str}..."
# Parse into hosts file
# Parse into file
gravity_ParseFileIntoDomains "${piholeDir}/${matterAndLight}" "${piholeDir}/${parsedMatter}"
# Format $parsedMatter line total as currency
num=$(printf "%'.0f" "$(wc -l < "${piholeDir}/${parsedMatter}")")
if [[ "${haveSourceUrls}" == true ]]; then
echo -e "${OVER} ${TICK} ${str}"
fi
echo -e " ${INFO} Number of domains being pulled in by gravity: ${COL_BLUE}${num}${COL_NC}"
echo -e "${OVER} ${TICK} ${str}"
echo -e " ${INFO} Gravity pulled in ${COL_BLUE}${num}${COL_NC} domains"
str="Removing duplicate domains"
if [[ "${haveSourceUrls}" == true ]]; then
echo -ne " ${INFO} ${str}..."
fi
echo -ne " ${INFO} ${str}..."
sort -u "${piholeDir}/${parsedMatter}" > "${piholeDir}/${preEventHorizon}"
chmod 644 "${piholeDir}/${preEventHorizon}"
echo -e "${OVER} ${TICK} ${str}"
if [[ "${haveSourceUrls}" == true ]]; then
echo -e "${OVER} ${TICK} ${str}"
# Format $preEventHorizon line total as currency
num=$(printf "%'.0f" "$(wc -l < "${piholeDir}/${preEventHorizon}")")
echo -e " ${INFO} Number of unique domains trapped in the Event Horizon: ${COL_BLUE}${num}${COL_NC}"
fi
# Format $preEventHorizon line total as currency
num=$(printf "%'.0f" "$(wc -l < "${piholeDir}/${preEventHorizon}")")
str="Storing ${COL_BLUE}${num}${COL_NC} unique blocking domains in database"
echo -ne " ${INFO} ${str}..."
database_table_from_file "gravity" "${piholeDir}/${preEventHorizon}"
echo -e "${OVER} ${TICK} ${str}"
}
# Whitelist user-defined domains
gravity_Whitelist() {
local num str
if [[ ! -f "${whitelistFile}" ]]; then
echo -e " ${INFO} Nothing to whitelist!"
return 0
fi
num=$(wc -l < "${whitelistFile}")
str="Number of whitelisted domains: ${num}"
echo -ne " ${INFO} ${str}..."
# Print everything from preEventHorizon into whitelistMatter EXCEPT domains in $whitelistFile
comm -23 "${piholeDir}/${preEventHorizon}" <(sort "${whitelistFile}") > "${piholeDir}/${whitelistMatter}"
echo -e "${OVER} ${INFO} ${str}"
# Report number of entries in a table
gravity_Table_Count() {
local table="${1}"
local str="${2}"
local num
num="$(sqlite3 "${gravityDBfile}" "SELECT COUNT(*) FROM ${table} WHERE enabled = 1;")"
echo -e " ${INFO} Number of ${str}: ${num}"
}
# Output count of blacklisted domains and regex filters
gravity_ShowBlockCount() {
local num
if [[ -f "${blacklistFile}" ]]; then
num=$(printf "%'.0f" "$(wc -l < "${blacklistFile}")")
echo -e " ${INFO} Number of blacklisted domains: ${num}"
fi
if [[ -f "${regexFile}" ]]; then
num=$(grep -cv "^#" "${regexFile}")
echo -e " ${INFO} Number of regex filters: ${num}"
fi
gravity_ShowCount() {
gravity_Table_Count "blacklist" "blacklisted domains"
gravity_Table_Count "whitelist" "whitelisted domains"
gravity_Table_Count "regex" "regex filters"
}
# Parse list of domains into hosts format
@@ -543,7 +602,7 @@ gravity_ParseDomainsIntoHosts() {
}
# Create "localhost" entries into hosts format
gravity_ParseLocalDomains() {
gravity_generateLocalList() {
local hostname
if [[ -s "/etc/hostname" ]]; then
@@ -559,6 +618,7 @@ gravity_ParseLocalDomains() {
# Empty $localList if it already exists, otherwise, create it
: > "${localList}"
chmod 644 "${localList}"
gravity_ParseDomainsIntoHosts "${localList}.tmp" "${localList}"
@@ -568,40 +628,6 @@ gravity_ParseLocalDomains() {
fi
}
# Create primary blacklist entries
gravity_ParseBlacklistDomains() {
local output status
# Empty $accretionDisc if it already exists, otherwise, create it
: > "${piholeDir}/${accretionDisc}"
if [[ -f "${piholeDir}/${whitelistMatter}" ]]; then
mv "${piholeDir}/${whitelistMatter}" "${piholeDir}/${accretionDisc}"
else
# There was no whitelist file, so use preEventHorizon instead of whitelistMatter.
cp "${piholeDir}/${preEventHorizon}" "${piholeDir}/${accretionDisc}"
fi
# Move the file over as /etc/pihole/gravity.list so dnsmasq can use it
output=$( { mv "${piholeDir}/${accretionDisc}" "${adList}"; } 2>&1 )
status="$?"
if [[ "${status}" -ne 0 ]]; then
echo -e "\\n ${CROSS} Unable to move ${accretionDisc} from ${piholeDir}\\n ${output}"
gravity_Cleanup "error"
fi
}
# Create user-added blacklist entries
gravity_ParseUserDomains() {
if [[ ! -f "${blacklistFile}" ]]; then
return 0
fi
# Copy the file over as /etc/pihole/black.list so dnsmasq can use it
cp "${blacklistFile}" "${blackList}" 2> /dev/null || \
echo -e "\\n ${CROSS} Unable to move ${blacklistFile##*/} to ${piholeDir}"
}
# Trap Ctrl-C
gravity_Trap() {
trap '{ echo -e "\\n\\n ${INFO} ${COL_LIGHT_RED}User-abort detected${COL_NC}"; gravity_Cleanup "error"; }' INT
@@ -633,6 +659,21 @@ gravity_Cleanup() {
echo -e "${OVER} ${TICK} ${str}"
if ${optimize_database} ; then
str="Optimizing domains database"
echo -ne " ${INFO} ${str}..."
# Run VACUUM command on database to optimize it
output=$( { sqlite3 "${gravityDBfile}" "VACUUM;"; } 2>&1 )
status="$?"
if [[ "${status}" -ne 0 ]]; then
echo -e "\\n ${CROSS} Unable to optimize gravity database ${gravityDBfile}\\n ${output}"
error="error"
else
echo -e "${OVER} ${TICK} ${str}"
fi
fi
# Only restart DNS service if offline
if ! pidof ${resolver} &> /dev/null; then
"${PIHOLE_COMMAND}" restartdns
@@ -659,17 +700,17 @@ Options:
for var in "$@"; do
case "${var}" in
"-f" | "--force" ) forceDelete=true;;
"-o" | "--optimize" ) optimize_database=true;;
"-h" | "--help" ) helpFunc;;
"-sd" | "--skip-download" ) skipDownload=true;;
"-b" | "--blacklist-only" ) listType="blacklist";;
"-w" | "--whitelist-only" ) listType="whitelist";;
"-wild" | "--wildcard-only" ) listType="wildcard"; dnsRestartType="restart";;
esac
done
# Trap Ctrl-C
gravity_Trap
# Move possibly existing legacy files to the gravity database
migrate_to_database
if [[ "${forceDelete:-}" == true ]]; then
str="Deleting existing list cache"
echo -ne "${INFO} ${str}..."
@@ -678,56 +719,24 @@ if [[ "${forceDelete:-}" == true ]]; then
echo -e "${OVER} ${TICK} ${str}"
fi
detect_pihole_blocking_status
# Determine which functions to run
if [[ "${skipDownload}" == false ]]; then
# Gravity needs to download blocklists
gravity_CheckDNSResolutionAvailable
gravity_GetBlocklistUrls
if [[ "${haveSourceUrls}" == true ]]; then
gravity_SetDownloadOptions
fi
# Gravity downloads blocklists next
gravity_CheckDNSResolutionAvailable
if gravity_GetBlocklistUrls; then
gravity_SetDownloadOptions
# Build preEventHorizon
gravity_ConsolidateDownloadedBlocklists
gravity_SortAndFilterConsolidatedList
else
# Gravity needs to modify Blacklist/Whitelist/Wildcards
echo -e " ${INFO} Using cached Event Horizon list..."
numberOf=$(printf "%'.0f" "$(wc -l < "${piholeDir}/${preEventHorizon}")")
echo -e " ${INFO} ${COL_BLUE}${numberOf}${COL_NC} unique domains trapped in the Event Horizon"
fi
# Perform when downloading blocklists, or modifying the whitelist
if [[ "${skipDownload}" == false ]] || [[ "${listType}" == "whitelist" ]]; then
gravity_Whitelist
fi
convert_wildcard_to_regex
gravity_ShowBlockCount
# Perform when downloading blocklists, or modifying the white/blacklist (not wildcards)
if [[ "${skipDownload}" == false ]] || [[ "${listType}" == *"list" ]]; then
str="Parsing domains into hosts format"
echo -ne " ${INFO} ${str}..."
gravity_ParseUserDomains
# Perform when downloading blocklists
if [[ ! "${listType:-}" == "blacklist" ]]; then
gravity_ParseLocalDomains
gravity_ParseBlacklistDomains
fi
echo -e "${OVER} ${TICK} ${str}"
gravity_Cleanup
fi
# Create local.list
gravity_generateLocalList
gravity_ShowCount
gravity_Cleanup
echo ""
# Determine if DNS has been restarted by this instance of gravity
if [[ -z "${dnsWasOffline:-}" ]]; then
# Use "force-reload" when restarting dnsmasq for everything but Wildcards
"${PIHOLE_COMMAND}" restartdns "${dnsRestartType:-force-reload}"
"${PIHOLE_COMMAND}" restartdns reload
fi
"${PIHOLE_COMMAND}" status

View File

@@ -35,7 +35,7 @@ pihole -g\fR
.br
\fBpihole\fR \fB-l\fR (\fBon|off|off noflush\fR)
.br
\fBpihole -up \fR[--checkonly]
\fBpihole -up \fR[--check-only]
.br
\fBpihole -v\fR [-p|-a|-f] [-c|-l|-hash]
.br
@@ -351,6 +351,12 @@ Switching Pi-hole subsystem branches
.br
Switch to core development branch
.br
\fBpihole arpflush\fR
.br
Flush information stored in Pi-hole's network tables
.br
.SH "SEE ALSO"
\fBlighttpd\fR(8), \fBpihole-FTL\fR(8)

33
pihole
View File

@@ -10,10 +10,8 @@
# Please see LICENSE file for your rights under this license.
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
readonly gravitylist="/etc/pihole/gravity.list"
readonly blacklist="/etc/pihole/black.list"
# setupVars is not readonly here because in some funcitons (checkout),
# setupVars is not readonly here because in some functions (checkout),
# it might get set again when the installer is sourced. This causes an
# error due to modifying a readonly variable.
setupVars="/etc/pihole/setupVars.conf"
@@ -56,6 +54,11 @@ flushFunc() {
exit 0
}
arpFunc() {
"${PI_HOLE_SCRIPT_DIR}"/piholeARPTable.sh "$@"
exit 0
}
updatePiholeFunc() {
shift
"${PI_HOLE_SCRIPT_DIR}"/update.sh "$@"
@@ -148,14 +151,6 @@ Time:
echo -e " ${INFO} Blocking already disabled, nothing to do"
exit 0
fi
if [[ -e "${gravitylist}" ]]; then
mv "${gravitylist}" "${gravitylist}.bck"
echo "" > "${gravitylist}"
fi
if [[ -e "${blacklist}" ]]; then
mv "${blacklist}" "${blacklist}.bck"
echo "" > "${blacklist}"
fi
if [[ $# > 1 ]]; then
local error=false
if [[ "${2}" == *"s" ]]; then
@@ -204,12 +199,6 @@ Time:
echo -e " ${INFO} Enabling blocking"
local str="Pi-hole Enabled"
if [[ -e "${gravitylist}.bck" ]]; then
mv "${gravitylist}.bck" "${gravitylist}"
fi
if [[ -e "${blacklist}.bck" ]]; then
mv "${blacklist}.bck" "${blacklist}"
fi
sed -i "/BLOCKING_ENABLED=/d" "${setupVars}"
echo "BLOCKING_ENABLED=true" >> "${setupVars}"
fi
@@ -313,7 +302,7 @@ tailFunc() {
# Colour everything else as gray
tail -f /var/log/pihole.log | sed -E \
-e "s,($(date +'%b %d ')| dnsmasq[.*[0-9]]),,g" \
-e "s,(.*(gravity.list|black.list|regex.list| config ).* is (0.0.0.0|::|NXDOMAIN|${IPV4_ADDRESS%/*}|${IPV6_ADDRESS:-NULL}).*),${COL_RED}&${COL_NC}," \
-e "s,(.*(gravity |black |regex | config ).* is (0.0.0.0|::|NXDOMAIN|${IPV4_ADDRESS%/*}|${IPV6_ADDRESS:-NULL}).*),${COL_RED}&${COL_NC}," \
-e "s,.*(query\\[A|DHCP).*,${COL_NC}&${COL_NC}," \
-e "s,.*,${COL_GRAY}&${COL_NC},"
exit 0
@@ -419,7 +408,8 @@ Options:
Add '-h' for more info on disable usage
restartdns Restart Pi-hole subsystems
checkout Switch Pi-hole subsystems to a different Github branch
Add '-h' for more info on checkout usage";
Add '-h' for more info on checkout usage
arpflush Flush information stored in Pi-hole's network tables";
exit 0
}
@@ -446,8 +436,8 @@ fi
case "${1}" in
"-w" | "whitelist" ) listFunc "$@";;
"-b" | "blacklist" ) listFunc "$@";;
"--wild" | "wildcard" ) listFunc "$@";;
"--regex" | "regex" ) listFunc "$@";;
"--wild" | "wildcard" ) listFunc "$@";;
"--regex" | "regex" ) listFunc "$@";;
"-d" | "debug" ) debugFunc "$@";;
"-f" | "flush" ) flushFunc "$@";;
"-up" | "updatePihole" ) updatePiholeFunc "$@";;
@@ -468,5 +458,6 @@ case "${1}" in
"checkout" ) piholeCheckoutFunc "$@";;
"tricorder" ) tricorderFunc;;
"updatechecker" ) updateCheckFunc "$@";;
"arpflush" ) arpFunc "$@";;
* ) helpFunc;;
esac

View File

@@ -1,4 +1,4 @@
FROM fedora:latest
FROM fedora:30
ENV GITDIR /etc/.pihole
ENV SCRIPTDIR /opt/pihole

View File

@@ -398,6 +398,7 @@ def test_FTL_detect_aarch64_no_errors(Pihole):
)
detectPlatform = Pihole.run('''
source /opt/pihole/basic-install.sh
create_pihole_user
FTLdetect
''')
expected_stdout = info_box + ' FTL Checks...'
@@ -418,6 +419,7 @@ def test_FTL_detect_armv6l_no_errors(Pihole):
mock_command('ldd', {'/bin/ls': ('/lib/ld-linux-armhf.so.3', '0')}, Pihole)
detectPlatform = Pihole.run('''
source /opt/pihole/basic-install.sh
create_pihole_user
FTLdetect
''')
expected_stdout = info_box + ' FTL Checks...'
@@ -439,6 +441,7 @@ def test_FTL_detect_armv7l_no_errors(Pihole):
mock_command('ldd', {'/bin/ls': ('/lib/ld-linux-armhf.so.3', '0')}, Pihole)
detectPlatform = Pihole.run('''
source /opt/pihole/basic-install.sh
create_pihole_user
FTLdetect
''')
expected_stdout = info_box + ' FTL Checks...'
@@ -455,6 +458,7 @@ def test_FTL_detect_x86_64_no_errors(Pihole):
'''
detectPlatform = Pihole.run('''
source /opt/pihole/basic-install.sh
create_pihole_user
FTLdetect
''')
expected_stdout = info_box + ' FTL Checks...'
@@ -471,6 +475,7 @@ def test_FTL_detect_unknown_no_errors(Pihole):
mock_command('uname', {'-m': ('mips', '0')}, Pihole)
detectPlatform = Pihole.run('''
source /opt/pihole/basic-install.sh
create_pihole_user
FTLdetect
''')
expected_stdout = 'Not able to detect architecture (unknown: mips)'
@@ -481,9 +486,17 @@ def test_FTL_download_aarch64_no_errors(Pihole):
'''
confirms only aarch64 package is downloaded for FTL engine
'''
# mock whiptail answers and ensure installer dependencies
mock_command('whiptail', {'*': ('', '0')}, Pihole)
Pihole.run('''
source /opt/pihole/basic-install.sh
distro_check
install_dependent_packages ${INSTALLER_DEPS[@]}
''')
download_binary = Pihole.run('''
source /opt/pihole/basic-install.sh
binary="pihole-FTL-aarch64-linux-gnu"
create_pihole_user
FTLinstall
''')
expected_stdout = tick_box + ' Downloading and Installing FTL'
@@ -495,9 +508,17 @@ def test_FTL_download_unknown_fails_no_errors(Pihole):
'''
confirms unknown binary is not downloaded for FTL engine
'''
# mock whiptail answers and ensure installer dependencies
mock_command('whiptail', {'*': ('', '0')}, Pihole)
Pihole.run('''
source /opt/pihole/basic-install.sh
distro_check
install_dependent_packages ${INSTALLER_DEPS[@]}
''')
download_binary = Pihole.run('''
source /opt/pihole/basic-install.sh
binary="pihole-FTL-mips"
create_pihole_user
FTLinstall
''')
expected_stdout = cross_box + ' Downloading and Installing FTL'
@@ -512,8 +533,16 @@ def test_FTL_download_binary_unset_no_errors(Pihole):
'''
confirms unset binary variable does not download FTL engine
'''
# mock whiptail answers and ensure installer dependencies
mock_command('whiptail', {'*': ('', '0')}, Pihole)
Pihole.run('''
source /opt/pihole/basic-install.sh
distro_check
install_dependent_packages ${INSTALLER_DEPS[@]}
''')
download_binary = Pihole.run('''
source /opt/pihole/basic-install.sh
create_pihole_user
FTLinstall
''')
expected_stdout = cross_box + ' Downloading and Installing FTL'
@@ -530,6 +559,7 @@ def test_FTL_binary_installed_and_responsive_no_errors(Pihole):
'''
installed_binary = Pihole.run('''
source /opt/pihole/basic-install.sh
create_pihole_user
FTLdetect
pihole-FTL version
''')