From f24b5fe77b796289f3add20feb3cd23715abcb7c Mon Sep 17 00:00:00 2001 From: Anders Pitman Date: Sun, 27 Sep 2020 22:24:03 -0600 Subject: [PATCH] Integrate CertMagic for auto TLS certs --- boringproxy.go | 33 ++++++++++++++++++--------------- todo.md | 1 + tunnel_manager.go | 13 +++++++++++-- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/boringproxy.go b/boringproxy.go index 3357cac..b57b5fe 100644 --- a/boringproxy.go +++ b/boringproxy.go @@ -10,20 +10,34 @@ import ( "sync" "strconv" "encoding/json" + "github.com/caddyserver/certmagic" ) type BoringProxy struct { tunMan *TunnelManager adminListener *AdminListener + certConfig *certmagic.Config } func NewBoringProxy() *BoringProxy { - tunMan := NewTunnelManager() + //certmagic.DefaultACME.DisableHTTPChallenge = true + certmagic.DefaultACME.DisableTLSALPNChallenge = true + //certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA + certConfig := certmagic.NewDefault() + + tunMan := NewTunnelManager(certConfig) adminListener := NewAdminListener() - p := &BoringProxy{tunMan, adminListener} + err := certConfig.ManageSync([]string{"anders.boringproxy.io"}) + if err != nil { + log.Println("CertMagic error") + log.Println(err) + } + + + p := &BoringProxy{tunMan, adminListener, certConfig} http.HandleFunc("/", p.handleAdminRequest) go http.Serve(adminListener, nil) @@ -113,8 +127,6 @@ func (p *BoringProxy) handleConnection(clientConn net.Conn) { // TODO: does this need to be closed manually, or is it handled when decryptedConn is closed? //defer clientConn.Close() - certBaseDir := "/home/anders/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/" - var serverName string decryptedConn := tls.Server(clientConn, &tls.Config{ @@ -122,16 +134,7 @@ func (p *BoringProxy) handleConnection(clientConn net.Conn) { serverName = clientHello.ServerName - certPath := certBaseDir + clientHello.ServerName + "/" + clientHello.ServerName + ".crt" - keyPath := certBaseDir + clientHello.ServerName + "/" + clientHello.ServerName + ".key" - - cert, err := tls.LoadX509KeyPair(certPath, keyPath) - if err != nil { - log.Println("getting cert failed") - return nil, err - } - - return &cert, nil + return p.certConfig.GetCertificate(clientHello) }, }) //defer decryptedConn.Close() @@ -140,7 +143,7 @@ func (p *BoringProxy) handleConnection(clientConn net.Conn) { // is automatically called on first read/write decryptedConn.Handshake() - adminDomain := "anders.webstreams.io" + adminDomain := "anders.boringproxy.io" if serverName == adminDomain { p.handleAdminConnection(decryptedConn) } else { diff --git a/todo.md b/todo.md index 885efb5..b9645c6 100644 --- a/todo.md +++ b/todo.md @@ -1 +1,2 @@ * Implement auth +* Persist tunnel config, and load at startup diff --git a/tunnel_manager.go b/tunnel_manager.go index 943e372..f0db987 100644 --- a/tunnel_manager.go +++ b/tunnel_manager.go @@ -1,23 +1,32 @@ package main import ( + "log" "errors" "sync" + "github.com/caddyserver/certmagic" ) type TunnelManager struct { tunnels map[string]int mutex *sync.Mutex + certConfig *certmagic.Config } -func NewTunnelManager() *TunnelManager { +func NewTunnelManager(certConfig *certmagic.Config) *TunnelManager { tunnels := make(map[string]int) mutex := &sync.Mutex{} - return &TunnelManager{tunnels, mutex} + return &TunnelManager{tunnels, mutex, certConfig} } func (m *TunnelManager) SetTunnel(host string, port int) { + err := m.certConfig.ManageSync([]string{host}) + if err != nil { + log.Println("CertMagic error") + log.Println(err) + } + m.mutex.Lock() m.tunnels[host] = port m.mutex.Unlock()