feat: add security system with system-wide proxy, DNS protection and encryption
- System-wide proxy: automatic Windows proxy configuration for all apps - DNS leak protection: force all DNS queries through VPN - Config encryption: AES-256-GCM encryption for all config files - File protection: strict access permissions for config directory - Leak detection: built-in security check system - Kill Switch: temporarily disabled (will be improved in next version) Security features: ✓ Automatic system proxy setup ✓ DNS leak protection (optional) ✓ AES-256-GCM config encryption ✓ File and directory protection ✓ Security leak checker ⚠ Kill Switch disabled (caused internet blocking issues) Emergency recovery scripts included: - ОТКЛЮЧИТЬ_KILLSWITCH.bat - EMERGENCY_FIX_INTERNET.bat - ЕСЛИ_СЛОМАЛСЯ_ИНТЕРНЕТ.txt Documentation: - Markdown/SECURITY_GUIDE.md - full security guide - БЕЗОПАСНОСТЬ_БЫСТРЫЙ_СТАРТ.md - quick start guide - CHANGELOG_SECURITY.md - detailed changelog
This commit is contained in:
323
internal/cli/security.go
Normal file
323
internal/cli/security.go
Normal file
@@ -0,0 +1,323 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"vpn-client/internal/config"
|
||||
"vpn-client/internal/security"
|
||||
)
|
||||
|
||||
// securityMenu отображает меню безопасности
|
||||
func securityMenu() {
|
||||
for {
|
||||
clearScreen()
|
||||
fmt.Println(bold("╔════════════════════════════════════════════════════════════╗"))
|
||||
fmt.Println(bold("║ 🔒 БЕЗОПАСНОСТЬ И ЗАЩИТА ║"))
|
||||
fmt.Println(bold("╚════════════════════════════════════════════════════════════╝"))
|
||||
fmt.Println()
|
||||
|
||||
secManager := security.NewSecurityManager(config.ConfigDir, "default-password")
|
||||
status := secManager.GetSecurityStatus()
|
||||
|
||||
// Показываем текущий статус
|
||||
fmt.Println(cyan("Текущий статус безопасности:"))
|
||||
fmt.Println(strings.Repeat("─", 60))
|
||||
|
||||
if status["kill_switch_enabled"].(bool) {
|
||||
fmt.Printf(" Kill Switch: %s (отключен в этой версии)\n", yellow("⚠"))
|
||||
} else {
|
||||
fmt.Printf(" Kill Switch: %s (отключен в этой версии)\n", yellow("⚠"))
|
||||
}
|
||||
|
||||
if status["dns_protection_enabled"].(bool) {
|
||||
fmt.Printf(" Защита DNS: %s (активна)\n", green("✓"))
|
||||
} else {
|
||||
fmt.Printf(" Защита DNS: %s (неактивна)\n", red("✗"))
|
||||
}
|
||||
|
||||
if status["encryption_enabled"].(bool) {
|
||||
fmt.Printf(" Шифрование конфигов: %s (включено)\n", green("✓"))
|
||||
} else {
|
||||
fmt.Printf(" Шифрование конфигов: %s (выключено)\n", yellow("⚠"))
|
||||
}
|
||||
|
||||
if status["config_dir_protected"].(bool) {
|
||||
fmt.Printf(" Защита директории: %s (активна)\n", green("✓"))
|
||||
} else {
|
||||
fmt.Printf(" Защита директории: %s (неактивна)\n", red("✗"))
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println(strings.Repeat("─", 60))
|
||||
fmt.Println()
|
||||
fmt.Println("1. Настроить Kill Switch")
|
||||
fmt.Println("2. Настроить защиту DNS")
|
||||
fmt.Println("3. Управление шифрованием конфигов")
|
||||
fmt.Println("4. Проверить утечки")
|
||||
fmt.Println("5. Защитить директорию конфигураций")
|
||||
fmt.Println("6. Показать текущие DNS серверы")
|
||||
fmt.Println("0. Назад")
|
||||
fmt.Println()
|
||||
|
||||
choice := readInput("Выберите действие: ")
|
||||
|
||||
switch choice {
|
||||
case "1":
|
||||
configureKillSwitch(secManager)
|
||||
case "2":
|
||||
configureDNSProtection(secManager)
|
||||
case "3":
|
||||
configureEncryption(secManager)
|
||||
case "4":
|
||||
checkForLeaks(secManager)
|
||||
case "5":
|
||||
protectConfigDirectory(secManager)
|
||||
case "6":
|
||||
showCurrentDNS()
|
||||
case "0":
|
||||
return
|
||||
default:
|
||||
fmt.Printf("%s Неверный выбор\n", red("✗"))
|
||||
pause()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func configureKillSwitch(secManager *security.SecurityManager) {
|
||||
clearScreen()
|
||||
fmt.Println(bold("╔════════════════════════════════════════════════════════════╗"))
|
||||
fmt.Println(bold("║ НАСТРОЙКА KILL SWITCH ║"))
|
||||
fmt.Println(bold("╚════════════════════════════════════════════════════════════╝"))
|
||||
fmt.Println()
|
||||
fmt.Println(red("⚠️ KILL SWITCH ВРЕМЕННО ОТКЛЮЧЕН В ЭТОЙ ВЕРСИИ"))
|
||||
fmt.Println()
|
||||
fmt.Println("Kill Switch был отключен из-за проблем с блокировкой интернета.")
|
||||
fmt.Println("Функция будет доработана и добавлена в следующей версии.")
|
||||
fmt.Println()
|
||||
fmt.Println("Для защиты используйте:")
|
||||
fmt.Println(" • Защиту DNS (предотвращает DNS утечки)")
|
||||
fmt.Println(" • Системный прокси (работает автоматически)")
|
||||
fmt.Println(" • Шифрование конфигураций")
|
||||
fmt.Println()
|
||||
pause()
|
||||
}
|
||||
|
||||
func configureDNSProtection(secManager *security.SecurityManager) {
|
||||
clearScreen()
|
||||
fmt.Println(bold("╔════════════════════════════════════════════════════════════╗"))
|
||||
fmt.Println(bold("║ НАСТРОЙКА ЗАЩИТЫ DNS ║"))
|
||||
fmt.Println(bold("╚════════════════════════════════════════════════════════════╝"))
|
||||
fmt.Println()
|
||||
fmt.Println("Защита DNS предотвращает утечку DNS запросов за пределы VPN.")
|
||||
fmt.Println()
|
||||
|
||||
secConfig, err := secManager.LoadSecurityConfig()
|
||||
if err != nil {
|
||||
fmt.Printf("%s Ошибка загрузки конфигурации: %v\n", red("✗"), err)
|
||||
pause()
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Текущий статус: ")
|
||||
if secConfig.DNSProtectionEnabled {
|
||||
fmt.Println(green("Включена"))
|
||||
} else {
|
||||
fmt.Println(red("Отключена"))
|
||||
}
|
||||
|
||||
fmt.Printf("\nТекущие VPN DNS серверы:\n")
|
||||
for i, dns := range secConfig.VPNDNSServers {
|
||||
fmt.Printf(" %d. %s\n", i+1, dns)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("1. Включить/отключить защиту DNS")
|
||||
fmt.Println("2. Изменить DNS серверы")
|
||||
fmt.Println("0. Назад")
|
||||
fmt.Println()
|
||||
|
||||
choice := readInput("Выберите действие: ")
|
||||
|
||||
switch choice {
|
||||
case "1":
|
||||
secConfig.DNSProtectionEnabled = !secConfig.DNSProtectionEnabled
|
||||
if err := secManager.SaveSecurityConfig(secConfig); err != nil {
|
||||
fmt.Printf("%s Ошибка сохранения: %v\n", red("✗"), err)
|
||||
} else {
|
||||
if secConfig.DNSProtectionEnabled {
|
||||
fmt.Printf("%s Защита DNS включена\n", green("✓"))
|
||||
} else {
|
||||
fmt.Printf("%s Защита DNS отключена\n", yellow("⚠"))
|
||||
}
|
||||
}
|
||||
pause()
|
||||
|
||||
case "2":
|
||||
fmt.Println("\nВведите DNS серверы (через запятую):")
|
||||
fmt.Println("Например: 1.1.1.1,8.8.8.8")
|
||||
fmt.Print("> ")
|
||||
|
||||
dnsInput := readInput("")
|
||||
dnsServers := strings.Split(dnsInput, ",")
|
||||
|
||||
var cleanDNS []string
|
||||
for _, dns := range dnsServers {
|
||||
dns = strings.TrimSpace(dns)
|
||||
if dns != "" {
|
||||
cleanDNS = append(cleanDNS, dns)
|
||||
}
|
||||
}
|
||||
|
||||
if len(cleanDNS) > 0 {
|
||||
secConfig.VPNDNSServers = cleanDNS
|
||||
if err := secManager.SaveSecurityConfig(secConfig); err != nil {
|
||||
fmt.Printf("%s Ошибка сохранения: %v\n", red("✗"), err)
|
||||
} else {
|
||||
fmt.Printf("%s DNS серверы обновлены\n", green("✓"))
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%s Не указаны DNS серверы\n", red("✗"))
|
||||
}
|
||||
pause()
|
||||
}
|
||||
}
|
||||
|
||||
func configureEncryption(secManager *security.SecurityManager) {
|
||||
clearScreen()
|
||||
fmt.Println(bold("╔════════════════════════════════════════════════════════════╗"))
|
||||
fmt.Println(bold("║ ШИФРОВАНИЕ КОНФИГУРАЦИЙ ║"))
|
||||
fmt.Println(bold("╚════════════════════════════════════════════════════════════╝"))
|
||||
fmt.Println()
|
||||
fmt.Println("Шифрование защищает ваши конфигурации VPN от несанкционированного")
|
||||
fmt.Println("доступа. Файлы шифруются с использованием AES-256-GCM.")
|
||||
fmt.Println()
|
||||
|
||||
secConfig, err := secManager.LoadSecurityConfig()
|
||||
if err != nil {
|
||||
fmt.Printf("%s Ошибка загрузки конфигурации: %v\n", red("✗"), err)
|
||||
pause()
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Текущий статус: ")
|
||||
if secConfig.EncryptionEnabled {
|
||||
fmt.Println(green("Включено"))
|
||||
} else {
|
||||
fmt.Println(red("Отключено"))
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("1. Включить шифрование")
|
||||
fmt.Println("2. Отключить шифрование")
|
||||
fmt.Println("0. Назад")
|
||||
fmt.Println()
|
||||
|
||||
choice := readInput("Выберите действие: ")
|
||||
|
||||
switch choice {
|
||||
case "1":
|
||||
secConfig.EncryptionEnabled = true
|
||||
if err := secManager.SaveSecurityConfig(secConfig); err != nil {
|
||||
fmt.Printf("%s Ошибка сохранения: %v\n", red("✗"), err)
|
||||
} else {
|
||||
fmt.Printf("%s Шифрование включено\n", green("✓"))
|
||||
fmt.Println("\nВнимание: Конфигурации будут зашифрованы автоматически")
|
||||
}
|
||||
pause()
|
||||
|
||||
case "2":
|
||||
fmt.Println(yellow("\n⚠ Предупреждение: Отключение шифрования снизит безопасность!"))
|
||||
confirm := readInput("Вы уверены? (yes/no): ")
|
||||
if strings.ToLower(confirm) == "yes" {
|
||||
secConfig.EncryptionEnabled = false
|
||||
if err := secManager.SaveSecurityConfig(secConfig); err != nil {
|
||||
fmt.Printf("%s Ошибка сохранения: %v\n", red("✗"), err)
|
||||
} else {
|
||||
fmt.Printf("%s Шифрование отключено\n", yellow("⚠"))
|
||||
}
|
||||
}
|
||||
pause()
|
||||
}
|
||||
}
|
||||
|
||||
func checkForLeaks(secManager *security.SecurityManager) {
|
||||
clearScreen()
|
||||
fmt.Println(bold("╔════════════════════════════════════════════════════════════╗"))
|
||||
fmt.Println(bold("║ ПРОВЕРКА УТЕЧЕК ║"))
|
||||
fmt.Println(bold("╚════════════════════════════════════════════════════════════╝"))
|
||||
fmt.Println()
|
||||
fmt.Println("Проверка безопасности соединения...")
|
||||
fmt.Println()
|
||||
|
||||
leaks, err := secManager.CheckForLeaks()
|
||||
if err != nil {
|
||||
fmt.Printf("%s Ошибка проверки: %v\n", red("✗"), err)
|
||||
pause()
|
||||
return
|
||||
}
|
||||
|
||||
if len(leaks) == 0 {
|
||||
fmt.Printf("%s Утечек не обнаружено!\n", green("✓"))
|
||||
fmt.Println("\nВаше соединение безопасно:")
|
||||
fmt.Println(" • DNS запросы защищены")
|
||||
fmt.Println(" • Kill Switch активен")
|
||||
fmt.Println(" • Трафик идет через VPN")
|
||||
} else {
|
||||
fmt.Printf("%s Обнаружены потенциальные утечки:\n\n", red("✗"))
|
||||
for i, leak := range leaks {
|
||||
fmt.Printf(" %d. %s\n", i+1, leak)
|
||||
}
|
||||
fmt.Println("\nРекомендации:")
|
||||
fmt.Println(" • Проверьте настройки безопасности")
|
||||
fmt.Println(" • Убедитесь, что VPN подключен")
|
||||
fmt.Println(" • Включите Kill Switch и защиту DNS")
|
||||
}
|
||||
|
||||
pause()
|
||||
}
|
||||
|
||||
func protectConfigDirectory(secManager *security.SecurityManager) {
|
||||
clearScreen()
|
||||
fmt.Println(bold("╔════════════════════════════════════════════════════════════╗"))
|
||||
fmt.Println(bold("║ ЗАЩИТА ДИРЕКТОРИИ КОНФИГУРАЦИЙ ║"))
|
||||
fmt.Println(bold("╚════════════════════════════════════════════════════════════╝"))
|
||||
fmt.Println()
|
||||
fmt.Println("Установка строгих прав доступа к файлам конфигураций...")
|
||||
fmt.Println()
|
||||
|
||||
if err := secManager.ProtectConfigDirectory(); err != nil {
|
||||
fmt.Printf("%s Ошибка: %v\n", red("✗"), err)
|
||||
} else {
|
||||
fmt.Printf("%s Директория конфигураций защищена\n", green("✓"))
|
||||
fmt.Println("\nТеперь только владелец может читать и изменять конфигурации")
|
||||
}
|
||||
|
||||
pause()
|
||||
}
|
||||
|
||||
func showCurrentDNS() {
|
||||
clearScreen()
|
||||
fmt.Println(bold("╔════════════════════════════════════════════════════════════╗"))
|
||||
fmt.Println(bold("║ ТЕКУЩИЕ DNS СЕРВЕРЫ ║"))
|
||||
fmt.Println(bold("╚════════════════════════════════════════════════════════════╝"))
|
||||
fmt.Println()
|
||||
|
||||
dnsServers, err := security.GetCurrentDNS()
|
||||
if err != nil {
|
||||
fmt.Printf("%s Ошибка получения DNS: %v\n", red("✗"), err)
|
||||
pause()
|
||||
return
|
||||
}
|
||||
|
||||
if len(dnsServers) == 0 {
|
||||
fmt.Println(yellow("DNS серверы не обнаружены"))
|
||||
} else {
|
||||
fmt.Println("Активные DNS серверы:")
|
||||
for i, dns := range dnsServers {
|
||||
fmt.Printf(" %d. %s\n", i+1, dns)
|
||||
}
|
||||
}
|
||||
|
||||
pause()
|
||||
}
|
||||
Reference in New Issue
Block a user