From 1a5ee744a8624013b0209d683bca6bbeac7c3cf4 Mon Sep 17 00:00:00 2001 From: Zoltan Papp Date: Wed, 3 Jul 2024 15:03:57 +0200 Subject: [PATCH] - add file based cert - print out the exposed address - handle empty exposed address --- encryption/cert.go | 19 ++++++++++++++++++ relay/cmd/main.go | 32 +++++++++++++++++++++++++++---- relay/server/relay.go | 4 ++++ relay/server/server.go | 4 ++++ signal/proto/signalexchange.proto | 2 +- 5 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 encryption/cert.go diff --git a/encryption/cert.go b/encryption/cert.go new file mode 100644 index 000000000..3f6d5c679 --- /dev/null +++ b/encryption/cert.go @@ -0,0 +1,19 @@ +package encryption + +import "crypto/tls" + +func LoadTLSConfig(certFile, keyFile string) (*tls.Config, error) { + serverCert, err := tls.LoadX509KeyPair(certFile, keyFile) + if err != nil { + return nil, err + } + + config := &tls.Config{ + Certificates: []tls.Certificate{serverCert}, + ClientAuth: tls.NoClientCert, + NextProtos: []string{ + "h2", "http/1.1", // enable HTTP/2 + }, + } + return config, nil +} diff --git a/relay/cmd/main.go b/relay/cmd/main.go index fb437e78d..a7cd5efa8 100644 --- a/relay/cmd/main.go +++ b/relay/cmd/main.go @@ -18,9 +18,12 @@ import ( var ( listenAddress string // in HA every peer connect to a common domain, the instance domain has been distributed during the p2p connection + // it is a domain:port or ip:port exposedAddress string letsencryptDataDir string letsencryptDomains []string + tlsCertFile string + tlsKeyFile string rootCmd = &cobra.Command{ Use: "relay", @@ -32,10 +35,13 @@ var ( func init() { _ = util.InitLog("trace", "console") - rootCmd.PersistentFlags().StringVarP(&listenAddress, "listen-address", "l", ":1235", "listen address") + rootCmd.PersistentFlags().StringVarP(&listenAddress, "listen-address", "l", ":443", "listen address") rootCmd.PersistentFlags().StringVarP(&exposedAddress, "exposed-address", "e", "", "instance domain address (or ip) and port, it will be distributes between peers") rootCmd.PersistentFlags().StringVarP(&letsencryptDataDir, "letsencrypt-data-dir", "d", "", "a directory to store Let's Encrypt data. Required if Let's Encrypt is enabled.") rootCmd.PersistentFlags().StringArrayVarP(&letsencryptDomains, "letsencrypt-domains", "a", nil, "list of domains to issue Let's Encrypt certificate for. Enables TLS using Let's Encrypt. Will fetch and renew certificate, and run the server with TLS") + rootCmd.PersistentFlags().StringVarP(&tlsCertFile, "tls-cert-file", "c", "", "") + rootCmd.PersistentFlags().StringVarP(&tlsKeyFile, "tls-key-file", "k", "", "") + } func waitForExitSignal() { @@ -45,20 +51,33 @@ func waitForExitSignal() { } func execute(cmd *cobra.Command, args []string) { + if exposedAddress == "" { + log.Errorf("exposed address is required") + os.Exit(1) + } + srvListenerCfg := server.ListenerConfig{ Address: listenAddress, } if hasLetsEncrypt() { - tlscfg, err := setupTLS() + tlsCfg, err := setupTLSCertManager() if err != nil { log.Errorf("%s", err) os.Exit(1) } - srvListenerCfg.TLSConfig = tlscfg + srvListenerCfg.TLSConfig = tlsCfg + } else if hasCertConfig() { + tlsCfg, err := encryption.LoadTLSConfig(tlsCertFile, tlsKeyFile) + if err != nil { + log.Errorf("%s", err) + os.Exit(1) + } + srvListenerCfg.TLSConfig = tlsCfg } tlsSupport := srvListenerCfg.TLSConfig != nil srv := server.NewServer(exposedAddress, tlsSupport) + log.Infof("server will be available on: %s", srv.InstanceURL()) err := srv.Listen(srvListenerCfg) if err != nil { log.Errorf("failed to bind server: %s", err) @@ -74,11 +93,16 @@ func execute(cmd *cobra.Command, args []string) { } } +func hasCertConfig() bool { + return tlsCertFile != "" && tlsKeyFile != "" + +} + func hasLetsEncrypt() bool { return letsencryptDataDir != "" && letsencryptDomains != nil && len(letsencryptDomains) > 0 } -func setupTLS() (*tls.Config, error) { +func setupTLSCertManager() (*tls.Config, error) { certManager, err := encryption.CreateCertManager(letsencryptDataDir, letsencryptDomains...) if err != nil { return nil, fmt.Errorf("failed creating LetsEncrypt cert manager: %v", err) diff --git a/relay/server/relay.go b/relay/server/relay.go index 9f0528b25..aff15a5fb 100644 --- a/relay/server/relay.go +++ b/relay/server/relay.go @@ -107,3 +107,7 @@ func (r *Relay) handShake(conn net.Conn) ([]byte, error) { } return peerID, nil } + +func (r *Relay) InstanceURL() string { + return r.instaceURL +} diff --git a/relay/server/server.go b/relay/server/server.go index 449819e61..5341cad2e 100644 --- a/relay/server/server.go +++ b/relay/server/server.go @@ -83,3 +83,7 @@ func (r *Server) Close() error { err := errors.Join(wErr, uErr) return err } + +func (r *Server) InstanceURL() string { + return r.relay.instaceURL +} diff --git a/signal/proto/signalexchange.proto b/signal/proto/signalexchange.proto index 5aa24d893..4431edd7c 100644 --- a/signal/proto/signalexchange.proto +++ b/signal/proto/signalexchange.proto @@ -61,7 +61,7 @@ message Body { // RosenpassConfig is a Rosenpass config of the remote peer our peer tries to connect to RosenpassConfig rosenpassConfig = 7; - // relayServerAddress is an IP:port of the relay server + // relayServerAddress is url of the relay server string relayServerAddress = 8; }