feat: implement optional mTLS and helper scripts
Signed-off-by: HeshamTB <hishaminv@gmail.com>
This commit is contained in:
parent
1f3eca1b1b
commit
da0b1c720e
7
cmd/hvpn-node/.gitignore
vendored
7
cmd/hvpn-node/.gitignore
vendored
@ -1,2 +1,7 @@
|
||||
hvpn-node
|
||||
|
||||
tmp/
|
||||
.air.toml
|
||||
client_cert.pem
|
||||
client_cert.key
|
||||
cert.key
|
||||
cert.pem
|
||||
|
@ -2,6 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
@ -32,6 +34,8 @@ var WgPort int
|
||||
var wgLink *hvpnnode3.WGLink
|
||||
|
||||
var httpPort int
|
||||
var TLS_ENABLED bool
|
||||
var tlsConfig *tls.Config
|
||||
|
||||
func main() {
|
||||
|
||||
@ -76,11 +80,18 @@ func run(ctx *cli.Context) {
|
||||
IdleTimeout: 120 * time.Second,
|
||||
Handler: handler,
|
||||
Addr: hostPort,
|
||||
TLSConfig: tlsConfig,
|
||||
}
|
||||
|
||||
defer wgLink.Close()
|
||||
if TLS_ENABLED {
|
||||
slog.Debug("Running with TLS")
|
||||
slog.Info("Running TLS or mTLS with a reverse proxy is recommended")
|
||||
slog.Warn(srv.ListenAndServeTLS(ctx.Path("cert"), ctx.Path("cert-private-key")).Error())
|
||||
} else {
|
||||
slog.Warn(srv.ListenAndServe().Error())
|
||||
}
|
||||
}
|
||||
|
||||
func createCliApp() *cli.App {
|
||||
app := cli.NewApp()
|
||||
@ -175,6 +186,48 @@ func createCliApp() *cli.App {
|
||||
app.Flags = append(app.Flags, &httpPort)
|
||||
|
||||
|
||||
/* TLS Flags */
|
||||
|
||||
TLS := cli.BoolFlag{
|
||||
Name: "enable-tls",
|
||||
Aliases: []string{ "tls" },
|
||||
Value: false,
|
||||
Category: "\rTLS:",
|
||||
Destination: &TLS_ENABLED,
|
||||
Action: func(ctx *cli.Context, b bool) error {
|
||||
tlsConf, err := setupTLS(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tlsConfig = tlsConf
|
||||
return nil
|
||||
},
|
||||
}
|
||||
app.Flags = append(app.Flags, &TLS)
|
||||
|
||||
mTLSClientCerts := cli.PathFlag{
|
||||
Name: "client-certs",
|
||||
Aliases: []string{"ca"},
|
||||
Usage: "A path to PEM file with client certificates; Enables TLS",
|
||||
Category: "\rTLS:",
|
||||
}
|
||||
app.Flags = append(app.Flags, &mTLSClientCerts)
|
||||
|
||||
TLSCert := cli.PathFlag{
|
||||
Name: "cert",
|
||||
Usage: "Server x509 certificate file",
|
||||
Category: "\rTLS:",
|
||||
}
|
||||
app.Flags = append(app.Flags, &TLSCert)
|
||||
|
||||
TLSCertKey := cli.PathFlag{
|
||||
Name: "cert-private-key",
|
||||
Usage: "Server x509 certificate private key file",
|
||||
Category: "\rTLS:",
|
||||
}
|
||||
app.Flags = append(app.Flags, &TLSCertKey)
|
||||
|
||||
|
||||
app.Action = func(ctx *cli.Context) error {
|
||||
err := setup(ctx)
|
||||
if err != nil {
|
||||
@ -367,3 +420,46 @@ func handleStdin(c chan struct{}) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createMTLS(clinetCert, serverCert, serverKey string) (*x509.CertPool, error) {
|
||||
clientCert, err := os.ReadFile(clinetCert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
certPool := x509.NewCertPool()
|
||||
ok := certPool.AppendCertsFromPEM(clientCert)
|
||||
if !ok {
|
||||
return nil, errors.New("mTLS: Could read and parase a single cert from client cert")
|
||||
}
|
||||
return certPool, nil
|
||||
}
|
||||
|
||||
func setupTLS(ctx *cli.Context) (*tls.Config, error) {
|
||||
ca := ctx.Path("client-certs")
|
||||
if ca == "" {
|
||||
return nil, errors.New("client-certs flag is not set to enable TLS")
|
||||
}
|
||||
|
||||
serverCert := ctx.Path("ca")
|
||||
if serverCert == "" {
|
||||
return nil, errors.New("cert flag is not set to enable TLS")
|
||||
}
|
||||
|
||||
serverKey := ctx.Path("cert-private-key")
|
||||
if serverKey == "" {
|
||||
return nil, errors.New("cert-private-key is not set to enable TLS")
|
||||
}
|
||||
|
||||
certPool, err := createMTLS(ca, serverCert, serverKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conf := tls.Config{
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
ClientCAs: certPool,
|
||||
}
|
||||
|
||||
return &conf, nil
|
||||
}
|
||||
|
||||
|
28
cmd/hvpn-node/init-certs.sh
Executable file
28
cmd/hvpn-node/init-certs.sh
Executable file
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
openssl req \
|
||||
-x509 \
|
||||
-new \
|
||||
-noenc \
|
||||
-sha256 \
|
||||
-newkey rsa:4096 \
|
||||
-outform PEM \
|
||||
-keyout client_cert.key \
|
||||
-out client_cert.pem \
|
||||
-days 3600 \
|
||||
-new \
|
||||
-subj "/C=US/ST=Ohio/L=Columbus/O=HVPN/OU=HVPN Client"
|
||||
|
||||
openssl req \
|
||||
-x509 \
|
||||
-new \
|
||||
-noenc \
|
||||
-sha256 \
|
||||
-newkey rsa:4096 \
|
||||
-outform PEM \
|
||||
-keyout cert.key \
|
||||
-out cert.pem \
|
||||
-days 3600 \
|
||||
-new \
|
||||
-subj "/C=US/ST=Ohio/L=Columbus/O=HVPN/OU=HVPN Server"
|
||||
|
Loading…
Reference in New Issue
Block a user