diff options
Diffstat (limited to 'internal/net')
| -rw-r--r-- | internal/net/server.go | 106 |
1 files changed, 88 insertions, 18 deletions
diff --git a/internal/net/server.go b/internal/net/server.go index 851a4b5..345122e 100644 --- a/internal/net/server.go +++ b/internal/net/server.go @@ -1,12 +1,18 @@ package net import ( + "crypto/rand" + "crypto/rsa" "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" "fmt" "log" + "math/big" "net" "net/http" "sync" + "time" "thehouseoficarus/internal/behavior" "thehouseoficarus/internal/color" @@ -70,13 +76,14 @@ type Session struct { } type Server struct { - config *config.Config - telnetLn net.Listener - telnetTLSLn net.Listener - httpServer *http.Server - httpsServer *http.Server - hub *Hub - handler func(*Session, string) + config *config.Config + telnetLn net.Listener + telnetTLSLn net.Listener + httpServer *http.Server + httpsServer *http.Server + httpsTLSConfig *tls.Config + hub *Hub + handler func(*Session, string) } type Hub struct { @@ -192,12 +199,20 @@ func NewServer(cfg *config.Config) (*Server, error) { } if cfg.TelnetTLS.Enabled { + var cert tls.Certificate if cfg.TelnetTLS.CertFile == "" || cfg.TelnetTLS.KeyFile == "" { - return nil, fmt.Errorf("telnet_tls enabled but cert_file and key_file are required") - } - cert, err := tls.LoadX509KeyPair(cfg.TelnetTLS.CertFile, cfg.TelnetTLS.KeyFile) - if err != nil { - return nil, fmt.Errorf("telnet_tls cert: %w", err) + var err error + cert, err = generateSelfSignedCert() + if err != nil { + return nil, fmt.Errorf("telnet_tls self-signed cert: %w", err) + } + log.Printf("telnet_tls: using self-signed certificate (no cert_file/key_file configured)") + } else { + var err error + cert, err = tls.LoadX509KeyPair(cfg.TelnetTLS.CertFile, cfg.TelnetTLS.KeyFile) + if err != nil { + return nil, fmt.Errorf("telnet_tls cert: %w", err) + } } tlsCfg := &tls.Config{ Certificates: []tls.Certificate{cert}, @@ -219,19 +234,68 @@ func NewServer(cfg *config.Config) (*Server, error) { } if cfg.HTTPS.Enabled { + var cert tls.Certificate if cfg.HTTPS.CertFile == "" || cfg.HTTPS.KeyFile == "" { - return nil, fmt.Errorf("https enabled but cert_file and key_file are required") + var err error + cert, err = generateSelfSignedCert() + if err != nil { + return nil, fmt.Errorf("https self-signed cert: %w", err) + } + log.Printf("https: using self-signed certificate (no cert_file/key_file configured)") + } else { + var err error + cert, err = tls.LoadX509KeyPair(cfg.HTTPS.CertFile, cfg.HTTPS.KeyFile) + if err != nil { + return nil, fmt.Errorf("https cert: %w", err) + } + } + s.httpsTLSConfig = &tls.Config{ + Certificates: []tls.Certificate{cert}, + MinVersion: tls.VersionTLS12, } s.httpsServer = &http.Server{ - Addr: fmt.Sprintf(":%d", cfg.HTTPS.Port), - Handler: newHTTPMux(s), - TLSConfig: &tls.Config{MinVersion: tls.VersionTLS12}, + Addr: fmt.Sprintf(":%d", cfg.HTTPS.Port), + Handler: newHTTPMux(s), } } return s, nil } +func generateSelfSignedCert() (tls.Certificate, error) { + key, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return tls.Certificate{}, fmt.Errorf("rsa key generation: %w", err) + } + serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) + if err != nil { + return tls.Certificate{}, fmt.Errorf("serial number: %w", err) + } + now := time.Now() + template := &x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{ + CommonName: "THOI Self-Signed Certificate", + }, + NotBefore: now.Add(-1 * time.Hour), + NotAfter: now.Add(365 * 24 * time.Hour), + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + IsCA: true, + DNSNames: []string{"localhost"}, + IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}, + } + certDER, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key) + if err != nil { + return tls.Certificate{}, fmt.Errorf("x509 creation: %w", err) + } + return tls.Certificate{ + Certificate: [][]byte{certDER}, + PrivateKey: key, + }, nil +} + func (s *Server) Hub() *Hub { return s.hub } @@ -300,8 +364,14 @@ func (s *Server) serveHTTP() { } func (s *Server) serveHTTPS() { - err := s.httpsServer.ListenAndServeTLS(s.config.HTTPS.CertFile, s.config.HTTPS.KeyFile) - if err != nil && err != http.ErrServerClosed { + addr := fmt.Sprintf(":%d", s.config.HTTPS.Port) + ln, err := net.Listen("tcp", addr) + if err != nil { + log.Printf("https server error: %v", err) + return + } + tlsLn := tls.NewListener(ln, s.httpsTLSConfig) + if err := s.httpsServer.Serve(tlsLn); err != nil && err != http.ErrServerClosed { log.Printf("https server error: %v", err) } } |
