package main import ( "context" "crypto/tls" "flag" "math/rand" "net" "net/http" "time" _ "git.xeserv.us/xena/route/internal" "git.xeserv.us/xena/route/internal/middleware" "git.xeserv.us/xena/route/internal/routecrypto" "github.com/Xe/ln" "github.com/caarlos0/env" "github.com/facebookgo/flagenv" _ "github.com/joho/godotenv/autoload" "github.com/lucas-clemente/quic-go/h2quic" ) var ( sslCertKey = flag.String("ssl-cert-key", "", "if set encrypt SSL certs with this key") ) func main() { flag.Parse() flagenv.Parse() rand.Seed(time.Now().Unix()) ctx, cancel := context.WithCancel(context.Background()) defer cancel() certKey, _ := routecrypto.ParseKey(*sslCertKey) scfg := Config{} err := env.Parse(&scfg) if err != nil { ln.FatalErr(ctx, err, ln.Action("parsing environment for config")) } scfg.CertKey = certKey s, err := New(scfg) if err != nil { ln.FatalErr(ctx, err, ln.Action("create server instance")) } go setupQuic(s, scfg) go setupTLS(s, scfg) // listen on HTTP listener l, err := net.Listen("tcp", scfg.WebAddr) if err != nil { ln.FatalErr(ctx, err, ln.Action("listening on HTTP port"), ln.F{"addr": scfg.WebAddr}) } defer l.Close() hs := &http.Server{ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodPatch, http.MethodPut, http.MethodPost: http.Error(w, "use https", http.StatusNotAcceptable) ln.Log(r.Context(), ln.Action("cannot redirect (wrong method)"), ln.F{"remote": r.RemoteAddr, "host": r.Host, "path": r.URL.Path}) return } r.URL.Host = r.Host r.URL.Scheme = "https" ln.Log(r.Context(), ln.Action("redirecting insecure HTTP to HTTPS"), ln.F{"remote": r.RemoteAddr, "host": r.Host, "path": r.URL.Path}) http.Redirect(w, r, r.URL.String(), http.StatusPermanentRedirect) }), Addr: scfg.WebAddr, } hs.Serve(l) } func setupQuic(s *Server, scfg Config) { qs := &h2quic.Server{ Server: &http.Server{ Handler: middleware.Trace(s), Addr: scfg.QuicAddr, TLSConfig: &tls.Config{ GetCertificate: s.GetCertificate, }, }, } s.QuicServer = qs for { ln.FatalErr(context.Background(), qs.ListenAndServe()) } } func setupTLS(s *Server, scfg Config) { hs := &http.Server{ Handler: middleware.Trace(s), Addr: scfg.SSLAddr, TLSConfig: &tls.Config{ GetCertificate: s.GetCertificate, }, } for { ln.FatalErr(context.Background(), hs.ListenAndServeTLS("", "")) } }