feat: Update notification cooldowns and add alerts to index
All checks were successful
Build Docker / BuildImage (push) Successful in 35s
All checks were successful
Build Docker / BuildImage (push) Successful in 35s
This commit is contained in:
parent
a2e173f777
commit
fa78390fc7
@ -1,2 +1,4 @@
|
||||
# HNSDoH Status
|
||||
This is a simple webserver to check the status of the Handshake DoH server.
|
||||
|
||||
It will check every 5 minutes to see if each node is up and running. It checks the node for plain dns, DNS over HTTPS, and DNS over TLS. For DNS over HTTPS and DNS over TLS, it will check the certificate to make sure it is valid.
|
||||
|
83
server.py
83
server.py
@ -56,6 +56,19 @@ if not os.path.exists(log_dir):
|
||||
os.mkdir("./logs")
|
||||
log_dir = "./logs"
|
||||
|
||||
if not os.path.exists(f"{log_dir}/node_status.json"):
|
||||
with open(f"{log_dir}/node_status.json", "w") as file:
|
||||
json.dump([], file)
|
||||
|
||||
if not os.path.exists(f"{log_dir}/sent_notifications.json"):
|
||||
with open(f"{log_dir}/sent_notifications.json", "w") as file:
|
||||
json.dump({}, file)
|
||||
else:
|
||||
with open(f"{log_dir}/sent_notifications.json", "r") as file:
|
||||
sent_notifications = json.load(file)
|
||||
|
||||
|
||||
|
||||
print(f"Log directory: {log_dir}", flush=True)
|
||||
|
||||
|
||||
@ -183,7 +196,8 @@ def check_doh(ip: str) -> bool:
|
||||
|
||||
finally:
|
||||
# Close the socket connection
|
||||
if ssock:
|
||||
# Check if ssock is defined
|
||||
if "ssock" in locals():
|
||||
ssock.close()
|
||||
return status
|
||||
|
||||
@ -330,24 +344,13 @@ def check_nodes() -> list:
|
||||
node["cert"]["expiry_date"], "%b %d %H:%M:%S %Y GMT"
|
||||
)
|
||||
if cert_expiry < datetime.now() + relativedelta.relativedelta(days=7):
|
||||
if node["ip"] not in sent_notifications:
|
||||
sent_notifications[node["ip"]] = datetime.now()
|
||||
send_down_notification(node)
|
||||
continue
|
||||
if sent_notifications[node["ip"]] < datetime.now() - relativedelta.relativedelta(days=1):
|
||||
send_down_notification(node)
|
||||
continue
|
||||
cert_853_expiry = datetime.strptime(
|
||||
node["cert_853"]["expiry_date"], "%b %d %H:%M:%S %Y GMT"
|
||||
)
|
||||
if cert_853_expiry < datetime.now() + relativedelta.relativedelta(days=7):
|
||||
if node["ip"] not in sent_notifications:
|
||||
sent_notifications[node["ip"]] = datetime.now()
|
||||
send_down_notification(node)
|
||||
continue
|
||||
if sent_notifications[node["ip"]] < datetime.now() - relativedelta.relativedelta(days=1):
|
||||
send_down_notification(node)
|
||||
continue
|
||||
return node_status
|
||||
|
||||
def check_nodes_from_log() -> list:
|
||||
@ -399,6 +402,29 @@ def send_notification(title, description,author):
|
||||
|
||||
|
||||
def send_down_notification(node):
|
||||
global sent_notifications
|
||||
|
||||
# Check if a notification has already been sent
|
||||
if node["ip"] not in sent_notifications:
|
||||
sent_notifications[node["ip"]] = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")
|
||||
else:
|
||||
last_send = datetime.strptime(sent_notifications[node["ip"]], "%Y-%m-%d %H:%M:%S")
|
||||
|
||||
if last_send > datetime.now() - relativedelta.relativedelta(hours=1):
|
||||
print(f"Notification already sent for {node['name']} in the last hr", flush=True)
|
||||
return
|
||||
|
||||
# Only send certain notifications once per day
|
||||
if node["plain_dns"] and node["doh"] and node["dot"]:
|
||||
if last_send > datetime.now() - relativedelta.relativedelta(days=1):
|
||||
print(f"Notification already sent for {node['name']} in the last day", flush=True)
|
||||
return
|
||||
|
||||
# Save the notification to the file
|
||||
sent_notifications[node["ip"]] = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")
|
||||
with open(f"{log_dir}/sent_notifications.json", "w") as file:
|
||||
json.dump(sent_notifications, file, indent=4)
|
||||
|
||||
title = f"{node['name']} is down"
|
||||
|
||||
description = f"{node['name']} ({node['ip']}) is down with the following issues:\n"
|
||||
@ -641,36 +667,48 @@ def api_refresh():
|
||||
def index():
|
||||
node_status = check_nodes_from_log()
|
||||
|
||||
alerts = []
|
||||
warnings = []
|
||||
for node in node_status:
|
||||
if not node["plain_dns"]:
|
||||
warnings.append(f"{node['name']} does not support plain DNS")
|
||||
alerts.append(f"{node['name']} does not support plain DNS")
|
||||
|
||||
if not node["doh"]:
|
||||
warnings.append(f"{node['name']} does not support DoH")
|
||||
alerts.append(f"{node['name']} does not support DoH")
|
||||
|
||||
if not node["dot"]:
|
||||
warnings.append(f"{node['name']} does not support DoT")
|
||||
alerts.append(f"{node['name']} does not support DoT")
|
||||
|
||||
if not node["cert"]["valid"]:
|
||||
warnings.append(f"{node['name']} has an invalid certificate")
|
||||
alerts.append(f"{node['name']} has an invalid certificate")
|
||||
|
||||
if not node["cert_853"]["valid"]:
|
||||
warnings.append(f"{node['name']} has an invalid certificate on port 853")
|
||||
alerts.append(f"{node['name']} has an invalid certificate on port 853")
|
||||
|
||||
cert_expiry = datetime.strptime(
|
||||
node["cert"]["expiry_date"], "%b %d %H:%M:%S %Y GMT"
|
||||
)
|
||||
if cert_expiry < datetime.now() + relativedelta.relativedelta(days=7):
|
||||
warnings.append(
|
||||
f"{node['name']} has a certificate expiring in less than 7 days on port 443"
|
||||
if cert_expiry < datetime.now():
|
||||
alerts.append(
|
||||
f"The {node['name']} node's certificate has expired"
|
||||
)
|
||||
continue
|
||||
elif cert_expiry < datetime.now() + relativedelta.relativedelta(days=7):
|
||||
warnings.append(
|
||||
f"The {node['name']} node's certificate is expiring {format_relative_time(cert_expiry)}"
|
||||
)
|
||||
continue
|
||||
cert_853_expiry = datetime.strptime(
|
||||
node["cert_853"]["expiry_date"], "%b %d %H:%M:%S %Y GMT"
|
||||
)
|
||||
if cert_853_expiry < datetime.now() + relativedelta.relativedelta(days=7):
|
||||
if cert_853_expiry < datetime.now():
|
||||
alerts.append(
|
||||
f"The {node['name']} node's certificate has expired for DNS over TLS (port 853)"
|
||||
)
|
||||
continue
|
||||
elif cert_853_expiry < datetime.now() + relativedelta.relativedelta(days=7):
|
||||
warnings.append(
|
||||
f"{node['name']} has a certificate expiring in less than 7 days on port 853"
|
||||
f"The {node['name']} node's certificate is expiring {format_relative_time(cert_853_expiry)} for DNS over TLS (port 853)"
|
||||
)
|
||||
|
||||
|
||||
@ -698,6 +736,7 @@ def index():
|
||||
"index.html",
|
||||
nodes=node_status,
|
||||
warnings=warnings,
|
||||
alerts=alerts,
|
||||
history=history_summary,
|
||||
last_check=last_check,
|
||||
)
|
||||
|
@ -10,7 +10,7 @@
|
||||
margin: 25px;
|
||||
display: block;
|
||||
}
|
||||
.warnings {
|
||||
.warnings,.errors {
|
||||
margin: auto;
|
||||
width: 1000px;
|
||||
max-width: 95%;
|
||||
|
@ -51,10 +51,22 @@
|
||||
<section id="intro">
|
||||
<div class="text-center">
|
||||
<h1 class="text-center" style="font-size: 60px;">HNS DoH Status</h1>
|
||||
<div class="errors">
|
||||
<!-- Check if errors is empty -->
|
||||
{% if alerts %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<h4 class="alert-heading">Alert</h4>
|
||||
{% for alert in alerts %}
|
||||
<p>{{ alert }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<div class="warnings">
|
||||
<!-- Check if warnings is empty -->
|
||||
{% if warnings %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<h4 class="alert-heading">Warning</h4>
|
||||
{% for warning in warnings %}
|
||||
<p>{{ warning }}</p>
|
||||
|
Loading…
Reference in New Issue
Block a user