cmd/tailscale/cli, ipn/ipnlocal: [funnel] add stream mode

Adds ability to start Funnel in the foreground and stream incoming
connections. When foreground process is stopped, Funnel is turned
back off for the port.

Exampe usage:
```
TAILSCALE_FUNNEL_V2=on tailscale funnel 8080
```

Updates #8489

Signed-off-by: Marwan Sulaiman <marwan@tailscale.com>
This commit is contained in:
Marwan Sulaiman
2023-08-17 11:47:35 -04:00
committed by Marwan Sulaiman
parent cb4a61f951
commit 35ff5bf5a6
11 changed files with 399 additions and 2 deletions

View File

@@ -1057,6 +1057,29 @@ func (lc *LocalClient) NetworkLockDisable(ctx context.Context, secret []byte) er
return nil
}
// StreamServe returns an io.ReadCloser that streams serve/Funnel
// connections made to the provided HostPort.
//
// If Serve and Funnel were not already enabled for the HostPort in the ServeConfig,
// the backend enables it for the duration of the context's lifespan and
// then turns it back off once the context is closed. If either are already enabled,
// then they remain that way but logs are still streamed
func (lc *LocalClient) StreamServe(ctx context.Context, hp ipn.ServeStreamRequest) (io.ReadCloser, error) {
req, err := http.NewRequestWithContext(ctx, "POST", "http://"+apitype.LocalAPIHost+"/localapi/v0/stream-serve", jsonBody(hp))
if err != nil {
return nil, err
}
res, err := lc.doLocalRequestNiceError(req)
if err != nil {
return nil, err
}
if res.StatusCode != 200 {
res.Body.Close()
return nil, errors.New(res.Status)
}
return res.Body, nil
}
// GetServeConfig return the current serve config.
//
// If the serve config is empty, it returns (nil, nil).