Инициализация проекта
Стабильный рабочий проект.
This commit is contained in:
179
Backend/WebServer/https_server.go
Normal file
179
Backend/WebServer/https_server.go
Normal file
@@ -0,0 +1,179 @@
|
||||
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)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user