Files
vServer/Backend/WebServer/https_server.go
Falknat 7a87617282 Инициализация проекта
Стабильный рабочий проект.
2025-10-02 06:02:45 +07:00

180 lines
5.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}
}