validate client certificate of frpc for tcpmux
This commit is contained in:
parent
184223cb2f
commit
2b91ac4d18
@ -649,6 +649,7 @@ transport.tls.force = true
|
||||
transport.tls.certFile = "certificate.crt"
|
||||
transport.tls.keyFile = "certificate.key"
|
||||
transport.tls.trustedCaFile = "ca.crt"
|
||||
transport.tls.clientCertSubjectRegex = "CN=client.com(.+)"
|
||||
```
|
||||
|
||||
You will need **a root CA cert** and **at least one SSL/TLS certificate**. It **can** be self-signed or regular (such as Let's Encrypt or another SSL/TLS certificate provider).
|
||||
|
@ -80,6 +80,9 @@ type TLSConfig struct {
|
||||
// ServerName specifies the custom server name of tls certificate. By
|
||||
// default, server name if same to ServerAddr.
|
||||
ServerName string `json:"serverName,omitempty"`
|
||||
// ClientCertificateSubjectRegex specifies the regex that is used to validate the client certificate subject.
|
||||
// If it's not set, the validation of the subject is disabled.
|
||||
ClientCertificateSubjectRegex string `json:"clientCertSubjectRegex,omitempty"`
|
||||
}
|
||||
|
||||
type LogConfig struct {
|
||||
|
@ -17,7 +17,10 @@ package net
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||
"github.com/fatedier/frp/pkg/util/log"
|
||||
"net"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
libnet "github.com/fatedier/golib/net"
|
||||
@ -55,3 +58,35 @@ func CheckAndEnableTLSServerConnWithTimeout(
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func IsClientCertificateSubjectValid(c net.Conn, tlsConfig v1.TLSServerConfig) bool {
|
||||
subjectRegex := tlsConfig.ClientCertificateSubjectRegex
|
||||
regex, err := regexp.Compile(subjectRegex)
|
||||
if err != nil {
|
||||
log.Trace("Client certificate subject validation is disabled")
|
||||
return true
|
||||
}
|
||||
|
||||
tlsConn, ok := c.(*tls.Conn)
|
||||
if !ok {
|
||||
log.Warn("Skip client certificate subject validation because its not a tls connection")
|
||||
return true
|
||||
}
|
||||
|
||||
state := tlsConn.ConnectionState()
|
||||
log.Trace("Validating client certificate subject using regex: %v", subjectRegex)
|
||||
if len(state.PeerCertificates) == 0 {
|
||||
log.Warn("No client certificates found in TLS connection, the verification was probably called to early.")
|
||||
return false
|
||||
}
|
||||
|
||||
for _, v := range state.PeerCertificates {
|
||||
subject := fmt.Sprintf("%v", v.Subject)
|
||||
if !regex.MatchString(subject) {
|
||||
log.Warn("Client certificate subject %v doesn't match regex %v", v.Subject, subjectRegex)
|
||||
return false
|
||||
}
|
||||
log.Trace("Client certificate subject is valid")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -484,6 +484,13 @@ func (svr *Service) HandleListener(l net.Listener) {
|
||||
session.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// Has to be called after session.AcceptStream() so that the client certificates are available
|
||||
if !utilnet.IsClientCertificateSubjectValid(c, svr.cfg.Transport.TLS) {
|
||||
session.Close()
|
||||
return
|
||||
}
|
||||
|
||||
go svr.handleConnection(ctx, stream)
|
||||
}
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user