123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- package main
- import (
- "crypto/rand"
- "crypto/rsa"
- "crypto/tls"
- "crypto/x509"
- "crypto/x509/pkix"
- "embed"
- "encoding/pem"
- "flag"
- "fmt"
- "io/fs"
- "log"
- "math/big"
- "net/http"
- "os"
- "time"
- )
- //go:embed www/*
- var embeddedFiles embed.FS
- const (
- certFile = "cert.pem"
- keyFile = "key.pem"
- )
- func main() {
- dev := flag.Bool("dev", true, "Serve files from www/ directory instead of embedded files")
- addr := flag.String("addr", ":8443", "HTTPS server address")
- flag.Parse()
- // Check and generate certs if needed
- if !fileExists(certFile) || !fileExists(keyFile) {
- fmt.Println("Certificates not found, generating self-signed certificate...")
- if err := generateSelfSignedCert(certFile, keyFile); err != nil {
- log.Fatalf("Failed to generate certificate: %v", err)
- }
- }
- var handler http.Handler
- if *dev {
- fmt.Println("Development mode: serving from www/ directory")
- handler = http.FileServer(http.Dir("www"))
- } else {
- fmt.Println("Production mode: serving embedded files")
- subFS, err := fs.Sub(embeddedFiles, "www")
- if err != nil {
- log.Fatalf("Failed to get sub filesystem: %v", err)
- }
- handler = http.FileServer(http.FS(subFS))
- }
- mux := http.NewServeMux()
- mux.Handle("/", handler)
- server := &http.Server{
- Addr: *addr,
- Handler: mux,
- TLSConfig: &tls.Config{
- MinVersion: tls.VersionTLS12,
- },
- }
- fmt.Printf("Starting HTTPS server on %s\n", *addr)
- log.Fatal(server.ListenAndServeTLS(certFile, keyFile))
- }
- func fileExists(filename string) bool {
- info, err := os.Stat(filename)
- return err == nil && !info.IsDir()
- }
- func generateSelfSignedCert(certPath, keyPath string) error {
- priv, err := rsa.GenerateKey(rand.Reader, 2048)
- if err != nil {
- return err
- }
- serialNumber, err := rand.Int(rand.Reader, big.NewInt(1<<62))
- if err != nil {
- return err
- }
- template := x509.Certificate{
- SerialNumber: serialNumber,
- Subject: pkix.Name{
- Organization: []string{"RedesKVM"},
- },
- NotBefore: time.Now(),
- NotAfter: time.Now().Add(365 * 24 * time.Hour),
- KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
- ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
- BasicConstraintsValid: true,
- }
- // Add localhost as SAN
- template.DNSNames = []string{"localhost"}
- derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
- if err != nil {
- return err
- }
- certOut, err := os.Create(certPath)
- if err != nil {
- return err
- }
- defer certOut.Close()
- if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
- return err
- }
- keyOut, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
- if err != nil {
- return err
- }
- defer keyOut.Close()
- privBytes := x509.MarshalPKCS1PrivateKey(priv)
- if err := pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: privBytes}); err != nil {
- return err
- }
- return nil
- }
|