New branch
This commit is contained in:
commit
58d70409b5
31 changed files with 9093 additions and 0 deletions
258
scripts/security-monitor.sh
Executable file
258
scripts/security-monitor.sh
Executable file
|
@ -0,0 +1,258 @@
|
|||
#############################################################
|
||||
# scripts/security-monitor.sh #
|
||||
#############################################################
|
||||
|
||||
cat > scripts/security-monitor.sh << 'EOFSECMON'
|
||||
#!/bin/bash
|
||||
|
||||
# VPN Security Monitor
|
||||
# Continuous monitoring of killswitch and VPN status
|
||||
# Version: 1.0.0
|
||||
|
||||
# Configuration
|
||||
CHECK_INTERVAL=10 # seconds
|
||||
ALERT_EMAIL="" # Set email for alerts
|
||||
LOG_FILE="/var/log/vpn-security-monitor.log"
|
||||
STATE_FILE="/var/run/vpn-monitor.state"
|
||||
|
||||
# Source network config
|
||||
if [ -f /opt/vpn-gateway/network.conf ]; then
|
||||
source /opt/vpn-gateway/network.conf
|
||||
fi
|
||||
|
||||
# Logging functions
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
|
||||
}
|
||||
|
||||
alert() {
|
||||
local message="$1"
|
||||
log "ALERT: $message"
|
||||
|
||||
# Send email alert if configured
|
||||
if [ -n "$ALERT_EMAIL" ]; then
|
||||
echo "$message" | mail -s "VPN Security Alert" "$ALERT_EMAIL" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# System notification (if available)
|
||||
if command -v notify-send >/dev/null 2>&1; then
|
||||
notify-send "VPN Security Alert" "$message" -u critical
|
||||
fi
|
||||
|
||||
# Log to syslog
|
||||
logger -t "vpn-security" -p auth.crit "$message"
|
||||
}
|
||||
|
||||
# Check functions
|
||||
check_killswitch() {
|
||||
# Verify DROP policies are active
|
||||
local policies_ok=true
|
||||
|
||||
for chain in INPUT OUTPUT FORWARD; do
|
||||
if ! iptables -L $chain -n | grep -q "policy DROP"; then
|
||||
alert "Killswitch policy missing for chain $chain!"
|
||||
policies_ok=false
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$policies_ok" = false ]; then
|
||||
log "Reactivating killswitch..."
|
||||
/usr/local/bin/vpn-killswitch.sh enable
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
check_vpn_connection() {
|
||||
if wg show wg0 >/dev/null 2>&1; then
|
||||
# VPN interface exists, check if it's actually working
|
||||
local endpoint=$(wg show wg0 endpoints | awk '{print $2}')
|
||||
|
||||
if [ -z "$endpoint" ]; then
|
||||
log "WARNING: VPN interface exists but no endpoint configured"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check last handshake
|
||||
local last_handshake=$(wg show wg0 latest-handshakes | awk '{print $2}')
|
||||
local current_time=$(date +%s)
|
||||
|
||||
if [ -n "$last_handshake" ] && [ "$last_handshake" -ne 0 ]; then
|
||||
local time_diff=$((current_time - last_handshake))
|
||||
|
||||
# If last handshake was more than 3 minutes ago, connection might be dead
|
||||
if [ $time_diff -gt 180 ]; then
|
||||
log "WARNING: Last WireGuard handshake was ${time_diff} seconds ago"
|
||||
return 2
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_dns_leaks() {
|
||||
# Check if DNS is going through VPN
|
||||
local dns_servers=$(cat /etc/resolv.conf | grep "^nameserver" | awk '{print $2}')
|
||||
|
||||
for dns in $dns_servers; do
|
||||
# Check if DNS server is in private range or VPN provider's DNS
|
||||
case "$dns" in
|
||||
10.*|172.16.*|172.17.*|172.18.*|172.19.*|172.2*|172.30.*|172.31.*|192.168.*|100.64.*)
|
||||
# Private IP, likely VPN DNS
|
||||
;;
|
||||
127.*)
|
||||
# Localhost, check if it's a DNS proxy
|
||||
if systemctl is-active systemd-resolved >/dev/null 2>&1; then
|
||||
log "WARNING: systemd-resolved is active, checking for leaks"
|
||||
# Additional checks for systemd-resolved
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
alert "Potential DNS leak detected! Public DNS server: $dns"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
check_leak_test() {
|
||||
# Try to reach internet without VPN
|
||||
local vpn_active=$(check_vpn_connection; echo $?)
|
||||
|
||||
if [ $vpn_active -eq 1 ]; then
|
||||
# VPN not active, internet should be blocked
|
||||
if ping -c 1 -W 1 8.8.8.8 >/dev/null 2>&1; then
|
||||
alert "CRITICAL: Internet accessible without VPN! Leak detected!"
|
||||
# Immediately re-enable killswitch
|
||||
/usr/local/bin/vpn-killswitch.sh enable
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
check_processes() {
|
||||
# Check for processes that might bypass VPN
|
||||
local suspicious_processes=$(netstat -tunp 2>/dev/null | grep -v "127.0.0.1\|::1\|$LAN_NET" | grep ESTABLISHED)
|
||||
|
||||
if [ -n "$suspicious_processes" ]; then
|
||||
log "WARNING: Detected network connections that might bypass VPN:"
|
||||
echo "$suspicious_processes" >> "$LOG_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
monitor_bandwidth() {
|
||||
# Monitor bandwidth to detect unusual activity
|
||||
if command -v vnstat >/dev/null 2>&1; then
|
||||
local current_tx=$(vnstat --oneline | cut -d';' -f9)
|
||||
local current_rx=$(vnstat --oneline | cut -d';' -f10)
|
||||
|
||||
if [ -f "$STATE_FILE" ]; then
|
||||
source "$STATE_FILE"
|
||||
|
||||
# Compare with previous values
|
||||
# Alert if sudden spike in traffic when VPN is down
|
||||
if ! check_vpn_connection && [ -n "$LAST_TX" ]; then
|
||||
# Calculate difference
|
||||
# If significant traffic when VPN is down, alert
|
||||
log "Bandwidth check: TX=$current_tx RX=$current_rx"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Save current state
|
||||
echo "LAST_TX='$current_tx'" > "$STATE_FILE"
|
||||
echo "LAST_RX='$current_rx'" >> "$STATE_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
auto_recovery() {
|
||||
local vpn_status=$(check_vpn_connection; echo $?)
|
||||
|
||||
if [ $vpn_status -eq 2 ]; then
|
||||
# Connection stale, try to reconnect
|
||||
log "Attempting auto-recovery of VPN connection..."
|
||||
|
||||
# Get last used server from config
|
||||
if [ -f /etc/wireguard/wg0.conf ]; then
|
||||
systemctl restart wg-quick@wg0 2>/dev/null || \
|
||||
wg-quick down wg0 2>/dev/null && wg-quick up wg0 2>/dev/null
|
||||
|
||||
sleep 5
|
||||
|
||||
if check_vpn_connection; then
|
||||
log "Auto-recovery successful"
|
||||
return 0
|
||||
else
|
||||
alert "Auto-recovery failed - manual intervention required"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main monitoring loop
|
||||
main() {
|
||||
log "VPN Security Monitor started"
|
||||
log "Check interval: ${CHECK_INTERVAL}s"
|
||||
|
||||
# Initial checks
|
||||
check_killswitch
|
||||
check_vpn_connection
|
||||
check_dns_leaks
|
||||
|
||||
local error_count=0
|
||||
|
||||
while true; do
|
||||
# Run all checks
|
||||
local all_ok=true
|
||||
|
||||
if ! check_killswitch; then
|
||||
all_ok=false
|
||||
((error_count++))
|
||||
fi
|
||||
|
||||
if ! check_leak_test; then
|
||||
all_ok=false
|
||||
((error_count++))
|
||||
fi
|
||||
|
||||
if ! check_dns_leaks; then
|
||||
all_ok=false
|
||||
((error_count++))
|
||||
fi
|
||||
|
||||
check_processes
|
||||
monitor_bandwidth
|
||||
|
||||
# Auto-recovery if needed
|
||||
if [ $error_count -gt 3 ]; then
|
||||
auto_recovery
|
||||
error_count=0
|
||||
fi
|
||||
|
||||
# Status indicator
|
||||
if [ "$all_ok" = true ]; then
|
||||
echo -n "."
|
||||
error_count=0
|
||||
else
|
||||
echo -n "!"
|
||||
fi
|
||||
|
||||
sleep "$CHECK_INTERVAL"
|
||||
done
|
||||
}
|
||||
|
||||
# Signal handlers
|
||||
trap 'log "Security monitor stopped"; exit 0' SIGTERM SIGINT
|
||||
|
||||
# Run main loop
|
||||
main
|
Loading…
Add table
Add a link
Reference in a new issue