Merge remote-tracking branch 'origin/development' into tweak/block-page-no-password

pull/1730/head
Mcat12 6 years ago
commit c7219fbdff
No known key found for this signature in database
GPG Key ID: ABB8FC9789AF524D

@ -1,32 +1,31 @@
**By submitting this pull request, I confirm the following:** `{please fill any appropriate checkboxes, e.g: [X]}`
**By submitting this pull request, I confirm the following:**
*please fill any appropriate checkboxes, e.g: [X]*
`{Please ensure that your pull request is for the 'development' branch!}`
- [ ] I have read and understood the [contributors guide](https://github.com/pi-hole/pi-hole/blob/master/CONTRIBUTING.md), as well as this entire template.
- [ ] I have made only one major change in my proposed changes.
- [ ] I have commented my proposed changes within the code.
- [ ] I have tested my proposed changes, and have included unit tests where possible.
- [ ] I am willing to help maintain this change if there are issues with it later.
- [ ] I give this submission freely and claim no ownership.
- [ ] It is compatible with the [EUPL 1.2 license](https://opensource.org/licenses/EUPL-1.1)
- [ ] I have squashed any insignificant commits. ([`git rebase`](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html))
- [] I have read and understood the [contributors guide](https://github.com/pi-hole/pi-hole/blob/master/CONTRIBUTING.md), as well as this entire template.
- [] I have made only one major change in my proposed changes.
- [] I have commented my proposed changes within the code.
- [] I have tested my proposed changes, and have included unit tests where possible.
- [] I am willing to help maintain this change if there are issues with it later.
- [] I give this submission freely and claim no ownership.
- [] It is compatible with the [EUPL 1.2 license](https://opensource.org/licenses/EUPL-1.1)
- [] I have squashed any insignificant commits. ([`git rebase`](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html))
- [] I have Signed Off all commits. ([`git commit --signoff`](https://git-scm.com/docs/git-commit#git-commit---signoff))
Please make sure you [Sign Off](https://github.com/pi-hole/pi-hole/wiki/How-to-signoff-your-commits.) all commits. Pi-hole enforces the [DCO](https://github.com/pi-hole/pi-hole/wiki/Contributing-to-the-project).
---
**What does this PR aim to accomplish?:**
*A detailed description, screenshots (if necessary), as well as links to any relevant GitHub issues*
`{A detailed description, screenshots (if necessary), as well as links to any relevant GitHub issues}`
**How does this PR accomplish the above?:**
*A detailed description (such as a changelog) and screenshots (if necessary) of the implemented fix*
`{A detailed description (such as a changelog) and screenshots (if necessary) of the implemented fix}`
**What documentation changes (if any) are needed to support this PR?:**
*A detailed list of any necessary changes*
`{A detailed list of any necessary changes}`
---
* You must follow the template instructions. Failure to do so will result in your pull request being closed.
* Please respect that Pi-hole is developed by volunteers, who can only reply in their spare time.
> * `{Please delete this quoted section when opening your pull request}`
> * You must follow the template instructions. Failure to do so will result in your issue being closed.
> * Please respect that Pi-hole is developed by volunteers, who can only reply in their spare time.
> * Detail helps us understand an issue quicker, but please ensure it's relevant.

67
.gitignore vendored

@ -3,4 +3,69 @@
*.swp
__pycache__
.cache
.pullapprove.yml
# Created by https://www.gitignore.io/api/jetbrains+iml
### JetBrains+iml ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# All idea files, with execptions
.idea
!.idea/codeStyles/*
!.idea/codeStyleSettings.xml
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Ruby plugin and RubyMine
/.rakeTasks
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### JetBrains+iml Patch ###
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
*.iml
.idea/misc.xml
*.ipr
# End of https://www.gitignore.io/api/jetbrains+iml

@ -0,0 +1,13 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="OTHER_INDENT_OPTIONS">
<value>
<option name="INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</value>
</option>
<MarkdownNavigatorCodeStyleSettings>
<option name="RIGHT_MARGIN" value="72" />
</MarkdownNavigatorCodeStyleSettings>
</code_scheme>
</component>

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

@ -0,0 +1,3 @@
linters:
shellcheck:
shell: bash

@ -28,6 +28,7 @@ When requesting or submitting new features, first consider whether it might be u
- Check the codebase to ensure that your feature doesn't already exist.
- Check the pull requests to ensure that another person hasn't already submitted the feature or fix.
- Read and understand the [DCO guidelines](https://github.com/pi-hole/pi-hole/wiki/Contributing-to-the-project) for the project.
## Technical Requirements

@ -1,314 +1,217 @@
<p align="center">
<a href=https://www.bountysource.com/trackers/3011939-pi-hole-pi-hole?utm_source=3011939&utm_medium=shield&utm_campaign=TRACKER_BADGE><img src="https://www.bountysource.com/badge/tracker?tracker_id=3011939"></a>
<a href="https://www.codacy.com/app/Pi-hole/pi-hole?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=pi-hole/pi-hole&amp;utm_campaign=Badge_Grade"><img src="https://api.codacy.com/project/badge/Grade/c558a0f8d7124c99b02b84f0f5564238"/></a>
<a href=https://travis-ci.org/pi-hole/pi-hole><img src="https://travis-ci.org/pi-hole/pi-hole.svg?branch=development"></a>
<a href="https://pi-hole.net"><img src="https://pi-hole.github.io/graphics/Vortex/Vortex_with_text.png" width="150" height="255" alt="Pi-hole"></a><br/>
<b>Network-wide ad blocking via your own Linux hardware</b><br/>
</p>
<p align="center">
<a href=https://discourse.pi-hole.net><img src="https://assets.pi-hole.net/static/Vortex_with_text_and_TM.png" width=210></a>
</p>
## Pi-hole®: The multi-platform, network-wide ad blocker
The Pi-hole is a [DNS sinkhole](https://en.wikipedia.org/wiki/DNS_Sinkhole) that protects your devices from unwanted content, without installing any client-side software.
Block ads for **all** your devices _without_ the need to install client-side software.
- **Easy-to-install**: our versatile installer walks you through the process, and [takes less than ten minutes](https://www.youtube.com/watch?v=vKWjx1AQYgs)
- **Resolute**: content is blocked in _non-browser locations_, such as ad-laden mobile apps and smart TVs
- **Responsive**: seamlessly speeds up the feel of everyday browsing by caching DNS queries
- **Lightweight**: runs smoothly with [minimal hardware and software requirements](https://discourse.pi-hole.net/t/hardware-software-requirements/273)
- **Robust**: a command line interface that is quality assured for interoperability
- **Insightful**: a beautiful responsive Web Interface dashboard to view and control your Pi-hole
- **Versatile**: can optionally function as a [DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026), ensuring *all* your devices are protected automatically
- **Scalable**: [capable of handling hundreds of millions of queries](https://pi-hole.net/2017/05/24/how-much-traffic-can-pi-hole-handle/) when installed on server-grade hardware
- **Modern**: blocks ads over both IPv4 and IPv6
- **Free**: open source software which helps ensure _you_ are the sole person in control of your privacy
## Executive Summary
The Pi-hole blocks ads at the DNS-level, so all your devices are protected.
-----
<a href="https://www.codacy.com/app/Pi-hole/pi-hole?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=pi-hole/pi-hole&amp;utm_campaign=Badge_Grade"><img src="https://api.codacy.com/project/badge/Grade/c558a0f8d7124c99b02b84f0f5564238" alt="Codacy Grade"/></a>
<a href="https://travis-ci.org/pi-hole/pi-hole"><img src="https://travis-ci.org/pi-hole/pi-hole.svg?branch=development" alt="Travis Build Status"/></a>
<a href="https://www.bountysource.com/trackers/3011939-pi-hole-pi-hole?utm_source=3011939&utm_medium=shield&utm_campaign=TRACKER_BADGE"><img src="https://www.bountysource.com/badge/tracker?tracker_id=3011939" alt="BountySource"/></a>
- **Easy-to-install** - our intelligent installer walks you through the process with no additional software needed on client devices
- **Universal** - ads are blocked in _non-browser locations_ such as ad-supported mobile apps and smart TVs
- **Quick** - installation takes less than ten minutes and it [_really_ is _that easy_](https://discourse.pi-hole.net/t/new-pi-hole-questions/3971/5?u=jacob.salmela)
- **Informative** - an administrative Web interface shows ad-blocking statistics
- **Lightweight** - designed to run on [minimal resources](https://discourse.pi-hole.net/t/hardware-software-requirements/273)
- **Scalable** - even in large environments, [Pi-hole can handle hundreds of millions of queries](https://pi-hole.net/2017/05/24/how-much-traffic-can-pi-hole-handle/) (with the right hardware specs)
- **Powerful** - advertisements are blocked over IPv4 _and_ IPv6
- **Fast** - it speeds up high-cost, high-latency networks by caching DNS queries and saves bandwidth by not downloading advertisement elements
- **Versatile** - Pi-hole can function also function as a DHCP server
# One-Step Automated Install
1. Install a [supported operating system](https://discourse.pi-hole.net/t/hardware-software-requirements/273/1)
2. Run the command below (it downloads [this script](https://github.com/pi-hole/pi-hole/blob/master/automated%20install/basic-install.sh) in case you want to read over it first!)
## One-Step Automated Install
Those who want to get started quickly and conveniently, may install Pi-hole using the following command:
#### `curl -sSL https://install.pi-hole.net | bash`
## Alternative Semi-Automated Install Methods
_If you wish to read over the script before running it, run `nano basic-install.sh` to open the file in a text viewer._
### Clone our repository and run the automated installer from your device.
## Alternative Install Methods
[Piping to `bash` is controversial](https://pi-hole.net/2016/07/25/curling-and-piping-to-bash), as it prevents you from [reading code that is about to run](https://github.com/pi-hole/pi-hole/blob/master/automated%20install/basic-install.sh) on your system. Therefore, we provide these alternative installation methods which allow code review before installation:
### Method 1: Clone our repository and run
```
git clone --depth 1 https://github.com/pi-hole/pi-hole.git Pi-hole
cd Pi-hole/automated\ install/
bash basic-install.sh
cd "Pi-hole/automated install/"
sudo bash basic-install.sh
```
##### Or
```bash
### Method 2: Manually download the installer and run
```
wget -O basic-install.sh https://install.pi-hole.net
bash basic-install.sh
sudo bash basic-install.sh
```
Once installed, [configure your router to have **DHCP clients use the Pi-hole as their DNS server**](https://discourse.pi-hole.net/t/how-do-i-configure-my-devices-to-use-pi-hole-as-their-dns-server/245) and then any device that connects to your network will have ads blocked without any further configuration.
If your router does not support setting the DNS server, you can [use Pi-hole's built in DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026); just be sure to disable DHCP on your router first.
Alternatively, you can manually set each device to use Pi-hole as their DNS server.
# What is Pi-hole and how do I install it?
<p align="center">
<a href=https://www.youtube.com/watch?v=vKWjx1AQYgs><img src="https://assets.pi-hole.net/static/video-explainer.png"></a>
</p>
# Pi-hole Is Free, But Powered By Your Donations
All [our developers](https://github.com/orgs/pi-hole/people) are volunteers, so *your donations help keep us innovating*. Sending a donation using our links below helps us offset a portion of our monthly costs.
- ![Paypal](https://assets.pi-hole.net/static/paypal.png) [Donate via PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY)
- ![Bitcoin](https://assets.pi-hole.net/static/Bitcoin.png) Bitcoin Address: 1GKnevUnVaQM2pQieMyeHkpr8DXfkpfAtL
## Other Ways To Support Us
### Affiliate Links
If you'd rather not send money, there are [other ways to support us](https://pi-hole.net/donate): you can sign up for services through our affiliate links, which will also help us offset some of the costs associated with keeping Pi-hole operational; or you can support us in some non-tangible ways as listed below.
### Contributing Code Via Pull Requests
We don't work on Pi-hole for monetary reasons; we work on it because we think it's fun and we think our software is important in today's world. To that end, we welcome all contributors--from novices to masters.
If you feel you have some code to contribute, we're happy to take a look. Just make sure to fill out our template when submitting a pull request. We're all volunteers on the project and without all the information in the template, it's very difficult for us to quickly get the code merged in.
You'll find that the [install script](https://github.com/pi-hole/pi-hole/blob/master/automated%20install/basic-install.sh) and the [debug script](https://github.com/pi-hole/pi-hole/blob/master/advanced/Scripts/piholeDebug.sh) have an abundance of comments. These are two important scripts but we think they can also be a valuable resource to those who want to learn how to write scripts or code a program, which is why they are fully commented. So we encourage anyone who likes to tinker to read through it and submit a PR for us to review.
### Presenting About Pi-hole
Word-of-mouth has immensely helped our project grow. If you are going to be presenting about Pi-hole at a conference, meetup, or even for a school project, [get a hold of us for some free swag](https://pi-hole.net/2017/05/17/giving-a-presentation-on-pi-hole-contact-us-first-for-some-goodies-and-support/) to hand out to your audience.
# Overview Of Features
## The Dashboard (Web Interface)
The [dashboard](https://github.com/pi-hole/AdminLTE#pi-hole-admin-dashboard) will (by default) be enabled during installation so you can view stats, change settings, and configure your Pi-hole.
![Pi-hole Dashboard](https://assets.pi-hole.net/static/dashboard.png)
There are several ways to [access the dashboard](https://discourse.pi-hole.net/t/how-do-i-access-pi-holes-dashboard-admin-interface/3168):
1. `http://<IP_ADDPRESS_OF_YOUR_PI_HOLE>/admin/`
2. `http:/pi.hole/admin/` (when using Pi-hole as your DNS server)
3. `http://pi.hole/` (when using Pi-hole as your DNS server)
### The Query Log
If enabled, the query log will show all of the DNS queries requested by clients using Pi-hole as their DNS server. Forwarded domains will show in green, and blocked (_Pi-holed_) domains will show in red. You can also white or black list domains from within this section.
<p align="center">
<img src="https://assets.pi-hole.net/static/query_log.png">
</p>
The query log and graphs are what have helped people [discover what sort of traffic is traversing their networks](https://pi-hole.net/2017/07/06/round-3-what-really-happens-on-your-network/).
#### Long-term Statistics
Using our Faster-Than-Light Engine ([FTL](https://github.com/pi-hole/FTL)), Pi-hole can store all of the domains queried in a database for retrieval or analysis later on. You can view this data as a graph, individual queries, or top clients/advertisers.
<p align="center">
<img src="https://assets.pi-hole.net/static/long-term-stats.png">
</p>
### Whitelist And Blacklist
Domains can be [whitelisted](https://discourse.pi-hole.net/t/commonly-whitelisted-domains/212) and/or [blacklisted](https://discourse.pi-hole.net/t/commonly-blacklisted-domains/305) using either the dashboard or [the `pihole` command](https://discourse.pi-hole.net/t/the-pihole-command-with-examples/738).
<p align="center">
<a href=https://github.com/pi-hole/pi-hole/wiki/Whitelisting-and-Blacklisting><img src="https://assets.pi-hole.net/static/whitelist.png"></a>
</p>
#### Additional Blocklists
By default, Pi-hole blocks over 100,000 known ad-serving domains. You can expand the blocking power of your Pi-hole by [adding additional lists](https://discourse.pi-hole.net/t/how-do-i-add-additional-block-lists-to-pi-hole/259) such as the ones found on [The Big Blocklist Collection](https://wally3k.github.io/).
<p align="center">
<a href=https://discourse.pi-hole.net/t/how-do-i-add-additional-block-lists-to-pi-hole/259><img src="https://assets.pi-hole.net/static/manage-ad-lists.png"></a>
</p>
### Enable And Disable Pi-hole
Sometimes you may want to stop using Pi-hole or turn it back on. You can trigger this via the dashboard or command line.
<p align="center">
<img src="https://assets.pi-hole.net/static/enable-disable.png">
</p>
## Post-install: Make your network take advantage of Pi-hole
### Tools
<p align="center">
<img src="https://assets.pi-hole.net/static/tools.png">
</p>
Once the installer has been run, you will need to [configure your router to have **DHCP clients use Pi-hole as their DNS server**](https://discourse.pi-hole.net/t/how-do-i-configure-my-devices-to-use-pi-hole-as-their-dns-server/245) which ensures that all devices connecting to your network will have content blocked without any further intervention.
If your router does not support setting the DNS server, you can [use Pi-hole's built in DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026); just be sure to disable DHCP on your router first (if it has that feature available).
#### Update Ad Lists
This runs `gravity` to download any newly-added domains from your source lists.
As a last resort, you can always manually set each device to use Pi-hole as their DNS server.
#### Query Ad Lists
You can find out what list a certain domain was on. This is useful for troubleshooting sites that may not work properly due to a blocked domain.
-----
#### `tail`ing Log Files
You can [watch the log files](https://discourse.pi-hole.net/t/how-do-i-watch-and-interpret-the-pihole-log-file/276) in real time to help debug any issues, or just see what's happening with your Pi-hole.
## Pi-hole is free, but powered by your support
There are many reoccurring costs involved with maintaining free, open source, and privacy respecting software; expenses which [our volunteer developers](https://github.com/orgs/pi-hole/people) pitch in to cover out-of-pocket. This is just one example of how strongly we feel about our software, as well as the importance of keeping it maintained.
#### Pi-hole Debugger
If you are having trouble with your Pi-hole, this is the place to go. You can run the debugger and it will attempt to diagnose any issues and then link to an FAQ with instructions on rectifying the problem.
<p align="center">
<img src="https://assets.pi-hole.net/static/debug-gui.png">
</p>
Make no mistake: **your support is absolutely vital to help keep us innovating!**
If run [via the command line](https://discourse.pi-hole.net/t/the-pihole-command-with-examples/738#debug), you will see red/yellow/green text, which makes it easy to identify any problems.
### Donations
Sending a donation using our links below is **extremely helpful** in offsetting a portion of our monthly expenses:
<p align="center">
<a href=https://discourse.pi-hole.net/t/the-pihole-command-with-examples/738#debugs><img src="https://assets.pi-hole.net/static/debug-cli.png"></a>
</p>
&nbsp;<img src="https://pi-hole.github.io/graphics/Badges/paypal-badge-black.svg" width="24" height="24" alt="PP"/> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3J2L3Z4DHW9UY">Donate via PayPal</a><br/>
&nbsp;<img src="https://pi-hole.github.io/graphics/Badges/bitcoin-badge-black.svg" width="24" height="24" alt="BTC"/> Bitcoin Address: <code>1GKnevUnVaQM2pQieMyeHkpr8DXfkpfAtL</code>
### Alternative support
If you'd rather not donate (_which is okay!_), there are other ways you can help support us:
After the debugger has finished, you have the option to upload it to our secure server for 48 hours. All you need to do then is provide one of our developers the unique token generated by the debugger (this is usually done via [our forums](https://discourse.pi-hole.net/c/bugs-problems-issues)).
- [Digital Ocean](http://www.digitalocean.com/?refcode=344d234950e1) affiliate link
- [Vultr](http://www.vultr.com/?ref=7190426) affiliate link
- [UNIXstickers.com](http://unixstickers.refr.cc/jacobs) affiliate link
- [Pi-hole Swag Store](https://pi-hole.net/shop/)
- Spreading the word about our software, and how you have benefited from it
<p align="center">
<a href=https://discourse.pi-hole.net/t/the-pihole-command-with-examples/738#debugs><img src="https://assets.pi-hole.net/static/debug-token.png"></a>
</p>
### Contributing via GitHub
We welcome _everyone_ to contribute to issue reports, suggest new features, and create pull requests.
However, most of the time, you will be able to solve any issues without any intervention from us. But if you can't, we're always around to help out.
If you have something to add - anything from a typo through to a whole new feature, we're happy to check it out! Just make sure to fill out our template when submitting your request; the questions that it asks will help the volunteers quickly understand what you're aiming to achieve.
### Settings
You'll find that the [install script](https://github.com/pi-hole/pi-hole/blob/master/automated%20install/basic-install.sh) and the [debug script](https://github.com/pi-hole/pi-hole/blob/master/advanced/Scripts/piholeDebug.sh) have an abundance of comments, which will help you better understand how Pi-hole works. They're also a valuable resource to those who want to learn how to write scripts or code a program! We encourage anyone who likes to tinker to read through it, and submit a pull request for us to review.
The settings page lets you control and configure your Pi-hole. You can do things like:
### Presentations about Pi-hole
Word-of-mouth continues to help our project grow immensely, and so we are helping make this easier for people.
- view networking information
- flush logs or disable the logging of queries
- [enable Pi-hole's built-in DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026)
- [manage block lists](https://discourse.pi-hole.net/t/how-do-i-add-additional-block-lists-to-pi-hole/259)
- exclude domains from the graphs and enable privacy options
- configure upstream DNS servers
- restart Pi-hole's services
- back up some of Pi-hole's important files
- and more!
If you are going to be presenting Pi-hole at a conference, meetup or even a school project, [get in touch with us](https://pi-hole.net/2017/05/17/giving-a-presentation-on-pi-hole-contact-us-first-for-some-goodies-and-support/) so we can hook you up with free swag to hand out to your audience!
<p align="center">
<img src="https://assets.pi-hole.net/static/settings-page.png">
</p>
-----
## Getting in touch with us
While we are primarily reachable on our <a href="https://discourse.pi-hole.net/">Discourse User Forum</a>, we can also be found on a variety of social media outlets. **Please be sure to check the FAQ's** before starting a new discussion, as we do not have the spare time to reply to every request for assistance.
## Built-in DHCP Server
<ul>
<li><a href="https://discourse.pi-hole.net/c/faqs">Frequently Asked Questions</a></li>
<li><a href="https://github.com/pi-hole/pi-hole/wiki">Pi-hole Wiki</a></li>
<li><a href="https://discourse.pi-hole.net/c/feature-requests?order=votes">Feature Requests</a></li>
</ul>
<br/>
<ul>
<li><a href="https://discourse.pi-hole.net/">Discourse User Forum</a></li>
<li><a href="https://www.reddit.com/r/pihole/">Reddit</a></li>
<li><a href="https://gitter.im/pi-hole/pi-hole">Gitter</a> (Real-time chat)</li>
<li><a href="https://twitter.com/The_Pi_Hole">Twitter</a></li>
<li><a href="https://www.youtube.com/channel/UCT5kq9w0wSjogzJb81C9U0w">YouTube</a></li>
<li><a href="https://www.facebook.com/ThePiHole/">Facebook</a></li>
</ul>
Pi-hole ships with a [built-in DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026). This allows you to let your network devices use Pi-hole as their DNS server if your router does not let you adjust the DHCP options.
-----
One nice feature of using Pi-hole's DHCP server if you can set hostnames and DHCP reservations so you'll [see hostnames in the query log instead of IP addresses](https://discourse.pi-hole.net/t/how-do-i-show-hostnames-instead-of-ip-addresses-in-the-dashboard/3530). You can still do this without using Pi-hole's DHCP server; it just takes a little more work. If you do plan to use Pi-hole's DHCP server, be sure to disable DHCP on your router first.
## Breakdown of Features
### The Command Line Interface
The `pihole` command has all the functionality necessary to be able to fully administer the Pi-hole, without the need of the Web Interface. It's fast, user-friendly, and auditable by anyone with understanding of `bash`.
<p align="center">
<a href=https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026><img src="https://assets.pi-hole.net/static/piholedhcpserver.png"></a>
</p>
<a href="https://pi-hole.github.io/graphics/Screenshots/blacklist-cli.gif"><img src="https://pi-hole.github.io/graphics/Screenshots/blacklist-cli.gif" alt="Pi-hole Blacklist Demo"/></a>
## The FTL Engine: Our API
A read-only API can be accessed at `admin/api.php` (the same output can be achieved on the CLI by running `pihole -c -j`).
It returns the following JSON:
``` json
{
"domains_being_blocked":111175,
"dns_queries_today":15669,
"ads_blocked_today":1752,
"ads_percentage_today":11.181314,
"unique_domains":1178,
"queries_forwarded":9177,
"queries_cached":4740,
"unique_clients":18
}
```
Some notable features include:
* [Whitelisting, Blacklisting and Wildcards](https://github.com/pi-hole/pi-hole/wiki/Core-Function-Breakdown#whitelisting-blacklisting-and-wildcards)
* [Debugging utility](https://github.com/pi-hole/pi-hole/wiki/Core-Function-Breakdown#debugger)
* [Viewing the live log file](https://github.com/pi-hole/pi-hole/wiki/Core-Function-Breakdown#tail)
* [Real-time Statistics via `ssh`](https://github.com/pi-hole/pi-hole/wiki/Core-Function-Breakdown#chronometer) or [your TFT LCD screen](http://www.amazon.com/exec/obidos/ASIN/B00ID39LM4/pihole09-20)
* [Updating Ad Lists](https://github.com/pi-hole/pi-hole/wiki/Core-Function-Breakdown#gravity)
* [Querying Ad Lists for blocked domains](https://github.com/pi-hole/pi-hole/wiki/Core-Function-Breakdown#query)
* [Enabling and Disabling Pi-hole](https://github.com/pi-hole/pi-hole/wiki/Core-Function-Breakdown#enable--disable)
* ... and *many* more!
More details on the API can be found [here](https://discourse.pi-hole.net/t/pi-hole-api/1863) and on [the repo itself](https://github.com/pi-hole/FTL).
You can read our [Core Feature Breakdown](https://github.com/pi-hole/pi-hole/wiki/Core-Function-Breakdown), as well as read up on [example usage](https://discourse.pi-hole.net/t/the-pihole-command-with-examples/738) for more information.
### Real-time Statistics, Courtesy Of The Time Cops
### The Web Interface Dashboard
This [optional dashboard](https://github.com/pi-hole/AdminLTE) allows you to view stats, change settings, and configure your Pi-hole. It's the power of the Command Line Interface, with none of the learning curve!
Using [chronometer2](https://github.com/pi-hole/pi-hole/blob/master/advanced/Scripts/chronometer.sh), you can view [real-time stats](https://discourse.pi-hole.net/t/how-do-i-view-my-pi-holes-stats-over-ssh-or-on-an-lcd-using-chronometer/240) via `ssh` or on an LCD screen such as the [2.8" LCD screen from Adafruit](http://amzn.to/1P0q1Fj).
<a href="https://pi-hole.github.io/graphics/Screenshots/dashboard.png"><img src="https://pi-hole.github.io/graphics/Screenshots/dashboard.png" width="888" height="522" alt="Pi-hole Dashboard"/></a>
Simply run `pihole -c` for some detailed information.
```
|¯¯¯(¯)__|¯|_ ___|¯|___ Pi-hole: v3.2
| ¯_/¯|__| ' \/ _ \ / -_) AdminLTE: v3.2
|_| |_| |_||_\___/_\___| FTL: v2.10
——————————————————————————————————————————————————————————
Hostname: pihole (Raspberry Pi 1, Model B)
Uptime: 11 days, 12:55:01
Task Load: 0.35 0.16 0.15 (Active: 5 of 33 tasks)
CPU usage: 48% (1 core @ 700 MHz, 47c)
RAM usage: 12% (Used: 54 MB of 434 MB)
HDD usage: 20% (Used: 1 GB of 7 GB)
LAN addr: 192.168.1.100 (Gateway: 192.168.1.1)
Pi-hole: Active (Blocking: 111175 sites)
Ads Today: 11% (1759 of 15812 queries)
Fwd DNS: 208.67.222.222 (Alt DNS: 3 others)
——————————————————————————————————————————————————————————
Recently blocked: www.google-analytics.com
Top Advertiser: www.example.org
Top Domain: www.example.org
Top Client: somehost
```
Some notable features include:
* Mobile friendly interface
* Password protection
* Detailed graphs and doughnut charts
* Top lists of domains and clients
* A filterable and sortable query log
* Long Term Statistics to view data over user defined time ranges
* The ability to easily manage and configure Pi-hole features
* ... and all the main features of the Command Line Interface!
<p align="center">
<img src="https://assets.pi-hole.net/static/chrono1.jpg">
</p>
There are several ways to [access the dashboard](https://discourse.pi-hole.net/t/how-do-i-access-pi-holes-dashboard-admin-interface/3168):
<p align="center">
<img src="https://assets.pi-hole.net/static/chrono2.jpg">
</p>
1. `http://<IP_ADDPRESS_OF_YOUR_PI_HOLE>/admin/`
2. `http:/pi.hole/admin/` (when using Pi-hole as your DNS server)
3. `http://pi.hole/` (when using Pi-hole as your DNS server)
# Get Help Or Connect With Us On The Web
- [Users Forum](https://discourse.pi-hole.net/)
- [FAQs](https://discourse.pi-hole.net/c/faqs)
- [Feature requests](https://discourse.pi-hole.net/c/feature-requests?order=votes)
- [Wiki](https://github.com/pi-hole/pi-hole/wiki)
- [Facebook](https://www.facebook.com/ThePiHole/)
- ![Twitter](https://assets.pi-hole.net/static/twitter.png) [Tweet @The_Pi_Hole](https://twitter.com/The_Pi_Hole)
- ![Reddit](https://assets.pi-hole.net/static/reddit.png) [Reddit /r/pihole](https://www.reddit.com/r/pihole/)
- ![YouTube](https://assets.pi-hole.net/static/youtube.png) [Pi-hole channel](https://www.youtube.com/channel/UCT5kq9w0wSjogzJb81C9U0w)
- [![Join the chat at https://gitter.im/pi-hole/pi-hole](https://badges.gitter.im/pi-hole/pi-hole.svg)](https://gitter.im/pi-hole/pi-hole?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# Technical Details
To summarize into a short sentence, the Pi-hole is an **advertising-aware DNS/Web server**. And while quite outdated at this point, [this original blog post about Pi-hole](https://jacobsalmela.com/2015/06/16/block-millions-ads-network-wide-with-a-raspberry-pi-hole-2-0/) goes into **great detail** about how it was setup and how it works. Syntactically, it's no longer accurate, but the same basic principles and logic still apply to Pi-hole's current state.
# Pi-hole Projects
- [An ad blocking Magic Mirror](https://zonksec.com/blog/magic-mirror-dns-filtering/#dnssoftware)
- [Pi-hole stats in your Mac's menu bar](https://getbitbar.com/plugins/Network/pi-hole.1m.py)
- [Get LED alerts for each blocked ad](http://thetimmy.silvernight.org/pages/endisbutton/)
- [Pi-hole on Ubuntu 14.04 on VirtualBox](http://hbalagtas.blogspot.com/2016/02/adblocking-with-pi-hole-and-ubuntu-1404.html)
- [Docker Pi-hole container (x86 and ARM)](https://hub.docker.com/r/diginc/pi-hole/)
- [Splunk: Pi-hole Visualiser](https://splunkbase.splunk.com/app/3023/)
- [Pi-hole Chrome extension](https://chrome.google.com/webstore/detail/pi-hole-list-editor/hlnoeoejkllgkjbnnnhfolapllcnaglh) ([open source](https://github.com/packtloss/pihole-extension))
- [Go Bananas for CHiP-hole ad blocking](https://www.hackster.io/jacobsalmela/chip-hole-network-wide-ad-blocker-98e037)
- [Sky-Hole](http://dlaa.me/blog/post/skyhole)
- [Pi-hole in the Cloud!](http://blog.codybunch.com/2015/07/28/Pi-Hole-in-the-cloud/)
- [unRaid-hole](https://github.com/spants/unraidtemplates/blob/master/Spants/unRaid-hole.xml#L13)--[Repo and more info](http://lime-technology.com/forum/index.php?PHPSESSID=c0eae3e5ef7e521f7866034a3336489d&topic=38486.0)
- [Pi-hole on/off button](http://thetimmy.silvernight.org/pages/endisbutton/)
- [Minibian Pi-hole](http://munkjensen.net/wiki/index.php/See_my_Pi-Hole#Minibian_Pi-hole)
- [Windows Tray Stat Application](https://github.com/goldbattle/copernicus)
- [Let your blink1 device blink when Pi-hole filters ads](https://gist.github.com/elpatron68/ec0b4c582e5abf604885ac1e068d233f)
- [Pi-hole Prometheus exporter](https://github.com/nlamirault/pihole_exporter): a [Prometheus](https://prometheus.io/) exporter for Pi-hole
- [Pi-hole Droid - open source Android client](https://github.com/friimaind/pi-hole-droid)
- [Windows DNS Swapper](https://github.com/roots84/DNS-Swapper), see [#1400](https://github.com/pi-hole/pi-hole/issues/1400)
# Coverage
- [Adafruit livestream install](https://www.youtube.com/watch?v=eg4u2j1HYlI)
- [TekThing: 5 fun, easy projects for a Raspberry Pi](https://youtu.be/QwrKlyC2kdM?t=1m42s)
- [Pi-hole on Adafruit's blog](https://blog.adafruit.com/2016/03/04/pi-hole-is-a-black-hole-for-internet-ads-piday-raspberrypi-raspberry_pi/)
- [The Defrag Show - MSDN/Channel 9](https://channel9.msdn.com/Shows/The-Defrag-Show/Defrag-Endoscope-USB-Camera-The-Final-HoloLens-Vote-Adblock-Pi-and-more?WT.mc_id=dlvr_twitter_ch9#time=20m39s)
- [MacObserver Podcast 585](http://www.macobserver.com/tmo/podcast/macgeekgab-585)
- [Medium: Block All Ads For $53](https://medium.com/@robleathern/block-ads-on-all-home-devices-for-53-18-a5f1ec139693#.gj1xpgr5d)
- [MakeUseOf: Adblock Everywhere, The Pi-hole Way](http://www.makeuseof.com/tag/adblock-everywhere-raspberry-pi-hole-way/)
- [Lifehacker: Turn Your Pi Into An Ad Blocker With A Single Command](http://lifehacker.com/turn-a-raspberry-pi-into-an-ad-blocker-with-a-single-co-1686093533)!
- [Pi-hole on TekThing](https://youtu.be/8Co59HU2gY0?t=2m)
- [Pi-hole on Security Now! Podcast](http://www.youtube.com/watch?v=p7-osq_y8i8&t=100m26s)
- [Foolish Tech Show](https://youtu.be/bYyena0I9yc?t=2m4s)
- [Pi-hole on Ubuntu](http://www.boyter.org/2015/12/pi-hole-ubuntu-14-04/)
- [Catchpoint: iOS 9 Ad Blocking](http://blog.catchpoint.com/2015/09/14/ad-blocking-apple/)
- [Build an Ad-Blocker for less than 10$ with Orange-Pi](http://www.devacron.com/orangepi-zero-as-an-ad-block-server-with-pi-hole/)
## The Faster-Than-Light Engine
The [FTL Engine](https://github.com/pi-hole/FTL) is a lightweight, purpose-built daemon used to provide statistics needed for the Web Interface, and its API can be easily integrated into your own projects. As the name implies, FTL does this all *very quickly*!
Some of the statistics you can integrate include:
* Total number of domains being blocked
* Total number of DNS queries today
* Total number of ads blocked today
* Percentage of ads blocked
* Unique domains
* Queries forwarded (to your chosen upstream DNS server)
* Queries cached
* Unique clients
The API can be accessed via [`telnet`](https://github.com/pi-hole/FTL), the Web (`admin/api.php`) and Command Line (`pihole -c -j`). You can out find [more details over here](https://discourse.pi-hole.net/t/pi-hole-api/1863).
-----
## The Origin Of Pi-hole
Pi-hole being a **advertising-aware DNS/Web server**, makes use of the following technologies:
* [`dnsmasq`](http://www.thekelleys.org.uk/dnsmasq/doc.html) - a lightweight DNS and DHCP server
* [`curl`](https://curl.haxx.se) - A command line tool for transferring data with URL syntax
* [`lighttpd`](https://www.lighttpd.net) - webserver designed and optimized for high performance
* [`php`](https://secure.php.net) - a popular general-purpose web scripting language
* [AdminLTE Dashboard](https://github.com/almasaeed2010/AdminLTE) - premium admin control panel based on Bootstrap 3.x
While quite outdated at this point, [this original blog post about Pi-hole](https://jacobsalmela.com/2015/06/16/block-millions-ads-network-wide-with-a-raspberry-pi-hole-2-0/) goes into **great detail** about how Pi-hole was originally setup and how it works. Syntactically, it's no longer accurate, but the same basic principles and logic still apply to Pi-hole's current state.
-----
## Pi-hole Projects
- [The Big Blocklist Collection](https://wally3k.github.io)
- [Docker Pi-hole container (x86 and ARM)](https://hub.docker.com/r/diginc/pi-hole/)
- [Pi-Hole in the cloud](http://blog.codybunch.com/2015/07/28/Pi-Hole-in-the-cloud/)
- [Pie in the Sky-Hole [A Pi-Hole in the cloud for ad-blocking via DNS]](https://dlaa.me/blog/post/skyhole)
- [Pi-hole Enable/Disable Button](http://thetimmy.silvernight.org/pages/endisbutton/)
- [Minibian Pi-hole](https://munkjensen.net/wiki/index.php/See_my_Pi-Hole#Minibian_Pi-hole)
- [CHiP-hole: Network-wide Ad-blocker](https://www.hackster.io/jacobsalmela/chip-hole-network-wide-ad-blocker-98e037)
- [Chrome Extension: Pi-Hole List Editor](https://chrome.google.com/webstore/detail/pi-hole-list-editor/hlnoeoejkllgkjbnnnhfolapllcnaglh) ([Source Code](https://github.com/packtloss/pihole-extension))
- [Splunk: Pi-hole Visualiser](https://splunkbase.splunk.com/app/3023/)
- [Adblocking with Pi-hole and Ubuntu 14.04 on VirtualBox](https://hbalagtas.blogspot.com.au/2016/02/adblocking-with-pi-hole-and-ubuntu-1404.html)
- [Pi-hole stats in your Mac's menu bar](https://getbitbar.com/plugins/Network/pi-hole.1m.py)
- [Pi-hole unRAID Template](https://forums.lime-technology.com/topic/36810-support-spants-nodered-mqtt-dashing-couchdb/)
- [Copernicus: Windows Tray Application](https://github.com/goldbattle/copernicus)
- [Let your blink1 device blink when Pi-hole filters ads](https://gist.github.com/elpatron68/ec0b4c582e5abf604885ac1e068d233f)
- [Pi-hole metrics](https://github.com/nlamirault/pihole_exporter) exporter for [Prometheus](https://prometheus.io/)
- [Magic Mirror with DNS Filtering](https://zonksec.com/blog/magic-mirror-dns-filtering/#dnssoftware)
- [Pi-hole Droid: Android client](https://github.com/friimaind/pi-hole-droid)
- [Windows DNS Swapper](https://github.com/roots84/DNS-Swapper), see [#1400](https://github.com/pi-hole/pi-hole/issues/1400)
-----
## Coverage
- [Lifehacker: Turn A Raspberry Pi Into An Ad Blocker With A Single Command](https://www.lifehacker.com.au/2015/02/turn-a-raspberry-pi-into-an-ad-blocker-with-a-single-command/)
- [MakeUseOf: Adblock Everywhere: The Raspberry Pi-Hole Way](http://www.makeuseof.com/tag/adblock-everywhere-raspberry-pi-hole-way/)
- [Catchpoint: Ad-Blocking on Apple iOS9: Valuing the End User Experience](http://blog.catchpoint.com/2015/09/14/ad-blocking-apple/)
- [Security Now Netcast: Pi-hole](https://www.youtube.com/watch?v=p7-osq_y8i8&t=100m26s)
- [TekThing: Raspberry Pi-Hole Makes Ads Disappear!](https://youtu.be/8Co59HU2gY0?t=2m)
- [Foolish Tech Show](https://youtu.be/bYyena0I9yc?t=2m4s)
- [Block Ads on All Home Devices for $53.18](https://medium.com/@robleathern/block-ads-on-all-home-devices-for-53-18-a5f1ec139693#.gj1xpgr5d)
- [Pi-Hole for Ubuntu 14.04](http://www.boyter.org/2015/12/pi-hole-ubuntu-14-04/)
- [MacObserver Podcast 585](https://www.macobserver.com/tmo/podcast/macgeekgab-585)
- [The Defrag Show: Endoscope USB Camera, The Final [HoloLens] Vote, Adblock Pi and more](https://channel9.msdn.com/Shows/The-Defrag-Show/Defrag-Endoscope-USB-Camera-The-Final-HoloLens-Vote-Adblock-Pi-and-more?WT.mc_id=dlvr_twitter_ch9#time=20m39s)
- [Adafruit: Pi-hole is a black hole for internet ads](https://blog.adafruit.com/2016/03/04/pi-hole-is-a-black-hole-for-internet-ads-piday-raspberrypi-raspberry_pi/)
- [Digital Trends: 5 Fun, Easy Projects You Can Try With a $35 Raspberry Pi](https://youtu.be/QwrKlyC2kdM?t=1m42s)
- [Adafruit: Raspberry Pi Quick Look at Pi Hole ad blocking server with Tony D](https://www.youtube.com/watch?v=eg4u2j1HYlI)
- [Devacron: OrangePi Zero as an Ad-Block server with Pi-Hole](http://www.devacron.com/orangepi-zero-as-an-ad-block-server-with-pi-hole/)
- [Linux Pro: The Hole Truth](http://www.linuxpromagazine.com/Issues/2017/200/The-sysadmin-s-daily-grind-Pi-hole)
- [CryptoAUSTRALIA: How We Tried 5 Privacy Focused Raspberry Pi Projects](https://blog.cryptoaustralia.org.au/2017/10/05/5-privacy-focused-raspberry-pi-projects/)
- [CryptoAUSTRALIA: Pi-hole Workshop](https://blog.cryptoaustralia.org.au/2017/11/02/pi-hole-network-wide-ad-blocker/)
- [Know How 355: Killing ads with a Raspberry Pi-Hole!](https://www.twit.tv/shows/know-how/episodes/355)

@ -39,7 +39,7 @@ interface=@INT@
cache-size=10000
log-queries
log-queries=extra
log-facility=/var/log/pihole.log
local-ttl=2

@ -15,7 +15,7 @@ pihole-FTL() {
ftl_port=$(cat /var/run/pihole-FTL.port 2> /dev/null)
if [[ -n "$ftl_port" ]]; then
# Open connection to FTL
exec 3<>"/dev/tcp/localhost/$ftl_port"
exec 3<>"/dev/tcp/127.0.0.1/$ftl_port"
# Test if connection is open
if { "true" >&3; } 2> /dev/null; then
@ -122,13 +122,13 @@ get_init_stats() {
}
# Convert seconds to human-readable format
hrSecs() {
hrSecs() {
day=$(( $1/60/60/24 )); hrs=$(( $1/3600%24 ))
mins=$(( ($1%3600)/60 )); secs=$(( $1%60 ))
[[ "$day" -ge "2" ]] && plu="s"
[[ "$day" -ge "1" ]] && days="$day day${plu}, " || days=""
printf "%s%02d:%02d:%02d\\n" "$days" "$hrs" "$mins" "$secs"
}
}
# Set Colour Codes
coltable="/opt/pihole/COL_TABLE"
@ -199,7 +199,7 @@ get_init_stats() {
# Test existence of temperature file
if [[ -f "/sys/class/thermal/thermal_zone0/temp" ]]; then
temp_file="/sys/class/thermal/thermal_zone0/temp"
elif [[ -f "/sys/class/hwmon/hwmon0/temp1_input" ]]; then
elif [[ -f "/sys/class/hwmon/hwmon0/temp1_input" ]]; then
temp_file="/sys/class/hwmon/hwmon0/temp1_input"
else
temp_file=""
@ -302,7 +302,8 @@ get_sys_stats() {
# Determine whether to display CPU clock speed as MHz or GHz
if [[ -n "$cpu_mhz" ]]; then
[[ "$cpu_mhz" -le "999" ]] && cpu_freq="$cpu_mhz MHz" || cpu_freq="$(calcFunc "$cpu_mhz"/1000) GHz"
[[ "$cpu_mhz" -le "999" ]] && cpu_freq="$cpu_mhz MHz" || cpu_freq="$(printf "%.1f" $(calcFunc "$cpu_mhz"/1000)) GHz"
[[ "${cpu_freq}" == *".0"* ]] && cpu_freq="${cpu_freq/.0/}"
fi
# Determine colour for temperature
@ -380,7 +381,7 @@ get_ftl_stats() {
local top_domain_raw
local top_client_raw
domains_being_blocked=$(printf "%.0f\\n" "${domains_being_blocked_raw}")
domains_being_blocked=$(printf "%.0f\\n" "${domains_being_blocked_raw}" 2> /dev/null)
dns_queries_today=$(printf "%.0f\\n" "${dns_queries_today_raw}")
ads_blocked_today=$(printf "%.0f\\n" "${ads_blocked_today_raw}")
ads_percentage_today=$(printf "%'.0f\\n" "${ads_percentage_today_raw}")
@ -403,9 +404,9 @@ get_ftl_stats() {
get_strings() {
# Expand or contract strings depending on screen size
if [[ "$chrono_width" == "large" ]]; then
phc_str=" ${COL_DARK_GRAY}Pi-hole"
lte_str=" ${COL_DARK_GRAY}Admin"
ftl_str=" ${COL_DARK_GRAY}FTL"
phc_str=" ${COL_DARK_GRAY}Core"
lte_str=" ${COL_DARK_GRAY}Web"
ftl_str=" ${COL_DARK_GRAY}FTL"
api_str="${COL_LIGHT_RED}API Offline"
host_info="$sys_type"
@ -419,7 +420,7 @@ get_strings() {
ph_info="Blocking: $domains_being_blocked sites"
total_str="Total: "
else
phc_str=" ${COL_DARK_GRAY}PH"
phc_str=" ${COL_DARK_GRAY}Core"
lte_str=" ${COL_DARK_GRAY}Web"
ftl_str=" ${COL_DARK_GRAY}FTL"
api_str="${COL_LIGHT_RED}API Down"
@ -530,7 +531,7 @@ chronoFunc() {
sleep 5
fi
fi
done
}

@ -19,7 +19,6 @@ addmode=true
verbose=true
domList=()
domToRemoveList=()
listMain=""
listAlt=""
@ -49,7 +48,8 @@ Options:
-nr, --noreload Update ${type}list without refreshing dnsmasq
-q, --quiet Make output less verbose
-h, --help Show this help dialog
-l, --list Display all your ${type}listed domains"
-l, --list Display all your ${type}listed domains
--nuke Removes all entries in a list"
exit 0
}
@ -70,7 +70,7 @@ HandleOther() {
validDomain=$(grep -P "^((-|_)*[a-z\d]((-|_)*[a-z\d])*(-|_)*)(\.(-|_)*([a-z\d]((-|_)*[a-z\d])*))*$" <<< "${domain}") # Valid chars check
validDomain=$(grep -P "^[^\.]{1,63}(\.[^\.]{1,63})*$" <<< "${validDomain}") # Length of each label
fi
if [[ -n "${validDomain}" ]]; then
domList=("${domList[@]}" ${validDomain})
else
@ -223,6 +223,15 @@ Displaylist() {
exit 0;
}
NukeList() {
if [[ -f "${listMain}" ]]; then
# Back up original list
cp "${listMain}" "${listMain}.bck~"
# Empty out file
echo "" > "${listMain}"
fi
}
for var in "$@"; do
case "${var}" in
"-w" | "whitelist" ) listMain="${whitelist}"; listAlt="${blacklist}";;
@ -230,10 +239,10 @@ for var in "$@"; do
"-wild" | "wildcard" ) listMain="${wildcardlist}";;
"-nr"| "--noreload" ) reload=false;;
"-d" | "--delmode" ) addmode=false;;
"-f" | "--force" ) force=true;;
"-q" | "--quiet" ) verbose=false;;
"-h" | "--help" ) helpFunc;;
"-l" | "--list" ) Displaylist;;
"--nuke" ) NukeList;;
* ) HandleOther "${var}";;
esac
done

@ -29,13 +29,14 @@ if [[ -f ${PIHOLE_COLTABLE_FILE} ]]; then
source ${PIHOLE_COLTABLE_FILE}
else
COL_NC='\e[0m' # No Color
COL_RED='\e[1;91m'
COL_GREEN='\e[1;32m'
COL_YELLOW='\e[1;33m'
COL_LIGHT_PURPLE='\e[1;35m'
COL_PURPLE='\e[1;35m'
COL_CYAN='\e[0;36m'
TICK="[${COL_LIGHT_GREEN}${COL_NC}]"
CROSS="[${COL_LIGHT_RED}${COL_NC}]"
TICK="[${COL_GREEN}${COL_NC}]"
CROSS="[${COL_RED}${COL_NC}]"
INFO="[i]"
DONE="${COL_LIGHT_GREEN} done!${COL_NC}"
OVER="\r\033[K"
fi
@ -175,7 +176,7 @@ show_disclaimer(){
source_setup_variables() {
# Display the current test that is running
log_write "\n${COL_LIGHT_PURPLE}*** [ INITIALIZING ]${COL_NC} Sourcing setup variables"
log_write "\n${COL_PURPLE}*** [ INITIALIZING ]${COL_NC} Sourcing setup variables"
# If the variable file exists,
if ls "${PIHOLE_SETUP_VARS_FILE}" 1> /dev/null 2>&1; then
log_write "${INFO} Sourcing ${PIHOLE_SETUP_VARS_FILE}...";
@ -183,7 +184,7 @@ source_setup_variables() {
source ${PIHOLE_SETUP_VARS_FILE}
else
# If it can't, show an error
log_write "${PIHOLE_SETUP_VARS_FILE} ${COL_LIGHT_RED}does not exist or cannot be read.${COL_NC}"
log_write "${PIHOLE_SETUP_VARS_FILE} ${COL_RED}does not exist or cannot be read.${COL_NC}"
fi
}
@ -214,14 +215,14 @@ copy_to_debug_log() {
sed 's/\[[0-9;]\{1,5\}m//g' > "${PIHOLE_DEBUG_LOG_SANITIZED}" <<< cat "${PIHOLE_DEBUG_LOG}"
}
initiate_debug() {
initialize_debug() {
# Clear the screen so the debug log is readable
clear
show_disclaimer
# Display that the debug process is beginning
log_write "${COL_LIGHT_PURPLE}*** [ INITIALIZING ]${COL_NC}"
log_write "${COL_PURPLE}*** [ INITIALIZING ]${COL_NC}"
# Timestamp the start of the log
log_write "${INFO} $(date "+%Y-%m-%d:%H:%M:%S") debug log has been initiated."
log_write "${INFO} $(date "+%Y-%m-%d:%H:%M:%S") debug log has been initialized."
}
# This is a function for visually displaying the curent test that is being run.
@ -230,7 +231,7 @@ initiate_debug() {
echo_current_diagnostic() {
# Colors are used for visually distinguishing each test in the output
# These colors do not show in the GUI, but the formatting will
log_write "\n${COL_LIGHT_PURPLE}*** [ DIAGNOSING ]:${COL_NC} ${1}"
log_write "\n${COL_PURPLE}*** [ DIAGNOSING ]:${COL_NC} ${1}"
}
compare_local_version_to_git_version() {
@ -255,7 +256,7 @@ compare_local_version_to_git_version() {
# move into it
cd "${git_dir}" || \
# If not, show an error
log_write "${COL_LIGHT_RED}Could not cd into ${git_dir}$COL_NC"
log_write "${COL_RED}Could not cd into ${git_dir}$COL_NC"
if git status &> /dev/null; then
# The current version the user is on
local remote_version
@ -269,7 +270,7 @@ compare_local_version_to_git_version() {
# echo this information out to the user in a nice format
# If the current version matches what pihole -v produces, the user is up-to-date
if [[ "${remote_version}" == "$(pihole -v | awk '/${search_term}/ {print $6}' | cut -d ')' -f1)" ]]; then
log_write "${TICK} ${pihole_component}: ${COL_LIGHT_GREEN}${remote_version}${COL_NC}"
log_write "${TICK} ${pihole_component}: ${COL_GREEN}${remote_version}${COL_NC}"
# If not,
else
# echo the current version in yellow, signifying it's something to take a look at, but not a critical error
@ -280,7 +281,7 @@ compare_local_version_to_git_version() {
# If the repo is on the master branch, they are on the stable codebase
if [[ "${remote_branch}" == "master" ]]; then
# so the color of the text is green
log_write "${INFO} Branch: ${COL_LIGHT_GREEN}${remote_branch}${COL_NC}"
log_write "${INFO} Branch: ${COL_GREEN}${remote_branch}${COL_NC}"
# If it is any other branch, they are in a developement branch
else
# So show that in yellow, signifying it's something to take a look at, but not a critical error
@ -308,7 +309,7 @@ check_ftl_version() {
# Compare the current FTL version to the remote version
if [[ "${FTL_VERSION}" == "$(pihole -v | awk '/FTL/ {print $6}' | cut -d ')' -f1)" ]]; then
# If they are the same, FTL is up-to-date
log_write "${TICK} ${ftl_name}: ${COL_LIGHT_GREEN}${FTL_VERSION}${COL_NC}"
log_write "${TICK} ${ftl_name}: ${COL_GREEN}${FTL_VERSION}${COL_NC}"
else
# If not, show it in yellow, signifying there is an update
log_write "${TICK} ${ftl_name}: ${COL_YELLOW}${FTL_VERSION}${COL_NC} (${FAQ_UPDATE_PI_HOLE})"
@ -345,7 +346,7 @@ get_program_version() {
# If the program does not have a version (the variable is empty)
if [[ -z "${program_version}" ]]; then
# Display and error
log_write "${CROSS} ${COL_LIGHT_RED}${program_name} version could not be detected.${COL_NC}"
log_write "${CROSS} ${COL_RED}${program_name} version could not be detected.${COL_NC}"
else
# Otherwise, display the version
log_write "${INFO} ${program_version}"
@ -368,13 +369,13 @@ is_os_supported() {
# If the variable is one of our supported OSes,
case "${the_os}" in
# Print it in green
"Raspbian") log_write "${TICK} ${COL_LIGHT_GREEN}${os_to_check}${COL_NC}";;
"Ubuntu") log_write "${TICK} ${COL_LIGHT_GREEN}${os_to_check}${COL_NC}";;
"Fedora") log_write "${TICK} ${COL_LIGHT_GREEN}${os_to_check}${COL_NC}";;
"Debian") log_write "${TICK} ${COL_LIGHT_GREEN}${os_to_check}${COL_NC}";;
"CentOS") log_write "${TICK} ${COL_LIGHT_GREEN}${os_to_check}${COL_NC}";;
"Raspbian") log_write "${TICK} ${COL_GREEN}${os_to_check}${COL_NC}";;
"Ubuntu") log_write "${TICK} ${COL_GREEN}${os_to_check}${COL_NC}";;
"Fedora") log_write "${TICK} ${COL_GREEN}${os_to_check}${COL_NC}";;
"Debian") log_write "${TICK} ${COL_GREEN}${os_to_check}${COL_NC}";;
"CentOS") log_write "${TICK} ${COL_GREEN}${os_to_check}${COL_NC}";;
# If not, show it in red and link to our software requirements page
*) log_write "${CROSS} ${COL_LIGHT_RED}${os_to_check}${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS})";
*) log_write "${CROSS} ${COL_RED}${os_to_check}${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS})";
esac
}
@ -418,7 +419,37 @@ diagnose_operating_system() {
get_distro_attributes
else
# If it doesn't exist, it's not a system we currently support and link to FAQ
log_write "${CROSS} ${COL_LIGHT_RED}${error_msg}${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS})"
log_write "${CROSS} ${COL_RED}${error_msg}${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS})"
fi
}
check_selinux() {
# SELinux is not supported by the Pi-hole
echo_current_diagnostic "SELinux"
# Check if a SELinux configuration file exists
if [[ -f /etc/selinux/config ]]; then
# If a SELinux configuration file was found, check the default SELinux mode.
DEFAULT_SELINUX=$(awk -F= '/^SELINUX=/ {print $2}' /etc/selinux/config)
case "${DEFAULT_SELINUX,,}" in
enforcing)
log_write "${CROSS} ${COL_RED}Default SELinux: $DEFAULT_SELINUX${COL_NC}"
;;
*) # 'permissive' and 'disabled'
log_write "${TICK} ${COL_GREEN}Default SELinux: $DEFAULT_SELINUX${COL_NC}";
;;
esac
# Check the current state of SELinux
CURRENT_SELINUX=$(getenforce)
case "${CURRENT_SELINUX,,}" in
enforcing)
log_write "${CROSS} ${COL_RED}Current SELinux: $CURRENT_SELINUX${COL_NC}"
;;
*) # 'permissive' and 'disabled'
log_write "${TICK} ${COL_GREEN}Current SELinux: $CURRENT_SELINUX${COL_NC}";
;;
esac
else
log_write "${INFO} ${COL_GREEN}SELinux not detected${COL_NC}";
fi
}
@ -430,19 +461,19 @@ processor_check() {
if [[ -z "${PROCESSOR}" ]]; then
# we couldn't detect it, so show an error
PROCESSOR=$(lscpu | awk '/Architecture/ {print $2}')
log_write "${CROSS} ${COL_LIGHT_RED}${PROCESSOR}${COL_NC} has not been tested with FTL, but may still work: (${FAQ_FTL_COMPATIBILITY})"
log_write "${CROSS} ${COL_RED}${PROCESSOR}${COL_NC} has not been tested with FTL, but may still work: (${FAQ_FTL_COMPATIBILITY})"
else
# Check if the architecture is currently supported for FTL
case "${PROCESSOR}" in
"amd64") "${TICK} ${COL_LIGHT_GREEN}${PROCESSOR}${COL_NC}"
"amd64") "${TICK} ${COL_GREEN}${PROCESSOR}${COL_NC}"
;;
"armv6l") "${TICK} ${COL_LIGHT_GREEN}${PROCESSOR}${COL_NC}"
"armv6l") "${TICK} ${COL_GREEN}${PROCESSOR}${COL_NC}"
;;
"armv6") "${TICK} ${COL_LIGHT_GREEN}${PROCESSOR}${COL_NC}"
"armv6") "${TICK} ${COL_GREEN}${PROCESSOR}${COL_NC}"
;;
"armv7l") "${TICK} ${COL_LIGHT_GREEN}${PROCESSOR}${COL_NC}"
"armv7l") "${TICK} ${COL_GREEN}${PROCESSOR}${COL_NC}"
;;
"aarch64") "${TICK} ${COL_LIGHT_GREEN}${PROCESSOR}${COL_NC}"
"aarch64") "${TICK} ${COL_GREEN}${PROCESSOR}${COL_NC}"
;;
# Otherwise, show the processor type
*) log_write "${INFO} ${PROCESSOR}";
@ -458,7 +489,7 @@ parse_setup_vars() {
parse_file "${PIHOLE_SETUP_VARS_FILE}"
else
# If not, show an error
log_write "${CROSS} ${COL_LIGHT_RED}Could not read ${PIHOLE_SETUP_VARS_FILE}.${COL_NC}"
log_write "${CROSS} ${COL_RED}Could not read ${PIHOLE_SETUP_VARS_FILE}.${COL_NC}"
fi
}
@ -468,16 +499,16 @@ does_ip_match_setup_vars() {
# IP address to check for
local ip_address="${2}"
# See what IP is in the setupVars.conf file
local setup_vars_ip=$(cat ${PIHOLE_SETUP_VARS_FILE} | grep IPV${protocol}_ADDRESS | cut -d '=' -f2)
local setup_vars_ip=$(< ${PIHOLE_SETUP_VARS_FILE} grep IPV${protocol}_ADDRESS | cut -d '=' -f2)
# If it's an IPv6 address
if [[ "${protocol}" == "6" ]]; then
# Strip off the / (CIDR notation)
if [[ "${ip_address%/*}" == "${setup_vars_ip%/*}" ]]; then
# if it matches, show it in green
log_write " ${COL_LIGHT_GREEN}${ip_address%/*}${COL_NC} matches the IP found in ${PIHOLE_SETUP_VARS_FILE}"
log_write " ${COL_GREEN}${ip_address%/*}${COL_NC} matches the IP found in ${PIHOLE_SETUP_VARS_FILE}"
else
# otherwise show it in red with an FAQ URL
log_write " ${COL_LIGHT_RED}${ip_address%/*}${COL_NC} does not match the IP found in ${PIHOLE_SETUP_VARS_FILE} (${FAQ_ULA})"
log_write " ${COL_RED}${ip_address%/*}${COL_NC} does not match the IP found in ${PIHOLE_SETUP_VARS_FILE} (${FAQ_ULA})"
fi
else
@ -485,10 +516,10 @@ does_ip_match_setup_vars() {
# since it exists in the setupVars.conf that way
if [[ "${ip_address}" == "${setup_vars_ip}" ]]; then
# show in green if it matches
log_write " ${COL_LIGHT_GREEN}${ip_address}${COL_NC} matches the IP found in ${PIHOLE_SETUP_VARS_FILE}"
log_write " ${COL_GREEN}${ip_address}${COL_NC} matches the IP found in ${PIHOLE_SETUP_VARS_FILE}"
else
# otherwise show it in red
log_write " ${COL_LIGHT_RED}${ip_address}${COL_NC} does not match the IP found in ${PIHOLE_SETUP_VARS_FILE} (${FAQ_ULA})"
log_write " ${COL_RED}${ip_address}${COL_NC} does not match the IP found in ${PIHOLE_SETUP_VARS_FILE} (${FAQ_ULA})"
fi
fi
}
@ -516,7 +547,7 @@ detect_ip_addresses() {
log_write ""
else
# If there are no IPs detected, explain that the protocol is not configured
log_write "${CROSS} ${COL_LIGHT_RED}No IPv${protocol} address(es) found on the ${PIHOLE_INTERFACE}${COL_NC} interace.\n"
log_write "${CROSS} ${COL_RED}No IPv${protocol} address(es) found on the ${PIHOLE_INTERFACE}${COL_NC} interface.\n"
return 1
fi
# If the protocol is v6
@ -563,13 +594,13 @@ ping_gateway() {
# If pinging the gateway is not successful,
if ! ${cmd} -c 3 -W 2 -n ${gateway} -I ${PIHOLE_INTERFACE} >/dev/null; then
# let the user know
log_write "${CROSS} ${COL_LIGHT_RED}Gateway did not respond.${COL_NC} ($FAQ_GATEWAY)\n"
log_write "${CROSS} ${COL_RED}Gateway did not respond.${COL_NC} ($FAQ_GATEWAY)\n"
# and return an error code
return 1
# Otherwise,
else
# show a success
log_write "${TICK} ${COL_LIGHT_GREEN}Gateway responded.${COL_NC}"
log_write "${TICK} ${COL_GREEN}Gateway responded.${COL_NC}"
# and return a success code
return 0
fi
@ -584,11 +615,11 @@ ping_internet() {
# Try to ping the address 3 times
if ! ${cmd} -W 2 -c 3 -n ${public_address} -I ${PIHOLE_INTERFACE} >/dev/null; then
# if it's unsuccessful, show an error
log_write "${CROSS} ${COL_LIGHT_RED}Cannot reach the Internet.${COL_NC}\n"
log_write "${CROSS} ${COL_RED}Cannot reach the Internet.${COL_NC}\n"
return 1
else
# Otherwise, show success
log_write "${TICK} ${COL_LIGHT_GREEN}Query responded.${COL_NC}\n"
log_write "${TICK} ${COL_GREEN}Query responded.${COL_NC}\n"
return 0
fi
}
@ -601,11 +632,11 @@ compare_port_to_service_assigned() {
local ftl="pihole-FTL"
if [[ "${service_name}" == "${resolver}" ]] || [[ "${service_name}" == "${web_server}" ]] || [[ "${service_name}" == "${ftl}" ]]; then
# if port 53 is dnsmasq, show it in green as it's standard
log_write "[${COL_LIGHT_GREEN}${port_number}${COL_NC}] is in use by ${COL_LIGHT_GREEN}${service_name}${COL_NC}"
log_write "[${COL_GREEN}${port_number}${COL_NC}] is in use by ${COL_GREEN}${service_name}${COL_NC}"
# Otherwise,
else
# Show the service name in red since it's non-standard
log_write "[${COL_LIGHT_RED}${port_number}${COL_NC}] is in use by ${COL_LIGHT_RED}${service_name}${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS_PORTS})"
log_write "[${COL_RED}${port_number}${COL_NC}] is in use by ${COL_RED}${service_name}${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS_PORTS})"
fi
}
@ -681,21 +712,21 @@ check_x_headers() {
# If the X-header found by curl matches what is should be,
if [[ $block_page == "$block_page_working" ]]; then
# display a success message
log_write "$TICK ${COL_LIGHT_GREEN}${block_page}${COL_NC}"
log_write "$TICK ${COL_GREEN}${block_page}${COL_NC}"
else
# Otherwise, show an error
log_write "$CROSS ${COL_LIGHT_RED}X-Header does not match or could not be retrieved.${COL_NC}"
log_write "${COL_LIGHT_RED}${full_curl_output_block_page}${COL_NC}"
log_write "$CROSS ${COL_RED}X-Header does not match or could not be retrieved.${COL_NC}"
log_write "${COL_RED}${full_curl_output_block_page}${COL_NC}"
fi
# Same logic applies to the dashbord as above, if the X-Header matches what a working system shoud have,
if [[ $dashboard == "$dashboard_working" ]]; then
# then we can show a success
log_write "$TICK ${COL_LIGHT_GREEN}${dashboard}${COL_NC}"
log_write "$TICK ${COL_GREEN}${dashboard}${COL_NC}"
else
# Othewise, it's a failure since the X-Headers either don't exist or have been modified in some way
log_write "$CROSS ${COL_LIGHT_RED}X-Header does not match or could not be retrieved.${COL_NC}"
log_write "${COL_LIGHT_RED}${full_curl_output_dashboard}${COL_NC}"
log_write "$CROSS ${COL_RED}X-Header does not match or could not be retrieved.${COL_NC}"
log_write "${COL_RED}${full_curl_output_dashboard}${COL_NC}"
fi
}
@ -740,10 +771,10 @@ dig_at() {
# 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
# If it can, show sucess
log_write "${TICK} ${random_url} ${COL_LIGHT_GREEN}is ${local_dig}${COL_NC} via ${COL_CYAN}localhost$COL_NC (${local_address})"
log_write "${TICK} ${random_url} ${COL_GREEN}is ${local_dig}${COL_NC} via ${COL_CYAN}localhost$COL_NC (${local_address})"
else
# Otherwise, show a failure
log_write "${CROSS} ${COL_LIGHT_RED}Failed to resolve${COL_NC} ${random_url} via ${COL_LIGHT_RED}localhost${COL_NC} (${local_address})"
log_write "${CROSS} ${COL_RED}Failed to resolve${COL_NC} ${random_url} via ${COL_RED}localhost${COL_NC} (${local_address})"
fi
# Next we need to check if Pi-hole can resolve a domain when the query is sent to it's IP address
@ -754,20 +785,20 @@ dig_at() {
# If Pi-hole can dig itself from it's IP (not the loopback address)
if pihole_dig=$(dig +tries=1 +time=2 -"${protocol}" "${random_url}" @${pihole_address} +short "${record_type}"); then
# show a success
log_write "${TICK} ${random_url} ${COL_LIGHT_GREEN}is ${pihole_dig}${COL_NC} via ${COL_CYAN}Pi-hole${COL_NC} (${pihole_address})"
log_write "${TICK} ${random_url} ${COL_GREEN}is ${pihole_dig}${COL_NC} via ${COL_CYAN}Pi-hole${COL_NC} (${pihole_address})"
else
# Othewise, show a failure
log_write "${CROSS} ${COL_LIGHT_RED}Failed to resolve${COL_NC} ${random_url} via ${COL_LIGHT_RED}Pi-hole${COL_NC} (${pihole_address})"
log_write "${CROSS} ${COL_RED}Failed to resolve${COL_NC} ${random_url} via ${COL_RED}Pi-hole${COL_NC} (${pihole_address})"
fi
# Finally, we need to make sure legitimate queries can out to the Internet using an external, public DNS server
# We are using the static remote_url here instead of a random one because we know it works with IPv4 and IPv6
if remote_dig=$(dig +tries=1 +time=2 -"${protocol}" "${remote_url}" @${remote_address} +short "${record_type}" | head -n1); then
# If successful, the real IP of the domain will be returned instead of Pi-hole's IP
log_write "${TICK} ${remote_url} ${COL_LIGHT_GREEN}is ${remote_dig}${COL_NC} via ${COL_CYAN}a remote, public DNS server${COL_NC} (${remote_address})"
log_write "${TICK} ${remote_url} ${COL_GREEN}is ${remote_dig}${COL_NC} via ${COL_CYAN}a remote, public DNS server${COL_NC} (${remote_address})"
else
# Otherwise, show an error
log_write "${CROSS} ${COL_LIGHT_RED}Failed to resolve${COL_NC} ${remote_url} via ${COL_LIGHT_RED}a remote, public DNS server${COL_NC} (${remote_address})"
log_write "${CROSS} ${COL_RED}Failed to resolve${COL_NC} ${remote_url} via ${COL_RED}a remote, public DNS server${COL_NC} (${remote_address})"
fi
}
@ -778,15 +809,21 @@ process_status(){
local i
# For each process,
for i in "${PIHOLE_PROCESSES[@]}"; do
# get its status via systemctl
local status_of_process=$(systemctl is-active "${i}")
# If systemd
if command -v systemctl &> /dev/null; then
# get its status via systemctl
local status_of_process=$(systemctl is-active "${i}")
else
# Otherwise, use the service command
local status_of_process=$(service "${i}" status | awk '/Active:/ {print $2}') &> /dev/null
fi
# and print it out to the user
if [[ "${status_of_process}" == "active" ]]; then
# If it's active, show it in green
log_write "${TICK} ${COL_LIGHT_GREEN}${i}${COL_NC} daemon is ${COL_LIGHT_GREEN}${status_of_process}${COL_NC}"
log_write "${TICK} ${COL_GREEN}${i}${COL_NC} daemon is ${COL_GREEN}${status_of_process}${COL_NC}"
else
# If it's not, show it in red
log_write "${CROSS} ${COL_LIGHT_RED}${i}${COL_NC} daemon is ${COL_LIGHT_RED}${status_of_process}${COL_NC}"
log_write "${CROSS} ${COL_RED}${i}${COL_NC} daemon is ${COL_RED}${status_of_process}${COL_NC}"
fi
done
}
@ -885,7 +922,7 @@ dir_check() {
:
else
# Otherwise, show an error
log_write "${COL_LIGHT_RED}${directory} does not exist.${COL_NC}"
log_write "${COL_RED}${directory} does not exist.${COL_NC}"
fi
done
}
@ -914,7 +951,7 @@ list_files_in_dir() {
for i in "${!REQUIRED_FILES[@]}"; do
if [[ "${dir_to_parse}/${each_file}" == ${REQUIRED_FILES[$i]} ]]; then
# display the filename
log_write "\n${COL_LIGHT_GREEN}$(ls -ld ${dir_to_parse}/${each_file})${COL_NC}"
log_write "\n${COL_GREEN}$(ls -ld ${dir_to_parse}/${each_file})${COL_NC}"
# Check if the file we want to view has a limit (because sometimes we just need a little bit of info from the file, not the entire thing)
case "${dir_to_parse}/${each_file}" in
# If it's Web server error log, just give the first 25 lines
@ -963,7 +1000,7 @@ analyze_gravity_list() {
# Get the lines that are in the file(s) and store them in an array for parsing later
IFS=$'\r\n'
local gravity_permissions=$(ls -ld "${PIHOLE_BLOCKLIST_FILE}")
log_write "${COL_LIGHT_GREEN}${gravity_permissions}${COL_NC}"
log_write "${COL_GREEN}${gravity_permissions}${COL_NC}"
local gravity_head=()
gravity_head=( $(head -n 4 ${PIHOLE_BLOCKLIST_FILE}) )
log_write " ${COL_CYAN}-----head of $(basename ${PIHOLE_BLOCKLIST_FILE})------${COL_NC}"
@ -989,7 +1026,7 @@ analyze_pihole_log() {
# Get the lines that are in the file(s) and store them in an array for parsing later
IFS=$'\r\n'
local pihole_log_permissions=$(ls -ld "${PIHOLE_LOG}")
log_write "${COL_LIGHT_GREEN}${pihole_log_permissions}${COL_NC}"
log_write "${COL_GREEN}${pihole_log_permissions}${COL_NC}"
local pihole_log_head=()
pihole_log_head=( $(head -n 20 ${PIHOLE_LOG}) )
log_write " ${COL_CYAN}-----head of $(basename ${PIHOLE_LOG})------${COL_NC}"
@ -1008,7 +1045,7 @@ analyze_pihole_log() {
# If the variable contains a value, it found an error in the log
if [[ -n ${error_to_check_for} ]]; then
# So we can print it in red to make it visible to the user
log_write " ${CROSS} ${COL_LIGHT_RED}${head_line}${COL_NC} (${FAQ_BAD_ADDRESS})"
log_write " ${CROSS} ${COL_RED}${head_line}${COL_NC} (${FAQ_BAD_ADDRESS})"
else
# If the variable does not a value (the current default behavior), so do not obfuscate anything
if [[ -z ${OBFUSCATE} ]]; then
@ -1037,7 +1074,7 @@ tricorder_use_nc_or_ssl() {
# Check for openssl first since encryption is a good thing
if command -v openssl &> /dev/null; then
# If the command exists,
log_write " * Using ${COL_LIGHT_GREEN}openssl${COL_NC} for transmission."
log_write " * Using ${COL_GREEN}openssl${COL_NC} for transmission."
# encrypt and transmit the log and store the token returned in a variable
tricorder_token=$(< ${PIHOLE_DEBUG_LOG_SANITIZED} openssl s_client -quiet -connect tricorder.pi-hole.net:${TRICORDER_SSL_PORT_NUMBER} 2> /dev/null)
# Otherwise,
@ -1058,9 +1095,9 @@ upload_to_tricorder() {
# Let the user know debugging is complete with something strikingly visual
log_write ""
log_write "${COL_LIGHT_PURPLE}********************************************${COL_NC}"
log_write "${COL_LIGHT_PURPLE}********************************************${COL_NC}"
log_write "${TICK} ${COL_LIGHT_GREEN}** FINISHED DEBUGGING! **${COL_NC}\n"
log_write "${COL_PURPLE}********************************************${COL_NC}"
log_write "${COL_PURPLE}********************************************${COL_NC}"
log_write "${TICK} ${COL_GREEN}** FINISHED DEBUGGING! **${COL_NC}\n"
# Provide information on what they should do with their token
log_write " * The debug log can be uploaded to tricorder.pi-hole.net for sharing with developers only."
@ -1082,7 +1119,7 @@ upload_to_tricorder() {
# If they say yes, run our function for uploading the log
[yY][eE][sS]|[yY]) tricorder_use_nc_or_ssl;;
# If they choose no, just exit out of the script
*) log_write " * Log will ${COL_LIGHT_GREEN}NOT${COL_NC} be uploaded to tricorder.";exit;
*) log_write " * Log will ${COL_GREEN}NOT${COL_NC} be uploaded to tricorder.";exit;
esac
fi
# Check if tricorder.pi-hole.net is reachable and provide token
@ -1091,19 +1128,19 @@ upload_to_tricorder() {
# Again, try to make this visually striking so the user realizes they need to do something with this information
# Namely, provide the Pi-hole devs with the token
log_write ""
log_write "${COL_LIGHT_PURPLE}***********************************${COL_NC}"
log_write "${COL_LIGHT_PURPLE}***********************************${COL_NC}"
log_write "${TICK} Your debug token is: ${COL_LIGHT_GREEN}${tricorder_token}${COL_NC}"
log_write "${COL_LIGHT_PURPLE}***********************************${COL_NC}"
log_write "${COL_LIGHT_PURPLE}***********************************${COL_NC}"
log_write "${COL_PURPLE}***********************************${COL_NC}"
log_write "${COL_PURPLE}***********************************${COL_NC}"
log_write "${TICK} Your debug token is: ${COL_GREEN}${tricorder_token}${COL_NC}"
log_write "${COL_PURPLE}***********************************${COL_NC}"
log_write "${COL_PURPLE}***********************************${COL_NC}"
log_write ""
log_write " * Provide the token above to the Pi-hole team for assistance at"
log_write " * ${FORUMS_URL}"
log_write " * Your log will self-destruct on our server after ${COL_LIGHT_RED}48 hours${COL_NC}."
log_write " * Your log will self-destruct on our server after ${COL_RED}48 hours${COL_NC}."
# If no token was generated
else
# Show an error and some help instructions
log_write "${CROSS} ${COL_LIGHT_RED}There was an error uploading your debug log.${COL_NC}"
log_write "${CROSS} ${COL_RED}There was an error uploading your debug log.${COL_NC}"
log_write " * Please try again or contact the Pi-hole team for assistance."
fi
# Finally, show where the log file is no matter the outcome of the function so users can look at it
@ -1112,13 +1149,14 @@ upload_to_tricorder() {
# Run through all the functions we made
make_temporary_log
initiate_debug
initialize_debug
# setupVars.conf needs to be sourced before the networking so the values are
# available to the other functions
source_setup_variables
check_component_versions
check_critical_program_versions
diagnose_operating_system
check_selinux
processor_check
check_networking
check_name_resolution

@ -0,0 +1,66 @@
#!/usr/bin/env bash
# Pi-hole: A black hole for Internet advertisements
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware.
#
# Checks for local or remote versions and branches
#
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
# Credit: https://stackoverflow.com/a/46324904
function json_extract() {
local key=$1
local json=$2
local string_regex='"([^"\]|\\.)*"'
local number_regex='-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?'
local value_regex="${string_regex}|${number_regex}|true|false|null"
local pair_regex="\"${key}\"[[:space:]]*:[[:space:]]*(${value_regex})"
if [[ ${json} =~ ${pair_regex} ]]; then
echo $(sed 's/^"\|"$//g' <<< "${BASH_REMATCH[1]}")
else
return 1
fi
}
function get_local_branch() {
# Return active branch
cd "${1}" 2> /dev/null || return 1
git rev-parse --abbrev-ref HEAD || return 1
}
function get_local_version() {
# Return active branch
cd "${1}" 2> /dev/null || return 1
git describe --long --dirty --tags || return 1
}
if [[ "$2" == "remote" ]]; then
if [[ "$3" == "reboot" ]]; then
sleep 30
fi
GITHUB_CORE_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/pi-hole/releases/latest' 2> /dev/null)")"
GITHUB_WEB_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/AdminLTE/releases/latest' 2> /dev/null)")"
GITHUB_FTL_VERSION="$(json_extract tag_name "$(curl -q 'https://api.github.com/repos/pi-hole/FTL/releases/latest' 2> /dev/null)")"
echo -n "${GITHUB_CORE_VERSION} ${GITHUB_WEB_VERSION} ${GITHUB_FTL_VERSION}" > "/etc/pihole/GitHubVersions"
else
CORE_BRANCH="$(get_local_branch /etc/.pihole)"
WEB_BRANCH="$(get_local_branch /var/www/html/admin)"
FTL_BRANCH="$(pihole-FTL branch)"
echo -n "${CORE_BRANCH} ${WEB_BRANCH} ${FTL_BRANCH}" > "/etc/pihole/localbranches"
CORE_VERSION="$(get_local_version /etc/.pihole)"
WEB_VERSION="$(get_local_version /var/www/html/admin)"
FTL_VERSION="$(pihole-FTL version)"
echo -n "${CORE_VERSION} ${WEB_VERSION} ${FTL_VERSION}" > "/etc/pihole/localversions"
fi

@ -110,7 +110,7 @@ SetWebPassword() {
fi
if [ "${PASSWORD}" == "${CONFIRM}" ] ; then
hash=$(HashPassword ${PASSWORD})
hash=$(HashPassword "${PASSWORD}")
# Save hash to file
change_setting "WEBPASSWORD" "${hash}"
echo -e " ${TICK} New password set"
@ -153,6 +153,7 @@ ProcessDNSSettings() {
if [[ "${DNSSEC}" == true ]]; then
echo "dnssec
trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
" >> "${dnsmasqconfig}"
fi
@ -174,6 +175,11 @@ trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE3
add_dnsmasq_setting "local-service"
else
# Listen only on one interface
# Use eth0 as fallback interface if interface is missing in setupVars.conf
if [ -z "${PIHOLE_INTERFACE}" ]; then
PIHOLE_INTERFACE="eth0"
fi
add_dnsmasq_setting "interface" "${PIHOLE_INTERFACE}"
fi
@ -240,7 +246,7 @@ ProcessDHCPSettings() {
source "${setupVars}"
if [[ "${DHCP_ACTIVE}" == "true" ]]; then
interface=$(grep 'PIHOLE_INTERFACE=' /etc/pihole/setupVars.conf | sed "s/.*=//")
interface="${PIHOLE_INTERFACE}"
# Use eth0 as fallback interface
if [ -z ${interface} ]; then
@ -248,7 +254,7 @@ ProcessDHCPSettings() {
fi
if [[ "${PIHOLE_DOMAIN}" == "" ]]; then
PIHOLE_DOMAIN="local"
PIHOLE_DOMAIN="lan"
change_setting "PIHOLE_DOMAIN" "${PIHOLE_DOMAIN}"
fi
@ -418,7 +424,7 @@ Options:
}
SetAdminEmail() {
if [[ "${1}" == *"-h"* ]]; then
if [[ "${1}" == "-h" ]] || [[ "${1}" == "--help" ]]; then
echo "Usage: pihole -a email <address>
Example: 'pihole -a email admin@address.com'
Set an administrative contact address for the Block Page

@ -9,37 +9,42 @@
// Sanitise HTTP_HOST output
$serverName = htmlspecialchars($_SERVER["HTTP_HOST"]);
if (!is_file("/etc/pihole/setupVars.conf"))
die("[ERROR] File not found: <code>/etc/pihole/setupVars.conf</code>");
// Get values from setupVars.conf
if (is_file("/etc/pihole/setupVars.conf")) {
$setupVars = parse_ini_file("/etc/pihole/setupVars.conf");
$svFQDN = $setupVars["FQDN"];
$svPasswd = !empty($setupVars["WEBPASSWORD"]);
$svEmail = (!empty($setupVars["ADMIN_EMAIL"]) && filter_var($setupVars["ADMIN_EMAIL"], FILTER_VALIDATE_EMAIL)) ? $setupVars["ADMIN_EMAIL"] : "";
unset($setupVars);
} else {
die("[ERROR] File not found: <code>/etc/pihole/setupVars.conf</code>");
}
$setupVars = parse_ini_file("/etc/pihole/setupVars.conf");
$svPasswd = !empty($setupVars["WEBPASSWORD"]);
$svEmail = (!empty($setupVars["ADMIN_EMAIL"]) && filter_var($setupVars["ADMIN_EMAIL"], FILTER_VALIDATE_EMAIL)) ? $setupVars["ADMIN_EMAIL"] : "";
unset($setupVars);
// Set landing page location, found within /var/www/html/
$landPage = "../landing.php";
// Set empty array for hostnames to be accepted as self address for splash page
// Define array for hostnames to be accepted as self address for splash page
$authorizedHosts = [];
// Append FQDN to $authorizedHosts
if (!empty($svFQDN)) array_push($authorizedHosts, $svFQDN);
// Append virtual hostname to $authorizedHosts
if (!empty($_SERVER["VIRTUAL_HOST"])) {
if (!empty($_SERVER["FQDN"])) {
// If setenv.add-environment = ("fqdn" => "true") is configured in lighttpd,
// append $serverName to $authorizedHosts
array_push($authorizedHosts, $serverName);
} else if (!empty($_SERVER["VIRTUAL_HOST"])) {
// Append virtual hostname to $authorizedHosts
array_push($authorizedHosts, $_SERVER["VIRTUAL_HOST"]);
}
// Set which extension types render as Block Page (Including "" for index.wxyz)
// Set which extension types render as Block Page (Including "" for index.ext)
$validExtTypes = array("asp", "htm", "html", "php", "rss", "xml", "");
// Get extension of current URL
$currentUrlExt = pathinfo($_SERVER["REQUEST_URI"], PATHINFO_EXTENSION);
// Check if this is served over HTTP or HTTPS
if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") {
$proto = "https";
} else {
$proto = "http";
}
// Set mobile friendly viewport
$viewPort = '<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>';
@ -49,8 +54,9 @@ function setHeader($type = "x") {
if (isset($type) && $type === "js") header("Content-Type: application/javascript");
}
// Determine block page redirect type
// Determine block page type
if ($serverName === "pi.hole") {
// Redirect to Web Interface
exit(header("Location: /admin"));
} elseif (filter_var($serverName, FILTER_VALIDATE_IP) || in_array($serverName, $authorizedHosts)) {
// Set Splash Page output
@ -60,22 +66,29 @@ if ($serverName === "pi.hole") {
<link rel='stylesheet' href='/pihole/blockingpage.css' type='text/css'/>
</head><body id='splashpage'><img src='/admin/img/logo.svg'/><br/>Pi-<b>hole</b>: Your black hole for Internet advertisements</body></html>
";
// Render splash page or landing page when directly browsing via IP or auth'd hostname
// Set splash/landing page based off presence of $landPage
$renderPage = is_file(getcwd()."/$landPage") ? include $landPage : "$splashPage";
unset($serverName, $svFQDN, $svPasswd, $svEmail, $authorizedHosts, $validExtTypes, $currentUrlExt, $viewPort);
// Unset variables so as to not be included in $landPage
unset($serverName, $svPasswd, $svEmail, $authorizedHosts, $validExtTypes, $currentUrlExt, $viewPort);
// Render splash/landing page when directly browsing via IP or authorised hostname
exit($renderPage);
} elseif ($currentUrlExt === "js") {
// Serve dummy Javascript for blocked domains
// Serve Pi-hole Javascript for blocked domains requesting JS
exit(setHeader("js").'var x = "Pi-hole: A black hole for Internet advertisements."');
} elseif (strpos($_SERVER["REQUEST_URI"], "?") !== FALSE && isset($_SERVER["HTTP_REFERER"])) {
// Serve blank image upon receiving REQUEST_URI w/ query string & HTTP_REFERRER (e.g: an iframe of a blocked domain)
// Serve blank image upon receiving REQUEST_URI w/ query string & HTTP_REFERRER
// e.g: An iframe of a blocked domain
exit(setHeader().'<html>
<head><script>window.close();</script></head>
<body><img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs="></body>
</html>');
} elseif (!in_array($currentUrlExt, $validExtTypes) || substr_count($_SERVER["REQUEST_URI"], "?")) {
// Serve SVG upon receiving non $validExtTypes URL extension or query string (e.g: not an iframe of a blocked domain)
// Serve SVG upon receiving non $validExtTypes URL extension or query string
// e.g: Not an iframe of a blocked domain, such as when browsing to a file/query directly
// QoL addition: Allow the SVG to be clicked on in order to quickly show the full Block Page
$blockImg = '<a href="/"><svg xmlns="http://www.w3.org/2000/svg" width="110" height="16"><defs><style>a {text-decoration: none;} circle {stroke: rgba(152,2,2,0.5); fill: none; stroke-width: 2;} rect {fill: rgba(152,2,2,0.5);} text {opacity: 0.3; font: 11px Arial;}</style></defs><circle cx="8" cy="8" r="7"/><rect x="10.3" y="-6" width="2" height="12" transform="rotate(45)"/><text x="19.3" y="12">Blocked by Pi-hole</text></svg></a>';
exit(setHeader()."<html>
<head>$viewPort</head>
@ -88,7 +101,7 @@ if ($serverName === "pi.hole") {
// Determine placeholder text based off $svPasswd presence
$wlPlaceHolder = empty($svPasswd) ? "No admin password set" : "Javascript disabled";
// Define admin email address text
// Define admin email address text based off $svEmail presence
$bpAskAdmin = !empty($svEmail) ? '<a href="mailto:'.$svEmail.'?subject=Site Blocked: '.$serverName.'"></a>' : "<span/>";
// Determine if at least one block list has been generated
@ -113,8 +126,10 @@ if (empty($adlistsUrls))
// Get total number of blocklists (Including Whitelist, Blacklist & Wildcard lists)
$adlistsCount = count($adlistsUrls) + 3;
// Get results of queryads.php exact search
// Set query timeout
ini_set("default_socket_timeout", 3);
// Logic for querying blocklists
function queryAds($serverName) {
// Determine the time it takes while querying adlists
$preQueryTime = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"];
@ -124,32 +139,39 @@ function queryAds($serverName) {
// Exception Handling
try {
if ($queryTime >= ini_get("default_socket_timeout")) {
// Define Exceptions
if (strpos($queryAds[0], "No exact results") !== FALSE) {
// Return "none" into $queryAds array
return array("0" => "none");
} else if ($queryTime >= ini_get("default_socket_timeout")) {
// Connection Timeout
throw new Exception ("Connection timeout (".ini_get("default_socket_timeout")."s)");
} elseif (!strpos($queryAds[0], ".") !== false) {
if (strpos($queryAds[0], "No exact results") !== FALSE) return array("0" => "none");
// Unknown $queryAds output
throw new Exception ("Unhandled error message (<code>$queryAds[0]</code>)");
}
return $queryAds;
} catch (Exception $e) {
// Return exception as array
return array("0" => "error", "1" => $e->getMessage());
}
}
// Get results of queryads.php exact search
$queryAds = queryAds($serverName);
if ($queryAds[0] === "error") {
// Pass error through to Block Page
if ($queryAds[0] === "error")
die("[ERROR]: Unable to parse results from <i>queryads.php</i>: <code>".$queryAds[1]."</code>");
} else {
$featuredTotal = count($queryAds);
// Place results into key => value array
$queryResults = null;
foreach ($queryAds as $str) {
$value = explode(" ", $str);
@$queryResults[$value[0]] .= "$value[1]";
}
// Count total number of matching blocklists
$featuredTotal = count($queryAds);
// Place results into key => value array
$queryResults = null;
foreach ($queryAds as $str) {
$value = explode(" ", $str);
@$queryResults[$value[0]] .= "$value[1]";
}
// Determine if domain has been blacklisted, whitelisted, wildcarded or CNAME blocked
@ -167,7 +189,8 @@ if (strpos($queryAds[0], "blacklist") !== FALSE) {
$featuredTotal = "0";
$notableFlagClass = "noblock";
// Determine appropriate info message if CNAME exists
// QoL addition: Determine appropriate info message if CNAME exists
// Suggests to the user that $serverName has a CNAME (alias) that may be blocked
$dnsRecord = dns_get_record("$serverName")[0];
if (array_key_exists("target", $dnsRecord)) {
$wlInfo = $dnsRecord['target'];
@ -184,9 +207,14 @@ $wlOutput = (isset($wlInfo) && $wlInfo !== "recentwl") ? "<a href='http://$wlInf
$phVersion = exec("cd /etc/.pihole/ && git describe --long --tags");
// Print $execTime on development branches
// Marginally faster than "git rev-parse --abbrev-ref HEAD"
// Testing for - is marginally faster than "git rev-parse --abbrev-ref HEAD"
if (explode("-", $phVersion)[1] != "0")
$execTime = microtime(true)-$_SERVER["REQUEST_TIME_FLOAT"];
// Please Note: Text is added via CSS to allow an admin to provide a localised
// language without the need to edit this file
setHeader();
?>
<!DOCTYPE html>
<!-- Pi-hole: A black hole for Internet advertisements
@ -198,13 +226,12 @@ if (explode("-", $phVersion)[1] != "0")
<head>
<meta charset="UTF-8">
<?=$viewPort ?>
<?=setHeader() ?>
<meta name="robots" content="noindex,nofollow"/>
<meta http-equiv="x-dns-prefetch-control" content="off">
<link rel="shortcut icon" href="http://pi.hole/admin/img/favicon.png" type="image/x-icon"/>
<link rel="stylesheet" href="http://pi.hole/pihole/blockingpage.css" type="text/css"/>
<link rel="shortcut icon" href="<?=$proto ?>://pi.hole/admin/img/favicon.png" type="image/x-icon"/>
<link rel="stylesheet" href="<?=$proto ?>://pi.hole/pihole/blockingpage.css" type="text/css"/>
<title><?=$serverName ?></title>
<script src="http://pi.hole/admin/scripts/vendor/jquery.min.js"></script>
<script src="<?=$proto ?>://pi.hole/admin/scripts/vendor/jquery.min.js"></script>
<script>
window.onload = function () {
<?php
@ -271,7 +298,7 @@ if (explode("-", $phVersion)[1] != "0")
<div id="bpMoreInfo">
<span id="bpFoundIn"><span><?=$featuredTotal ?></span><?=$adlistsCount ?></span>
<pre id='bpQueryOutput'><?php if ($featuredTotal > 0) foreach ($queryResults as $num => $value) { echo "<span>[$num]:</span>$adlistsUrls[$num]\n"; } ?></pre>
<form id="bpWLButtons" class="buttons">
<input id="bpWLDomain" type="text" value="<?=$serverName ?>" disabled/>
<input id="bpWLPassword" type="password" placeholder="<?=$wlPlaceHolder ?>" disabled style="display: none"/><button id="bpWhitelist" type="button" disabled></button>

@ -2,18 +2,16 @@
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware.
#
# lighttpd config for Pi-hole
# Lighttpd config for Pi-hole
#
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
###############################################################################
# FILE AUTOMATICALLY OVERWRITTEN BY PI-HOLE INSTALL/UPDATE PROCEDURE. #
# ANY CHANGES MADE TO THIS FILE AFTER INSTALL WILL BE LOST ON THE NEXT UPDATE #
# #
# CHANGES SHOULD BE MADE IN A SEPERATE CONFIG FILE: #
# CHANGES SHOULD BE MADE IN A SEPARATE CONFIG FILE: #
# /etc/lighttpd/external.conf #
###############################################################################
@ -39,7 +37,6 @@ server.port = 80
accesslog.filename = "/var/log/lighttpd/access.log"
accesslog.format = "%{%s}t|%V|%r|%s|%b"
index-file.names = ( "index.php", "index.html", "index.lighttpd.html" )
url.access-deny = ( "~", ".inc", ".md", ".yml", ".ini" )
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
@ -50,16 +47,19 @@ compress.filetype = ( "application/javascript", "text/css", "text/html
# default listening port for IPv6 falls back to the IPv4 port
include_shell "/usr/share/lighttpd/use-ipv6.pl " + server.port
include_shell "/usr/share/lighttpd/create-mime.assign.pl"
# Prevent Lighttpd from enabling Let's Encrypt SSL for every blocked domain
#include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
include_shell "find /etc/lighttpd/conf-enabled -name '*.conf' -a ! -name 'letsencrypt.conf' -printf 'include \"%p\"\n' 2>/dev/null"
# If the URL starts with /admin, it is the Web interface
$HTTP["url"] =~ "^/admin/" {
# Create a response header for debugging using curl -I
# Create a response header for debugging using curl -I
setenv.add-response-header = (
"X-Pi-hole" => "The Pi-hole Web interface is working!",
"X-Frame-Options" => "DENY"
)
$HTTP["url"] =~ ".ttf$" {
# Allow Block Page access to local fonts
setenv.add-response-header = ( "Access-Control-Allow-Origin" => "*" )

@ -7,13 +7,11 @@
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
###############################################################################
# FILE AUTOMATICALLY OVERWRITTEN BY PI-HOLE INSTALL/UPDATE PROCEDURE. #
# ANY CHANGES MADE TO THIS FILE AFTER INSTALL WILL BE LOST ON THE NEXT UPDATE #
# #
# CHANGES SHOULD BE MADE IN A SEPERATE CONFIG FILE: #
# CHANGES SHOULD BE MADE IN A SEPARATE CONFIG FILE: #
# /etc/lighttpd/external.conf #
###############################################################################
@ -74,11 +72,12 @@ fastcgi.server = ( ".php" =>
# If the URL starts with /admin, it is the Web interface
$HTTP["url"] =~ "^/admin/" {
# Create a response header for debugging using curl -I
# Create a response header for debugging using curl -I
setenv.add-response-header = (
"X-Pi-hole" => "The Pi-hole Web interface is working!",
"X-Frame-Options" => "DENY"
)
$HTTP["url"] =~ ".ttf$" {
# Allow Block Page access to local fonts
setenv.add-response-header = ( "Access-Control-Allow-Origin" => "*" )

@ -25,9 +25,13 @@ start() {
if is_running; then
echo "pihole-FTL is already running"
else
touch /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port
touch /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole.log
mkdir -p /var/run/pihole
mkdir -p /var/log/pihole
chown pihole:pihole /var/run/pihole /var/log/pihole
rm /var/run/pihole/FTL.sock
chown pihole:pihole /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port /etc/pihole
chmod 0644 /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port
chmod 0644 /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole.log
su -s /bin/sh -c "/usr/bin/pihole-FTL" "$FTLUSER"
echo
fi

@ -14,13 +14,10 @@
# is updated or re-installed. Please make any changes to the appropriate crontab
# or other cron file snippets.
# Pi-hole: Update the ad sources once a week on Sunday at 01:59
# Download any updates from the adlists
# Pi-hole: Update the ad sources once a week on Sunday at a random time in the
# early morning. Download any updates from the adlists
59 1 * * 7 root PATH="$PATH:/usr/local/bin/" pihole updateGravity
# Pi-hole: Update Pi-hole! Uncomment to enable auto update
#30 2 * * 7 root PATH="$PATH:/usr/local/bin/" pihole updatePihole
# Pi-hole: Flush the log daily at 00:00
# The flush script will use logrotate if available
# parameter "once": logrotate only once (default is twice)
@ -28,3 +25,10 @@
00 00 * * * root PATH="$PATH:/usr/local/bin/" pihole flush once quiet
@reboot root /usr/sbin/logrotate /etc/pihole/logrotate
# Pi-hole: Grab local version and branch every 10 minutes
*/10 * * * * root PATH="$PATH:/usr/local/bin/" pihole updatechecker local
# Pi-hole: Grab remote version every 24 hours
59 17 * * * root PATH="$PATH:/usr/local/bin/" pihole updatechecker remote
@reboot root PATH="$PATH:/usr/local/bin/" pihole updatechecker remote reboot

@ -2,7 +2,7 @@
# shellcheck disable=SC1090
# Pi-hole: A black hole for Internet advertisements
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
# (c) 2017-2018 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware.
#
# Installs and Updates Pi-hole
@ -14,7 +14,7 @@
#
# Install with this command (from your Linux machine):
#
# curl -L install.pi-hole.net | bash
# curl -sSL https://install.pi-hole.net | bash
# -e option instructs bash to immediately exit if any command [1] has a non-zero exit status
# We do not want users to end up with a partially working install, so we exit the script
@ -28,9 +28,8 @@ set -e
# Local variables will be in lowercase and will exist only within functions
# It's still a work in progress, so you may see some variance in this guideline until it is complete
# We write to a temporary file before moving the log to the pihole folder
tmpLog=/tmp/pihole-install.log
instalLogLoc=/etc/pihole/install.log
# Location for final installation log storage
installLogLoc=/etc/pihole/install.log
# This is an important file as it contains information specific to the machine it's being installed on
setupVars=/etc/pihole/setupVars.conf
# Pi-hole uses lighttpd as a Web server, and this is the config file for it
@ -208,9 +207,10 @@ elif command -v rpm &> /dev/null; then
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 net-tools newt procps-ng)
PIHOLE_DEPS=(bc bind-utils cronie curl dnsmasq findutils nmap-ncat sudo unzip wget idn2)
PIHOLE_DEPS=(bc bind-utils cronie curl dnsmasq findutils nmap-ncat sudo unzip wget libidn2 psmisc)
PIHOLE_WEB_DEPS=(lighttpd lighttpd-fastcgi php php-common php-cli php-pdo)
if ! grep -q 'Fedora' /etc/redhat-release; then
# EPEL (https://fedoraproject.org/wiki/EPEL) is required for lighttpd on CentOS
if grep -qi 'centos' /etc/redhat-release; then
INSTALLER_DEPS=("${INSTALLER_DEPS[@]}" "epel-release");
fi
LIGHTTPD_USER="lighttpd"
@ -218,7 +218,7 @@ elif command -v rpm &> /dev/null; then
LIGHTTPD_CFG="lighttpd.conf.fedora"
DNSMASQ_USER="nobody"
# If neither apt-get or rmp/dnf are not found
# If neither apt-get or rmp/dnf are found
else
# it's not an OS we can support,
echo -e " ${CROSS} OS distribution not supported"
@ -503,15 +503,21 @@ testIPv6() {
# first will contain fda2 (ULA)
first="$(cut -f1 -d":" <<< "$1")"
# value1 will contain 253 which is the decimal value corresponding to 0xfd
value1=$(((0x$first)/256))
value1=$(( (0x$first)/256 ))
# will contain 162 which is the decimal value corresponding to 0xa2
value2=$(((0x$first)%256))
value2=$(( (0x$first)%256 ))
# the ULA test is testing for fc00::/7 according to RFC 4193
(((value1&254)==252)) && echo "ULA" || true
if (( (value1&254)==252 )); then
echo "ULA"
fi
# the GUA test is testing for 2000::/3 according to RFC 4291
(((value1&112)==32)) && echo "GUA" || true
if (( (value1&112)==32 )); then
echo "GUA"
fi
# the LL test is testing for fe80::/10 according to RFC 4193
(((value1==254) && ((value2&192)==128))) && echo "Link-local" || true
if (( (value1)==254 )) && (( (value2&192)==128 )); then
echo "Link-local"
fi
}
# A dialog for showing the user about IPv6 blocking
@ -709,8 +715,8 @@ setStaticIPv4() {
}> "${IFCFG_FILE}"
# Use ip to immediately set the new address
ip addr replace dev "${PIHOLE_INTERFACE}" "${IPV4_ADDRESS}"
# If NetworkMangler command line interface exists,
if command -v nmcli &> /dev/null;then
# If NetworkMangler command line interface exists and ready to mangle,
if command -v nmcli &> /dev/null && nmcli general status &> /dev/null; then
# Tell NetworkManagler to read our new sysconfig file
nmcli con load "${IFCFG_FILE}" > /dev/null
fi
@ -764,9 +770,10 @@ setDNS() {
Norton ""
Comodo ""
DNSWatch ""
Quad9 ""
Custom "")
# In a whiptail dialog, show the options
DNSchoices=$(whiptail --separate-output --menu "Select Upstream DNS Provider. To use your own, select Custom." ${r} ${c} 6 \
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
{ echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
@ -805,6 +812,11 @@ setDNS() {
PIHOLE_DNS_1="84.200.69.80"
PIHOLE_DNS_2="84.200.70.40"
;;
Quad9)
echo "Quad9 servers"
PIHOLE_DNS_1="9.9.9.9"
PIHOLE_DNS_2="149.112.112.112"
;;
Custom)
# Until the DNS settings are selected,
until [[ "${DNSSettingsCorrect}" = True ]]; do
@ -1232,7 +1244,7 @@ install_dependent_packages() {
echo -e "${OVER} ${TICK} Checking for $i"
else
#
echo -e "${OVER} ${CROSS} Checking for $i (will be installed)"
echo -e "${OVER} ${INFO} Checking for $i (will be installed)"
#
installArray+=("${i}")
fi
@ -1257,19 +1269,19 @@ install_dependent_packages() {
if ${PKG_MANAGER} -q list installed "${i}" &> /dev/null; then
echo -e "${OVER} ${TICK} Checking for $i"
else
echo -e "${OVER} ${CROSS} Checking for $i (will be installed)"
echo -e "${OVER} ${INFO} Checking for $i (will be installed)"
#
installArray+=("${i}")
fi
done
#
if [[ "${#installArray[@]}" -gt 0 ]]; then
#
if [[ "${#installArray[@]}" -gt 0 ]]; then
#
"${PKG_INSTALL[@]}" "${installArray[@]}" &> /dev/null
return
fi
echo ""
return 0
"${PKG_INSTALL[@]}" "${installArray[@]}" &> /dev/null
return
fi
echo ""
return 0
}
# Create logfiles if necessary
@ -1323,7 +1335,7 @@ installPiholeWeb() {
else
# don't do anything
echo -e "${OVER} ${CROSS} ${str}
No default index.lighttpd.html file found... not backing up"
No default index.lighttpd.html file found... not backing up"
fi
# Install Sudoers file
@ -1356,6 +1368,10 @@ installCron() {
echo -ne " ${INFO} ${str}..."
# Copy the cron file over from the local repo
cp ${PI_HOLE_LOCAL_REPO}/advanced/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
sed -i "s/59 17/$((1 + RANDOM % 58)) $((12 + RANDOM % 8))/" /etc/cron.d/pihole
echo -e "${OVER} ${TICK} ${str}"
}
@ -1668,14 +1684,14 @@ update_dialogs() {
"${opt2a}" "${opt2b}" 3>&2 2>&1 1>&3) || \
{ echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; }
# Set the variable based on if the user user chooses
# Set the variable based on if the user chooses
case ${UpdateCmd} in
# repair, or
${opt1a})
echo -e " ${INFO} ${opt1a} option selected"
useUpdateVars=true
;;
# recongigure,
# reconfigure,
${opt2a})
echo -e " ${INFO} ${opt2a} option selected"
useUpdateVars=false
@ -1849,7 +1865,7 @@ FTLdetect() {
#If the installed version matches the latest version, then check the installed sha1sum of the binary vs the remote sha1sum. If they do not match, then download
echo -e " ${INFO} Checking for existing FTL binary..."
local ftlLoc=$(which pihole-FTL)
local ftlLoc=$(which pihole-FTL 2>/dev/null)
if [[ ${ftlLoc} ]]; then
local FTLversion=$(/usr/bin/pihole-FTL tag)
@ -1875,14 +1891,28 @@ FTLdetect() {
# Install FTL
FTLinstall "${binary}" || return 1
fi
}
make_temporary_log() {
# Create a random temporary file for the log
TEMPLOG=$(mktemp /tmp/pihole_temp.XXXXXX)
# Open handle 3 for templog
# https://stackoverflow.com/questions/18460186/writing-outputs-to-log-file-and-console
exec 3>"$TEMPLOG"
# Delete templog, but allow for addressing via file handle
# This lets us write to the log without having a temporary file on the drive, which
# is meant to be a security measure so there is not a lingering file on the drive during the install process
rm "$TEMPLOG"
}
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}"
}
main() {
######## FIRST CHECK ########
# Show the Pi-hole logo so people know it's genuine since the logo and name are trademarked
show_ascii_berry
# Must be root to install
local str="Root user check"
echo ""
@ -1891,6 +1921,9 @@ main() {
if [[ "${EUID}" -eq 0 ]]; then
# they are root and all is good
echo -e " ${TICK} ${str}"
# Show the Pi-hole logo so people know it's genuine since the logo and name are trademarked
show_ascii_berry
make_temporary_log
# Otherwise,
else
# They do not have enough privileges, so let the user know
@ -1997,8 +2030,15 @@ main() {
# just install the Core dependencies
DEPS=("${PIHOLE_DEPS[@]}")
fi
install_dependent_packages DEPS[@]
# On some systems, lighttpd is not enabled on first install. We need to enable it here if the user
# has chosen to install the web interface, else the `LIGHTTPD_ENABLED` check will fail
if [[ "${INSTALL_WEB}" == true ]]; then
enable_service lighttpd
fi
if [[ -x "$(command -v systemctl)" ]]; then
# Value will either be 1, if true, or 0
LIGHTTPD_ENABLED=$(systemctl is-enabled lighttpd | grep -c 'enabled' || true)
@ -2008,14 +2048,14 @@ main() {
fi
# Install and log everything to a file
installPihole | tee ${tmpLog}
installPihole | tee -a /proc/$$/fd/3
else
# Source ${setupVars} to use predefined user variables in the functions
source ${setupVars}
# Clone/Update the repos
clone_or_update_repos
# Source ${setupVars} for use in the rest of the functions
source ${setupVars}
# Install packages used by the Pi-hole
if [[ "${INSTALL_WEB}" == true ]]; then
# Install the Web dependencies
@ -2034,12 +2074,11 @@ main() {
# Value will either be 1, if true, or 0
LIGHTTPD_ENABLED=$(service lighttpd status | awk '/Loaded:/ {print $0}' | grep -c 'enabled' || true)
fi
updatePihole | tee ${tmpLog}
updatePihole | tee -a /proc/$$/fd/3
fi
# Move the log file into /etc/pihole for storage
mv ${tmpLog} ${instalLogLoc}
# Copy the temp log file into final log location for storage
copy_to_install_log
if [[ "${INSTALL_WEB}" == true ]]; then
# Add password to web UI if there is none
@ -2077,6 +2116,10 @@ main() {
# Download and compile the aggregated block list
runGravity
# Force an update of the updatechecker
. /opt/pihole/updatecheck.sh
. /opt/pihole/updatecheck.sh x remote
#
if [[ "${useUpdateVars}" == false ]]; then
displayFinalMessage "${pw}"
@ -2112,7 +2155,7 @@ main() {
fi
# Display where the log file is
echo -e "\\n ${INFO} The install log is located at: /etc/pihole/install.log
echo -e "\\n ${INFO} The install log is located at: ${installLogLoc}
${COL_LIGHT_GREEN}${INSTALL_TYPE} Complete! ${COL_NC}"
}

@ -68,8 +68,8 @@ if [[ -r "${piholeDir}/pihole.conf" ]]; then
fi
# Determine if DNS resolution is available before proceeding
gravity_DNSLookup() {
local lookupDomain="pi.hole" plural=""
gravity_CheckDNSResolutionAvailable() {
local lookupDomain="pi.hole"
# Determine if $localList does not exist
if [[ ! -e "${localList}" ]]; then
@ -88,6 +88,19 @@ gravity_DNSLookup() {
exit 1
fi
# If the /etc/resolv.conf contains resolvers other than 127.0.0.1 then the local dnsmasq will not be queried and pi.hole is NXDOMAIN.
# This means that even though name resolution is working, the getent hosts check fails and the holddown timer keeps ticking and eventualy fails
# So we check the output of the last command and if it failed, attempt to use dig +short as a fallback
if timeout 1 dig +short "${lookupDomain}" &> /dev/null; then
if [[ -n "${secs:-}" ]]; then
echo -e "${OVER} ${TICK} DNS resolution is now available\\n"
fi
return 0
elif [[ -n "${secs:-}" ]]; then
echo -e "${OVER} ${CROSS} DNS resolution is not available"
exit 1
fi
# Determine error output message
if pidof dnsmasq &> /dev/null; then
echo -e " ${CROSS} DNS resolution is currently unavailable"
@ -98,21 +111,20 @@ gravity_DNSLookup() {
# Ensure DNS server is given time to be resolvable
secs="120"
echo -ne " ${INFO} Waiting up to ${secs} seconds before continuing..."
echo -ne " ${INFO} Time until retry: ${secs}"
until timeout 1 getent hosts "${lookupDomain}" &> /dev/null; do
[[ "${secs:-}" -eq 0 ]] && break
[[ "${secs:-}" -ne 1 ]] && plural="s"
echo -ne "${OVER} ${INFO} Waiting up to ${secs} second${plural} before continuing..."
echo -ne "${OVER} ${INFO} Time until retry: ${secs}"
: $((secs--))
sleep 1
done
# Try again
gravity_DNSLookup
gravity_CheckDNSResolutionAvailable
}
# Retrieve blocklist URLs and parse domains from adlists.list
gravity_Collapse() {
gravity_GetBlocklistUrls() {
echo -e " ${INFO} ${COL_BOLD}Neutrino emissions detected${COL_NC}..."
# Determine if adlists file needs handling
@ -139,7 +151,8 @@ gravity_Collapse() {
awk -F '[/:]' '{
# Remove URL protocol & optional username:password@
gsub(/(.*:\/\/|.*:.*@)/, "", $0)
print $1
if(length($1)>0){print $1}
else {print "local"}
}' <<< "$(printf '%s\n' "${sources[@]}")" 2> /dev/null
)"
@ -152,7 +165,7 @@ gravity_Collapse() {
}
# Define options for when retrieving blocklists
gravity_Supernova() {
gravity_SetDownloadOptions() {
local url domain agent cmd_ext str
echo ""
@ -177,7 +190,7 @@ gravity_Supernova() {
if [[ "${skipDownload}" == false ]]; then
echo -e " ${INFO} Target: ${domain} (${url##*/})"
gravity_Pull "${url}" "${cmd_ext}" "${agent}"
gravity_DownloadBlocklistFromUrl "${url}" "${cmd_ext}" "${agent}"
echo ""
fi
done
@ -185,16 +198,17 @@ gravity_Supernova() {
}
# Download specified URL and perform checks on HTTP status and file content
gravity_Pull() {
gravity_DownloadBlocklistFromUrl() {
local url="${1}" cmd_ext="${2}" agent="${3}" heisenbergCompensator="" patternBuffer str httpCode success=""
# Create temp file to store content on disk instead of RAM
patternBuffer=$(mktemp -p "/tmp" --suffix=".phgpb")
# Determine if $saveLocation has read permission
if [[ -r "${saveLocation}" ]]; then
if [[ -r "${saveLocation}" && $url != "file"* ]]; then
# Have curl determine if a remote file has been modified since last retrieval
# Uses "Last-Modified" header, which certain web servers do not provide (e.g: raw github urls)
# Note: Don't do this for local files, always download them
heisenbergCompensator="-z ${saveLocation}"
fi
@ -203,20 +217,32 @@ gravity_Pull() {
# shellcheck disable=SC2086
httpCode=$(curl -s -L ${cmd_ext} ${heisenbergCompensator} -w "%{http_code}" -A "${agent}" "${url}" -o "${patternBuffer}" 2> /dev/null)
# Determine "Status:" output based on HTTP response
case "${httpCode}" in
"200") echo -e "${OVER} ${TICK} ${str} Retrieval successful"; success=true;;
"304") echo -e "${OVER} ${TICK} ${str} No changes detected"; success=true;;
"000") echo -e "${OVER} ${CROSS} ${str} Connection Refused";;
"403") echo -e "${OVER} ${CROSS} ${str} Forbidden";;
"404") echo -e "${OVER} ${CROSS} ${str} Not found";;
"408") echo -e "${OVER} ${CROSS} ${str} Time-out";;
"451") echo -e "${OVER} ${CROSS} ${str} Unavailable For Legal Reasons";;
"500") echo -e "${OVER} ${CROSS} ${str} Internal Server Error";;
"504") echo -e "${OVER} ${CROSS} ${str} Connection Timed Out (Gateway)";;
"521") echo -e "${OVER} ${CROSS} ${str} Web Server Is Down (Cloudflare)";;
"522") echo -e "${OVER} ${CROSS} ${str} Connection Timed Out (Cloudflare)";;
* ) echo -e "${OVER} ${CROSS} ${str} ${httpCode}";;
case $url in
# Did we "download" a remote file?
"http"*)
# Determine "Status:" output based on HTTP response
case "${httpCode}" in
"200") echo -e "${OVER} ${TICK} ${str} Retrieval successful"; success=true;;
"304") echo -e "${OVER} ${TICK} ${str} No changes detected"; success=true;;
"000") echo -e "${OVER} ${CROSS} ${str} Connection Refused";;
"403") echo -e "${OVER} ${CROSS} ${str} Forbidden";;
"404") echo -e "${OVER} ${CROSS} ${str} Not found";;
"408") echo -e "${OVER} ${CROSS} ${str} Time-out";;
"451") echo -e "${OVER} ${CROSS} ${str} Unavailable For Legal Reasons";;
"500") echo -e "${OVER} ${CROSS} ${str} Internal Server Error";;
"504") echo -e "${OVER} ${CROSS} ${str} Connection Timed Out (Gateway)";;
"521") echo -e "${OVER} ${CROSS} ${str} Web Server Is Down (Cloudflare)";;
"522") echo -e "${OVER} ${CROSS} ${str} Connection Timed Out (Cloudflare)";;
* ) echo -e "${OVER} ${CROSS} ${str} ${httpCode}";;
esac;;
# Did we "download" a local file?
"file"*)
if [[ -s "${patternBuffer}" ]]; then
echo -e "${OVER} ${TICK} ${str} Retrieval successful"; success=true
else
echo -e "${OVER} ${CROSS} ${str} Not found / empty list"
fi;;
*) echo -e "${OVER} ${CROSS} ${str} ${url} ${httpCode}";;
esac
# Determine if the blocklist was downloaded and saved correctly
@ -243,36 +269,22 @@ gravity_Pull() {
# Parse source files into domains format
gravity_ParseFileIntoDomains() {
local source="${1}" destination="${2}" commentPattern firstLine abpFilter
local source="${1}" destination="${2}" firstLine abpFilter
# Determine if we are parsing a consolidated list
if [[ "${source}" == "${piholeDir}/${matterAndLight}" ]]; then
# Define symbols used as comments: #;@![/
commentPattern="[#;@![\\/]"
# Parse Domains/Hosts files by removing comments & host IPs
# Logic: Ignore lines which begin with comments
awk '!/^'"${commentPattern}"'/ {
# Determine if there are multiple words seperated by a space
if(NF>1) {
# Remove comments (including prefixed spaces/tabs)
if($0 ~ /'"${commentPattern}"'/) { gsub("( |\t)'"${commentPattern}"'.*", "", $0) }
# Determine if there are aliased domains
if($3) {
# Remove IP address
$1=""
# Remove space which is left in $0 when removing $1
gsub("^ ", "", $0)
print $0
} else if($2) {
# Print single domain without IP
print $2
}
# If there are no words seperated by space
} else if($1) {
print $1
}
}' "${source}" 2> /dev/null > "${destination}"
# Remove comments and print only the domain name
# 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 left field (the domain) and leave
#+ the right (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}
return 0
fi
@ -353,7 +365,7 @@ gravity_ParseFileIntoDomains() {
}
# Create (unfiltered) "Matter and Light" consolidated list
gravity_Schwarzschild() {
gravity_ConsolidateDownloadedBlocklists() {
local str lastLine
str="Consolidating blocklists"
@ -381,7 +393,7 @@ gravity_Schwarzschild() {
}
# Parse consolidated list into (filtered, unique) domains-only format
gravity_Filter() {
gravity_SortAndFilterConsolidatedList() {
local str num
str="Extracting domains from blocklists"
@ -393,7 +405,7 @@ gravity_Filter() {
# Format $parsedMatter line total as currency
num=$(printf "%'.0f" "$(wc -l < "${piholeDir}/${parsedMatter}")")
echo -e "${OVER} ${TICK} ${str}
${INFO} ${COL_BLUE}${num}${COL_NC} domains being pulled in by gravity"
${INFO} Number of domains being pulled in by gravity: ${COL_BLUE}${num}${COL_NC}"
str="Removing duplicate domains"
echo -ne " ${INFO} ${str}..."
@ -402,31 +414,30 @@ gravity_Filter() {
# Format $preEventHorizon line total as currency
num=$(printf "%'.0f" "$(wc -l < "${piholeDir}/${preEventHorizon}")")
echo -e " ${INFO} ${COL_BLUE}${num}${COL_NC} unique domains trapped in the Event Horizon"
echo -e " ${INFO} Number of unique domains trapped in the Event Horizon: ${COL_BLUE}${num}${COL_NC}"
}
# Whitelist unique blocklist domain sources
gravity_WhitelistBLD() {
local uniqDomains plural="" str
gravity_WhitelistBlocklistSourceUrls() {
local uniqDomains str
echo ""
# Create array of unique $sourceDomains
mapfile -t uniqDomains <<< "$(awk '{ if(!a[$1]++) { print $1 } }' <<< "$(printf '%s\n' "${sourceDomains[@]}")")"
[[ "${#uniqDomains[@]}" -ne 1 ]] && plural="s"
str="Adding ${#uniqDomains[@]} blocklist source domain${plural} to the whitelist"
str="Number of blocklist source domains being added to the whitelist: ${#uniqDomains[@]}"
echo -ne " ${INFO} ${str}..."
# Whitelist $uniqDomains
"${PIHOLE_COMMAND}" -w -nr -q "${uniqDomains[*]}" &> /dev/null
"${PIHOLE_COMMAND}" -w -nr -q ${uniqDomains[*]} &> /dev/null
echo -e "${OVER} ${TICK} ${str}"
echo -e "${OVER} ${INFO} ${str}"
}
# Whitelist user-defined domains
gravity_Whitelist() {
local num plural="" str
local num str
if [[ ! -f "${whitelistFile}" ]]; then
echo -e " ${INFO} Nothing to whitelist!"
@ -434,24 +445,22 @@ gravity_Whitelist() {
fi
num=$(wc -l < "${whitelistFile}")
[[ "${num}" -ne 1 ]] && plural="s"
str="Whitelisting ${num} domain${plural}"
str="Number of whitelisted domains: ${num}"
echo -ne " ${INFO} ${str}..."
# Print everything from preEventHorizon into whitelistMatter EXCEPT domains in $whitelistFile
grep -F -x -v -f "${whitelistFile}" "${piholeDir}/${preEventHorizon}" > "${piholeDir}/${whitelistMatter}"
echo -e "${OVER} ${TICK} ${str}"
echo -e "${OVER} ${INFO} ${str}"
}
# Output count of blacklisted domains and wildcards
gravity_ShowBlockCount() {
local num plural
local num
if [[ -f "${blacklistFile}" ]]; then
num=$(printf "%'.0f" "$(wc -l < "${blacklistFile}")")
plural=; [[ "${num}" -ne 1 ]] && plural="s"
echo -e " ${INFO} Blacklisted ${num} domain${plural}"
echo -e " ${INFO} Number of blacklisted domains: ${num}"
fi
if [[ -f "${wildcardFile}" ]]; then
@ -460,8 +469,7 @@ gravity_ShowBlockCount() {
if [[ -n "${IPV4_ADDRESS}" ]] && [[ -n "${IPV6_ADDRESS}" ]];then
num=$(( num/2 ))
fi
plural=; [[ "${num}" -ne 1 ]] && plural="s"
echo -e " ${INFO} Wildcard blocked ${num} domain${plural}"
echo -e " ${INFO} Number of wildcard blocked domains: ${num}"
fi
}
@ -555,7 +563,7 @@ gravity_Cleanup() {
rm ${piholeDir}/*.tmp 2> /dev/null
rm /tmp/*.phgpb 2> /dev/null
# Ensure this function only runs when gravity_Supernova() has completed
# Ensure this function only runs when gravity_SetDownloadOptions() has completed
if [[ "${gravity_Blackbody:-}" == true ]]; then
# Remove any unused .domains files
for file in ${piholeDir}/*.${domainsExtension}; do
@ -617,12 +625,12 @@ fi
# Determine which functions to run
if [[ "${skipDownload}" == false ]]; then
# Gravity needs to download blocklists
gravity_DNSLookup
gravity_Collapse
gravity_Supernova
gravity_Schwarzschild
gravity_Filter
gravity_WhitelistBLD
gravity_CheckDNSResolutionAvailable
gravity_GetBlocklistUrls
gravity_SetDownloadOptions
gravity_ConsolidateDownloadedBlocklists
gravity_SortAndFilterConsolidatedList
gravity_WhitelistBlocklistSourceUrls
else
# Gravity needs to modify Blacklist/Whitelist/Wildcards
echo -e " ${INFO} Using cached Event Horizon list..."

@ -85,7 +85,8 @@ updateGravityFunc() {
# Scan an array of files for matching strings
scanList(){
local domain="${1}" lists="${2}" type="${3:-}"
# Escape full stops
local domain="${1//./\\.}" lists="${2}" type="${3:-}"
# Prevent grep from printing file path
cd "/etc/pihole" || exit 1
@ -154,7 +155,7 @@ Options:
# Strip valid options, leaving only the domain and invalid options
# This allows users to place the options before or after the domain
options=$(sed -E 's/ ?-(bp|adlists?|all|exact)//g' <<< "${options}")
options=$(sed -E 's/ ?-(bp|adlists?|all|exact) ?//g' <<< "${options}")
# Handle remaining options
# If $options contain non ASCII characters, convert to punycode
@ -199,7 +200,7 @@ Options:
# Scan Wildcards
if [[ -e "${wildcardlist}" ]]; then
# Determine all subdomains, domain and TLDs
# Determine all subdomains, domain and TLDs
mapfile -t wildcards <<< "$(processWildcards "${domainQuery}")"
for match in "${wildcards[@]}"; do
@ -335,7 +336,7 @@ restartDNS() {
if [[ "${svcOption}" =~ "reload" ]]; then
# Using SIGHUP will NOT re-read any *.conf files
svc="killall -s SIGHUP dnsmasq"
elif [[ -z "${svcOption}" ]]; then
else
# Get PID of dnsmasq to determine if it needs to start or restart
if pidof dnsmasq &> /dev/null; then
svcOption="restart"
@ -358,6 +359,9 @@ restartDNS() {
[[ ! -t 1 ]] && local OVER=""
echo -e "${OVER} ${CROSS} ${output}"
fi
# Send signal to FTL to have it re-parse the gravity files
killall -s SIGHUP pihole-FTL
}
piholeEnable() {
@ -440,13 +444,17 @@ Specify whether the Pi-hole log should be used
Options:
on Enable the Pi-hole log at /var/log/pihole.log
off Disable the Pi-hole log at /var/log/pihole.log"
off Disable and flush the Pi-hole log at /var/log/pihole.log
off noflush Disable the Pi-hole log at /var/log/pihole.log"
exit 0
elif [[ "${1}" == "off" ]]; then
# Disable logging
sed -i 's/^log-queries/#log-queries/' /etc/dnsmasq.d/01-pihole.conf
sed -i 's/^QUERY_LOGGING=true/QUERY_LOGGING=false/' /etc/pihole/setupVars.conf
pihole -f
if [[ "${2}" != "noflush" ]]; then
# Flush logs
pihole -f
fi
echo -e " ${INFO} Disabling logging..."
local str="Logging has been disabled!"
elif [[ "${1}" == "on" ]]; then
@ -482,7 +490,7 @@ statusFunc() {
# Determine if Pi-hole's addn-hosts configs are commented out
addnConfigs=$(grep -i "addn-hosts=/" /etc/dnsmasq.d/01-pihole.conf)
if [[ "${addnConfigs}" =~ "#" ]]; then
# A config is commented out
case "${1}" in
@ -578,6 +586,11 @@ tricorderFunc() {
fi
}
updateCheckFunc() {
"${PI_HOLE_SCRIPT_DIR}"/updatecheck.sh "$@"
exit 0
}
helpFunc() {
echo "Usage: pihole [options]
Example: 'pihole -w -h'
@ -649,5 +662,6 @@ case "${1}" in
"-t" | "tail" ) tailFunc;;
"checkout" ) piholeCheckoutFunc "$@";;
"tricorder" ) tricorderFunc;;
"updatechecker" ) updateCheckFunc "$@";;
* ) helpFunc;;
esac

Loading…
Cancel
Save