mirror of
https://github.com/cloudflare/cloudflared
synced 2026-06-08 13:33:07 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 58c5e25b9a | |||
| 25e72f7760 | |||
| 7613410855 | |||
| c40cb7dc56 |
@@ -1,3 +1,8 @@
|
||||
2020.11.7
|
||||
- 2020-11-13 TUN-3514: Stop setting --is-autoupdated flag after autoupdate because it can break named tunnel running in k8s
|
||||
- 2020-11-15 TUN-3548, TUN-3547: Bastion mode can be specified as a service, doesn't require URL.
|
||||
- 2020-11-16 TUN-3549: Use a separate handler for each websocket proxy
|
||||
|
||||
2020.11.6
|
||||
- 2020-11-14 TUN-3546: Fix panic in tlsconfig.LoadOriginCA
|
||||
|
||||
|
||||
@@ -202,7 +202,6 @@ func (a *AutoUpdater) Run(ctx context.Context) error {
|
||||
if a.configurable.enabled {
|
||||
updateOutcome := loggedUpdate(a.logger, updateOptions{})
|
||||
if updateOutcome.Updated {
|
||||
os.Args = append(os.Args, "--is-autoupdated=true")
|
||||
if IsSysV() {
|
||||
// SysV doesn't have a mechanism to keep service alive, we have to restart the process
|
||||
a.logger.Info("Restarting service managed by SysV...")
|
||||
|
||||
+9
-2
@@ -89,7 +89,7 @@ func parseSingleOriginService(c *cli.Context, allowURLFromArgs bool) (OriginServ
|
||||
if c.IsSet("hello-world") {
|
||||
return new(helloWorld), nil
|
||||
}
|
||||
if c.IsSet("url") {
|
||||
if c.IsSet("url") || c.IsSet(config.BastionFlag) {
|
||||
originURL, err := config.ValidateUrl(c, allowURLFromArgs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Error validating origin URL")
|
||||
@@ -128,6 +128,7 @@ func (ing Ingress) CatchAll() *Rule {
|
||||
func validate(ingress []config.UnvalidatedIngressRule, defaults OriginRequestConfig) (Ingress, error) {
|
||||
rules := make([]Rule, len(ingress))
|
||||
for i, r := range ingress {
|
||||
cfg := setConfig(defaults, r.OriginRequest)
|
||||
var service OriginService
|
||||
|
||||
if prefix := "unix:"; strings.HasPrefix(r.Service, prefix) {
|
||||
@@ -143,6 +144,12 @@ func validate(ingress []config.UnvalidatedIngressRule, defaults OriginRequestCon
|
||||
service = &srv
|
||||
} else if r.Service == "hello_world" || r.Service == "hello-world" || r.Service == "helloworld" {
|
||||
service = new(helloWorld)
|
||||
} else if r.Service == "bastion" || cfg.BastionMode {
|
||||
// Bastion mode will always start a Websocket proxy server, which will
|
||||
// overwrite the localService.URL field when `start` is called. So,
|
||||
// leave the URL field empty for now.
|
||||
cfg.BastionMode = true
|
||||
service = new(localService)
|
||||
} else {
|
||||
// Validate URL services
|
||||
u, err := url.Parse(r.Service)
|
||||
@@ -178,7 +185,7 @@ func validate(ingress []config.UnvalidatedIngressRule, defaults OriginRequestCon
|
||||
Hostname: r.Hostname,
|
||||
Service: service,
|
||||
Path: pathRegex,
|
||||
Config: setConfig(defaults, r.OriginRequest),
|
||||
Config: cfg,
|
||||
}
|
||||
}
|
||||
return Ingress{Rules: rules, defaults: defaults}, nil
|
||||
|
||||
@@ -35,6 +35,7 @@ func Test_parseIngress(t *testing.T) {
|
||||
fourOhFour := newStatusCode(404)
|
||||
defaultConfig := setConfig(originRequestFromYAML(config.OriginRequestConfig{}), config.OriginRequestConfig{})
|
||||
require.Equal(t, defaultKeepAliveConnections, defaultConfig.KeepAliveConnections)
|
||||
tr := true
|
||||
type args struct {
|
||||
rawYAML string
|
||||
}
|
||||
@@ -209,6 +210,47 @@ ingress:
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "URL isn't necessary if using bastion",
|
||||
args: args{rawYAML: `
|
||||
ingress:
|
||||
- hostname: bastion.foo.com
|
||||
originRequest:
|
||||
bastionMode: true
|
||||
- service: http_status:404
|
||||
`},
|
||||
want: []Rule{
|
||||
{
|
||||
Hostname: "bastion.foo.com",
|
||||
Service: &localService{},
|
||||
Config: setConfig(originRequestFromYAML(config.OriginRequestConfig{}), config.OriginRequestConfig{BastionMode: &tr}),
|
||||
},
|
||||
{
|
||||
Service: &fourOhFour,
|
||||
Config: defaultConfig,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Bastion service",
|
||||
args: args{rawYAML: `
|
||||
ingress:
|
||||
- hostname: bastion.foo.com
|
||||
service: bastion
|
||||
- service: http_status:404
|
||||
`},
|
||||
want: []Rule{
|
||||
{
|
||||
Hostname: "bastion.foo.com",
|
||||
Service: &localService{},
|
||||
Config: setConfig(originRequestFromYAML(config.OriginRequestConfig{}), config.OriginRequestConfig{BastionMode: &tr}),
|
||||
},
|
||||
{
|
||||
Service: &fourOhFour,
|
||||
Config: defaultConfig,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Hostname contains port",
|
||||
args: args{rawYAML: `
|
||||
|
||||
@@ -96,8 +96,7 @@ func (o *localService) start(wg *sync.WaitGroup, log logger.Service, shutdownC <
|
||||
o.transport = transport
|
||||
|
||||
// Start a proxy if one is needed
|
||||
staticHost := o.staticHost()
|
||||
if originRequiresProxy(staticHost, cfg) {
|
||||
if staticHost := o.staticHost(); originRequiresProxy(staticHost, cfg) {
|
||||
if err := o.startProxy(staticHost, wg, log, shutdownC, errC, cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+55
-41
@@ -147,56 +147,70 @@ func StartProxyServer(logger logger.Service, listener net.Listener, staticHost s
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
h := handler{
|
||||
upgrader: upgrader,
|
||||
logger: logger,
|
||||
staticHost: staticHost,
|
||||
streamHandler: streamHandler,
|
||||
}
|
||||
|
||||
httpServer := &http.Server{Addr: listener.Addr().String(), Handler: nil}
|
||||
httpServer := &http.Server{Addr: listener.Addr().String(), Handler: &h}
|
||||
go func() {
|
||||
<-shutdownC
|
||||
httpServer.Close()
|
||||
}()
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
// If remote is an empty string, get the destination from the client.
|
||||
finalDestination := staticHost
|
||||
if finalDestination == "" {
|
||||
if jumpDestination := r.Header.Get(h2mux.CFJumpDestinationHeader); jumpDestination == "" {
|
||||
logger.Error("Did not receive final destination from client. The --destination flag is likely not set")
|
||||
return
|
||||
} else {
|
||||
finalDestination = jumpDestination
|
||||
}
|
||||
}
|
||||
|
||||
stream, err := net.Dial("tcp", finalDestination)
|
||||
if err != nil {
|
||||
logger.Errorf("Cannot connect to remote: %s", err)
|
||||
return
|
||||
}
|
||||
defer stream.Close()
|
||||
|
||||
if !websocket.IsWebSocketUpgrade(r) {
|
||||
w.Write(nonWebSocketRequestPage())
|
||||
return
|
||||
}
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
logger.Errorf("failed to upgrade: %s", err)
|
||||
return
|
||||
}
|
||||
conn.SetReadDeadline(time.Now().Add(pongWait))
|
||||
conn.SetPongHandler(func(string) error { conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
||||
done := make(chan struct{})
|
||||
go pinger(logger, conn, done)
|
||||
defer func() {
|
||||
done <- struct{}{}
|
||||
conn.Close()
|
||||
}()
|
||||
|
||||
streamHandler(&Conn{conn}, stream, r.Header)
|
||||
})
|
||||
|
||||
return httpServer.Serve(listener)
|
||||
}
|
||||
|
||||
// HTTP handler for the websocket proxy.
|
||||
type handler struct {
|
||||
logger logger.Service
|
||||
staticHost string
|
||||
upgrader websocket.Upgrader
|
||||
streamHandler func(wsConn *Conn, remoteConn net.Conn, requestHeaders http.Header)
|
||||
}
|
||||
|
||||
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// If remote is an empty string, get the destination from the client.
|
||||
finalDestination := h.staticHost
|
||||
if finalDestination == "" {
|
||||
if jumpDestination := r.Header.Get(h2mux.CFJumpDestinationHeader); jumpDestination == "" {
|
||||
h.logger.Error("Did not receive final destination from client. The --destination flag is likely not set")
|
||||
return
|
||||
} else {
|
||||
finalDestination = jumpDestination
|
||||
}
|
||||
}
|
||||
|
||||
stream, err := net.Dial("tcp", finalDestination)
|
||||
if err != nil {
|
||||
h.logger.Errorf("Cannot connect to remote: %s", err)
|
||||
return
|
||||
}
|
||||
defer stream.Close()
|
||||
|
||||
if !websocket.IsWebSocketUpgrade(r) {
|
||||
w.Write(nonWebSocketRequestPage())
|
||||
return
|
||||
}
|
||||
conn, err := h.upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
h.logger.Errorf("failed to upgrade: %s", err)
|
||||
return
|
||||
}
|
||||
conn.SetReadDeadline(time.Now().Add(pongWait))
|
||||
conn.SetPongHandler(func(string) error { conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
||||
done := make(chan struct{})
|
||||
go pinger(h.logger, conn, done)
|
||||
defer func() {
|
||||
done <- struct{}{}
|
||||
conn.Close()
|
||||
}()
|
||||
|
||||
h.streamHandler(&Conn{conn}, stream, r.Header)
|
||||
}
|
||||
|
||||
// SendSSHPreamble sends the final SSH destination address to the cloudflared SSH proxy
|
||||
// The destination is preceded by its length
|
||||
// Not part of sshserver module to fix compilation for incompatible operating systems
|
||||
|
||||
Reference in New Issue
Block a user