Alte Schannel-Stacks brechen an einem TLS-1.3-ClientHello kommentarlos ab: sie nehmen die TCP-Verbindung an, lesen den ClientHello und setzen zurueck, ohne ein Zertifikat zu schicken. Herunterhandeln hilft dann nicht — TLS 1.3 darf gar nicht erst angeboten werden. max_tls_version (Default 1.3) deckelt die Hoechstversion; die Validierung lehnt eine Hoechstversion unterhalb der Mindestversion ab. check erkennt zusaetzlich zurueckgesetzte Verbindungen und nennt die beiden plausiblen Ursachen: fehlendes LDAPS-Zertifikat auf dem Server oder TLS-1.3-Inkompatibilitaet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NBHF4R9EAejDJUMdwr6C68
119 lines
3.5 KiB
Go
119 lines
3.5 KiB
Go
// Package config lädt und validiert die Portal-Konfiguration.
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// Duration erlaubt Dauerangaben als String ("10m") in YAML.
|
|
type Duration time.Duration
|
|
|
|
func (d *Duration) UnmarshalYAML(node *yaml.Node) error {
|
|
var s string
|
|
if err := node.Decode(&s); err != nil {
|
|
return fmt.Errorf("Dauer muss eine Zeichenkette sein (z. B. \"10m\"): %w", err)
|
|
}
|
|
parsed, err := time.ParseDuration(s)
|
|
if err != nil {
|
|
return fmt.Errorf("ungültige Dauer %q (erwartet z. B. \"10m\", \"90s\"): %w", s, err)
|
|
}
|
|
if parsed <= 0 {
|
|
return fmt.Errorf("Dauer %q muss positiv sein", s)
|
|
}
|
|
*d = Duration(parsed)
|
|
return nil
|
|
}
|
|
|
|
func (d Duration) String() string { return time.Duration(d).String() }
|
|
|
|
type Config struct {
|
|
Portal PortalConfig `yaml:"portal"`
|
|
OPNsense OPNsenseConfig `yaml:"opnsense"`
|
|
AD ADConfig `yaml:"ad"`
|
|
Matching MatchingConfig `yaml:"matching"`
|
|
Logging LoggingConfig `yaml:"logging"`
|
|
}
|
|
|
|
type PortalConfig struct {
|
|
Listen string `yaml:"listen"`
|
|
TLSCert string `yaml:"tls_cert"`
|
|
TLSKey string `yaml:"tls_key"`
|
|
SessionTTL Duration `yaml:"session_ttl"`
|
|
Title string `yaml:"title"`
|
|
LogoFile string `yaml:"logo_file"`
|
|
SupportContact string `yaml:"support_contact"`
|
|
UpdateCheck bool `yaml:"update_check"`
|
|
}
|
|
|
|
type OPNsenseConfig struct {
|
|
URL string `yaml:"url"`
|
|
APIKey string `yaml:"api_key"`
|
|
APIKeyFile string `yaml:"api_key_file"`
|
|
APISecret string `yaml:"api_secret"`
|
|
APISecretFile string `yaml:"api_secret_file"`
|
|
CAFile string `yaml:"ca_file"`
|
|
InsecureSkipVerify bool `yaml:"insecure_skip_verify"`
|
|
}
|
|
|
|
type ADConfig struct {
|
|
Domain string `yaml:"domain"`
|
|
BaseDN string `yaml:"base_dn"`
|
|
Servers []string `yaml:"servers"`
|
|
Port int `yaml:"port"`
|
|
TLSMode string `yaml:"tls_mode"` // "ldaps" (Default) oder "starttls"
|
|
// MinTLSVersion ist die niedrigste akzeptierte TLS-Version zum
|
|
// Verzeichnisdienst: "1.0", "1.1", "1.2" (Default) oder "1.3".
|
|
// Unter 1.2 nur für Altsysteme, die nichts Besseres können.
|
|
MinTLSVersion string `yaml:"min_tls_version"`
|
|
// MaxTLSVersion deckelt die angebotene TLS-Version, Default "1.3".
|
|
// Auf "1.2" setzen, wenn ein alter Schannel-Stack den Verbindungsaufbau
|
|
// bereits am TLS-1.3-ClientHello abbricht.
|
|
MaxTLSVersion string `yaml:"max_tls_version"`
|
|
BindUser string `yaml:"bind_user"`
|
|
BindPassword string `yaml:"bind_password"`
|
|
BindPasswordFile string `yaml:"bind_password_file"`
|
|
VPNGroup string `yaml:"vpn_group"`
|
|
CAFile string `yaml:"ca_file"`
|
|
Timeout Duration `yaml:"timeout"`
|
|
}
|
|
|
|
type MatchingConfig struct {
|
|
CNPattern string `yaml:"cn_pattern"`
|
|
CNRegex string `yaml:"cn_regex"`
|
|
}
|
|
|
|
type LoggingConfig struct {
|
|
Level string `yaml:"level"`
|
|
AuditLog string `yaml:"audit_log"`
|
|
MaxSizeMB int `yaml:"max_size_mb"`
|
|
MaxBackups int `yaml:"max_backups"`
|
|
Compress bool `yaml:"compress"`
|
|
}
|
|
|
|
// Defaults liefert eine Config mit allen Vorgabewerten.
|
|
func Defaults() *Config {
|
|
return &Config{
|
|
Portal: PortalConfig{
|
|
Listen: "0.0.0.0:8443",
|
|
SessionTTL: Duration(10 * time.Minute),
|
|
Title: "VPN-Portal",
|
|
},
|
|
AD: ADConfig{
|
|
Port: 636,
|
|
TLSMode: "ldaps",
|
|
MinTLSVersion: "1.2",
|
|
MaxTLSVersion: "1.3",
|
|
Timeout: Duration(8 * time.Second),
|
|
},
|
|
Matching: MatchingConfig{CNPattern: "{username}"},
|
|
Logging: LoggingConfig{
|
|
Level: "info",
|
|
MaxSizeMB: 50,
|
|
MaxBackups: 5,
|
|
Compress: true,
|
|
},
|
|
}
|
|
}
|