Files
vServer/Backend/WebServer/https_server.go
Falknat 02ae56b78c Большое обновление GUI интерфейс
Большое обновление GUI интерфейс

- Добавлен фраемворr Walles
- Удалена консольная версия
- Проработан интерфейс и дизайн
- Добавлено кеширование для быстрой реакции.
- Сделан .ps1 сборщик для удобной сборки проекта.
- Обновлён Readme
2025-11-14 08:40:25 +07:00

185 lines
5.7 KiB
Go
Raw 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"
// GetHTTPSStatus возвращает статус HTTPS сервера
func GetHTTPSStatus() bool {
return httpsServer != nil
}
// Запуск 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)
}
}