route/cmd/routed/main.go

108 lines
2.4 KiB
Go

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"
"git.xeserv.us/xena/route/internal/server"
"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 := server.Config{}
err := env.Parse(&scfg)
if err != nil {
ln.FatalErr(ctx, err, ln.Action("parsing environment for config"))
}
scfg.CertKey = certKey
s, err := server.New(scfg)
if err != nil {
ln.FatalErr(ctx, err, ln.Action("create server instance"))
}
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.Server, scfg server.Config) {
qs := &h2quic.Server{
Server: &http.Server{
Handler: middleware.Trace(s),
Addr: scfg.QuicAddr,
TLSConfig: &tls.Config{
GetCertificate: s.GetCertificate,
},
},
}
for {
qs.ListenAndServeTLS("", "")
}
}
func setupTLS(s *server.Server, scfg server.Config) {
hs := &http.Server{
Handler: middleware.Trace(s),
Addr: scfg.SSLAddr,
TLSConfig: &tls.Config{
GetCertificate: s.GetCertificate,
},
}
for {
hs.ListenAndServeTLS("", "")
}
}