mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 16:01:05 +00:00
TUN-3725: Warp-routing is independent of ingress
- Changed warp-routing configuration to its own yaml. - Ingress Rules host matching is indepedent of warp-routing.
This commit is contained in:

committed by
Nuno Diegues

parent
368066a966
commit
b4700a52e3
@@ -24,14 +24,21 @@ const (
|
||||
|
||||
type proxy struct {
|
||||
ingressRules ingress.Ingress
|
||||
warpRouting *ingress.WarpRoutingService
|
||||
tags []tunnelpogs.Tag
|
||||
log *zerolog.Logger
|
||||
bufferPool *buffer.Pool
|
||||
}
|
||||
|
||||
func NewOriginProxy(ingressRules ingress.Ingress, tags []tunnelpogs.Tag, log *zerolog.Logger) connection.OriginProxy {
|
||||
func NewOriginProxy(
|
||||
ingressRules ingress.Ingress,
|
||||
warpRouting *ingress.WarpRoutingService,
|
||||
tags []tunnelpogs.Tag,
|
||||
log *zerolog.Logger) connection.OriginProxy {
|
||||
|
||||
return &proxy{
|
||||
ingressRules: ingressRules,
|
||||
warpRouting: warpRouting,
|
||||
tags: tags,
|
||||
log: log,
|
||||
bufferPool: buffer.NewPool(512 * 1024),
|
||||
@@ -46,6 +53,22 @@ func (p *proxy) Proxy(w connection.ResponseWriter, req *http.Request, sourceConn
|
||||
lbProbe := isLBProbeRequest(req)
|
||||
|
||||
p.appendTagHeaders(req)
|
||||
if sourceConnectionType == connection.TypeTCP {
|
||||
if p.warpRouting == nil {
|
||||
err := errors.New(`cloudflared received a request from Warp client, but your configuration has disabled ingress from Warp clients. To enable this, set "warp-routing:\n\t enabled: true" in your config.yaml`)
|
||||
p.log.Error().Msg(err.Error())
|
||||
return err
|
||||
}
|
||||
resp, err := p.handleProxyConn(w, req, nil, p.warpRouting.Proxy)
|
||||
if err != nil {
|
||||
p.logRequestError(err, cfRay, ingress.ServiceWarpRouting)
|
||||
w.WriteErrorResponse()
|
||||
return err
|
||||
}
|
||||
p.logOriginResponse(resp, cfRay, lbProbe, ingress.ServiceWarpRouting)
|
||||
return nil
|
||||
}
|
||||
|
||||
rule, ruleNum := p.ingressRules.FindMatchingRule(req.Host, req.URL.Path)
|
||||
p.logRequest(req, cfRay, lbProbe, ruleNum)
|
||||
|
||||
@@ -66,13 +89,37 @@ func (p *proxy) Proxy(w connection.ResponseWriter, req *http.Request, sourceConn
|
||||
respHeader = websocket.NewResponseHeader(req)
|
||||
}
|
||||
|
||||
connClosedChan := make(chan struct{})
|
||||
err := p.proxyConnection(connClosedChan, w, req, rule)
|
||||
if hostHeader := rule.Config.HTTPHostHeader; hostHeader != "" {
|
||||
req.Header.Set("Host", hostHeader)
|
||||
req.Host = hostHeader
|
||||
}
|
||||
|
||||
connectionProxy, ok := rule.Service.(ingress.StreamBasedOriginProxy)
|
||||
if !ok {
|
||||
p.log.Error().Msgf("%s is not a connection-oriented service", rule.Service)
|
||||
return fmt.Errorf("Not a connection-oriented service")
|
||||
}
|
||||
resp, err := p.handleProxyConn(w, req, respHeader, connectionProxy)
|
||||
if err != nil {
|
||||
p.logErrorAndWriteResponse(w, err, cfRay, ruleNum)
|
||||
return err
|
||||
}
|
||||
|
||||
p.logOriginResponse(resp, cfRay, lbProbe, ruleNum)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *proxy) handleProxyConn(
|
||||
w connection.ResponseWriter,
|
||||
req *http.Request,
|
||||
respHeader http.Header,
|
||||
connectionProxy ingress.StreamBasedOriginProxy) (*http.Response, error) {
|
||||
connClosedChan := make(chan struct{})
|
||||
err := p.proxyConnection(connClosedChan, w, req, connectionProxy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
status := http.StatusSwitchingProtocols
|
||||
resp := &http.Response{
|
||||
Status: http.StatusText(status),
|
||||
@@ -83,9 +130,8 @@ func (p *proxy) Proxy(w connection.ResponseWriter, req *http.Request, sourceConn
|
||||
w.WriteRespHeaders(http.StatusSwitchingProtocols, nil)
|
||||
|
||||
<-connClosedChan
|
||||
return resp, nil
|
||||
|
||||
p.logOriginResponse(resp, cfRay, lbProbe, ruleNum)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *proxy) logErrorAndWriteResponse(w connection.ResponseWriter, err error, cfRay string, ruleNum int) {
|
||||
@@ -141,18 +187,8 @@ func (p *proxy) proxyHTTP(w connection.ResponseWriter, req *http.Request, rule *
|
||||
}
|
||||
|
||||
func (p *proxy) proxyConnection(connClosedChan chan struct{},
|
||||
conn io.ReadWriter, req *http.Request, rule *ingress.Rule) error {
|
||||
if hostHeader := rule.Config.HTTPHostHeader; hostHeader != "" {
|
||||
req.Header.Set("Host", hostHeader)
|
||||
req.Host = hostHeader
|
||||
}
|
||||
|
||||
connectionService, ok := rule.Service.(ingress.StreamBasedOriginProxy)
|
||||
if !ok {
|
||||
p.log.Error().Msgf("%s is not a connection-oriented service", rule.Service)
|
||||
return fmt.Errorf("Not a connection-oriented service")
|
||||
}
|
||||
originConn, err := connectionService.EstablishConnection(req)
|
||||
conn io.ReadWriter, req *http.Request, connectionProxy ingress.StreamBasedOriginProxy) error {
|
||||
originConn, err := connectionProxy.EstablishConnection(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -190,7 +226,7 @@ func (p *proxy) appendTagHeaders(r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *proxy) logRequest(r *http.Request, cfRay string, lbProbe bool, ruleNum int) {
|
||||
func (p *proxy) logRequest(r *http.Request, cfRay string, lbProbe bool, rule interface{}) {
|
||||
if cfRay != "" {
|
||||
p.log.Debug().Msgf("CF-RAY: %s %s %s %s", cfRay, r.Method, r.URL, r.Proto)
|
||||
} else if lbProbe {
|
||||
@@ -199,7 +235,7 @@ func (p *proxy) logRequest(r *http.Request, cfRay string, lbProbe bool, ruleNum
|
||||
p.log.Debug().Msgf("All requests should have a CF-RAY header. Please open a support ticket with Cloudflare. %s %s %s ", r.Method, r.URL, r.Proto)
|
||||
}
|
||||
p.log.Debug().Msgf("CF-RAY: %s Request Headers %+v", cfRay, r.Header)
|
||||
p.log.Debug().Msgf("CF-RAY: %s Serving with ingress rule %d", cfRay, ruleNum)
|
||||
p.log.Debug().Msgf("CF-RAY: %s Serving with ingress rule %v", cfRay, rule)
|
||||
|
||||
if contentLen := r.ContentLength; contentLen == -1 {
|
||||
p.log.Debug().Msgf("CF-RAY: %s Request Content length unknown", cfRay)
|
||||
@@ -208,14 +244,14 @@ func (p *proxy) logRequest(r *http.Request, cfRay string, lbProbe bool, ruleNum
|
||||
}
|
||||
}
|
||||
|
||||
func (p *proxy) logOriginResponse(r *http.Response, cfRay string, lbProbe bool, ruleNum int) {
|
||||
func (p *proxy) logOriginResponse(r *http.Response, cfRay string, lbProbe bool, rule interface{}) {
|
||||
responseByCode.WithLabelValues(strconv.Itoa(r.StatusCode)).Inc()
|
||||
if cfRay != "" {
|
||||
p.log.Debug().Msgf("CF-RAY: %s Status: %s served by ingress %d", cfRay, r.Status, ruleNum)
|
||||
p.log.Debug().Msgf("CF-RAY: %s Status: %s served by ingress %d", cfRay, r.Status, rule)
|
||||
} else if lbProbe {
|
||||
p.log.Debug().Msgf("Response to Load Balancer health check %s", r.Status)
|
||||
} else {
|
||||
p.log.Debug().Msgf("Status: %s served by ingress %d", r.Status, ruleNum)
|
||||
p.log.Debug().Msgf("Status: %s served by ingress %v", r.Status, rule)
|
||||
}
|
||||
p.log.Debug().Msgf("CF-RAY: %s Response Headers %+v", cfRay, r.Header)
|
||||
|
||||
@@ -226,14 +262,13 @@ func (p *proxy) logOriginResponse(r *http.Response, cfRay string, lbProbe bool,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *proxy) logRequestError(err error, cfRay string, ruleNum int) {
|
||||
func (p *proxy) logRequestError(err error, cfRay string, rule interface{}) {
|
||||
requestErrors.Inc()
|
||||
if cfRay != "" {
|
||||
p.log.Error().Msgf("CF-RAY: %s Proxying to ingress %d error: %v", cfRay, ruleNum, err)
|
||||
p.log.Error().Msgf("CF-RAY: %s Proxying to ingress %v error: %v", cfRay, rule, err)
|
||||
} else {
|
||||
p.log.Error().Msgf("Proxying to ingress %d error: %v", ruleNum, err)
|
||||
p.log.Error().Msgf("Proxying to ingress %v error: %v", rule, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func findCfRayHeader(req *http.Request) string {
|
||||
|
@@ -5,7 +5,6 @@ import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -14,6 +13,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cloudflared/logger"
|
||||
|
||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||
"github.com/cloudflare/cloudflared/connection"
|
||||
"github.com/cloudflare/cloudflared/h2mux"
|
||||
@@ -30,7 +31,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
testTags = []tunnelpogs.Tag(nil)
|
||||
testTags = []tunnelpogs.Tag(nil)
|
||||
unusedWarpRoutingService = (*ingress.WarpRoutingService)(nil)
|
||||
)
|
||||
|
||||
type mockHTTPRespWriter struct {
|
||||
@@ -129,7 +131,7 @@ func TestProxySingleOrigin(t *testing.T) {
|
||||
errC := make(chan error)
|
||||
require.NoError(t, ingressRule.StartOrigins(&wg, &log, ctx.Done(), errC))
|
||||
|
||||
proxy := NewOriginProxy(ingressRule, testTags, &log)
|
||||
proxy := NewOriginProxy(ingressRule, unusedWarpRoutingService, testTags, &log)
|
||||
t.Run("testProxyHTTP", testProxyHTTP(t, proxy))
|
||||
t.Run("testProxyWebsocket", testProxyWebsocket(t, proxy))
|
||||
t.Run("testProxySSE", testProxySSE(t, proxy))
|
||||
@@ -262,7 +264,7 @@ func TestProxyMultipleOrigins(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
require.NoError(t, ingress.StartOrigins(&wg, &log, ctx.Done(), errC))
|
||||
|
||||
proxy := NewOriginProxy(ingress, testTags, &log)
|
||||
proxy := NewOriginProxy(ingress, unusedWarpRoutingService, testTags, &log)
|
||||
|
||||
tests := []struct {
|
||||
url string
|
||||
@@ -340,7 +342,7 @@ func TestProxyError(t *testing.T) {
|
||||
|
||||
log := zerolog.Nop()
|
||||
|
||||
proxy := NewOriginProxy(ingress, testTags, &log)
|
||||
proxy := NewOriginProxy(ingress, unusedWarpRoutingService, testTags, &log)
|
||||
|
||||
respWriter := newMockHTTPRespWriter()
|
||||
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1", nil)
|
||||
@@ -372,7 +374,7 @@ func TestProxyBastionMode(t *testing.T) {
|
||||
|
||||
ingressRule.StartOrigins(&wg, log, ctx.Done(), errC)
|
||||
|
||||
proxy := NewOriginProxy(ingressRule, testTags, log)
|
||||
proxy := NewOriginProxy(ingressRule, unusedWarpRoutingService, testTags, log)
|
||||
|
||||
t.Run("testBastionWebsocket", testBastionWebsocket(proxy))
|
||||
cancel()
|
||||
@@ -429,9 +431,9 @@ func TestTCPStream(t *testing.T) {
|
||||
|
||||
ingressConfig := &config.Configuration{
|
||||
Ingress: []config.UnvalidatedIngressRule{
|
||||
config.UnvalidatedIngressRule{
|
||||
{
|
||||
Hostname: "*",
|
||||
Service: ingress.ServiceTeamnet,
|
||||
Service: "bastion",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -442,11 +444,10 @@ func TestTCPStream(t *testing.T) {
|
||||
errC := make(chan error)
|
||||
ingressRule.StartOrigins(&wg, logger, ctx.Done(), errC)
|
||||
|
||||
proxy := NewOriginProxy(ingressRule, testTags, logger)
|
||||
proxy := NewOriginProxy(ingressRule, ingress.NewWarpRoutingService(), testTags, logger)
|
||||
|
||||
t.Run("testTCPStream", testTCPStreamProxy(proxy))
|
||||
cancel()
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
type mockTCPRespWriter struct {
|
||||
|
Reference in New Issue
Block a user