Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 5 additions & 44 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,48 +1,9 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
.pytest_cache/
.env
.venv
venv/
ENV/
env.bak/
venv.bak/
*.egg-info/
dist/
build/

# Security Analysis Results (user-generated)
*.json
*_results.txt
*_report.txt
*_audit.json
daily_check.json
weekly_audit.json
security_check.json

# macOS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# Temporary files
*.tmp
*.temp
*.log

# User configuration
config.local.py
.env
.log
*.log
163 changes: 163 additions & 0 deletions src/vpn_config_detector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import logging
import subprocess
import platform
from typing import Dict, Optional, List, Any

class VPNConfigurationError(Exception):
"""Custom exception for VPN configuration detection errors."""
pass

class VPNConfigDetector:
"""
A comprehensive VPN configuration detection and analysis class.

Handles error detection, logging, and retrieval of VPN connection details.
"""

def __init__(self, log_level: int = logging.INFO):
"""
Initialize VPN configuration detector with logging.

Args:
log_level (int): Logging level, defaults to INFO
"""
logging.basicConfig(
level=log_level,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
self.logger = logging.getLogger(__name__)

def detect_vpn_connections(self) -> List[Dict[str, Any]]:
"""
Detect active VPN connections across different interfaces.

Returns:
List of dictionaries containing VPN connection details

Raises:
VPNConfigurationError: If detection fails
"""
try:
# Detect OS and use appropriate method
os_name = platform.system().lower()

if os_name == 'darwin': # macOS
return self._detect_vpn_macos()
elif os_name == 'linux':
return self._detect_vpn_linux()
else:
self.logger.warning(f"Unsupported OS: {os_name}")
return []

except Exception as e:
self.logger.error(f"Unexpected error during VPN detection: {e}")
raise VPNConfigurationError(f"Unexpected VPN detection error: {e}")

def _detect_vpn_macos(self) -> List[Dict[str, Any]]:
"""
Detect VPN connections on macOS.

Returns:
List of VPN connection details
"""
try:
result = subprocess.run(
['scutil', '--nc', 'list'],
capture_output=True,
text=True,
timeout=5
)

# Basic parsing of scutil output
vpn_connections = []
for line in result.stdout.split('\n'):
if 'VPN' in line or 'Connected' in line:
vpn_connections.append({
'interface': 'utun',
'status': 'active',
'protocol': 'Unknown'
})

if not vpn_connections:
self.logger.info("No VPN connections detected on macOS")

return vpn_connections

except subprocess.TimeoutExpired:
self.logger.error("macOS VPN detection timed out")
return []
except Exception as e:
self.logger.error(f"macOS VPN detection error: {e}")
return []

def _detect_vpn_linux(self) -> List[Dict[str, Any]]:
"""
Detect VPN connections on Linux.

Returns:
List of VPN connection details
"""
try:
# Check for typical VPN interface names
vpn_interfaces = ['tun', 'tap', 'ppp']
vpn_connections = []

result = subprocess.run(
['ip', 'link', 'show'],
capture_output=True,
text=True,
timeout=5
)

for line in result.stdout.split('\n'):
for interface in vpn_interfaces:
if interface in line.lower():
vpn_connections.append({
'interface': line.split(':')[1].strip(),
'status': 'active',
'protocol': 'OpenVPN' if 'tun' in interface else 'Unknown'
})

if not vpn_connections:
self.logger.info("No VPN connections detected on Linux")

return vpn_connections

except subprocess.TimeoutExpired:
self.logger.error("Linux VPN detection timed out")
return []
except Exception as e:
self.logger.error(f"Linux VPN detection error: {e}")
return []

def validate_vpn_configuration(self, config: Dict[str, Any]) -> bool:
"""
Validate VPN configuration for potential security issues.

Args:
config (Dict[str, Any]): VPN configuration to validate

Returns:
bool: Whether configuration passes basic security checks
"""
try:
if not config:
self.logger.warning("Empty VPN configuration")
return False

# Add specific validation checks
if config.get('protocol') not in ['OpenVPN', 'WireGuard', 'IPSec', 'Unknown']:
self.logger.warning(f"Unsupported VPN protocol: {config.get('protocol')}")
return False

return True

except Exception as e:
self.logger.error(f"Configuration validation error: {e}")
return False

# Configure default logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
43 changes: 43 additions & 0 deletions tests/test_vpn_config_detector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import pytest
import logging
from src.vpn_config_detector import VPNConfigDetector, VPNConfigurationError

def test_vpn_config_detector_initialization():
"""Test VPN configuration detector initialization."""
detector = VPNConfigDetector()
assert detector is not None
assert detector.logger is not None

def test_detect_vpn_connections_empty():
"""Test VPN connection detection with no connections."""
detector = VPNConfigDetector(log_level=logging.DEBUG)
connections = detector.detect_vpn_connections()
assert isinstance(connections, list)

def test_validate_vpn_configuration():
"""Test VPN configuration validation."""
detector = VPNConfigDetector()

# Test valid configuration
valid_config = {
'protocol': 'OpenVPN',
'interface': 'tun0'
}
assert detector.validate_vpn_configuration(valid_config) is True

# Test invalid configuration
invalid_config = {
'protocol': 'UnknownProtocol'
}
assert detector.validate_vpn_configuration(invalid_config) is False
assert detector.validate_vpn_configuration({}) is False

def test_error_handling():
"""Test error handling in VPN configuration detection."""
detector = VPNConfigDetector(log_level=logging.DEBUG)

# Test with an edge case configuration
assert detector.validate_vpn_configuration({
'protocol': 'Unknown',
'interface': 'testing'
}) is True