Merge pull request #656 from nikr-canva/http2-origins

Add Http2Origin option to force HTTP/2 origin connections
This commit is contained in:
Silver 2022-06-16 12:23:07 -05:00 committed by GitHub
commit ee87c43eb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 5 deletions

View File

@ -837,6 +837,13 @@ func configureProxyFlags(shouldHide bool) []cli.Flag {
EnvVars: []string{"TUNNEL_NO_CHUNKED_ENCODING"}, EnvVars: []string{"TUNNEL_NO_CHUNKED_ENCODING"},
Hidden: shouldHide, Hidden: shouldHide,
}), }),
altsrc.NewBoolFlag(&cli.BoolFlag{
Name: ingress.Http2OriginFlag,
Usage: "Enables HTTP/2 origin servers.",
EnvVars: []string{"TUNNEL_ORIGIN_ENABLE_HTTP2"},
Hidden: shouldHide,
Value: false,
}),
} }
return append(flags, sshFlags(shouldHide)...) return append(flags, sshFlags(shouldHide)...)
} }

View File

@ -227,6 +227,8 @@ type OriginRequestConfig struct {
ProxyType *string `yaml:"proxyType" json:"proxyType,omitempty"` ProxyType *string `yaml:"proxyType" json:"proxyType,omitempty"`
// IP rules for the proxy service // IP rules for the proxy service
IPRules []IngressIPRule `yaml:"ipRules" json:"ipRules,omitempty"` IPRules []IngressIPRule `yaml:"ipRules" json:"ipRules,omitempty"`
// Attempt to connect to origin with HTTP/2
Http2Origin *bool `yaml:"http2Origin" json:"http2Origin,omitempty"`
} }
type IngressIPRule struct { type IngressIPRule struct {

View File

@ -144,7 +144,8 @@ var rawJsonConfig = []byte(`
"ports": [443, 4443], "ports": [443, 4443],
"allow": true "allow": true
} }
] ],
"http2Origin": true
} }
`) `)
@ -191,6 +192,7 @@ func assertConfig(
assert.Equal(t, true, *config.NoTLSVerify) assert.Equal(t, true, *config.NoTLSVerify)
assert.Equal(t, uint(9000), *config.ProxyPort) assert.Equal(t, uint(9000), *config.ProxyPort)
assert.Equal(t, "socks", *config.ProxyType) assert.Equal(t, "socks", *config.ProxyType)
assert.Equal(t, true, *config.Http2Origin)
privateV4 := "10.0.0.0/8" privateV4 := "10.0.0.0/8"
privateV6 := "fc00::/7" privateV6 := "fc00::/7"

View File

@ -36,6 +36,7 @@ const (
NoChunkedEncodingFlag = "no-chunked-encoding" NoChunkedEncodingFlag = "no-chunked-encoding"
ProxyAddressFlag = "proxy-address" ProxyAddressFlag = "proxy-address"
ProxyPortFlag = "proxy-port" ProxyPortFlag = "proxy-port"
Http2OriginFlag = "http2-origin"
) )
const ( const (
@ -128,6 +129,7 @@ func originRequestFromSingeRule(c *cli.Context) OriginRequestConfig {
var proxyAddress = defaultProxyAddress var proxyAddress = defaultProxyAddress
var proxyPort uint var proxyPort uint
var proxyType string var proxyType string
var http2Origin bool
if flag := ProxyConnectTimeoutFlag; c.IsSet(flag) { if flag := ProxyConnectTimeoutFlag; c.IsSet(flag) {
connectTimeout = config.CustomDuration{Duration: c.Duration(flag)} connectTimeout = config.CustomDuration{Duration: c.Duration(flag)}
} }
@ -171,9 +173,13 @@ func originRequestFromSingeRule(c *cli.Context) OriginRequestConfig {
// Note TUN-3758 , we use Int because UInt is not supported with altsrc // Note TUN-3758 , we use Int because UInt is not supported with altsrc
proxyPort = uint(c.Int(flag)) proxyPort = uint(c.Int(flag))
} }
if flag := Http2OriginFlag; c.IsSet(flag) {
http2Origin = c.Bool(flag)
}
if c.IsSet(Socks5Flag) { if c.IsSet(Socks5Flag) {
proxyType = socksProxy proxyType = socksProxy
} }
return OriginRequestConfig{ return OriginRequestConfig{
ConnectTimeout: connectTimeout, ConnectTimeout: connectTimeout,
TLSTimeout: tlsTimeout, TLSTimeout: tlsTimeout,
@ -190,6 +196,7 @@ func originRequestFromSingeRule(c *cli.Context) OriginRequestConfig {
ProxyAddress: proxyAddress, ProxyAddress: proxyAddress,
ProxyPort: proxyPort, ProxyPort: proxyPort,
ProxyType: proxyType, ProxyType: proxyType,
Http2Origin: http2Origin,
} }
} }
@ -255,6 +262,9 @@ func originRequestFromConfig(c config.OriginRequestConfig) OriginRequestConfig {
} }
} }
} }
if c.Http2Origin != nil {
out.Http2Origin = *c.Http2Origin
}
return out return out
} }
@ -298,6 +308,8 @@ type OriginRequestConfig struct {
ProxyType string `yaml:"proxyType" json:"proxyType"` ProxyType string `yaml:"proxyType" json:"proxyType"`
// IP rules for the proxy service // IP rules for the proxy service
IPRules []ipaccess.Rule `yaml:"ipRules" json:"ipRules"` IPRules []ipaccess.Rule `yaml:"ipRules" json:"ipRules"`
// Attempt to connect to origin with HTTP/2
Http2Origin bool `yaml:"http2Origin" json:"http2Origin"`
} }
func (defaults *OriginRequestConfig) setConnectTimeout(overrides config.OriginRequestConfig) { func (defaults *OriginRequestConfig) setConnectTimeout(overrides config.OriginRequestConfig) {
@ -403,6 +415,12 @@ func (defaults *OriginRequestConfig) setIPRules(overrides config.OriginRequestCo
} }
} }
func (defaults *OriginRequestConfig) setHttp2Origin(overrides config.OriginRequestConfig) {
if val := overrides.Http2Origin; val != nil {
defaults.Http2Origin = *val
}
}
// SetConfig gets config for the requests that cloudflared sends to origins. // SetConfig gets config for the requests that cloudflared sends to origins.
// Each field has a setter method which sets a value for the field by trying to find: // Each field has a setter method which sets a value for the field by trying to find:
// 1. The user config for this rule // 1. The user config for this rule
@ -428,6 +446,7 @@ func setConfig(defaults OriginRequestConfig, overrides config.OriginRequestConfi
cfg.setProxyAddress(overrides) cfg.setProxyAddress(overrides)
cfg.setProxyType(overrides) cfg.setProxyType(overrides)
cfg.setIPRules(overrides) cfg.setIPRules(overrides)
cfg.setHttp2Origin(overrides)
return cfg return cfg
} }
@ -475,6 +494,7 @@ func ConvertToRawOriginConfig(c OriginRequestConfig) config.OriginRequestConfig
ProxyPort: zeroUIntToNil(c.ProxyPort), ProxyPort: zeroUIntToNil(c.ProxyPort),
ProxyType: emptyStringToNil(c.ProxyType), ProxyType: emptyStringToNil(c.ProxyType),
IPRules: convertToRawIPRules(c.IPRules), IPRules: convertToRawIPRules(c.IPRules),
Http2Origin: defaultBoolToNil(c.Http2Origin),
} }
} }

View File

@ -290,6 +290,7 @@ func newHTTPTransport(service OriginService, cfg OriginRequestConfig, log *zerol
TLSHandshakeTimeout: cfg.TLSTimeout.Duration, TLSHandshakeTimeout: cfg.TLSTimeout.Duration,
ExpectContinueTimeout: 1 * time.Second, ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: &tls.Config{RootCAs: originCertPool, InsecureSkipVerify: cfg.NoTLSVerify}, TLSClientConfig: &tls.Config{RootCAs: originCertPool, InsecureSkipVerify: cfg.NoTLSVerify},
ForceAttemptHTTP2: cfg.Http2Origin,
} }
if _, isHelloWorld := service.(*helloWorld); !isHelloWorld && cfg.OriginServerName != "" { if _, isHelloWorld := service.(*helloWorld); !isHelloWorld && cfg.OriginServerName != "" {
httpTransport.TLSClientConfig.ServerName = cfg.OriginServerName httpTransport.TLSClientConfig.ServerName = cfg.OriginServerName

View File

@ -182,25 +182,25 @@ func TestMarshalJSON(t *testing.T) {
{ {
name: "Nil", name: "Nil",
path: nil, path: nil,
expected: `{"hostname":"example.com","path":null,"service":"https://localhost:8000","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}}`, expected: `{"hostname":"example.com","path":null,"service":"https://localhost:8000","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}}`,
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","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}}`, expected: `{"hostname":"example.com","path":null,"service":"https://localhost:8000","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}}`,
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","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}}`, expected: `{"hostname":"example.com","path":"","service":"https://localhost:8000","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}}`,
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","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}}`, expected: `{"hostname":"example.com","path":"/echo","service":"https://localhost:8000","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}}`,
want: true, want: true,
}, },
} }