Add HSTS & cipher suites, handle fallback cert errors & change default port to 443
This commit is contained in:
parent 0602811709
commit 7c70be21d7
3 changed files with 86 additions and 29 deletions
102 certificates.go
102
certificates.go | @ -1,6 +1,7 @@ | |||
package main | ||||
| ||||
import ( | ||||
"bytes" | ||||
"crypto/rand" | ||||
"crypto/rsa" | ||||
"crypto/tls" | ||||
| @ -12,38 +13,85 @@ import ( | |||
"time" | ||||
) | ||||
| ||||
var fallbackCertKey, _ = rsa.GenerateKey(rand.Reader, 1024) | ||||
var fallbackCertSpecification = &x509.Certificate{ | ||||
Subject: pkix.Name{ | ||||
CommonName: strings.TrimPrefix(string(MainDomainSuffix), "."), | ||||
}, | ||||
SerialNumber: big.NewInt(0), | ||||
NotBefore: time.Now(), | ||||
NotAfter: time.Now().AddDate(100, 0, 0), | ||||
} | ||||
var fallbackCertBytes, _ = x509.CreateCertificate( | ||||
rand.Reader, | ||||
fallbackCertSpecification, | ||||
fallbackCertSpecification, | ||||
fallbackCertKey.Public(), | ||||
fallbackCertKey, | ||||
) | ||||
var fallbackCert, _ = tls.X509KeyPair(pem.EncodeToMemory(&pem.Block{ | ||||
Bytes: fallbackCertBytes, | ||||
Type: "CERTIFICATE", | ||||
}), pem.EncodeToMemory(&pem.Block{ | ||||
Bytes: x509.MarshalPKCS1PrivateKey(fallbackCertKey), | ||||
Type: "RSA PRIVATE KEY", | ||||
})) | ||||
| ||||
// tlsConfig contains the configuration for generating, serving and cleaning up Let's Encrypt certificates. | ||||
var tlsConfig = &tls.Config{ | ||||
GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { | ||||
// TODO: check DNS name & get certificate from Let's Encrypt | ||||
return &fallbackCert, nil | ||||
return FallbackCertificate(), nil | ||||
}, | ||||
PreferServerCipherSuites: true, | ||||
// TODO: optimize cipher suites, minimum TLS version, etc. | ||||
| ||||
// generated 2021-07-13, Mozilla Guideline v5.6, Go 1.14.4, intermediate configuration | ||||
// https://ssl-config.mozilla.org/#server=go&version=1.14.4&config=intermediate&guideline=5.6 | ||||
MinVersion: tls.VersionTLS12, | ||||
CipherSuites: []uint16{ | ||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, | ||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, | ||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, | ||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, | ||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, | ||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, | ||||
}, | ||||
} | ||||
| ||||
// TODO: HSTS header with includeSubdomains & preload for MainDomainSuffix and RawDomain | ||||
// GetHSTSHeader returns a HSTS header with includeSubdomains & preload for MainDomainSuffix and RawDomain, or an empty | ||||
// string for custom domains. | ||||
func GetHSTSHeader(host []byte) string { | ||||
if bytes.HasSuffix(host, MainDomainSuffix) || bytes.Equal(host, RawDomain) { | ||||
return "max-age=63072000; includeSubdomains; preload" | ||||
} else { | ||||
return "" | ||||
} | ||||
} | ||||
| ||||
var fallbackCertificate *tls.Certificate | ||||
// FallbackCertificate generates a new self-signed TLS certificate on demand. | ||||
func FallbackCertificate() *tls.Certificate { | ||||
if fallbackCertificate != nil { | ||||
return fallbackCertificate | ||||
} | ||||
| ||||
fallbackSerial, err := rand.Int(rand.Reader, (&big.Int{}).Lsh(big.NewInt(1), 159)) | ||||
if err != nil { | ||||
panic(err) | ||||
} | ||||
| ||||
fallbackCertKey, err := rsa.GenerateKey(rand.Reader, 1024) | ||||
if err != nil { | ||||
panic(err) | ||||
} | ||||
| ||||
fallbackCertSpecification := &x509.Certificate{ | ||||
Subject: pkix.Name{ | ||||
CommonName: strings.TrimPrefix(string(MainDomainSuffix), "."), | ||||
}, | ||||
SerialNumber: fallbackSerial, | ||||
NotBefore: time.Now(), | ||||
NotAfter: time.Now().AddDate(100, 0, 0), | ||||
} | ||||
| ||||
fallbackCertBytes, err := x509.CreateCertificate( | ||||
rand.Reader, | ||||
fallbackCertSpecification, | ||||
fallbackCertSpecification, | ||||
fallbackCertKey.Public(), | ||||
fallbackCertKey, | ||||
) | ||||
if err != nil { | ||||
panic(err) | ||||
} | ||||
| ||||
fallbackCert, err := tls.X509KeyPair(pem.EncodeToMemory(&pem.Block{ | ||||
Bytes: fallbackCertBytes, | ||||
Type: "CERTIFICATE", | ||||
}), pem.EncodeToMemory(&pem.Block{ | ||||
Bytes: x509.MarshalPKCS1PrivateKey(fallbackCertKey), | ||||
Type: "RSA PRIVATE KEY", | ||||
})) | ||||
if err != nil { | ||||
panic(err) | ||||
} | ||||
| ||||
fallbackCertificate = &fallbackCert | ||||
return fallbackCertificate | ||||
} | ||||
| |
11 handler.go
11
handler.go | @ -28,6 +28,11 @@ func handler(ctx *fasthttp.RequestCtx) { | |||
// Enable caching, but require revalidation to reduce confusion | ||||
ctx.Response.Header.Set("Cache-Control", "must-revalidate") | ||||
| ||||
// Add HSTS for RawDomain and MainDomainSuffix | ||||
if hsts := GetHSTSHeader(ctx.Host()); hsts != "" { | ||||
ctx.Response.Header.Set("Strict-Transport-Security", hsts) | ||||
} | ||||
| ||||
// Block all methods not required for static pages | ||||
if !ctx.IsGet() && !ctx.IsHead() && !ctx.IsOptions() { | ||||
ctx.Response.Header.Set("Allow", "GET, HEAD, OPTIONS") | ||||
| @ -275,7 +280,11 @@ func handler(ctx *fasthttp.RequestCtx) { | |||
func returnErrorPage(ctx *fasthttp.RequestCtx, code int) { | ||||
ctx.Response.SetStatusCode(code) | ||||
ctx.Response.Header.SetContentType("text/html; charset=utf-8") | ||||
ctx.Response.SetBody(bytes.ReplaceAll(NotFoundPage, []byte("%status"), []byte(strconv.Itoa(code)+" "+fasthttp.StatusMessage(code)))) | ||||
message := fasthttp.StatusMessage(code) | ||||
if code == fasthttp.StatusFailedDependency { | ||||
message += " - owner, repo or branch doesn't exist" | ||||
} | ||||
ctx.Response.SetBody(bytes.ReplaceAll(NotFoundPage, []byte("%status"), []byte(strconv.Itoa(code)+" "+message))) | ||||
} | ||||
| ||||
// BranchExistanceCacheTimeout specifies the timeout for the default branch cache. It can be quite long. | ||||
| |
2 main.go
2
main.go | @ -79,7 +79,7 @@ func main() { | |||
GiteaRoot = bytes.TrimSuffix(GiteaRoot, []byte{'/'}) | ||||
| ||||
// Use HOST and PORT environment variables to determine listening address | ||||
address := fmt.Sprintf("%s:%s", envOr("HOST", "[::]"), envOr("PORT", "80")) | ||||
address := fmt.Sprintf("%s:%s", envOr("HOST", "[::]"), envOr("PORT", "443")) | ||||
fmt.Printf("Listening on https://%s\n", address) | ||||
| ||||
// Enable compression by wrapping the handler() method with the compression function provided by FastHTTP | ||||
| |
Loading…
Add table
Add a link
Reference in a new issue