CI/CD: Add GitLab CI/CD pipeline for Hostinger deployment
- Updated .gitlab-ci.yml with complete build, test, and deploy stages - Added authentication redirect fix in Program.cs (302 redirect for admin routes) - Fixed Cookie vs Bearer authentication conflict for admin panel - Configure pipeline to build from .NET 9.0 source - Deploy to Hostinger VPS with proper environment variables - Include rollback capability for production deployments 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
346
TeleBot/Scripts/tor-health-monitor.sh
Normal file
346
TeleBot/Scripts/tor-health-monitor.sh
Normal file
@@ -0,0 +1,346 @@
|
||||
#!/bin/bash
|
||||
|
||||
################################################################################
|
||||
# TOR Health Monitoring Script
|
||||
#
|
||||
# Purpose: Continuous monitoring of TOR connectivity and TeleBot TOR usage
|
||||
# Usage: ./tor-health-monitor.sh [--daemon] [--interval=60]
|
||||
# Output: Health reports and alerts
|
||||
#
|
||||
# Features:
|
||||
# - Real-time TOR connectivity monitoring
|
||||
# - Circuit health tracking
|
||||
# - IP leak detection
|
||||
# - Automated alerting
|
||||
# - Historical logging
|
||||
#
|
||||
# Author: Mr Tickles, Security Consultant
|
||||
# Date: 2025-10-01
|
||||
################################################################################
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Configuration
|
||||
INTERVAL=60 # Check interval in seconds
|
||||
DAEMON_MODE=false
|
||||
LOG_DIR="/var/log/telebot"
|
||||
HEALTH_LOG="$LOG_DIR/tor-health.log"
|
||||
ALERT_LOG="$LOG_DIR/tor-alerts.log"
|
||||
STATE_DIR="/var/lib/telebot"
|
||||
TOR_SOCKS_PORT=9050
|
||||
EMAIL_ALERTS=false
|
||||
ALERT_EMAIL="admin@example.com"
|
||||
|
||||
# Parse arguments
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--daemon)
|
||||
DAEMON_MODE=true
|
||||
shift
|
||||
;;
|
||||
--interval=*)
|
||||
INTERVAL="${arg#*=}"
|
||||
shift
|
||||
;;
|
||||
--email=*)
|
||||
ALERT_EMAIL="${arg#*=}"
|
||||
EMAIL_ALERTS=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Create directories
|
||||
mkdir -p "$LOG_DIR" "$STATE_DIR"
|
||||
|
||||
################################################################################
|
||||
# Logging Functions
|
||||
################################################################################
|
||||
|
||||
log() {
|
||||
local level=$1
|
||||
shift
|
||||
local message="$@"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
echo "[$timestamp] [$level] $message" >> "$HEALTH_LOG"
|
||||
|
||||
if [ "$DAEMON_MODE" = false ]; then
|
||||
case $level in
|
||||
INFO)
|
||||
echo -e "${BLUE}[INFO]${NC} $message"
|
||||
;;
|
||||
SUCCESS)
|
||||
echo -e "${GREEN}[✓]${NC} $message"
|
||||
;;
|
||||
WARNING)
|
||||
echo -e "${YELLOW}[⚠]${NC} $message"
|
||||
;;
|
||||
ERROR)
|
||||
echo -e "${RED}[✗]${NC} $message"
|
||||
;;
|
||||
ALERT)
|
||||
echo -e "${RED}[ALERT]${NC} $message"
|
||||
echo "[$timestamp] [ALERT] $message" >> "$ALERT_LOG"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
send_alert() {
|
||||
local subject="$1"
|
||||
local message="$2"
|
||||
|
||||
log ALERT "$subject: $message"
|
||||
|
||||
if [ "$EMAIL_ALERTS" = true ]; then
|
||||
echo "$message" | mail -s "TeleBot TOR Alert: $subject" "$ALERT_EMAIL" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Health Check Functions
|
||||
################################################################################
|
||||
|
||||
check_tor_service() {
|
||||
if systemctl is-active --quiet tor 2>/dev/null; then
|
||||
log SUCCESS "TOR service is running"
|
||||
return 0
|
||||
else
|
||||
log ERROR "TOR service is not running"
|
||||
send_alert "TOR Service Down" "TOR service is not running. TeleBot location is EXPOSED!"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_tor_socks() {
|
||||
if netstat -tln 2>/dev/null | grep -q ":${TOR_SOCKS_PORT} "; then
|
||||
log SUCCESS "TOR SOCKS5 proxy is listening on port ${TOR_SOCKS_PORT}"
|
||||
return 0
|
||||
else
|
||||
log ERROR "TOR SOCKS5 proxy is not listening"
|
||||
send_alert "TOR SOCKS5 Down" "TOR SOCKS5 proxy not available. Traffic cannot be routed through TOR!"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_tor_circuits() {
|
||||
local bootstrap_status=$(journalctl -u tor -n 100 --no-pager 2>/dev/null | \
|
||||
grep -i "Bootstrapped" | tail -1)
|
||||
|
||||
if echo "$bootstrap_status" | grep -q "100%"; then
|
||||
log SUCCESS "TOR circuits are established (100%)"
|
||||
return 0
|
||||
else
|
||||
log WARNING "TOR circuits may not be fully established"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_tor_ip() {
|
||||
local tor_ip=""
|
||||
local direct_ip=""
|
||||
|
||||
# Get IP through TOR
|
||||
tor_ip=$(timeout 15 curl --socks5 127.0.0.1:${TOR_SOCKS_PORT} -s https://api.ipify.org 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$tor_ip" ]; then
|
||||
log ERROR "Failed to get IP through TOR"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get direct IP
|
||||
direct_ip=$(timeout 10 curl -s https://api.ipify.org 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$direct_ip" ]; then
|
||||
log WARNING "Failed to get direct IP (network issue?)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Compare IPs
|
||||
if [ "$tor_ip" != "$direct_ip" ]; then
|
||||
log SUCCESS "TOR IP ($tor_ip) is different from direct IP ($direct_ip)"
|
||||
|
||||
# Save IPs for tracking
|
||||
echo "$tor_ip" > "$STATE_DIR/current_tor_ip"
|
||||
echo "$direct_ip" > "$STATE_DIR/real_ip"
|
||||
|
||||
return 0
|
||||
else
|
||||
log ERROR "TOR IP matches direct IP - TOR may not be working!"
|
||||
send_alert "TOR IP Mismatch" "TOR IP ($tor_ip) matches direct IP! TOR may be bypassed!"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_telebot_process() {
|
||||
if pgrep -f "TeleBot" > /dev/null; then
|
||||
local pid=$(pgrep -f "TeleBot" | head -1)
|
||||
log SUCCESS "TeleBot is running (PID: $pid)"
|
||||
|
||||
# Check TOR connections
|
||||
local tor_conns=$(lsof -p "$pid" -i TCP 2>/dev/null | grep -c ":${TOR_SOCKS_PORT}" || echo 0)
|
||||
|
||||
if [ "$tor_conns" -gt 0 ]; then
|
||||
log SUCCESS "TeleBot has $tor_conns active TOR connections"
|
||||
else
|
||||
log WARNING "TeleBot has no active TOR connections"
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
log WARNING "TeleBot is not running"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_ip_leaks() {
|
||||
if ! pgrep -f "TeleBot" > /dev/null; then
|
||||
return 0 # Can't check if not running
|
||||
fi
|
||||
|
||||
local pid=$(pgrep -f "TeleBot" | head -1)
|
||||
|
||||
# Check for direct external connections
|
||||
local external_conns=$(ss -tnp 2>/dev/null | grep "$pid" | \
|
||||
grep -v "127.0.0.1" | \
|
||||
grep -v "::1" | \
|
||||
grep -v ":${TOR_SOCKS_PORT}" | \
|
||||
wc -l)
|
||||
|
||||
if [ "$external_conns" -eq 0 ]; then
|
||||
log SUCCESS "No IP leaks detected (all connections through TOR)"
|
||||
return 0
|
||||
else
|
||||
log ERROR "Detected $external_conns direct external connections - IP LEAK!"
|
||||
send_alert "IP Leak Detected" "TeleBot has $external_conns direct external connections not through TOR!"
|
||||
|
||||
# Log the suspicious connections
|
||||
ss -tnp 2>/dev/null | grep "$pid" | \
|
||||
grep -v "127.0.0.1" | \
|
||||
grep -v "::1" | \
|
||||
grep -v ":${TOR_SOCKS_PORT}" >> "$ALERT_LOG"
|
||||
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_dns_leaks() {
|
||||
# Monitor for DNS queries not through TOR
|
||||
local dns_count=$(timeout 5 tcpdump -i any -c 10 'port 53' 2>/dev/null | wc -l || echo 0)
|
||||
|
||||
if [ "$dns_count" -eq 0 ]; then
|
||||
log SUCCESS "No DNS leaks detected"
|
||||
return 0
|
||||
else
|
||||
log WARNING "Detected DNS queries - potential DNS leak"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Performance Metrics
|
||||
################################################################################
|
||||
|
||||
measure_tor_latency() {
|
||||
local start_time=$(date +%s%N)
|
||||
local test_result=$(timeout 10 curl --socks5 127.0.0.1:${TOR_SOCKS_PORT} -s -o /dev/null -w "%{http_code}" https://check.torproject.org 2>/dev/null || echo "0")
|
||||
local end_time=$(date +%s%N)
|
||||
|
||||
if [ "$test_result" = "200" ]; then
|
||||
local latency=$(( (end_time - start_time) / 1000000 )) # Convert to milliseconds
|
||||
log INFO "TOR latency: ${latency}ms"
|
||||
echo "$latency" > "$STATE_DIR/tor_latency"
|
||||
|
||||
if [ "$latency" -gt 5000 ]; then
|
||||
log WARNING "TOR latency is high (${latency}ms)"
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
log ERROR "Failed to measure TOR latency"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Main Health Check
|
||||
################################################################################
|
||||
|
||||
run_health_check() {
|
||||
local check_id=$(date +%Y%m%d_%H%M%S)
|
||||
log INFO "==================== Health Check $check_id ===================="
|
||||
|
||||
local total_checks=0
|
||||
local passed_checks=0
|
||||
|
||||
# Run all checks
|
||||
for check in check_tor_service check_tor_socks check_tor_circuits \
|
||||
check_tor_ip check_telebot_process check_ip_leaks \
|
||||
check_dns_leaks measure_tor_latency; do
|
||||
total_checks=$((total_checks + 1))
|
||||
|
||||
if $check; then
|
||||
passed_checks=$((passed_checks + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Calculate health score
|
||||
local health_score=$((passed_checks * 100 / total_checks))
|
||||
|
||||
log INFO "Health Score: $health_score% ($passed_checks/$total_checks checks passed)"
|
||||
|
||||
# Save health score
|
||||
echo "$health_score" > "$STATE_DIR/health_score"
|
||||
|
||||
# Alert if health is poor
|
||||
if [ "$health_score" -lt 80 ]; then
|
||||
send_alert "Poor Health Score" "TOR health score is $health_score%. Review logs: $HEALTH_LOG"
|
||||
fi
|
||||
|
||||
log INFO "================================================================"
|
||||
echo ""
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Daemon Mode
|
||||
################################################################################
|
||||
|
||||
run_daemon() {
|
||||
log INFO "Starting TOR health monitor daemon (interval: ${INTERVAL}s)"
|
||||
|
||||
# Create PID file
|
||||
echo $$ > "$STATE_DIR/monitor.pid"
|
||||
|
||||
# Trap signals
|
||||
trap 'log INFO "Stopping TOR health monitor daemon"; rm -f "$STATE_DIR/monitor.pid"; exit 0' SIGTERM SIGINT
|
||||
|
||||
while true; do
|
||||
run_health_check
|
||||
sleep "$INTERVAL"
|
||||
done
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Main
|
||||
################################################################################
|
||||
|
||||
main() {
|
||||
if [ "$DAEMON_MODE" = true ]; then
|
||||
run_daemon
|
||||
else
|
||||
run_health_check
|
||||
fi
|
||||
}
|
||||
|
||||
# Execute
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user