mirror of
https://git.sr.ht/~emersion/tlstunnel
synced 2024-11-19 15:53:50 +01:00
Add client_auth directive
This commit is contained in:
parent
c888547e5b
commit
c3623f6b38
39
config.go
39
config.go
@ -39,7 +39,8 @@ type frontendConfig struct {
|
||||
} `scfg:"listen"`
|
||||
Backend *backendConfig `scfg:"backend"`
|
||||
TLS struct {
|
||||
Load *[2]string `scfg:"load"`
|
||||
Load *[2]string `scfg:"load"`
|
||||
ClientAuth *[2]string `scfg:"client_auth"`
|
||||
} `scfg:"tls"`
|
||||
Protocol []string `scfg:"protocol"`
|
||||
}
|
||||
@ -129,6 +130,25 @@ func parseFrontend(srv *Server, cfg *frontendConfig) error {
|
||||
srv.UnmanagedCerts = append(srv.UnmanagedCerts, cert)
|
||||
unmanaged = true
|
||||
}
|
||||
if cfg.TLS.ClientAuth != nil {
|
||||
clientAuth, err := parseClientAuth(cfg.TLS.ClientAuth[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf(`directive "tls.client_auth": %w`, err)
|
||||
}
|
||||
|
||||
clientCAs, err := os.ReadFile(cfg.TLS.ClientAuth[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf(`directive "tls.client_auth": %w`, err)
|
||||
}
|
||||
|
||||
pool := x509.NewCertPool()
|
||||
if ok := pool.AppendCertsFromPEM(clientCAs); !ok {
|
||||
return fmt.Errorf("failed to append to client pool")
|
||||
}
|
||||
|
||||
frontend.ClientAuth = clientAuth
|
||||
frontend.ClientCAs = pool
|
||||
}
|
||||
|
||||
frontend.Protocols = cfg.Protocol
|
||||
|
||||
@ -292,3 +312,20 @@ func parseTLSOnDemand(srv *Server, cfg *tlsOnDemandConfig) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseClientAuth(clientAuth string) (tls.ClientAuthType, error) {
|
||||
var auth tls.ClientAuthType
|
||||
switch clientAuth {
|
||||
case "request":
|
||||
auth = tls.RequestClientCert
|
||||
case "require":
|
||||
auth = tls.RequireAnyClientCert
|
||||
case "verify":
|
||||
auth = tls.RequireAnyClientCert
|
||||
case "require_and_verify":
|
||||
auth = tls.RequireAndVerifyClientCert
|
||||
default:
|
||||
return auth, fmt.Errorf("unknown client auth %s", clientAuth)
|
||||
}
|
||||
return auth, nil
|
||||
}
|
||||
|
11
server.go
11
server.go
@ -3,6 +3,7 @@ package tlstunnel
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -312,6 +313,10 @@ func (ln *Listener) handle(conn net.Conn) error {
|
||||
}
|
||||
|
||||
tlsConfig.NextProtos = append(tlsConfig.NextProtos, fe.Protocols...)
|
||||
if fe.ClientAuth != tls.NoClientCert {
|
||||
tlsConfig.ClientAuth = fe.ClientAuth
|
||||
tlsConfig.ClientCAs = fe.ClientCAs
|
||||
}
|
||||
return tlsConfig, nil
|
||||
}
|
||||
tlsConn := tls.Server(conn, tlsConfig)
|
||||
@ -362,8 +367,10 @@ func (ln *Listener) matchFrontend(serverName string) (*Frontend, error) {
|
||||
}
|
||||
|
||||
type Frontend struct {
|
||||
Backend Backend
|
||||
Protocols []string
|
||||
Backend Backend
|
||||
Protocols []string
|
||||
ClientAuth tls.ClientAuthType
|
||||
ClientCAs *x509.CertPool
|
||||
}
|
||||
|
||||
func (fe *Frontend) handle(downstream net.Conn, tlsState *tls.ConnectionState) error {
|
||||
|
@ -93,6 +93,17 @@ The following directives are supported:
|
||||
|
||||
This disables automatic TLS.
|
||||
|
||||
*client_auth* <type> <cert>
|
||||
Configures client authentication.
|
||||
|
||||
The available verification types are the following:
|
||||
request, require, verify, require_and_verify. They are
|
||||
defined here:
|
||||
https://pkg.go.dev/crypto/tls#ClientAuthType.
|
||||
|
||||
The certificate must be a PEM file and is used as a CA to validate
|
||||
client certificates.
|
||||
|
||||
*protocol* <name>...
|
||||
List of supported application-layer protocols.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user