1
0
mirror of https://github.com/pi-hole/pi-hole synced 2024-12-23 15:28:07 +00:00
pi-hole/advanced/Scripts/webpage.sh

513 lines
13 KiB
Bash
Raw Normal View History

2016-11-16 20:34:43 +00:00
#!/usr/bin/env bash
# Pi-hole: A black hole for Internet advertisements
2017-02-22 17:55:20 +00:00
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
# Network-wide ad blocking via your own hardware.
#
# Web interface settings
2016-11-16 20:34:43 +00:00
#
2017-02-22 17:55:20 +00:00
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
2016-12-28 02:14:47 +00:00
readonly setupVars="/etc/pihole/setupVars.conf"
readonly dnsmasqconfig="/etc/dnsmasq.d/01-pihole.conf"
readonly dhcpconfig="/etc/dnsmasq.d/02-pihole-dhcp.conf"
2017-01-25 09:33:25 +00:00
# 03 -> wildcards
readonly dhcpstaticconfig="/etc/dnsmasq.d/04-pihole-static-dhcp.conf"
2016-12-28 02:14:47 +00:00
coltable="/opt/pihole/COL_TABLE"
if [[ -f ${coltable} ]]; then
source ${coltable}
fi
2016-11-16 20:34:43 +00:00
helpFunc() {
echo "Usage: pihole -a [options]
Example: pihole -a -p password
Set options for the Admin Console
Options:
-p, password Set Admin Console password
-c, celsius Set Celsius as preferred temperature unit
-f, fahrenheit Set Fahrenheit as preferred temperature unit
-k, kelvin Set Kelvin as preferred temperature unit
-r, hostrecord Add a name to the DNS associated to an IPv4/IPv6 address
-h, --help Show this help dialog
-i, interface Specify dnsmasq's interface listening behavior
Add '-h' for more info on interface usage"
exit 0
2016-11-16 20:34:43 +00:00
}
2016-12-28 02:14:47 +00:00
add_setting() {
echo "${1}=${2}" >> "${setupVars}"
}
delete_setting() {
sed -i "/${1}/d" "${setupVars}"
}
change_setting() {
delete_setting "${1}"
add_setting "${1}" "${2}"
}
add_dnsmasq_setting() {
if [[ "${2}" != "" ]]; then
echo "${1}=${2}" >> "${dnsmasqconfig}"
else
echo "${1}" >> "${dnsmasqconfig}"
fi
}
delete_dnsmasq_setting() {
sed -i "/${1}/d" "${dnsmasqconfig}"
}
SetTemperatureUnit() {
2016-12-28 02:14:47 +00:00
change_setting "TEMPERATUREUNIT" "${unit}"
echo -e " ${TICK} Set temperature unit to ${unit}"
2016-11-16 20:34:43 +00:00
}
HashPassword() {
# Compute password hash twice to avoid rainbow table vulnerability
return=$(echo -n ${1} | sha256sum | sed 's/\s.*$//')
return=$(echo -n ${return} | sha256sum | sed 's/\s.*$//')
echo ${return}
2017-05-02 21:24:37 +00:00
}
SetWebPassword() {
2016-12-13 14:54:41 +00:00
if [ "${SUDO_USER}" == "www-data" ]; then
echo "Security measure: user www-data is not allowed to change webUI password!"
echo "Exiting"
exit 1
fi
2016-12-13 14:54:41 +00:00
if [ "${SUDO_USER}" == "lighttpd" ]; then
echo "Security measure: user lighttpd is not allowed to change webUI password!"
echo "Exiting"
exit 1
fi
if (( ${#args[2]} > 0 )) ; then
readonly PASSWORD="${args[2]}"
readonly CONFIRM="${PASSWORD}"
else
# Prevents a bug if the user presses Ctrl+C and it continues to hide the text typed.
2017-07-07 01:44:40 +00:00
# So we reset the terminal via stty if the user does press Ctrl+C
trap '{ echo -e "\nNo password will be set" ; stty sane ; exit 1; }' INT
read -s -p "Enter New Password (Blank for no password): " PASSWORD
echo ""
if [ "${PASSWORD}" == "" ]; then
change_setting "WEBPASSWORD" ""
echo -e " ${TICK} Password Removed"
exit 0
fi
read -s -p "Confirm Password: " CONFIRM
echo ""
fi
2017-03-27 17:37:19 +00:00
2017-03-23 22:47:30 +00:00
if [ "${PASSWORD}" == "${CONFIRM}" ] ; then
2017-05-02 21:24:37 +00:00
hash=$(HashPassword ${PASSWORD})
# Save hash to file
2016-12-28 02:14:47 +00:00
change_setting "WEBPASSWORD" "${hash}"
echo -e " ${TICK} New password set"
else
echo -e " ${CROSS} Passwords don't match. Your password has not been changed"
2017-03-23 22:47:30 +00:00
exit 1
fi
2016-11-16 20:34:43 +00:00
}
2016-12-28 02:14:47 +00:00
ProcessDNSSettings() {
source "${setupVars}"
2017-01-13 16:49:55 +00:00
delete_dnsmasq_setting "server"
COUNTER=1
while [[ 1 ]]; do
var=PIHOLE_DNS_${COUNTER}
if [ -z "${!var}" ]; then
break;
fi
add_dnsmasq_setting "server" "${!var}"
let COUNTER=COUNTER+1
done
2016-12-28 02:14:47 +00:00
delete_dnsmasq_setting "domain-needed"
if [[ "${DNS_FQDN_REQUIRED}" == true ]]; then
add_dnsmasq_setting "domain-needed"
fi
delete_dnsmasq_setting "bogus-priv"
if [[ "${DNS_BOGUS_PRIV}" == true ]]; then
add_dnsmasq_setting "bogus-priv"
fi
2017-01-12 15:02:41 +00:00
delete_dnsmasq_setting "dnssec"
delete_dnsmasq_setting "trust-anchor="
if [[ "${DNSSEC}" == true ]]; then
echo "dnssec
trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
" >> "${dnsmasqconfig}"
fi
2017-02-22 13:43:07 +00:00
delete_dnsmasq_setting "host-record"
2017-03-06 13:02:56 +00:00
if [ ! -z "${HOSTRECORD}" ]; then
2017-02-22 13:43:07 +00:00
add_dnsmasq_setting "host-record" "${HOSTRECORD}"
fi
# Setup interface listening behavior of dnsmasq
delete_dnsmasq_setting "interface"
delete_dnsmasq_setting "local-service"
2017-03-01 09:59:55 +00:00
if [[ "${DNSMASQ_LISTENING}" == "all" ]]; then
# Listen on all interfaces, permit all origins
add_dnsmasq_setting "except-interface" "nonexisting"
elif [[ "${DNSMASQ_LISTENING}" == "local" ]]; then
# Listen only on all interfaces, but only local subnets
add_dnsmasq_setting "local-service"
else
# Listen only on one interface
add_dnsmasq_setting "interface" "${PIHOLE_INTERFACE}"
fi
2016-12-28 02:14:47 +00:00
}
SetDNSServers() {
2016-12-11 15:54:27 +00:00
# Save setting to file
2017-01-13 16:49:55 +00:00
delete_setting "PIHOLE_DNS"
IFS=',' read -r -a array <<< "${args[2]}"
for index in "${!array[@]}"
do
add_setting "PIHOLE_DNS_$((index+1))" "${array[index]}"
done
if [[ "${args[3]}" == "domain-needed" ]]; then
2016-12-28 02:14:47 +00:00
change_setting "DNS_FQDN_REQUIRED" "true"
2016-12-14 15:09:57 +00:00
else
2016-12-28 02:14:47 +00:00
change_setting "DNS_FQDN_REQUIRED" "false"
2016-12-14 15:09:57 +00:00
fi
2016-12-14 15:16:25 +00:00
2017-01-13 16:49:55 +00:00
if [[ "${args[4]}" == "bogus-priv" ]]; then
2016-12-28 02:14:47 +00:00
change_setting "DNS_BOGUS_PRIV" "true"
2016-12-14 15:16:25 +00:00
else
2016-12-28 02:14:47 +00:00
change_setting "DNS_BOGUS_PRIV" "false"
2016-12-14 15:16:25 +00:00
fi
2016-12-14 15:09:57 +00:00
2017-01-13 16:49:55 +00:00
if [[ "${args[5]}" == "dnssec" ]]; then
2017-01-12 15:02:41 +00:00
change_setting "DNSSEC" "true"
else
change_setting "DNSSEC" "false"
fi
2017-01-05 20:45:06 +00:00
ProcessDNSSettings
2016-12-28 02:14:47 +00:00
# Restart dnsmasq to load new configuration
RestartDNS
2016-12-11 15:54:27 +00:00
}
SetExcludeDomains() {
2016-12-28 02:14:47 +00:00
change_setting "API_EXCLUDE_DOMAINS" "${args[2]}"
}
SetExcludeClients() {
2016-12-28 02:14:47 +00:00
change_setting "API_EXCLUDE_CLIENTS" "${args[2]}"
}
Poweroff(){
nohup bash -c "sleep 5; poweroff" &> /dev/null </dev/null &
}
Reboot() {
nohup bash -c "sleep 5; reboot" &> /dev/null </dev/null &
2016-12-11 21:33:27 +00:00
}
RestartDNS() {
local str="Restarting DNS service"
[[ -t 1 ]] && echo -ne " ${INFO} ${str}"
if command -v systemctl &> /dev/null; then
output=$( { systemctl restart dnsmasq; } 2>&1 )
else
output=$( { service dnsmasq restart; } 2>&1 )
fi
2016-12-12 09:38:21 +00:00
if [[ -z "${output}" ]]; then
[[ -t 1 ]] && echo -e "${OVER} ${TICK} ${str}"
else
[[ ! -t 1 ]] && OVER=""
echo -e "${OVER} ${CROSS} ${output}"
fi
2016-12-12 09:38:21 +00:00
}
SetQueryLogOptions() {
2016-12-28 02:14:47 +00:00
change_setting "API_QUERY_LOG_SHOW" "${args[2]}"
}
ProcessDHCPSettings() {
source "${setupVars}"
2017-01-02 09:50:59 +00:00
if [[ "${DHCP_ACTIVE}" == "true" ]]; then
interface=$(grep 'PIHOLE_INTERFACE=' /etc/pihole/setupVars.conf | sed "s/.*=//")
2017-01-02 09:50:59 +00:00
# Use eth0 as fallback interface
if [ -z ${interface} ]; then
interface="eth0"
fi
2016-12-28 02:14:47 +00:00
if [[ "${PIHOLE_DOMAIN}" == "" ]]; then
PIHOLE_DOMAIN="local"
change_setting "PIHOLE_DOMAIN" "${PIHOLE_DOMAIN}"
fi
if [[ "${DHCP_LEASETIME}" == "0" ]]; then
leasetime="infinite"
elif [[ "${DHCP_LEASETIME}" == "" ]]; then
2017-07-28 15:30:03 +00:00
leasetime="24"
change_setting "DHCP_LEASETIME" "${leasetime}"
elif [[ "${DHCP_LEASETIME}" == "24h" ]]; then
#Installation is affected by known bug, introduced in a previous version.
#This will automatically clean up setupVars.conf and remove the unnecessary "h"
leasetime="24"
change_setting "DHCP_LEASETIME" "${leasetime}"
else
leasetime="${DHCP_LEASETIME}h"
fi
# Write settings to file
echo "###############################################################################
2016-12-28 02:14:47 +00:00
# DHCP SERVER CONFIG FILE AUTOMATICALLY POPULATED BY PI-HOLE WEB INTERFACE. #
# ANY CHANGES MADE TO THIS FILE WILL BE LOST ON CHANGE #
###############################################################################
dhcp-authoritative
dhcp-range=${DHCP_START},${DHCP_END},${leasetime}
2016-12-28 02:14:47 +00:00
dhcp-option=option:router,${DHCP_ROUTER}
dhcp-leasefile=/etc/pihole/dhcp.leases
2016-12-30 16:31:57 +00:00
#quiet-dhcp
" > "${dhcpconfig}"
if [[ "${PIHOLE_DOMAIN}" != "none" ]]; then
echo "domain=${PIHOLE_DOMAIN}" >> "${dhcpconfig}"
fi
if [[ "${DHCP_IPv6}" == "true" ]]; then
echo "#quiet-dhcp6
2016-12-28 02:14:47 +00:00
#enable-ra
dhcp-option=option6:dns-server,[::]
2016-12-29 14:26:23 +00:00
dhcp-range=::100,::1ff,constructor:${interface},ra-names,slaac,${leasetime}
2016-12-28 20:02:48 +00:00
ra-param=*,0,0
" >> "${dhcpconfig}"
fi
2016-12-28 02:14:47 +00:00
2017-01-02 09:50:59 +00:00
else
if [[ -f "${dhcpconfig}" ]]; then
rm "${dhcpconfig}" &> /dev/null
fi
2017-01-02 09:50:59 +00:00
fi
2016-12-12 12:15:07 +00:00
}
EnableDHCP() {
2016-12-28 02:14:47 +00:00
change_setting "DHCP_ACTIVE" "true"
change_setting "DHCP_START" "${args[2]}"
change_setting "DHCP_END" "${args[3]}"
change_setting "DHCP_ROUTER" "${args[4]}"
change_setting "DHCP_LEASETIME" "${args[5]}"
change_setting "PIHOLE_DOMAIN" "${args[6]}"
change_setting "DHCP_IPv6" "${args[7]}"
2016-12-12 14:34:05 +00:00
2016-12-28 02:14:47 +00:00
# Remove possible old setting from file
delete_dnsmasq_setting "dhcp-"
delete_dnsmasq_setting "quiet-dhcp"
ProcessDHCPSettings
2016-12-12 14:34:05 +00:00
RestartDNS
}
DisableDHCP() {
2016-12-28 02:14:47 +00:00
change_setting "DHCP_ACTIVE" "false"
# Remove possible old setting from file
delete_dnsmasq_setting "dhcp-"
delete_dnsmasq_setting "quiet-dhcp"
2016-12-12 14:34:05 +00:00
2017-01-02 09:50:59 +00:00
ProcessDHCPSettings
2016-12-12 14:34:05 +00:00
RestartDNS
}
SetWebUILayout() {
2016-12-28 02:14:47 +00:00
change_setting "WEBUIBOXEDLAYOUT" "${args[2]}"
2016-12-13 13:59:52 +00:00
}
2017-03-31 18:35:52 +00:00
CustomizeAdLists() {
2017-03-31 19:05:45 +00:00
list="/etc/pihole/adlists.list"
2017-03-31 18:35:52 +00:00
if [[ "${args[2]}" == "enable" ]]; then
2017-03-31 18:35:52 +00:00
sed -i "\\@${args[3]}@s/^#http/http/g" "${list}"
elif [[ "${args[2]}" == "disable" ]]; then
2017-03-31 18:35:52 +00:00
sed -i "\\@${args[3]}@s/^http/#http/g" "${list}"
elif [[ "${args[2]}" == "add" ]]; then
2017-03-31 19:13:04 +00:00
echo "${args[3]}" >> ${list}
elif [[ "${args[2]}" == "del" ]]; then
2017-03-31 22:00:56 +00:00
var=$(echo "${args[3]}" | sed 's/\//\\\//g')
sed -i "/${var}/Id" "${list}"
2017-03-31 18:35:52 +00:00
else
echo "Not permitted"
return 1
fi
}
SetPrivacyMode() {
if [[ "${args[2]}" == "true" ]]; then
2016-12-28 02:14:47 +00:00
change_setting "API_PRIVACY_MODE" "true"
2016-12-16 16:33:01 +00:00
else
2016-12-28 02:14:47 +00:00
change_setting "API_PRIVACY_MODE" "false"
2016-12-16 16:33:01 +00:00
fi
}
ResolutionSettings() {
2016-12-28 02:14:47 +00:00
typ="${args[2]}"
state="${args[3]}"
if [[ "${typ}" == "forward" ]]; then
2016-12-28 02:14:47 +00:00
change_setting "API_GET_UPSTREAM_DNS_HOSTNAME" "${state}"
elif [[ "${typ}" == "clients" ]]; then
2016-12-28 02:14:47 +00:00
change_setting "API_GET_CLIENT_HOSTNAME" "${state}"
fi
2016-12-16 16:33:01 +00:00
}
2017-01-25 09:33:25 +00:00
AddDHCPStaticAddress() {
mac="${args[2]}"
ip="${args[3]}"
host="${args[4]}"
if [[ "${ip}" == "noip" ]]; then
# Static host name
echo "dhcp-host=${mac},${host}" >> "${dhcpstaticconfig}"
2017-01-25 09:33:25 +00:00
elif [[ "${host}" == "nohost" ]]; then
# Static IP
echo "dhcp-host=${mac},${ip}" >> "${dhcpstaticconfig}"
2017-01-25 09:33:25 +00:00
else
# Full info given
echo "dhcp-host=${mac},${ip},${host}" >> "${dhcpstaticconfig}"
2017-01-25 09:33:25 +00:00
fi
}
RemoveDHCPStaticAddress() {
mac="${args[2]}"
sed -i "/dhcp-host=${mac}.*/d" "${dhcpstaticconfig}"
}
SetHostRecord() {
if [[ "${1}" == "-h" ]] || [[ "${1}" == "--help" ]]; then
echo "Usage: pihole -a hostrecord <domain> [IPv4-address],[IPv6-address]
Example: 'pihole -a hostrecord home.domain.com 192.168.1.1,2001:db8:a0b:12f0::1'
Add a name to the DNS associated to an IPv4/IPv6 address
Options:
\"\" Empty: Remove host record
-h, --help Show this help dialog"
exit 0
fi
if [[ -n "${args[3]}" ]]; then
2017-02-22 13:43:07 +00:00
change_setting "HOSTRECORD" "${args[2]},${args[3]}"
echo -e " ${TICK} Setting host record for ${args[2]} to ${args[3]}"
2017-02-22 13:43:07 +00:00
else
change_setting "HOSTRECORD" ""
echo -e " ${TICK} Removing host record"
2017-02-22 13:43:07 +00:00
fi
ProcessDNSSettings
# Restart dnsmasq to load new configuration
RestartDNS
}
SetListeningMode() {
source "${setupVars}"
2017-05-14 01:47:56 +00:00
if [[ "$3" == "-h" ]] || [[ "$3" == "--help" ]]; then
echo "Usage: pihole -a -i [interface]
Example: 'pihole -a -i local'
Specify dnsmasq's network interface listening behavior
Interfaces:
local Listen on all interfaces, but only allow queries from
devices that are at most one hop away (local devices)
single Listen only on ${PIHOLE_INTERFACE} interface
all Listen on all interfaces, permit all origins"
exit 0
fi
if [[ "${args[2]}" == "all" ]]; then
echo -e " ${INFO} Listening on all interfaces, permiting all origins. Please use a firewall!"
change_setting "DNSMASQ_LISTENING" "all"
elif [[ "${args[2]}" == "local" ]]; then
echo -e " ${INFO} Listening on all interfaces, permiting origins from one hop away (LAN)"
change_setting "DNSMASQ_LISTENING" "local"
else
echo -e " ${INFO} Listening only on interface ${PIHOLE_INTERFACE}"
change_setting "DNSMASQ_LISTENING" "single"
fi
# Don't restart DNS server yet because other settings
# will be applied afterwards if "-web" is set
if [[ "${args[3]}" != "-web" ]]; then
ProcessDNSSettings
# Restart dnsmasq to load new configuration
RestartDNS
fi
}
Teleporter() {
2017-03-05 13:08:44 +00:00
local datetimestamp=$(date "+%Y-%m-%d_%H-%M-%S")
php /var/www/html/admin/scripts/pi-hole/php/teleporter.php > "pi-hole-teleporter_${datetimestamp}.zip"
}
audit()
{
echo "${args[2]}" >> /etc/pihole/auditlog.list
}
2016-12-28 16:25:14 +00:00
main() {
args=("$@")
case "${args[1]}" in
"-p" | "password" ) SetWebPassword;;
"-c" | "celsius" ) unit="C"; SetTemperatureUnit;;
"-f" | "fahrenheit" ) unit="F"; SetTemperatureUnit;;
"-k" | "kelvin" ) unit="K"; SetTemperatureUnit;;
"setdns" ) SetDNSServers;;
"setexcludedomains" ) SetExcludeDomains;;
"setexcludeclients" ) SetExcludeClients;;
"poweroff" ) Poweroff;;
2016-12-28 16:25:14 +00:00
"reboot" ) Reboot;;
"restartdns" ) RestartDNS;;
"setquerylog" ) SetQueryLogOptions;;
"enabledhcp" ) EnableDHCP;;
"disabledhcp" ) DisableDHCP;;
"layout" ) SetWebUILayout;;
"-h" | "--help" ) helpFunc;;
"privacymode" ) SetPrivacyMode;;
"resolve" ) ResolutionSettings;;
2017-01-25 09:35:45 +00:00
"addstaticdhcp" ) AddDHCPStaticAddress;;
"removestaticdhcp" ) RemoveDHCPStaticAddress;;
"-r" | "hostrecord" ) SetHostRecord "$3";;
"-i" | "interface" ) SetListeningMode "$@";;
2017-03-05 13:08:44 +00:00
"-t" | "teleporter" ) Teleporter;;
2017-03-31 19:03:56 +00:00
"adlist" ) CustomizeAdLists;;
"audit" ) audit;;
2016-12-28 16:25:14 +00:00
* ) helpFunc;;
esac
shift
if [[ $# = 0 ]]; then
helpFunc
fi
}