2023-04-21 03:21:46 +01:00
|
|
|
package servers
|
2023-04-22 18:11:21 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
|
|
|
"fmt"
|
|
|
|
"github.com/MrMelon54/violet/utils"
|
|
|
|
"github.com/gorilla/mux"
|
|
|
|
"github.com/sethvargo/go-limiter/httplimit"
|
|
|
|
"github.com/sethvargo/go-limiter/memorystore"
|
|
|
|
"log"
|
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// NewHttpsServer creates and runs a http server containing the public https
|
|
|
|
// endpoints for the reverse proxy.
|
|
|
|
func NewHttpsServer(conf *Conf) *http.Server {
|
|
|
|
s := &http.Server{
|
2023-04-24 15:36:21 +01:00
|
|
|
Addr: conf.HttpsListen,
|
|
|
|
Handler: setupRateLimiter(300).Middleware(conf.Router),
|
2023-04-22 18:11:21 +01:00
|
|
|
DisableGeneralOptionsHandler: false,
|
|
|
|
TLSConfig: &tls.Config{GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
|
|
|
// error out on invalid domains
|
|
|
|
if !conf.Domains.IsValid(info.ServerName) {
|
|
|
|
return nil, fmt.Errorf("invalid hostname used: '%s'", info.ServerName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// find a certificate
|
|
|
|
cert := conf.Certs.GetCertForDomain(info.ServerName)
|
|
|
|
if cert == nil {
|
|
|
|
return nil, fmt.Errorf("failed to find certificate for: '%s'", info.ServerName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// time to return
|
|
|
|
return cert, nil
|
|
|
|
}},
|
|
|
|
ReadTimeout: 150 * time.Second,
|
|
|
|
ReadHeaderTimeout: 150 * time.Second,
|
|
|
|
WriteTimeout: 150 * time.Second,
|
|
|
|
IdleTimeout: 150 * time.Second,
|
|
|
|
MaxHeaderBytes: 4096000,
|
|
|
|
ConnState: func(conn net.Conn, state http.ConnState) {
|
|
|
|
fmt.Printf("%s => %s: %s\n", conn.LocalAddr(), conn.RemoteAddr(), state.String())
|
|
|
|
},
|
|
|
|
}
|
|
|
|
log.Printf("[HTTPS] Starting HTTPS server on: '%s'\n", s.Addr)
|
|
|
|
go utils.RunBackgroundHttps("HTTPS", s)
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
// setupRateLimiter is an internal function to create a middleware to manage
|
|
|
|
// rate limits.
|
|
|
|
func setupRateLimiter(rateLimit uint64) mux.MiddlewareFunc {
|
|
|
|
// create memory store
|
|
|
|
store, err := memorystore.New(&memorystore.Config{
|
|
|
|
Tokens: rateLimit,
|
|
|
|
Interval: time.Minute,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// create a middleware using ips as the key for rate limits
|
|
|
|
middleware, err := httplimit.NewMiddleware(store, httplimit.IPKeyFunc())
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
return middleware.Handle
|
|
|
|
}
|