package webserver import ( "crypto/tls" "fmt" "io" "log" "net/http" "os" "path/filepath" "strings" tools "vServer/Backend/tools" ) var certDir = "WebServer/cert/" var certMap map[string]*tls.Certificate var fallbackCert *tls.Certificate var httpsServer *http.Server var port_https string = "443" // Запуск https сервера func StartHTTPS() { if tools.Port_check("HTTPS", "localhost", port_https) { return } // Отключаем вывод ошибок TLS в консоль log.SetOutput(io.Discard) // Конфигурация TLS tlsConfig := &tls.Config{ GetCertificate: func(chi *tls.ClientHelloInfo) (*tls.Certificate, error) { serverName := chi.ServerName if serverName == "" { tools.Logs_file(1, "HTTPS", "⚠️ Подключение без SNI (возможно по IP)", "logs_https.log", false) } else if cert, ok := certMap[serverName]; ok { // Найден точный сертификат для домена return cert, nil } else { // Пробуем найти сертификат для родительского домена parentDomain := getParentDomain(serverName) if parentDomain != "" { if cert, ok := certMap[parentDomain]; ok { tools.Logs_file(1, "HTTPS", "✅ Используем сертификат родительского домена "+parentDomain+" для "+serverName, "logs_https.log", false) return cert, nil } } tools.Logs_file(1, "HTTPS", "⚠️ Нет сертификата для: "+serverName, "logs_https.log", false) } if fallbackCert != nil { tools.Logs_file(1, "HTTPS", "⚠️ Используем fallback-сертификат", "logs_https.log", false) return fallbackCert, nil } tools.Logs_file(1, "HTTPS", "❌ Нет fallback-сертификата — соединение будет отклонено", "logs_https.log", true) return nil, nil }, } // Запуск сервера httpsServer = &http.Server{ Addr: ":" + port_https, TLSConfig: tlsConfig, Handler: nil, } tools.Logs_file(0, "HTTPS", "✅ HTTPS сервер запущен на порту "+port_https, "logs_https.log", true) if err := httpsServer.ListenAndServeTLS("", ""); err != nil { // Игнорируем нормальную ошибку при остановке сервера if err.Error() != "http: Server closed" { tools.Logs_file(1, "HTTPS", "❌ Ошибка запуска сервера: "+err.Error(), "logs_https.log", true) } } } // Извлекает родительский домен из поддомена func getParentDomain(domain string) string { parts := strings.Split(domain, ".") if len(parts) <= 2 { return "" // Уже основной домен или некорректный формат } // Возвращаем домен без первого поддомена return strings.Join(parts[1:], ".") } // Проверяет, существует ли сертификат для домена func Cert_start() { fallbackCert = loadFallbackCertificate(filepath.Join(certDir, "no_cert")) certMap = loadCertificates(certDir) } func checkHostCert(r *http.Request) bool { if _, err := os.Stat(certDir + r.Host); err != nil { return false } return true } func loadCertificates(certDir string) map[string]*tls.Certificate { certMap := make(map[string]*tls.Certificate) entries, err := os.ReadDir(certDir) if err != nil { tools.Logs_file(1, "HTTPS", "📁 Ошибка чтения каталога сертификатов: "+err.Error(), "logs_https.log", true) } for _, entry := range entries { if !entry.IsDir() || entry.Name() == "no_cert" { continue } domain := entry.Name() certPath := filepath.Join(certDir, domain, "certificate.crt") keyPath := filepath.Join(certDir, domain, "private.key") cert, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { tools.Logs_file(1, "HTTPS", "⚠️ Ошибка загрузки сертификата для "+domain+": "+err.Error(), "logs_https.log", true) continue } certMap[domain] = &cert tools.Logs_file(0, "HTTPS", "✅ Загрузили сертификат для: "+tools.Color(domain, tools.Голубой), "logs_https.log", true) } return certMap } func loadFallbackCertificate(fallbackDir string) *tls.Certificate { certPath := filepath.Join(fallbackDir, "certificate.crt") keyPath := filepath.Join(fallbackDir, "private.key") cert, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { tools.Logs_file(1, "HTTPS", "⚠️ Не удалось загрузить fallback-сертификат: "+err.Error(), "logs_https.log", true) return nil } tools.Logs_file(0, "HTTPS", "✅ Fallback-сертификат загружен", "logs_https.log", true) return &cert } func ReloadCertificates() { fmt.Println("") fmt.Println("🔒 Перезагружаем SSL сертификаты...") fmt.Println("") // Выгружаем старые сертификаты certMap = make(map[string]*tls.Certificate) fallbackCert = nil fmt.Println("⏹️ Старые сертификаты выгружены") // Загружаем сертификаты заново Cert_start() fmt.Println("✅ SSL сертификаты успешно перезагружены!") fmt.Println("") } // StopHTTPSServer останавливает HTTPS сервер func StopHTTPSServer() { // Останавливаем HTTPS сервер if httpsServer != nil { httpsServer.Close() httpsServer = nil tools.Logs_file(0, "HTTPS", "HTTPS сервер остановлен", "logs_https.log", true) } }