TUN-7124: Add intercept ingress rule for management requests

This commit is contained in:
Devin Carr
2023-03-21 11:42:25 -07:00
parent f686da832f
commit be64362fdb
25 changed files with 2741 additions and 43 deletions

View File

@@ -35,13 +35,22 @@ const (
// FindMatchingRule returns the index of the Ingress Rule which matches the given
// hostname and path. This function assumes the last rule matches everything,
// which is the case if the rules were instantiated via the ingress#Validate method
// which is the case if the rules were instantiated via the ingress#Validate method.
//
// Negative index rule signifies local cloudflared rules (not-user defined).
func (ing Ingress) FindMatchingRule(hostname, path string) (*Rule, int) {
// The hostname might contain port. We only want to compare the host part with the rule
host, _, err := net.SplitHostPort(hostname)
if err == nil {
hostname = host
}
for i, rule := range ing.LocalRules {
if rule.Matches(hostname, path) {
// Local rule matches return a negative rule index to distiguish local rules from user-defined rules in logs
// Full range would be [-1 .. )
return &rule, -1 - i
}
}
for i, rule := range ing.Rules {
if rule.Matches(hostname, path) {
return &rule, i
@@ -67,6 +76,9 @@ func matchHost(ruleHost, reqHost string) bool {
// Ingress maps eyeball requests to origins.
type Ingress struct {
// Set of ingress rules that are not added to remote config, e.g. management
LocalRules []Rule
// Rules that are provided by the user from remote or local configuration
Rules []Rule `json:"ingress"`
Defaults OriginRequestConfig `json:"originRequest"`
}
@@ -145,24 +157,6 @@ func newDefaultOrigin(c *cli.Context, log *zerolog.Logger) Ingress {
return ingress
}
// WarpRoutingService starts a tcp stream between the origin and requests from
// warp clients.
type WarpRoutingService struct {
Proxy StreamBasedOriginProxy
}
func NewWarpRoutingService(config WarpRoutingConfig) *WarpRoutingService {
svc := &rawTCPService{
name: ServiceWarpRouting,
dialer: net.Dialer{
Timeout: config.ConnectTimeout.Duration,
KeepAlive: config.TCPKeepAlive.Duration,
},
}
return &WarpRoutingService{Proxy: svc}
}
// Get a single origin service from the CLI/config.
func parseSingleOriginService(c *cli.Context, allowURLFromArgs bool) (OriginService, error) {
if c.IsSet(HelloWorldFlag) {

View File

@@ -17,6 +17,12 @@ type StreamBasedOriginProxy interface {
EstablishConnection(ctx context.Context, dest string) (OriginConnection, error)
}
// HTTPLocalProxy can be implemented by cloudflared services that want to handle incoming http requests.
type HTTPLocalProxy interface {
// Handler is how cloudflared proxies eyeball requests to the local cloudflared services
http.Handler
}
func (o *unixSocketPath) RoundTrip(req *http.Request) (*http.Response, error) {
req.URL.Scheme = o.scheme
return o.transport.RoundTrip(req)

View File

@@ -17,6 +17,7 @@ import (
"github.com/cloudflare/cloudflared/hello"
"github.com/cloudflare/cloudflared/ipaccess"
"github.com/cloudflare/cloudflared/management"
"github.com/cloudflare/cloudflared/socks"
"github.com/cloudflare/cloudflared/tlsconfig"
)
@@ -278,6 +279,54 @@ func (o statusCode) MarshalJSON() ([]byte, error) {
return json.Marshal(o.String())
}
// WarpRoutingService starts a tcp stream between the origin and requests from
// warp clients.
type WarpRoutingService struct {
Proxy StreamBasedOriginProxy
}
func NewWarpRoutingService(config WarpRoutingConfig) *WarpRoutingService {
svc := &rawTCPService{
name: ServiceWarpRouting,
dialer: net.Dialer{
Timeout: config.ConnectTimeout.Duration,
KeepAlive: config.TCPKeepAlive.Duration,
},
}
return &WarpRoutingService{Proxy: svc}
}
// ManagementService starts a local HTTP server to handle incoming management requests.
type ManagementService struct {
HTTPLocalProxy
}
func newManagementService(managementProxy HTTPLocalProxy) *ManagementService {
return &ManagementService{
HTTPLocalProxy: managementProxy,
}
}
func (o *ManagementService) start(log *zerolog.Logger, _ <-chan struct{}, cfg OriginRequestConfig) error {
return nil
}
func (o *ManagementService) String() string {
return "management"
}
func (o ManagementService) MarshalJSON() ([]byte, error) {
return json.Marshal(o.String())
}
func NewManagementRule(management *management.ManagementService) Rule {
return Rule{
Hostname: management.Hostname,
Service: newManagementService(management),
}
}
type NopReadCloser struct{}
// Read always returns EOF to signal end of input