feat: mTLS support (#68)

Signed-off-by: Jiri Novotny <k4chn1k@gmail.com>
This commit is contained in:
Jiri Novotny
2021-02-18 16:07:33 +01:00
committed by Jianhui Zhao
parent 2d3f9cf6d8
commit b7cc62b0e7
6 changed files with 56 additions and 1 deletions

View File

@@ -30,6 +30,7 @@ This is the server program of [rtty](https://github.com/zhaojh329/rtty)
statik -src=frontend/dist
## Authorization
### Token
Generate a token
$ rttys token
@@ -40,6 +41,11 @@ Use token
$ rttys run -t 34762d07637276694b938d23f10d7164
### mTLS
You can enable mTLS by specifying device CA storage (valid file) in config file or from CLI (variable ssl-devs).
Appending to CA storage is possible on-the-fly, you can reload CA certs by sendig SIGUSR1 signal.
Device(s) without valid CA in storage will be disconnected in TLS handshake.
## Running as a Linux service
Move the rttys binary into /usr/local/bin/

View File

@@ -2,6 +2,7 @@ package main
import (
"encoding/binary"
"crypto/x509"
"github.com/gorilla/websocket"
jsoniter "github.com/json-iterator/go"
@@ -32,6 +33,7 @@ type broker struct {
userMessage chan *usrMessage
cmdMessage chan []byte
webMessage chan *webResp
devCertPool *x509.CertPool
}
func newBroker(cfg *config.Config) *broker {

View File

@@ -5,7 +5,7 @@ GitCommit=$(git log --pretty=format:"%h" -1)
BuildTime=$(date +%FT%T%z)
[ $# -lt 2 ] && {
echo "Usage: $0 linux amb64"
echo "Usage: $0 linux amd64"
exit 1
}

View File

@@ -19,6 +19,7 @@ type Config struct {
WebPort int
SslCert string
SslKey string
SslDevices string
HTTPUsername string
HTTPPassword string
Token string
@@ -49,6 +50,7 @@ func Parse(c *cli.Context) *Config {
WebRedirURL: c.String("web-redir-url"),
SslCert: c.String("ssl-cert"),
SslKey: c.String("ssl-key"),
SslDevices: c.String("ssl-devs"),
HTTPUsername: c.String("http-username"),
HTTPPassword: c.String("http-password"),
Token: c.String("token"),
@@ -74,6 +76,7 @@ func Parse(c *cli.Context) *Config {
getConfigOpt(yamlCfg, "web-redir-url", &cfg.WebRedirURL)
getConfigOpt(yamlCfg, "ssl-cert", &cfg.SslCert)
getConfigOpt(yamlCfg, "ssl-key", &cfg.SslKey)
getConfigOpt(yamlCfg, "ssl-devs", &cfg.SslDevices)
getConfigOpt(yamlCfg, "http-username", &cfg.HTTPUsername)
getConfigOpt(yamlCfg, "http-password", &cfg.HTTPPassword)
getConfigOpt(yamlCfg, "token", &cfg.Token)

View File

@@ -6,8 +6,10 @@ import (
"context"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"encoding/binary"
"io"
"io/ioutil"
"net"
"strings"
"sync"
@@ -272,6 +274,18 @@ func listenDevice(br *broker) {
tlsConfig.Time = time.Now
tlsConfig.Rand = rand.Reader
caCert, err := ioutil.ReadFile(cfg.SslDevices)
if err != nil {
log.Warn().Msgf("mTLS not used: %s", err.Error())
} else {
br.devCertPool = x509.NewCertPool()
br.devCertPool.AppendCertsFromPEM(caCert)
// Create the TLS Config with the CA pool and enable Client certificate validation
tlsConfig.ClientCAs = br.devCertPool
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
}
ln = tls.NewListener(ln, tlsConfig)
log.Info().Msgf("Listen device on: %s SSL on", cfg.AddrDev)
} else {

30
main.go
View File

@@ -3,7 +3,10 @@ package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"runtime"
"io/ioutil"
"github.com/rs/zerolog/log"
"github.com/urfave/cli/v2"
@@ -17,6 +20,8 @@ func runRttys(c *cli.Context) {
rlog.SetPath(c.String("log"))
cfg := config.Parse(c)
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGUSR1)
if cfg.HTTPUsername == "" {
fmt.Println("You must configure the http username by commandline or config file")
@@ -46,6 +51,26 @@ func runRttys(c *cli.Context) {
listenDeviceWeb(br)
httpStart(br)
go func() {
for {
s := <-sigs
switch s {
case syscall.SIGUSR1:
if br.devCertPool != nil {
log.Info().Msg("Reload certs for mTLS")
caCert, err := ioutil.ReadFile(cfg.SslDevices)
if err != nil {
log.Info().Msgf("mTLS update faled: %s", err.Error())
} else {
br.devCertPool.AppendCertsFromPEM(caCert)
}
} else {
log.Warn().Msg("Reload certs failed: mTLS not used")
}
}
}
}()
select {}
}
@@ -105,6 +130,11 @@ func main() {
Value: "",
Usage: "ssl key file Path",
},
&cli.StringFlag{
Name: "ssl-devs",
Value: "",
Usage: "mtls CA storage in PEM file Path",
},
&cli.StringFlag{
Name: "http-username",
Value: "",