feat: auto tls sni
Signed-off-by: Steven Kreitzer <skre@skre.me>
This commit is contained in:
parent
a665d3245a
commit
b5be8a6fa4
|
@ -205,6 +205,8 @@ type OriginRequestConfig struct {
|
||||||
HTTPHostHeader *string `yaml:"httpHostHeader" json:"httpHostHeader,omitempty"`
|
HTTPHostHeader *string `yaml:"httpHostHeader" json:"httpHostHeader,omitempty"`
|
||||||
// Hostname on the origin server certificate.
|
// Hostname on the origin server certificate.
|
||||||
OriginServerName *string `yaml:"originServerName" json:"originServerName,omitempty"`
|
OriginServerName *string `yaml:"originServerName" json:"originServerName,omitempty"`
|
||||||
|
// Auto configure the Hostname on the origin server certificate.
|
||||||
|
MatchSNIToHost *bool `yaml:"matchSNItoHost" json:"matchSNItoHost,omitempty"`
|
||||||
// Path to the CA for the certificate of your origin.
|
// Path to the CA for the certificate of your origin.
|
||||||
// This option should be used only if your certificate is not signed by Cloudflare.
|
// This option should be used only if your certificate is not signed by Cloudflare.
|
||||||
CAPool *string `yaml:"caPool" json:"caPool,omitempty"`
|
CAPool *string `yaml:"caPool" json:"caPool,omitempty"`
|
||||||
|
|
|
@ -32,6 +32,7 @@ const (
|
||||||
ProxyKeepAliveTimeoutFlag = "proxy-keepalive-timeout"
|
ProxyKeepAliveTimeoutFlag = "proxy-keepalive-timeout"
|
||||||
HTTPHostHeaderFlag = "http-host-header"
|
HTTPHostHeaderFlag = "http-host-header"
|
||||||
OriginServerNameFlag = "origin-server-name"
|
OriginServerNameFlag = "origin-server-name"
|
||||||
|
MatchSNIToHostFlag = "match-sni-to-host"
|
||||||
NoTLSVerifyFlag = "no-tls-verify"
|
NoTLSVerifyFlag = "no-tls-verify"
|
||||||
NoChunkedEncodingFlag = "no-chunked-encoding"
|
NoChunkedEncodingFlag = "no-chunked-encoding"
|
||||||
ProxyAddressFlag = "proxy-address"
|
ProxyAddressFlag = "proxy-address"
|
||||||
|
@ -118,6 +119,7 @@ func originRequestFromSingleRule(c *cli.Context) OriginRequestConfig {
|
||||||
var keepAliveTimeout = defaultKeepAliveTimeout
|
var keepAliveTimeout = defaultKeepAliveTimeout
|
||||||
var httpHostHeader string
|
var httpHostHeader string
|
||||||
var originServerName string
|
var originServerName string
|
||||||
|
var matchSNItoHost bool
|
||||||
var caPool string
|
var caPool string
|
||||||
var noTLSVerify bool
|
var noTLSVerify bool
|
||||||
var disableChunkedEncoding bool
|
var disableChunkedEncoding bool
|
||||||
|
@ -150,6 +152,9 @@ func originRequestFromSingleRule(c *cli.Context) OriginRequestConfig {
|
||||||
if flag := OriginServerNameFlag; c.IsSet(flag) {
|
if flag := OriginServerNameFlag; c.IsSet(flag) {
|
||||||
originServerName = c.String(flag)
|
originServerName = c.String(flag)
|
||||||
}
|
}
|
||||||
|
if flag := MatchSNIToHostFlag; c.IsSet(flag) {
|
||||||
|
matchSNItoHost = c.Bool(flag)
|
||||||
|
}
|
||||||
if flag := tlsconfig.OriginCAPoolFlag; c.IsSet(flag) {
|
if flag := tlsconfig.OriginCAPoolFlag; c.IsSet(flag) {
|
||||||
caPool = c.String(flag)
|
caPool = c.String(flag)
|
||||||
}
|
}
|
||||||
|
@ -185,6 +190,7 @@ func originRequestFromSingleRule(c *cli.Context) OriginRequestConfig {
|
||||||
KeepAliveTimeout: keepAliveTimeout,
|
KeepAliveTimeout: keepAliveTimeout,
|
||||||
HTTPHostHeader: httpHostHeader,
|
HTTPHostHeader: httpHostHeader,
|
||||||
OriginServerName: originServerName,
|
OriginServerName: originServerName,
|
||||||
|
MatchSNIToHost: matchSNItoHost,
|
||||||
CAPool: caPool,
|
CAPool: caPool,
|
||||||
NoTLSVerify: noTLSVerify,
|
NoTLSVerify: noTLSVerify,
|
||||||
DisableChunkedEncoding: disableChunkedEncoding,
|
DisableChunkedEncoding: disableChunkedEncoding,
|
||||||
|
@ -229,6 +235,9 @@ func originRequestFromConfig(c config.OriginRequestConfig) OriginRequestConfig {
|
||||||
if c.OriginServerName != nil {
|
if c.OriginServerName != nil {
|
||||||
out.OriginServerName = *c.OriginServerName
|
out.OriginServerName = *c.OriginServerName
|
||||||
}
|
}
|
||||||
|
if c.MatchSNIToHost != nil {
|
||||||
|
out.MatchSNIToHost = *c.MatchSNIToHost
|
||||||
|
}
|
||||||
if c.CAPool != nil {
|
if c.CAPool != nil {
|
||||||
out.CAPool = *c.CAPool
|
out.CAPool = *c.CAPool
|
||||||
}
|
}
|
||||||
|
@ -287,6 +296,8 @@ type OriginRequestConfig struct {
|
||||||
HTTPHostHeader string `yaml:"httpHostHeader" json:"httpHostHeader"`
|
HTTPHostHeader string `yaml:"httpHostHeader" json:"httpHostHeader"`
|
||||||
// Hostname on the origin server certificate.
|
// Hostname on the origin server certificate.
|
||||||
OriginServerName string `yaml:"originServerName" json:"originServerName"`
|
OriginServerName string `yaml:"originServerName" json:"originServerName"`
|
||||||
|
// Auto configure the Hostname on the origin server certificate.
|
||||||
|
MatchSNIToHost bool `yaml:"matchSNItoHost" json:"matchSNItoHost"`
|
||||||
// Path to the CA for the certificate of your origin.
|
// Path to the CA for the certificate of your origin.
|
||||||
// This option should be used only if your certificate is not signed by Cloudflare.
|
// This option should be used only if your certificate is not signed by Cloudflare.
|
||||||
CAPool string `yaml:"caPool" json:"caPool"`
|
CAPool string `yaml:"caPool" json:"caPool"`
|
||||||
|
@ -362,6 +373,12 @@ func (defaults *OriginRequestConfig) setOriginServerName(overrides config.Origin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (defaults *OriginRequestConfig) setMatchSNIToHost(overrides config.OriginRequestConfig) {
|
||||||
|
if val := overrides.MatchSNIToHost; val != nil {
|
||||||
|
defaults.MatchSNIToHost = *val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (defaults *OriginRequestConfig) setCAPool(overrides config.OriginRequestConfig) {
|
func (defaults *OriginRequestConfig) setCAPool(overrides config.OriginRequestConfig) {
|
||||||
if val := overrides.CAPool; val != nil {
|
if val := overrides.CAPool; val != nil {
|
||||||
defaults.CAPool = *val
|
defaults.CAPool = *val
|
||||||
|
@ -447,6 +464,7 @@ func setConfig(defaults OriginRequestConfig, overrides config.OriginRequestConfi
|
||||||
cfg.setTCPKeepAlive(overrides)
|
cfg.setTCPKeepAlive(overrides)
|
||||||
cfg.setHTTPHostHeader(overrides)
|
cfg.setHTTPHostHeader(overrides)
|
||||||
cfg.setOriginServerName(overrides)
|
cfg.setOriginServerName(overrides)
|
||||||
|
cfg.setMatchSNIToHost(overrides)
|
||||||
cfg.setCAPool(overrides)
|
cfg.setCAPool(overrides)
|
||||||
cfg.setNoTLSVerify(overrides)
|
cfg.setNoTLSVerify(overrides)
|
||||||
cfg.setDisableChunkedEncoding(overrides)
|
cfg.setDisableChunkedEncoding(overrides)
|
||||||
|
@ -501,6 +519,7 @@ func ConvertToRawOriginConfig(c OriginRequestConfig) config.OriginRequestConfig
|
||||||
KeepAliveTimeout: keepAliveTimeout,
|
KeepAliveTimeout: keepAliveTimeout,
|
||||||
HTTPHostHeader: emptyStringToNil(c.HTTPHostHeader),
|
HTTPHostHeader: emptyStringToNil(c.HTTPHostHeader),
|
||||||
OriginServerName: emptyStringToNil(c.OriginServerName),
|
OriginServerName: emptyStringToNil(c.OriginServerName),
|
||||||
|
MatchSNIToHost: defaultBoolToNil(c.MatchSNIToHost),
|
||||||
CAPool: emptyStringToNil(c.CAPool),
|
CAPool: emptyStringToNil(c.CAPool),
|
||||||
NoTLSVerify: defaultBoolToNil(c.NoTLSVerify),
|
NoTLSVerify: defaultBoolToNil(c.NoTLSVerify),
|
||||||
DisableChunkedEncoding: defaultBoolToNil(c.DisableChunkedEncoding),
|
DisableChunkedEncoding: defaultBoolToNil(c.DisableChunkedEncoding),
|
||||||
|
|
|
@ -2,7 +2,9 @@ package ingress
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
@ -48,9 +50,28 @@ func (o *httpService) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
req.Header.Set("X-Forwarded-Host", req.Host)
|
req.Header.Set("X-Forwarded-Host", req.Host)
|
||||||
req.Host = o.hostHeader
|
req.Host = o.hostHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.matchSNIToHost {
|
||||||
|
o.SetOriginServerName(req)
|
||||||
|
}
|
||||||
|
|
||||||
return o.transport.RoundTrip(req)
|
return o.transport.RoundTrip(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *httpService) SetOriginServerName(req *http.Request) {
|
||||||
|
o.transport.DialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
conn, err := o.transport.DialContext(ctx, network, addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tls.Client(conn, &tls.Config{
|
||||||
|
RootCAs: o.transport.TLSClientConfig.RootCAs,
|
||||||
|
InsecureSkipVerify: o.transport.TLSClientConfig.InsecureSkipVerify,
|
||||||
|
ServerName: req.Host,
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (o *statusCode) RoundTrip(_ *http.Request) (*http.Response, error) {
|
func (o *statusCode) RoundTrip(_ *http.Request) (*http.Response, error) {
|
||||||
if o.defaultResp {
|
if o.defaultResp {
|
||||||
o.log.Warn().Msgf(ErrNoIngressRulesCLI.Error())
|
o.log.Warn().Msgf(ErrNoIngressRulesCLI.Error())
|
||||||
|
|
|
@ -71,6 +71,7 @@ type httpService struct {
|
||||||
url *url.URL
|
url *url.URL
|
||||||
hostHeader string
|
hostHeader string
|
||||||
transport *http.Transport
|
transport *http.Transport
|
||||||
|
matchSNIToHost bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *httpService) start(log *zerolog.Logger, _ <-chan struct{}, cfg OriginRequestConfig) error {
|
func (o *httpService) start(log *zerolog.Logger, _ <-chan struct{}, cfg OriginRequestConfig) error {
|
||||||
|
@ -80,6 +81,7 @@ func (o *httpService) start(log *zerolog.Logger, _ <-chan struct{}, cfg OriginRe
|
||||||
}
|
}
|
||||||
o.hostHeader = cfg.HTTPHostHeader
|
o.hostHeader = cfg.HTTPHostHeader
|
||||||
o.transport = transport
|
o.transport = transport
|
||||||
|
o.matchSNIToHost = cfg.MatchSNIToHost
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -204,25 +204,25 @@ func TestMarshalJSON(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "Nil",
|
name: "Nil",
|
||||||
path: nil,
|
path: nil,
|
||||||
expected: `{"hostname":"example.com","path":null,"service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
expected: `{"hostname":"example.com","path":null,"service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","matchSNItoHost":false,"caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Nil regex",
|
name: "Nil regex",
|
||||||
path: &Regexp{Regexp: nil},
|
path: &Regexp{Regexp: nil},
|
||||||
expected: `{"hostname":"example.com","path":null,"service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
expected: `{"hostname":"example.com","path":null,"service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","matchSNItoHost":false,"caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Empty",
|
name: "Empty",
|
||||||
path: &Regexp{Regexp: regexp.MustCompile("")},
|
path: &Regexp{Regexp: regexp.MustCompile("")},
|
||||||
expected: `{"hostname":"example.com","path":"","service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
expected: `{"hostname":"example.com","path":"","service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","matchSNItoHost":false,"caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Basic",
|
name: "Basic",
|
||||||
path: &Regexp{Regexp: regexp.MustCompile("/echo")},
|
path: &Regexp{Regexp: regexp.MustCompile("/echo")},
|
||||||
expected: `{"hostname":"example.com","path":"/echo","service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
expected: `{"hostname":"example.com","path":"/echo","service":"https://localhost:8000","Handlers":null,"originRequest":{"connectTimeout":30,"tlsTimeout":10,"tcpKeepAlive":30,"noHappyEyeballs":false,"keepAliveTimeout":90,"keepAliveConnections":100,"httpHostHeader":"","originServerName":"","matchSNItoHost":false,"caPool":"","noTLSVerify":false,"disableChunkedEncoding":false,"bastionMode":false,"proxyAddress":"127.0.0.1","proxyPort":0,"proxyType":"","ipRules":null,"http2Origin":false,"access":{"teamName":"","audTag":null}}}`,
|
||||||
want: true,
|
want: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue