Updated for Pi-Hole v6!

This commit is contained in:
iRaven 2025-04-30 20:15:41 -05:00
parent b23e2d93aa
commit 5cbb03f774

136
main.py
View File

@ -49,12 +49,34 @@ def loginToNPM(apiurl, user, pw): # To retrieve NPM's API session token
return None return None
def loginToPihole(serveraddr, phpassword, session):
def loginToPihole(apiurl, phpassword): # NEW Method as of Pi-Hole version 6.0 and newer.
# I truly appreciate them fixing but this broke so many things.
apiurl = "http://" + serveraddr + "/api/auth"
passwordjson = {"password": phpassword}
loginrq = session.request("POST", apiurl, json=passwordjson, verify=False)
log.debug("Sent POST for getting Pi-hole API authorization.")
if loginrq.status_code == 200: # yay
log.debug("API returned a 200, proceeding.") # We're good c:
log.info("Logged into Pi-hole API on "+serveraddr+"!")
fullresponse = loginrq.json()
phpsessid = fullresponse["session"]["sid"]
token = fullresponse["session"]["csrf"]
log.debug("phpsessid: " + phpsessid + " Token: "+ token)
return {'phpsessid': phpsessid, "csrftoken": token}
elif loginrq.status_code == 401: # Unauthorized
log.debug("Pi-hole returned a 401, halting!")
log.error("The Pi-hole retured an unauthorized error!")
log.error("Please make sure your Pi-hole password in conf.json is correct and accurate.")
return None
else:
log.error("Pi-hole returned this " + str(apireq.status_code) + " in error: "+ apireq.text)
def loginToPiholeOld(apiurl, phpassword):
# For whatever reason, Pi-hole's web CSRF token is in a hidden <div> element returned by the login.php in the homepage right after you login. # For whatever reason, Pi-hole's web CSRF token is in a hidden <div> element returned by the login.php in the homepage right after you login.
# This took *WAY* too long to figure out. This should be in the header for ease-of-use. # This took *WAY* too long to figure out. This should be in the header for ease-of-use.
session = requests.Session() session = requests.Session()
url = apiurl + "/login.php" url = "http://" + apiurl + "/admin/login.php"
loginrq = session.post(url,data={"pw": phpassword}) loginrq = session.post(url,data={"pw": phpassword})
phpsessid = (str(loginrq.cookies.get_dict()["PHPSESSID"])) phpsessid = (str(loginrq.cookies.get_dict()["PHPSESSID"]))
regex = r'(<div id="token" hidden>)(\S+)(<\/div>)' regex = r'(<div id="token" hidden>)(\S+)(<\/div>)'
@ -133,13 +155,9 @@ def getNPMHosts(apiurl,type):
log.error("Please make sure your Nginx Proxy Manager API key or URL in conf.json is correct and accurate.") log.error("Please make sure your Nginx Proxy Manager API key or URL in conf.json is correct and accurate.")
return None return None
def addPiHoleHosts(apiurl, phpassword, targetsvr, list, filter): def filterPiHoleHosts(targetsvr, list, filter):
url = apiurl + "/scripts/pi-hole/php/customcname.php"
hostname = apiurl.split("/")[2]
piauth = loginToPihole(apiurl,phpassword)
# Adding filter functionality # Adding filter functionality
if filter is not None: if filter is not None:
log.info("A domain filter was applied for " + hostname + ". Filtering out domains in this run.")
filterlist = filter.replace(" ","").split(",") filterlist = filter.replace(" ","").split(",")
for domain in filterlist: for domain in filterlist:
log.debug("Filtering domain " + domain) log.debug("Filtering domain " + domain)
@ -147,12 +165,38 @@ def addPiHoleHosts(apiurl, phpassword, targetsvr, list, filter):
log.debug("Host " + host + " Filter " + domain) log.debug("Host " + host + " Filter " + domain)
if domain in host: if domain in host:
index = list.index(host) index = list.index(host)
log.info("Removing host " + host + " from the hostlist on " + hostname + " due to the filtered domain " + domain + " .") log.info("Removing host " + host + " from the filtered host list due to the filtered domain " + domain + ".")
list.remove(host) list.remove(host)
else: else:
log.debug("The domain " + host + "does not contain the domain " + domain) log.debug("The domain " + host + "does not contain the domain " + domain)
log.debug(domain + " domain was filtered, moving on to next one") log.debug(domain + " domain was filtered, moving on to next one")
log.info("Domains were filtered. Adding the list to the server...") log.info("Domains were filtered. Adding the list to the server...")
return list
def addPiHoleHosts(apiurl, phpassword, targetsvr, list, session):
baseurl = "http://" + apiurl + "/api/config/dns/cnameRecords/"
piauth = loginToPihole(apiurl,phpassword,session)
hostname = apiurl
# Moved filter functionality to filterPiHoleHosts().
for i in list:
log.debug("Adding host " + i + " to " + hostname + " Pi-hole CNAME list.")
url = baseurl + i + "," + targetsvr
apireq = requests.put(url,cookies={"sid": piauth["phpsessid"]},headers={"X-CSRF-TOKEN": piauth["csrftoken"]})
response = apireq.json()
if apireq.status_code == 201: # Check if the API returned a "created object" message
log.info("Added " + i + " to " + hostname + " CNAME list.")
log.debug("PiHole API returned true. Message returned: "+ apireq.text)
elif apireq.status_code == 400 and ("Item already present" in response['error']['message']):
log.info("There is already a CNAME record for " + i)
else:
log.error("Pi-hole returned this " + str(apireq.status_code) + " in error: "+ apireq.text)
def addPiHoleHostsOld(apiurl, phpassword, targetsvr, list):
url = "http://" + apiurl + "/scripts/pi-hole/php/customcname.php"
hostname = apiurl
piauth = loginToPiholeOld(apiurl,phpassword)
# Moved filter functionality to filterPiHoleHosts().
for i in list: for i in list:
payload = {"action": "add", "domain": i, "target": targetsvr, "token": piauth["csrftoken"]} payload = {"action": "add", "domain": i, "target": targetsvr, "token": piauth["csrftoken"]}
apireq = requests.post(url,data=payload,cookies={"PHPSESSID": piauth["phpsessid"]}) apireq = requests.post(url,data=payload,cookies={"PHPSESSID": piauth["phpsessid"]})
@ -173,8 +217,25 @@ def addPiHoleHosts(apiurl, phpassword, targetsvr, list, filter):
except: except:
log.error("Pi-hole returned this message and was not JSON: "+ response) log.error("Pi-hole returned this message and was not JSON: "+ response)
def removePiHoleHosts(apiurl, phpassword, targetsvr, list, session):
baseurl = "http://" + apiurl + "/api/config/dns/cnameRecords/"
piauth = loginToPihole(apiurl,phpassword,session)
hostname = apiurl
# Moved filter functionality to filterPiHoleHosts().
for i in list:
log.debug("Adding host " + i + " to " + hostname + " Pi-hole CNAME list.")
url = baseurl + i + "," + targetsvr
apireq = requests.put(url,cookies={"sid": piauth["phpsessid"]},headers={"X-CSRF-TOKEN": piauth["csrftoken"]})
response = apireq.json()
if apireq.status_code == 201: # Check if the API returned a "created object" message
log.info("Added " + i + " to " + hostname + " CNAME list.")
log.debug("PiHole API returned true. Message returned: "+ apireq.text)
elif apireq.status_code == 400 and ("Item already present" in response['error']['message']):
log.info("There is already a CNAME record for " + i)
else:
log.error("Pi-hole returned this " + str(apireq.status_code) + " in error: "+ apireq.text)
def removePiHoleHosts(apiurl, phpassword, targetsvr, list): def removePiHoleHostsOld(apiurl, phpassword, targetsvr, list):
url = apiurl + "/scripts/pi-hole/php/customcname.php" url = apiurl + "/scripts/pi-hole/php/customcname.php"
piauth = loginToPihole(apiurl,phpassword) piauth = loginToPihole(apiurl,phpassword)
for i in list: for i in list:
@ -199,6 +260,7 @@ log.info("Getting all NPM hosts.")
proxyhosts = getNPMHosts(cfg['npmdnshostname'],"proxy") # Get All Proxy Hosts proxyhosts = getNPMHosts(cfg['npmdnshostname'],"proxy") # Get All Proxy Hosts
redirhosts = getNPMHosts(cfg['npmdnshostname'],"redir") # Get All Redir Hosts redirhosts = getNPMHosts(cfg['npmdnshostname'],"redir") # Get All Redir Hosts
deadhosts = getNPMHosts(cfg['npmdnshostname'],"dead") # Get All 404 Hosts deadhosts = getNPMHosts(cfg['npmdnshostname'],"dead") # Get All 404 Hosts
session = requests.Session()
if ((proxyhosts == None) or (redirhosts == None) or (deadhosts == None)): if ((proxyhosts == None) or (redirhosts == None) or (deadhosts == None)):
log.error("One (or more) of the lists of hosts returned None. Check above for any errors while retriving hosts from NPM.") log.error("One (or more) of the lists of hosts returned None. Check above for any errors while retriving hosts from NPM.")
@ -211,23 +273,47 @@ else:
else: else:
allhosts = proxyhosts + redirhosts allhosts = proxyhosts + redirhosts
log.info("Adding all hosts in the list to specified Pi-Hole server at "+ cfg["piholeurl"] + "...") log.info("Adding all hosts in the list to specified Pi-Hole server at "+ cfg["piholeurl"] + "...")
addPiHoleHosts(cfg["piholeurl"],cfg["piholepass"],cfg["npmdnshostname"],allhosts,None) ## I'll clean up the following later lmfao
log.info("Succeeded in adding all hosts in the list to specified Pi-Hole server at "+ cfg["piholeurl"]) if cfg["phOldVersion"] == True:
if cfg['filterenabled'] == "True": addPiHoleHostsOld(cfg["piholeurl"],cfg["piholepass"],cfg["npmdnshostname"],allhosts)
log.debug("The filter server option was enabled.") log.info("Succeeded in adding all hosts in the list to specified Pi-Hole server at "+ cfg["piholeurl"])
try: if cfg['filterenabled'] == "True":
if cfg["filterlist"] is not str(''): log.debug("The filter server option was enabled.")
log.info("Adding all hosts in the list to filtered Pi-Hole server at "+ cfg["filteredpiholeurl"] + "...") try:
if cfg["filteredpiholepass"] is not str(''): if cfg["filterlist"] is not str(''):
addPiHoleHosts(cfg["filteredpiholeurl"],cfg["filteredpiholepass"],cfg["npmdnshostname"],allhosts,cfg["filterlist"]) filteredhosts = filterPiHoleHosts(cfg["npmdnshostname"],allhosts,cfg["filterlist"])
log.info("Adding all hosts in the list to filtered Pi-Hole server at "+ cfg["filteredpiholeurl"] + "...")
if cfg["filteredpiholepass"] is not str(''):
addPiHoleHostsOld(cfg["filteredpiholeurl"],cfg["filteredpiholepass"],cfg["npmdnshostname"],filteredhosts)
else:
addPiHoleHostsOld(cfg["filteredpiholeurl"],cfg["piholepass"],cfg["npmdnshostname"],filteredhosts)
log.info("Succeeded in adding all hosts in the list to filtered Pi-Hole server at "+ cfg["filteredpiholeurl"])
else: else:
addPiHoleHosts(cfg["filteredpiholeurl"],cfg["piholepass"],cfg["npmdnshostname"],allhosts,cfg["filterlist"]) log.error("There is nothing in the filter!")
log.info("Succeeded in adding all hosts in the list to filtered Pi-Hole server at "+ cfg["filteredpiholeurl"]) log.error("Make sure you put at least 1 (one) domain in the filter list.")
else: except KeyError:
log.error("There is nothing in the filter!")
log.error("Make sure you put at least 1 (one) domain in the filter list.")
else:
addPiHoleHosts(cfg["piholeurl"],cfg["piholepass"],cfg["npmdnshostname"],allhosts,session)
log.info("Succeeded in adding all hosts in the list to specified Pi-Hole server at "+ cfg["piholeurl"])
if cfg['filterenabled'] == "True":
log.debug("The filter server option was enabled.")
try:
if cfg["filterlist"] is not str(''):
log.info("Filtering all hosts for filtered Pi-hole server " + cfg["filteredpiholeurl"])
filteredhosts = filterPiHoleHosts(cfg["npmdnshostname"],allhosts,cfg["filterlist"])
log.info("Adding all hosts in the list to filtered Pi-Hole server at "+ cfg["filteredpiholeurl"] + "...")
if cfg["filteredpiholepass"] is not str(''):
addPiHoleHosts(cfg["filteredpiholeurl"],cfg["filteredpiholepass"],cfg["npmdnshostname"],filteredhosts,session)
else:
addPiHoleHosts(cfg["filteredpiholeurl"],cfg["piholepass"],cfg["npmdnshostname"],filteredhosts,session)
log.info("Succeeded in adding all hosts in the list to filtered Pi-Hole server at "+ cfg["filteredpiholeurl"])
else:
log.error("There is nothing in the filter!")
log.error("Make sure you put at least 1 (one) domain in the filter list.")
except KeyError:
log.error("There is nothing in the filter!") log.error("There is nothing in the filter!")
log.error("Make sure you put at least 1 (one) domain in the filter list.") log.error("Make sure you put at least 1 (one) domain in the filter list.")
except KeyError:
log.error("There is nothing in the filter!")
log.error("Make sure you put at least 1 (one) domain in the filter list.")
log.debug("Script ending") log.debug("Script ending")