Skip to content
This repository has been archived by the owner on Dec 17, 2022. It is now read-only.

Commit

Permalink
added client certificate support for tunnel
Browse files Browse the repository at this point in the history
  • Loading branch information
jerson committed Feb 5, 2021
1 parent cb6993f commit f3909f6
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 33 deletions.
14 changes: 14 additions & 0 deletions client/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ type Options struct {
inspectaddr string
inspectpublic bool
tls bool
tlsClientCrt string
tlsClientKey string
args []string
}

Expand Down Expand Up @@ -103,6 +105,16 @@ func ParseArgs() (opts *Options, err error) {
false,
"Use dial for tls port")

tlsClientCrt := flag.String(
"tlsClientCrt",
"",
"Path to a TLS Client CRT file if server requires")

tlsClientKey := flag.String(
"tlsClientKey",
"",
"Path to a TLS Client Key file if server requires")

inspectaddr := flag.String(
"inspectaddr",
defaultInspectAddr,
Expand All @@ -127,6 +139,8 @@ func ParseArgs() (opts *Options, err error) {
inspectaddr: *inspectaddr,
inspectpublic: *inspectpublic,
tls: *tls,
tlsClientCrt: *tlsClientCrt,
tlsClientKey: *tlsClientKey,
command: flag.Arg(0),
}

Expand Down
10 changes: 10 additions & 0 deletions client/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type Configuration struct {
AuthToken string `yaml:"auth_token,omitempty"`
Tunnels map[string]*TunnelConfiguration `yaml:"tunnels,omitempty"`
TLS bool `yaml:"tls,omitempty"`
TLSClientCrt string `yaml:"tls_client_crt,omitempty"`
TLSClientKey string `yaml:"tls_client_key,omitempty"`
LogTo string `yaml:"-"`
Path string `yaml:"-"`
}
Expand Down Expand Up @@ -82,6 +84,14 @@ func LoadConfiguration(opts *Options) (config *Configuration, err error) {
config.InspectAddr = opts.inspectaddr
}

if opts.tlsClientCrt != "" {
config.TLSClientCrt = opts.tlsClientCrt
}

if opts.tlsClientKey != "" {
config.TLSClientKey = opts.tlsClientKey
}

if config.InspectAddr == "" {
config.InspectAddr = defaultInspectAddr
}
Expand Down
25 changes: 21 additions & 4 deletions client/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ type ClientModel struct {
tunnelConfig map[string]*TunnelConfiguration
configPath string
TLS bool
TLSClientCrt string
TLSClientKey string
}

func newClientModel(config *Configuration, ctl mvc.Controller) *ClientModel {
Expand Down Expand Up @@ -104,18 +106,33 @@ func newClientModel(config *Configuration, ctl mvc.Controller) *ClientModel {

// TLS for dial port
TLS: config.TLS,

// TLSClientCrt for connect using a client certificate
TLSClientCrt: config.TLSClientCrt,

// TLSClientKey for connect using a client certificate
TLSClientKey: config.TLSClientKey,
}

m.tlsConfig = &tls.Config{}
// configure TLS
if config.TrustHostRootCerts {
m.Info("Trusting host's root certificates")
m.tlsConfig = &tls.Config{}
} else {
m.Info("Trusting root CAs: %v", rootCrtPaths)
var err error
if m.tlsConfig, err = LoadTLSConfig(rootCrtPaths); err != nil {
m.Info("using root CAs: %v", rootCrtPaths)
rootCAs, err := LoadTLSRootCAs(rootCrtPaths)
if err != nil {
panic(err)
}
m.tlsConfig.RootCAs = rootCAs
}

if m.TLSClientCrt != "" {
certificates, err := LoadTLSCertificate(m.TLSClientCrt, m.TLSClientKey)
if err != nil {
panic(err)
}
m.tlsConfig.Certificates = certificates
}

// configure TLS SNI
Expand Down
12 changes: 10 additions & 2 deletions client/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"pgrok/client/assets"
)

func LoadTLSConfig(rootCertPaths []string) (*tls.Config, error) {
func LoadTLSRootCAs(rootCertPaths []string) (*x509.CertPool, error) {
pool := x509.NewCertPool()

for _, certPath := range rootCertPaths {
Expand All @@ -31,5 +31,13 @@ func LoadTLSConfig(rootCertPaths []string) (*tls.Config, error) {
pool.AddCert(certs[0])
}

return &tls.Config{RootCAs: pool}, nil
return pool, nil
}

func LoadTLSCertificate(certPath, certKey string) ([]tls.Certificate, error) {
cert, err := tls.LoadX509KeyPair(certPath, certKey)
if err != nil {
return nil, err
}
return []tls.Certificate{cert}, nil
}
41 changes: 22 additions & 19 deletions server/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,41 @@ import (
)

type Options struct {
httpAddr string
httpsAddr string
tunnelAddr string
domain string
tlsCrt string
tlsKey string
tlsClientCA string
logto string
loglevel string
httpAddr string
httpsAddr string
tunnelAddr string
tunnelTLSClientCA string
domain string
tlsCrt string
tlsKey string
tlsClientCA string
logto string
loglevel string
}

func parseArgs() *Options {
httpAddr := flag.String("httpAddr", ":80", "Public address for HTTP connections, empty string to disable")
httpsAddr := flag.String("httpsAddr", ":443", "Public address listening for HTTPS connections, emptry string to disable")
tunnelAddr := flag.String("tunnelAddr", ":4443", "Public address listening for pgrok client")
tunnelTLSClientCA := flag.String("tunnelTLSClientCA", "", "Path to a TLS Client CA file if you want enable mutual auth for tunnel")
domain := flag.String("domain", "ejemplo.me", "Domain where the tunnels are hosted")
tlsCrt := flag.String("tlsCrt", "", "Path to a TLS certificate file")
tlsKey := flag.String("tlsKey", "", "Path to a TLS key file")
tlsClientCA := flag.String("tlsClientCA", "", "Path to a TLS Client CA file if you want enable mutual auth")
tlsClientCA := flag.String("tlsClientCA", "", "Path to a TLS Client CA file if you want enable mutual auth for subdomains")
logto := flag.String("log", "stdout", "Write log messages to this file. 'stdout' and 'none' have special meanings")
loglevel := flag.String("log-level", "DEBUG", "The level of messages to log. One of: DEBUG, INFO, WARNING, ERROR")
flag.Parse()

return &Options{
httpAddr: *httpAddr,
httpsAddr: *httpsAddr,
tunnelAddr: *tunnelAddr,
domain: *domain,
tlsCrt: *tlsCrt,
tlsKey: *tlsKey,
tlsClientCA: *tlsClientCA,
logto: *logto,
loglevel: *loglevel,
httpAddr: *httpAddr,
httpsAddr: *httpsAddr,
tunnelAddr: *tunnelAddr,
tunnelTLSClientCA: *tunnelTLSClientCA,
domain: *domain,
tlsCrt: *tlsCrt,
tlsKey: *tlsKey,
tlsClientCA: *tlsClientCA,
logto: *logto,
loglevel: *loglevel,
}
}
14 changes: 7 additions & 7 deletions server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,26 +120,26 @@ func Main() {
// start listeners
listeners = make(map[string]*conn.Listener)

// load tls configuration
tlsConfig, err := LoadTLSConfig(opts.tlsCrt, opts.tlsKey)
if err != nil {
panic(err)
}

// listen for http
if opts.httpAddr != "" {
listeners["http"] = startHttpListener(opts.httpAddr, nil)
}

// listen for https
if opts.httpsAddr != "" {
tlsConfigServer, err := LoadTLSConfigServer(opts.tlsCrt, opts.tlsKey, opts.tlsClientCA)
tlsConfigServer, err := LoadTLSConfigWithCA(opts.tlsCrt, opts.tlsKey, opts.tlsClientCA)
if err != nil {
panic(err)
}
listeners["https"] = startHttpListener(opts.httpsAddr, tlsConfigServer)
}

// load tls configuration
tlsConfig, err := LoadTLSConfigWithCA(opts.tlsCrt, opts.tlsKey, opts.tunnelTLSClientCA)
if err != nil {
panic(err)
}

// pgrok clients
tunnelListener(opts.tunnelAddr, tlsConfig)
}
2 changes: 1 addition & 1 deletion server/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func LoadTLSConfig(crtPath, keyPath string) (tlsConfig *tls.Config, err error) {
return
}

func LoadTLSConfigServer(crtPath, keyPath, clientCAPath string) (tlsConfig *tls.Config, err error) {
func LoadTLSConfigWithCA(crtPath, keyPath, clientCAPath string) (tlsConfig *tls.Config, err error) {

tlsConfig, err = LoadTLSConfig(crtPath, keyPath)
if err != nil {
Expand Down

0 comments on commit f3909f6

Please sign in to comment.