Sync all scripts from website downloads — 352 scripts total

Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
This commit is contained in:
2026-05-25 03:31:08 +02:00
parent dbd6bf0324
commit a1a17e81a1
332 changed files with 174509 additions and 1106 deletions
+372
View File
@@ -0,0 +1,372 @@
#!/bin/bash
################################################################################
# Script Name: dovecot-metrics-exporter.sh
# Description: Prometheus exporter for Dovecot IMAP/POP3 server metrics
#
# Collects connection counts, authentication stats, mailbox operations,
# process info, and protocol-level metrics from doveadm and Dovecot stats.
#
# Author: Phil Connor
# Contact: contact@mylinux.work
# Website: https://mylinux.work
# License: MIT
# Version: 1.0
#
# Usage:
# # Output to stdout
# ./dovecot-metrics-exporter.sh
#
# # Textfile collector mode (atomic write)
# ./dovecot-metrics-exporter.sh --textfile
#
# # Custom output file
# ./dovecot-metrics-exporter.sh -o /path/to/metrics.prom
#
################################################################################
# ============================================================================
# CONFIGURATION VARIABLES
# ============================================================================
TEXTFILE_DIR="/var/lib/node_exporter"
OUTPUT_FILE=""
HOSTNAME=$(hostname)
# ============================================================================
# HELPER FUNCTIONS
# ============================================================================
show_usage() {
cat <<EOF
Usage: $0 [OPTIONS]
Export Dovecot IMAP/POP3 server metrics as Prometheus metrics.
MODES:
--textfile Write to node_exporter textfile collector
(writes to $TEXTFILE_DIR/dovecot-metrics.prom)
OPTIONS:
-o, --output Output file path (for custom locations)
-h, --help Show this help message
EXAMPLES:
$0 # Output to stdout
$0 --textfile # Write to textfile collector
$0 -o /tmp/dovecot.prom # Write to custom file
EOF
exit 0
}
parse_args() {
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help) show_usage ;;
--textfile) OUTPUT_FILE="$TEXTFILE_DIR/dovecot-metrics.prom"; shift ;;
-o|--output) OUTPUT_FILE="$2"; shift 2 ;;
*) echo "Unknown option: $1" >&2; exit 1 ;;
esac
done
}
# Safe integer extraction — returns 0 on failure
safe_int() {
local val="$1"
if [[ "$val" =~ ^[0-9]+$ ]]; then
echo "$val"
else
echo 0
fi
}
# ============================================================================
# METRIC GENERATION
# ============================================================================
generate_metrics() {
local START_TIME
START_TIME=$(date +%s.%N)
# --- Exporter info ---
echo "# HELP dovecot_up Exporter status (1=up, 0=down)"
echo "# TYPE dovecot_up gauge"
# Check if Dovecot is running
if systemctl is-active --quiet dovecot 2>/dev/null; then
echo "dovecot_up 1"
else
echo "dovecot_up 0"
fi
echo ""
echo "# HELP dovecot_exporter_info Exporter version information"
echo "# TYPE dovecot_exporter_info gauge"
echo 'dovecot_exporter_info{version="1.0"} 1'
echo ""
# --- Dovecot version ---
echo "# HELP dovecot_version_info Dovecot version information"
echo "# TYPE dovecot_version_info gauge"
local dovecot_version
dovecot_version=$(dovecot --version 2>/dev/null | awk '{print $1}') || dovecot_version="unknown"
echo "dovecot_version_info{version=\"${dovecot_version}\"} 1"
echo ""
# --- Process counts ---
echo "# HELP dovecot_processes Number of running Dovecot processes by type"
echo "# TYPE dovecot_processes gauge"
for proc_type in imap pop3 lmtp managesieve submission auth anvil; do
count=$(pgrep -c "dovecot/${proc_type}" 2>/dev/null) || count=0
echo "dovecot_processes{type=\"${proc_type}\"} ${count}"
done
local total_procs
total_procs=$(pgrep -c dovecot 2>/dev/null) || total_procs=0
echo "dovecot_processes{type=\"total\"} ${total_procs}"
echo ""
# --- Connected users (from doveadm) ---
echo "# HELP dovecot_connected_users Number of currently connected users by protocol"
echo "# TYPE dovecot_connected_users gauge"
local imap_users=0 pop3_users=0 lmtp_users=0 managesieve_users=0
if command -v doveadm >/dev/null 2>&1; then
imap_users=$(doveadm who -1 2>/dev/null | grep -c 'imap' 2>/dev/null) || imap_users=0
pop3_users=$(doveadm who -1 2>/dev/null | grep -c 'pop3' 2>/dev/null) || pop3_users=0
lmtp_users=$(doveadm who -1 2>/dev/null | grep -c 'lmtp' 2>/dev/null) || lmtp_users=0
managesieve_users=$(doveadm who -1 2>/dev/null | grep -c 'managesieve' 2>/dev/null) || managesieve_users=0
fi
echo "dovecot_connected_users{protocol=\"imap\"} ${imap_users}"
echo "dovecot_connected_users{protocol=\"pop3\"} ${pop3_users}"
echo "dovecot_connected_users{protocol=\"lmtp\"} ${lmtp_users}"
echo "dovecot_connected_users{protocol=\"managesieve\"} ${managesieve_users}"
echo ""
# --- Total connections (from doveadm who) ---
echo "# HELP dovecot_connections_total Total active connections by protocol"
echo "# TYPE dovecot_connections_total gauge"
local imap_conns=0 pop3_conns=0
if command -v doveadm >/dev/null 2>&1; then
imap_conns=$(doveadm who -1 2>/dev/null | grep 'imap' | awk '{sum+=$3} END {print sum+0}' 2>/dev/null) || imap_conns=0
pop3_conns=$(doveadm who -1 2>/dev/null | grep 'pop3' | awk '{sum+=$3} END {print sum+0}' 2>/dev/null) || pop3_conns=0
fi
echo "dovecot_connections_total{protocol=\"imap\"} ${imap_conns}"
echo "dovecot_connections_total{protocol=\"pop3\"} ${pop3_conns}"
echo ""
# --- Authentication stats from mail.log ---
local LOG_FILE="/var/log/mail.log"
if [[ ! -f "$LOG_FILE" ]]; then
LOG_FILE="/var/log/maillog"
fi
echo "# HELP dovecot_auth_success_total Successful authentication attempts by protocol"
echo "# TYPE dovecot_auth_success_total counter"
local imap_auth_ok=0 pop3_auth_ok=0
if [[ -f "$LOG_FILE" ]]; then
imap_auth_ok=$(grep -c 'imap-login: Info: Login:' "$LOG_FILE" 2>/dev/null) || imap_auth_ok=0
pop3_auth_ok=$(grep -c 'pop3-login: Info: Login:' "$LOG_FILE" 2>/dev/null) || pop3_auth_ok=0
fi
echo "dovecot_auth_success_total{protocol=\"imap\"} ${imap_auth_ok}"
echo "dovecot_auth_success_total{protocol=\"pop3\"} ${pop3_auth_ok}"
echo ""
echo "# HELP dovecot_auth_failed_total Failed authentication attempts by protocol"
echo "# TYPE dovecot_auth_failed_total counter"
local imap_auth_fail=0 pop3_auth_fail=0
if [[ -f "$LOG_FILE" ]]; then
imap_auth_fail=$(grep -c 'imap-login:.*auth failed\|imap-login: Info: Aborted login' "$LOG_FILE" 2>/dev/null) || imap_auth_fail=0
pop3_auth_fail=$(grep -c 'pop3-login:.*auth failed\|pop3-login: Info: Aborted login' "$LOG_FILE" 2>/dev/null) || pop3_auth_fail=0
fi
echo "dovecot_auth_failed_total{protocol=\"imap\"} ${imap_auth_fail}"
echo "dovecot_auth_failed_total{protocol=\"pop3\"} ${pop3_auth_fail}"
echo ""
# --- TLS connections ---
echo "# HELP dovecot_tls_connections_total TLS connections by status"
echo "# TYPE dovecot_tls_connections_total counter"
local tls_yes=0 tls_no=0
if [[ -f "$LOG_FILE" ]]; then
tls_yes=$(grep -c 'Login:.*TLS' "$LOG_FILE" 2>/dev/null) || tls_yes=0
tls_no=$(grep 'Login:' "$LOG_FILE" 2>/dev/null | grep -cv 'TLS' 2>/dev/null) || tls_no=0
fi
echo "dovecot_tls_connections_total{tls=\"yes\"} ${tls_yes}"
echo "dovecot_tls_connections_total{tls=\"no\"} ${tls_no}"
echo ""
# --- Authentication methods ---
echo "# HELP dovecot_auth_method_total Logins by authentication method"
echo "# TYPE dovecot_auth_method_total counter"
if [[ -f "$LOG_FILE" ]]; then
for method in PLAIN LOGIN CRAM-MD5 DIGEST-MD5; do
count=$(grep -c "Login:.*method=${method}" "$LOG_FILE" 2>/dev/null) || count=0
echo "dovecot_auth_method_total{method=\"${method}\"} ${count}"
done
else
for method in PLAIN LOGIN CRAM-MD5 DIGEST-MD5; do
echo "dovecot_auth_method_total{method=\"${method}\"} 0"
done
fi
echo ""
# --- Disconnections ---
echo "# HELP dovecot_disconnections_total Client disconnections by reason"
echo "# TYPE dovecot_disconnections_total counter"
local dc_logout=0 dc_timeout=0 dc_closed=0 dc_internal=0
if [[ -f "$LOG_FILE" ]]; then
dc_logout=$(grep -c 'Logged out' "$LOG_FILE" 2>/dev/null) || dc_logout=0
dc_timeout=$(grep -c 'Disconnected.*Timed out\|Connection timed out' "$LOG_FILE" 2>/dev/null) || dc_timeout=0
dc_closed=$(grep -c 'Disconnected.*Connection closed' "$LOG_FILE" 2>/dev/null) || dc_closed=0
dc_internal=$(grep -c 'Disconnected.*Internal error' "$LOG_FILE" 2>/dev/null) || dc_internal=0
fi
echo "dovecot_disconnections_total{reason=\"logout\"} ${dc_logout}"
echo "dovecot_disconnections_total{reason=\"timeout\"} ${dc_timeout}"
echo "dovecot_disconnections_total{reason=\"connection_closed\"} ${dc_closed}"
echo "dovecot_disconnections_total{reason=\"internal_error\"} ${dc_internal}"
echo ""
# --- LMTP delivery stats ---
echo "# HELP dovecot_lmtp_deliveries_total LMTP deliveries by status"
echo "# TYPE dovecot_lmtp_deliveries_total counter"
local lmtp_ok=0 lmtp_reject=0 lmtp_tempfail=0
if [[ -f "$LOG_FILE" ]]; then
lmtp_ok=$(grep -c 'lmtp.*saved mail' "$LOG_FILE" 2>/dev/null) || lmtp_ok=0
lmtp_reject=$(grep -c 'lmtp.*rejected' "$LOG_FILE" 2>/dev/null) || lmtp_reject=0
lmtp_tempfail=$(grep -c 'lmtp.*temporary failure\|lmtp.*temp-fail' "$LOG_FILE" 2>/dev/null) || lmtp_tempfail=0
fi
echo "dovecot_lmtp_deliveries_total{status=\"delivered\"} ${lmtp_ok}"
echo "dovecot_lmtp_deliveries_total{status=\"rejected\"} ${lmtp_reject}"
echo "dovecot_lmtp_deliveries_total{status=\"tempfail\"} ${lmtp_tempfail}"
echo ""
# --- Sieve stats ---
echo "# HELP dovecot_sieve_actions_total Sieve filter actions"
echo "# TYPE dovecot_sieve_actions_total counter"
local sieve_filed=0 sieve_discard=0 sieve_redirect=0 sieve_reject=0
if [[ -f "$LOG_FILE" ]]; then
sieve_filed=$(grep -c 'sieve:.*stored mail\|sieve:.*fileinto' "$LOG_FILE" 2>/dev/null) || sieve_filed=0
sieve_discard=$(grep -c 'sieve:.*discard' "$LOG_FILE" 2>/dev/null) || sieve_discard=0
sieve_redirect=$(grep -c 'sieve:.*redirect' "$LOG_FILE" 2>/dev/null) || sieve_redirect=0
sieve_reject=$(grep -c 'sieve:.*reject' "$LOG_FILE" 2>/dev/null) || sieve_reject=0
fi
echo "dovecot_sieve_actions_total{action=\"filed\"} ${sieve_filed}"
echo "dovecot_sieve_actions_total{action=\"discard\"} ${sieve_discard}"
echo "dovecot_sieve_actions_total{action=\"redirect\"} ${sieve_redirect}"
echo "dovecot_sieve_actions_total{action=\"reject\"} ${sieve_reject}"
echo ""
# --- Dovecot stats (if old_stats or stats plugin enabled) ---
# Try doveadm stats dump for Dovecot 2.3+
echo "# HELP dovecot_mail_commands_total Mail commands executed"
echo "# TYPE dovecot_mail_commands_total counter"
local cmds_select=0 cmds_fetch=0 cmds_store=0 cmds_search=0 cmds_copy=0 cmds_expunge=0
if command -v doveadm >/dev/null 2>&1; then
local stats_output
stats_output=$(doveadm stats dump session 2>/dev/null | head -20)
if [[ -n "$stats_output" ]]; then
cmds_select=$(echo "$stats_output" | awk '{sum+=$4} END {print sum+0}') || cmds_select=0
cmds_fetch=$(echo "$stats_output" | awk '{sum+=$5} END {print sum+0}') || cmds_fetch=0
fi
fi
# Fallback: count from logs
if [[ -f "$LOG_FILE" ]]; then
cmds_copy=$(grep -c 'Copy\|copy' "$LOG_FILE" 2>/dev/null | head -1) || cmds_copy=0
cmds_expunge=$(grep -c 'Expunged' "$LOG_FILE" 2>/dev/null) || cmds_expunge=0
fi
echo "dovecot_mail_commands_total{command=\"copy\"} ${cmds_copy}"
echo "dovecot_mail_commands_total{command=\"expunge\"} ${cmds_expunge}"
echo ""
# --- Mail storage quota (top users if doveadm quota available) ---
echo "# HELP dovecot_quota_usage_bytes User quota usage in bytes (top users)"
echo "# TYPE dovecot_quota_usage_bytes gauge"
echo "# HELP dovecot_quota_limit_bytes User quota limit in bytes"
echo "# TYPE dovecot_quota_limit_bytes gauge"
if command -v doveadm >/dev/null 2>&1; then
doveadm quota get -A 2>/dev/null | grep 'STORAGE' | head -20 | while IFS=$'\t' read -r user type value limit _; do
local usage_bytes=$((value * 1024))
local limit_bytes=$((limit * 1024))
echo "dovecot_quota_usage_bytes{user=\"${user}\"} ${usage_bytes}"
echo "dovecot_quota_limit_bytes{user=\"${user}\"} ${limit_bytes}"
done 2>/dev/null
fi
echo ""
# --- Dovecot uptime ---
echo "# HELP dovecot_uptime_seconds Dovecot process uptime in seconds"
echo "# TYPE dovecot_uptime_seconds gauge"
local dovecot_pid uptime_seconds=0
dovecot_pid=$(pgrep -o dovecot 2>/dev/null) || dovecot_pid=""
if [[ -n "$dovecot_pid" ]] && [[ -d "/proc/${dovecot_pid}" ]]; then
local start_time
start_time=$(stat -c %Y "/proc/${dovecot_pid}" 2>/dev/null) || start_time=0
if [[ "$start_time" -gt 0 ]]; then
uptime_seconds=$(( $(date +%s) - start_time ))
fi
fi
echo "dovecot_uptime_seconds ${uptime_seconds}"
echo ""
# --- Memory usage ---
echo "# HELP dovecot_memory_bytes Total memory usage of all Dovecot processes"
echo "# TYPE dovecot_memory_bytes gauge"
local total_mem=0
total_mem=$(pgrep dovecot 2>/dev/null | xargs -I {} cat /proc/{}/status 2>/dev/null | awk '/VmRSS/{sum+=$2} END {print sum*1024+0}') || total_mem=0
echo "dovecot_memory_bytes ${total_mem}"
echo ""
# --- Script execution time ---
local END_TIME
END_TIME=$(date +%s.%N)
local DURATION
DURATION=$(echo "$END_TIME - $START_TIME" | bc)
echo "# HELP dovecot_exporter_duration_seconds Time to generate all metrics"
echo "# TYPE dovecot_exporter_duration_seconds gauge"
echo "dovecot_exporter_duration_seconds ${DURATION}"
echo ""
echo "# HELP dovecot_exporter_last_run_timestamp Unix timestamp of last successful run"
echo "# TYPE dovecot_exporter_last_run_timestamp gauge"
echo "dovecot_exporter_last_run_timestamp $(date +%s)"
}
# ============================================================================
# MAIN EXECUTION
# ============================================================================
main() {
parse_args "$@"
if [ -n "$OUTPUT_FILE" ]; then
local output_dir
output_dir="$(dirname "$OUTPUT_FILE")"
mkdir -p "$output_dir"
local temp_file
temp_file=$(mktemp "${output_dir}/.dovecot_metrics.XXXXXX")
if ! generate_metrics > "$temp_file" 2>/dev/null; then
rm -f "$temp_file"
echo "ERROR: Failed to generate metrics" >&2
exit 1
fi
local file_lines
file_lines=$(wc -l < "$temp_file" 2>/dev/null || echo 0)
if [ "$file_lines" -lt 10 ]; then
rm -f "$temp_file"
echo "ERROR: Metrics file too small ($file_lines lines), keeping previous" >&2
exit 1
fi
chmod 644 "$temp_file"
mv -f "$temp_file" "$OUTPUT_FILE"
echo "Metrics written to $OUTPUT_FILE ($file_lines lines)" >&2
else
generate_metrics
fi
}
main "$@"