From d066dce13cbcd56172517713fbc6ff04cea60944 Mon Sep 17 00:00:00 2001 From: Joe Groocock Date: Thu, 23 Mar 2023 22:15:23 +0000 Subject: [PATCH 1/2] Implement listening on TLS/HTTPS This uses Go's vanilla ListenAndServeTLS(), and as such none of the normal TLS toggles are available for the user to configure. This provides a basic H2+TLS1.3 with modern cipher experience, which should be good enough for use on the open internet. Signed-off-by: Joe Groocock --- README.md | 1 + cmd/syncv3/main.go | 29 ++++++++++++++++++++--------- v3.go | 13 ++++++++++--- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index cb572384..9ec88112 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Using a Docker image: ``` docker run --rm -e "SYNCV3_SERVER=https://matrix-client.matrix.org" -e "SYNCV3_SECRET=$(cat .secret)" -e "SYNCV3_BINDADDR=:8008" -e "SYNCV3_DB=user=$(whoami) dbname=syncv3 sslmode=disable host=host.docker.internal" -p 8008:8008 ghcr.io/matrix-org/sliding-sync:v0.98.0 ``` +Optionally also set `SYNCV3_TLS_CERT=path/to/cert.pem` and `SYNCV3_TLS_KEY=path/to/key.pem` to listen on HTTPS instead of HTTP. Then visit http://localhost:8008/client/ (with trailing slash) and paste in the `access_token` for any account on `-server`. diff --git a/cmd/syncv3/main.go b/cmd/syncv3/main.go index ca2d2f37..9daa8af8 100644 --- a/cmd/syncv3/main.go +++ b/cmd/syncv3/main.go @@ -26,6 +26,8 @@ const ( // Optional fields EnvBindAddr = "SYNCV3_BINDADDR" + EnvTLSCert = "SYNCV3_TLS_CERT" + EnvTLSKey = "SYNCV3_TLS_KEY" EnvPPROF = "SYNCV3_PPROF" EnvPrometheus = "SYNCV3_PROM" EnvDebug = "SYNCV3_DEBUG" @@ -34,14 +36,16 @@ const ( var helpMsg = fmt.Sprintf(` Environment var -%s Required. The destination homeserver to talk to (CS API HTTPS URL) e.g 'https://matrix-client.matrix.org' -%s Required. The postgres connection string: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING -%s (Default: 0.0.0.0:8008) The interface and port to listen on. -%s Required. A secret to use to encrypt access tokens. Must remain the same for the lifetime of the database. -%s Defualt: unset. The bind addr for pprof debugging e.g ':6060'. If not set, does not listen. -%s Default: unset. The bind addr for Prometheus metrics, which will be accessible at /metrics at this address. -%s Default: unset. The Jaeger URL to send spans to e.g http://localhost:14268/api/traces - if unset does not send OTLP traces. -`, EnvServer, EnvDB, EnvBindAddr, EnvSecret, EnvPPROF, EnvPrometheus, EnvJaeger) +%s Required. The destination homeserver to talk to (CS API HTTPS URL) e.g 'https://matrix-client.matrix.org' +%s Required. The postgres connection string: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING +%s Required. A secret to use to encrypt access tokens. Must remain the same for the lifetime of the database. +%s Default: 0.0.0.0:8008. The interface and port to listen on. +%s Default: unset. Path to a certificate file to serve to HTTPS clients. Specifying this enables TLS on the bound address. +%s Default: unset. Path to a key file for the certificate. Must be provided along with the certificate file. +%s Default: unset. The bind addr for pprof debugging e.g ':6060'. If not set, does not listen. +%s Default: unset. The bind addr for Prometheus metrics, which will be accessible at /metrics at this address. +%s Default: unset. The Jaeger URL to send spans to e.g http://localhost:14268/api/traces - if unset does not send OTLP traces. +`, EnvServer, EnvDB, EnvSecret, EnvBindAddr, EnvTLSCert, EnvTLSKey, EnvPPROF, EnvPrometheus, EnvJaeger) func defaulting(in, dft string) string { if in == "" { @@ -59,6 +63,8 @@ func main() { EnvDB: os.Getenv(EnvDB), EnvSecret: os.Getenv(EnvSecret), EnvBindAddr: defaulting(os.Getenv(EnvBindAddr), "0.0.0.0:8008"), + EnvTLSCert: os.Getenv(EnvTLSCert), + EnvTLSKey: os.Getenv(EnvTLSKey), EnvPPROF: os.Getenv(EnvPPROF), EnvPrometheus: os.Getenv(EnvPrometheus), EnvDebug: os.Getenv(EnvDebug), @@ -73,6 +79,11 @@ func main() { os.Exit(1) } } + if (args[EnvTLSCert] != "" || args[EnvTLSKey] != "") && (args[EnvTLSCert] == "" || args[EnvTLSKey] == "") { + fmt.Print(helpMsg) + fmt.Printf("\nboth %s and %s must be set together\n", EnvTLSCert, EnvTLSKey) + os.Exit(1) + } // pprof if args[EnvPPROF] != "" { go func() { @@ -106,6 +117,6 @@ func main() { if args[EnvJaeger] != "" { h3 = otelhttp.NewHandler(h3, "Sync") } - syncv3.RunSyncV3Server(h3, args[EnvBindAddr], args[EnvServer]) + syncv3.RunSyncV3Server(h3, args[EnvBindAddr], args[EnvServer], args[EnvTLSCert], args[EnvTLSKey]) select {} // block forever } diff --git a/v3.go b/v3.go index d1efe81a..ce6b335c 100644 --- a/v3.go +++ b/v3.go @@ -108,7 +108,7 @@ func Setup(destHomeserver, postgresURI, secret string, opts Opts) (*handler2.Han } // RunSyncV3Server is the main entry point to the server -func RunSyncV3Server(h http.Handler, bindAddr, destV2Server string) { +func RunSyncV3Server(h http.Handler, bindAddr, destV2Server, tlsCert, tlsKey string) { // HTTP path routing r := mux.NewRouter() r.Handle("/_matrix/client/v3/sync", allowCORS(h)) @@ -159,8 +159,15 @@ func RunSyncV3Server(h http.Handler, bindAddr, destV2Server string) { } // Block forever - logger.Info().Msgf("listening on %s", bindAddr) - if err := http.ListenAndServe(bindAddr, srv); err != nil { + var err error + if tlsCert != "" { + logger.Info().Msgf("listening TLS on %s", bindAddr) + err = http.ListenAndServeTLS(bindAddr, tlsCert, tlsKey, srv) + } else { + logger.Info().Msgf("listening on %s", bindAddr) + err = http.ListenAndServe(bindAddr, srv) + } + if err != nil { logger.Fatal().Err(err).Msg("failed to listen and serve") } } From c76c04128e89b2a76c4b80e09e301802bcea4e7a Mon Sep 17 00:00:00 2001 From: David Robertson Date: Wed, 29 Mar 2023 12:17:26 +0100 Subject: [PATCH 2/2] require tlsCert and tlsKey to be nonempty Co-authored-by: kegsay --- v3.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v3.go b/v3.go index ce6b335c..9ade13b6 100644 --- a/v3.go +++ b/v3.go @@ -160,7 +160,7 @@ func RunSyncV3Server(h http.Handler, bindAddr, destV2Server, tlsCert, tlsKey str // Block forever var err error - if tlsCert != "" { + if tlsCert != "" && tlsKey != "" { logger.Info().Msgf("listening TLS on %s", bindAddr) err = http.ListenAndServeTLS(bindAddr, tlsCert, tlsKey, srv) } else {