Release Argo Tunnel Client 2018.5.4
This commit is contained in:
parent
9135a4837c
commit
75d7561b5d
|
@ -11,6 +11,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -113,11 +114,13 @@ func enoughOptionsSet(c *cli.Context) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleDeprecatedOptions(c *cli.Context) {
|
func handleDeprecatedOptions(c *cli.Context) error {
|
||||||
// Fail if the user provided an old authentication method
|
// Fail if the user provided an old authentication method
|
||||||
if c.IsSet("api-key") || c.IsSet("api-email") || c.IsSet("api-ca-key") {
|
if c.IsSet("api-key") || c.IsSet("api-email") || c.IsSet("api-ca-key") {
|
||||||
logger.Fatal("You don't need to give us your api-key anymore. Please use the new login method. Just run cloudflared login")
|
logger.Error("You don't need to give us your api-key anymore. Please use the new login method. Just run cloudflared login")
|
||||||
|
return fmt.Errorf("Client provided deprecated options")
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate url. It can be either from --url or argument
|
// validate url. It can be either from --url or argument
|
||||||
|
@ -162,26 +165,30 @@ func dnsProxyStandAlone(c *cli.Context) bool {
|
||||||
return c.IsSet("proxy-dns") && (!c.IsSet("hostname") && !c.IsSet("tag") && !c.IsSet("hello-world"))
|
return c.IsSet("proxy-dns") && (!c.IsSet("hostname") && !c.IsSet("tag") && !c.IsSet("hello-world"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getOriginCert(c *cli.Context) []byte {
|
func getOriginCert(c *cli.Context) ([]byte, error) {
|
||||||
if c.String("origincert") == "" {
|
if c.String("origincert") == "" {
|
||||||
logger.Warnf("Cannot determine default origin certificate path. No file %s in %v", defaultCredentialFile, defaultConfigDirs)
|
logger.Warnf("Cannot determine default origin certificate path. No file %s in %v", defaultCredentialFile, defaultConfigDirs)
|
||||||
if isRunningFromTerminal() {
|
if isRunningFromTerminal() {
|
||||||
logger.Fatalf("You need to specify the origin certificate path with --origincert option, or set TUNNEL_ORIGIN_CERT environment variable. See %s for more information.", argumentsUrl)
|
logger.Errorf("You need to specify the origin certificate path with --origincert option, or set TUNNEL_ORIGIN_CERT environment variable. See %s for more information.", argumentsUrl)
|
||||||
|
return nil, fmt.Errorf("Client didn't specify origincert path when running from terminal")
|
||||||
} else {
|
} else {
|
||||||
logger.Fatalf("You need to specify the origin certificate path by specifying the origincert option in the configuration file, or set TUNNEL_ORIGIN_CERT environment variable. See %s for more information.", serviceUrl)
|
logger.Errorf("You need to specify the origin certificate path by specifying the origincert option in the configuration file, or set TUNNEL_ORIGIN_CERT environment variable. See %s for more information.", serviceUrl)
|
||||||
|
return nil, fmt.Errorf("Client didn't specify origincert path")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check that the user has acquired a certificate using the login command
|
// Check that the user has acquired a certificate using the login command
|
||||||
originCertPath, err := homedir.Expand(c.String("origincert"))
|
originCertPath, err := homedir.Expand(c.String("origincert"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatalf("Cannot resolve path %s", c.String("origincert"))
|
logger.WithError(err).Errorf("Cannot resolve path %s", c.String("origincert"))
|
||||||
|
return nil, fmt.Errorf("Cannot resolve path %s", c.String("origincert"))
|
||||||
}
|
}
|
||||||
ok, err := fileExists(originCertPath)
|
ok, err := fileExists(originCertPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("Cannot check if origin cert exists at path %s", c.String("origincert"))
|
logger.Errorf("Cannot check if origin cert exists at path %s", c.String("origincert"))
|
||||||
|
return nil, fmt.Errorf("Cannot check if origin cert exists at path %s", c.String("origincert"))
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Fatalf(`Cannot find a valid certificate for your origin at the path:
|
logger.Errorf(`Cannot find a valid certificate for your origin at the path:
|
||||||
|
|
||||||
%s
|
%s
|
||||||
|
|
||||||
|
@ -190,19 +197,22 @@ If you don't have a certificate signed by Cloudflare, run the command:
|
||||||
|
|
||||||
%s login
|
%s login
|
||||||
`, originCertPath, os.Args[0])
|
`, originCertPath, os.Args[0])
|
||||||
|
return nil, fmt.Errorf("Cannot find a valid certificate at the path %s", originCertPath)
|
||||||
}
|
}
|
||||||
// Easier to send the certificate as []byte via RPC than decoding it at this point
|
// Easier to send the certificate as []byte via RPC than decoding it at this point
|
||||||
originCert, err := ioutil.ReadFile(originCertPath)
|
originCert, err := ioutil.ReadFile(originCertPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatalf("Cannot read %s to load origin certificate", originCertPath)
|
logger.WithError(err).Errorf("Cannot read %s to load origin certificate", originCertPath)
|
||||||
|
return nil, fmt.Errorf("Cannot read %s to load origin certificate", originCertPath)
|
||||||
}
|
}
|
||||||
return originCert
|
return originCert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareTunnelConfig(c *cli.Context, buildInfo *origin.BuildInfo, logger, protoLogger *logrus.Logger) *origin.TunnelConfig {
|
func prepareTunnelConfig(c *cli.Context, buildInfo *origin.BuildInfo, logger, protoLogger *logrus.Logger) (*origin.TunnelConfig, error) {
|
||||||
hostname, err := validation.ValidateHostname(c.String("hostname"))
|
hostname, err := validation.ValidateHostname(c.String("hostname"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("Invalid hostname")
|
logger.WithError(err).Error("Invalid hostname")
|
||||||
|
return nil, errors.Wrap(err, "Invalid hostname")
|
||||||
}
|
}
|
||||||
clientID := c.String("id")
|
clientID := c.String("id")
|
||||||
if !c.IsSet("id") {
|
if !c.IsSet("id") {
|
||||||
|
@ -211,22 +221,28 @@ func prepareTunnelConfig(c *cli.Context, buildInfo *origin.BuildInfo, logger, pr
|
||||||
|
|
||||||
tags, err := NewTagSliceFromCLI(c.StringSlice("tag"))
|
tags, err := NewTagSliceFromCLI(c.StringSlice("tag"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("Tag parse failure")
|
logger.WithError(err).Error("Tag parse failure")
|
||||||
|
return nil, errors.Wrap(err, "Tag parse failure")
|
||||||
}
|
}
|
||||||
|
|
||||||
tags = append(tags, tunnelpogs.Tag{Name: "ID", Value: clientID})
|
tags = append(tags, tunnelpogs.Tag{Name: "ID", Value: clientID})
|
||||||
|
|
||||||
url, err := validateUrl(c)
|
url, err := validateUrl(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("Error validating url")
|
logger.WithError(err).Error("Error validating url")
|
||||||
|
return nil, errors.Wrap(err, "Error validating url")
|
||||||
}
|
}
|
||||||
logger.Infof("Proxying tunnel requests to %s", url)
|
logger.Infof("Proxying tunnel requests to %s", url)
|
||||||
|
|
||||||
originCert := getOriginCert(c)
|
originCert, err := getOriginCert(c)
|
||||||
|
|
||||||
originCertPool, err := loadCertPool(c)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal(err)
|
return nil, errors.Wrap(err, "Error getting origin cert")
|
||||||
|
}
|
||||||
|
|
||||||
|
originCertPool, err := loadCertPool(c, logger)
|
||||||
|
if err != nil {
|
||||||
|
logger.WithError(err).Error("Error loading cert pool")
|
||||||
|
return nil, errors.Wrap(err, "Error loading cert pool")
|
||||||
}
|
}
|
||||||
|
|
||||||
tunnelMetrics := origin.NewTunnelMetrics()
|
tunnelMetrics := origin.NewTunnelMetrics()
|
||||||
|
@ -272,10 +288,10 @@ func prepareTunnelConfig(c *cli.Context, buildInfo *origin.BuildInfo, logger, pr
|
||||||
IsAutoupdated: c.Bool("is-autoupdated"),
|
IsAutoupdated: c.Bool("is-autoupdated"),
|
||||||
GracePeriod: c.Duration("grace-period"),
|
GracePeriod: c.Duration("grace-period"),
|
||||||
RunFromTerminal: isRunningFromTerminal(),
|
RunFromTerminal: isRunningFromTerminal(),
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadCertPool(c *cli.Context) (*x509.CertPool, error) {
|
func loadCertPool(c *cli.Context, logger *logrus.Logger) (*x509.CertPool, error) {
|
||||||
const originCAPoolFlag = "origin-ca-pool"
|
const originCAPoolFlag = "origin-ca-pool"
|
||||||
originCAPoolFilename := c.String(originCAPoolFlag)
|
originCAPoolFilename := c.String(originCAPoolFlag)
|
||||||
var originCustomCAPool []byte
|
var originCustomCAPool []byte
|
||||||
|
@ -293,5 +309,10 @@ func loadCertPool(c *cli.Context) (*x509.CertPool, error) {
|
||||||
return nil, errors.Wrap(err, "error loading the certificate pool")
|
return nil, errors.Wrap(err, "error loading the certificate pool")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Windows users should be notified that they can use the flag
|
||||||
|
if runtime.GOOS == "windows" && originCAPoolFilename == "" {
|
||||||
|
logger.Infof("cloudflared does not support loading the system root certificate pool on Windows. Please use the --%s to specify it", originCAPoolFlag)
|
||||||
|
}
|
||||||
|
|
||||||
return originCertPool, nil
|
return originCertPool, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,22 +16,25 @@ import (
|
||||||
|
|
||||||
var logger = log.CreateLogger()
|
var logger = log.CreateLogger()
|
||||||
|
|
||||||
func configMainLogger(c *cli.Context) {
|
func configMainLogger(c *cli.Context) error {
|
||||||
logLevel, err := logrus.ParseLevel(c.String("loglevel"))
|
logLevel, err := logrus.ParseLevel(c.String("loglevel"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("Unknown logging level specified")
|
logger.WithError(err).Error("Unknown logging level specified")
|
||||||
|
return errors.Wrap(err, "Unknown logging level specified")
|
||||||
}
|
}
|
||||||
logger.SetLevel(logLevel)
|
logger.SetLevel(logLevel)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func configProtoLogger(c *cli.Context) *logrus.Logger {
|
func configProtoLogger(c *cli.Context) (*logrus.Logger, error) {
|
||||||
protoLogLevel, err := logrus.ParseLevel(c.String("proto-loglevel"))
|
protoLogLevel, err := logrus.ParseLevel(c.String("proto-loglevel"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("Unknown protocol logging level specified")
|
logger.WithError(err).Fatal("Unknown protocol logging level specified")
|
||||||
|
return nil, errors.Wrap(err, "Unknown protocol logging level specified")
|
||||||
}
|
}
|
||||||
protoLogger := logrus.New()
|
protoLogger := logrus.New()
|
||||||
protoLogger.Level = protoLogLevel
|
protoLogger.Level = protoLogLevel
|
||||||
return protoLogger
|
return protoLogger, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initLogFile(c *cli.Context, loggers ...*logrus.Logger) error {
|
func initLogFile(c *cli.Context, loggers ...*logrus.Logger) error {
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"gopkg.in/urfave/cli.v2"
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -33,9 +35,10 @@ func runApp(app *cli.App, shutdownC chan struct{}) {
|
||||||
app.Run(os.Args)
|
app.Run(os.Args)
|
||||||
}
|
}
|
||||||
|
|
||||||
var launchdTemplate = ServiceTemplate{
|
func newLaunchdTemplate(installPath, stdoutPath, stderrPath string) *ServiceTemplate {
|
||||||
Path: installPath(),
|
return &ServiceTemplate{
|
||||||
Content: fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
|
Path: installPath,
|
||||||
|
Content: fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
@ -59,33 +62,46 @@ var launchdTemplate = ServiceTemplate{
|
||||||
<key>ThrottleInterval</key>
|
<key>ThrottleInterval</key>
|
||||||
<integer>20</integer>
|
<integer>20</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>`, launchdIdentifier, stdoutPath(), stderrPath()),
|
</plist>`, launchdIdentifier, stdoutPath, stderrPath),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isRootUser() bool {
|
func isRootUser() bool {
|
||||||
return os.Geteuid() == 0
|
return os.Geteuid() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func installPath() string {
|
func installPath() (string, error) {
|
||||||
// User is root, use /Library/LaunchDaemons instead of home directory
|
// User is root, use /Library/LaunchDaemons instead of home directory
|
||||||
if isRootUser() {
|
if isRootUser() {
|
||||||
return fmt.Sprintf("/Library/LaunchDaemons/%s.plist", launchdIdentifier)
|
return fmt.Sprintf("/Library/LaunchDaemons/%s.plist", launchdIdentifier), nil
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", userHomeDir(), launchdIdentifier)
|
userHomeDir, err := userHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", userHomeDir, launchdIdentifier), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func stdoutPath() string {
|
func stdoutPath() (string, error) {
|
||||||
if isRootUser() {
|
if isRootUser() {
|
||||||
return fmt.Sprintf("/Library/Logs/%s.out.log", launchdIdentifier)
|
return fmt.Sprintf("/Library/Logs/%s.out.log", launchdIdentifier), nil
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/Library/Logs/%s.out.log", userHomeDir(), launchdIdentifier)
|
userHomeDir, err := userHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s/Library/Logs/%s.out.log", userHomeDir, launchdIdentifier), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func stderrPath() string {
|
func stderrPath() (string, error) {
|
||||||
if isRootUser() {
|
if isRootUser() {
|
||||||
return fmt.Sprintf("/Library/Logs/%s.err.log", launchdIdentifier)
|
return fmt.Sprintf("/Library/Logs/%s.err.log", launchdIdentifier), nil
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/Library/Logs/%s.err.log", userHomeDir(), launchdIdentifier)
|
userHomeDir, err := userHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s/Library/Logs/%s.err.log", userHomeDir, launchdIdentifier), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func installLaunchd(c *cli.Context) error {
|
func installLaunchd(c *cli.Context) error {
|
||||||
|
@ -100,13 +116,30 @@ func installLaunchd(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
etPath, err := os.Executable()
|
etPath, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Infof("error determining executable path")
|
logger.WithError(err).Errorf("Error determining executable path")
|
||||||
return fmt.Errorf("error determining executable path: %v", err)
|
return fmt.Errorf("Error determining executable path: %v", err)
|
||||||
|
}
|
||||||
|
installPath, err := installPath()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Error determining install path")
|
||||||
|
}
|
||||||
|
stdoutPath, err := stdoutPath()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error determining stdout path")
|
||||||
|
}
|
||||||
|
stderrPath, err := stderrPath()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error determining stderr path")
|
||||||
|
}
|
||||||
|
launchdTemplate := newLaunchdTemplate(installPath, stdoutPath, stderrPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.WithError(err).Errorf("error creating launchd template")
|
||||||
|
return errors.Wrap(err, "error creating launchd template")
|
||||||
}
|
}
|
||||||
templateArgs := ServiceTemplateArgs{Path: etPath}
|
templateArgs := ServiceTemplateArgs{Path: etPath}
|
||||||
err = launchdTemplate.Generate(&templateArgs)
|
err = launchdTemplate.Generate(&templateArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Infof("error generating launchd template")
|
logger.WithError(err).Errorf("error generating launchd template")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
plistPath, err := launchdTemplate.ResolvePath()
|
plistPath, err := launchdTemplate.ResolvePath()
|
||||||
|
@ -115,7 +148,7 @@ func installLaunchd(c *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("Outputs are logged to %s and %s", stderrPath(), stdoutPath())
|
logger.Infof("Outputs are logged to %s and %s", stderrPath, stdoutPath)
|
||||||
return runCommand("launchctl", "load", plistPath)
|
return runCommand("launchctl", "load", plistPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +158,22 @@ func uninstallLaunchd(c *cli.Context) error {
|
||||||
} else {
|
} else {
|
||||||
logger.Infof("Uninstalling Argo Tunnel as an user launch agent")
|
logger.Infof("Uninstalling Argo Tunnel as an user launch agent")
|
||||||
}
|
}
|
||||||
|
installPath, err := installPath()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error determining install path")
|
||||||
|
}
|
||||||
|
stdoutPath, err := stdoutPath()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error determining stdout path")
|
||||||
|
}
|
||||||
|
stderrPath, err := stderrPath()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error determining stderr path")
|
||||||
|
}
|
||||||
|
launchdTemplate := newLaunchdTemplate(installPath, stdoutPath, stderrPath)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error creating launchd template")
|
||||||
|
}
|
||||||
plistPath, err := launchdTemplate.ResolvePath()
|
plistPath, err := launchdTemplate.ResolvePath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Infof("error resolving launchd template path")
|
logger.WithError(err).Infof("error resolving launchd template path")
|
||||||
|
@ -136,6 +185,6 @@ func uninstallLaunchd(c *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("Outputs are logged to %s and %s", stderrPath(), stdoutPath())
|
logger.Infof("Outputs are logged to %s and %s", stderrPath, stdoutPath)
|
||||||
return launchdTemplate.Remove()
|
return launchdTemplate.Remove()
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
|
|
||||||
"github.com/coreos/go-systemd/daemon"
|
"github.com/coreos/go-systemd/daemon"
|
||||||
"github.com/facebookgo/grace/gracenet"
|
"github.com/facebookgo/grace/gracenet"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -275,9 +276,15 @@ func main() {
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
app.Action = func(c *cli.Context) error {
|
app.Action = func(c *cli.Context) (err error) {
|
||||||
raven.CapturePanic(func() { startServer(c, shutdownC) }, nil)
|
tags := make(map[string]string)
|
||||||
return nil
|
tags["hostname"] = c.String("hostname")
|
||||||
|
raven.SetTagsContext(tags)
|
||||||
|
raven.CapturePanicAndWait(func() { err = startServer(c, shutdownC) }, nil)
|
||||||
|
if err != nil {
|
||||||
|
raven.CaptureErrorAndWait(err, nil)
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
app.Before = func(context *cli.Context) error {
|
app.Before = func(context *cli.Context) error {
|
||||||
if context.String("config") == "" {
|
if context.String("config") == "" {
|
||||||
|
@ -370,7 +377,7 @@ func main() {
|
||||||
runApp(app, shutdownC)
|
runApp(app, shutdownC)
|
||||||
}
|
}
|
||||||
|
|
||||||
func startServer(c *cli.Context, shutdownC chan struct{}) {
|
func startServer(c *cli.Context, shutdownC chan struct{}) error {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
listeners := gracenet.Net{}
|
listeners := gracenet.Net{}
|
||||||
errC := make(chan error)
|
errC := make(chan error)
|
||||||
|
@ -380,18 +387,26 @@ func startServer(c *cli.Context, shutdownC chan struct{}) {
|
||||||
|
|
||||||
// check whether client provides enough flags or env variables. If not, print help.
|
// check whether client provides enough flags or env variables. If not, print help.
|
||||||
if ok := enoughOptionsSet(c); !ok {
|
if ok := enoughOptionsSet(c); !ok {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
configMainLogger(c)
|
if err := configMainLogger(c); err != nil {
|
||||||
protoLogger := configProtoLogger(c)
|
return errors.Wrap(err, "Error configuring logger")
|
||||||
|
}
|
||||||
|
|
||||||
|
protoLogger, err := configProtoLogger(c)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Error configuring protocol logger")
|
||||||
|
}
|
||||||
if c.String("logfile") != "" {
|
if c.String("logfile") != "" {
|
||||||
if err := initLogFile(c, logger, protoLogger); err != nil {
|
if err := initLogFile(c, logger, protoLogger); err != nil {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeprecatedOptions(c)
|
if err := handleDeprecatedOptions(c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
buildInfo := origin.GetBuildInfo()
|
buildInfo := origin.GetBuildInfo()
|
||||||
logger.Infof("Build info: %+v", *buildInfo)
|
logger.Infof("Build info: %+v", *buildInfo)
|
||||||
|
@ -402,7 +417,7 @@ func startServer(c *cli.Context, shutdownC chan struct{}) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
runDNSProxyServer(c, dnsReadySignal, shutdownC)
|
errC <- runDNSProxyServer(c, dnsReadySignal, shutdownC)
|
||||||
}()
|
}()
|
||||||
} else {
|
} else {
|
||||||
close(dnsReadySignal)
|
close(dnsReadySignal)
|
||||||
|
@ -414,15 +429,20 @@ func startServer(c *cli.Context, shutdownC chan struct{}) {
|
||||||
// update needs to be after DNS proxy is up to resolve equinox server address
|
// update needs to be after DNS proxy is up to resolve equinox server address
|
||||||
if isAutoupdateEnabled(c) {
|
if isAutoupdateEnabled(c) {
|
||||||
if initUpdate(&listeners) {
|
if initUpdate(&listeners) {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
logger.Infof("Autoupdate frequency is set to %v", c.Duration("autoupdate-freq"))
|
logger.Infof("Autoupdate frequency is set to %v", c.Duration("autoupdate-freq"))
|
||||||
go autoupdate(c.Duration("autoupdate-freq"), &listeners, shutdownC)
|
wg.Add(1)
|
||||||
|
go func(){
|
||||||
|
defer wg.Done()
|
||||||
|
autoupdate(c.Duration("autoupdate-freq"), &listeners, shutdownC)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
metricsListener, err := listeners.Listen("tcp", c.String("metrics"))
|
metricsListener, err := listeners.Listen("tcp", c.String("metrics"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("Error opening metrics server listener")
|
logger.WithError(err).Error("Error opening metrics server listener")
|
||||||
|
return errors.Wrap(err, "Error opening metrics server listener")
|
||||||
}
|
}
|
||||||
defer metricsListener.Close()
|
defer metricsListener.Close()
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
@ -438,14 +458,14 @@ func startServer(c *cli.Context, shutdownC chan struct{}) {
|
||||||
close(connectedSignal)
|
close(connectedSignal)
|
||||||
}
|
}
|
||||||
// no grace period, handle SIGINT/SIGTERM immediately
|
// no grace period, handle SIGINT/SIGTERM immediately
|
||||||
waitToShutdown(&wg, errC, shutdownC, graceShutdownSignal, 0)
|
return waitToShutdown(&wg, errC, shutdownC, graceShutdownSignal, 0)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsSet("hello-world") {
|
if c.IsSet("hello-world") {
|
||||||
helloListener, err := hello.CreateTLSListener("127.0.0.1:")
|
helloListener, err := hello.CreateTLSListener("127.0.0.1:")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("Cannot start Hello World Server")
|
logger.WithError(err).Error("Cannot start Hello World Server")
|
||||||
|
return errors.Wrap(err, "Cannot start Hello World Server")
|
||||||
}
|
}
|
||||||
defer helloListener.Close()
|
defer helloListener.Close()
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
@ -456,7 +476,10 @@ func startServer(c *cli.Context, shutdownC chan struct{}) {
|
||||||
c.Set("url", "https://"+helloListener.Addr().String())
|
c.Set("url", "https://"+helloListener.Addr().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
tunnelConfig := prepareTunnelConfig(c, buildInfo, logger, protoLogger)
|
tunnelConfig, err := prepareTunnelConfig(c, buildInfo, logger, protoLogger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if c.IsSet("pidFile") {
|
if c.IsSet("pidFile") {
|
||||||
go writePidFile(connectedSignal, c.String("pidfile"))
|
go writePidFile(connectedSignal, c.String("pidfile"))
|
||||||
|
@ -468,14 +491,14 @@ func startServer(c *cli.Context, shutdownC chan struct{}) {
|
||||||
errC <- origin.StartTunnelDaemon(tunnelConfig, graceShutdownSignal, connectedSignal)
|
errC <- origin.StartTunnelDaemon(tunnelConfig, graceShutdownSignal, connectedSignal)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
waitToShutdown(&wg, errC, shutdownC, graceShutdownSignal, c.Duration("grace-period"))
|
return waitToShutdown(&wg, errC, shutdownC, graceShutdownSignal, c.Duration("grace-period"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitToShutdown(wg *sync.WaitGroup,
|
func waitToShutdown(wg *sync.WaitGroup,
|
||||||
errC chan error,
|
errC chan error,
|
||||||
shutdownC, graceShutdownSignal chan struct{},
|
shutdownC, graceShutdownSignal chan struct{},
|
||||||
gracePeriod time.Duration,
|
gracePeriod time.Duration,
|
||||||
) {
|
) error {
|
||||||
var err error
|
var err error
|
||||||
if gracePeriod > 0 {
|
if gracePeriod > 0 {
|
||||||
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceShutdownSignal, gracePeriod)
|
err = waitForSignalWithGraceShutdown(errC, shutdownC, graceShutdownSignal, gracePeriod)
|
||||||
|
@ -484,11 +507,8 @@ func waitToShutdown(wg *sync.WaitGroup,
|
||||||
close(graceShutdownSignal)
|
close(graceShutdownSignal)
|
||||||
}
|
}
|
||||||
|
|
||||||
var errCode int
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("Quitting due to error")
|
logger.WithError(err).Error("Quitting due to error")
|
||||||
raven.CaptureErrorAndWait(err, nil)
|
|
||||||
errCode = 1
|
|
||||||
} else {
|
} else {
|
||||||
logger.Info("Quitting...")
|
logger.Info("Quitting...")
|
||||||
}
|
}
|
||||||
|
@ -498,7 +518,7 @@ func waitToShutdown(wg *sync.WaitGroup,
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
os.Exit(errCode)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePidFile(waitForSignal chan struct{}, pidFile string) {
|
func writePidFile(waitForSignal chan struct{}, pidFile string) {
|
||||||
|
@ -515,14 +535,15 @@ func writePidFile(waitForSignal chan struct{}, pidFile string) {
|
||||||
fmt.Fprintf(file, "%d", os.Getpid())
|
fmt.Fprintf(file, "%d", os.Getpid())
|
||||||
}
|
}
|
||||||
|
|
||||||
func userHomeDir() string {
|
func userHomeDir() (string, error) {
|
||||||
// This returns the home dir of the executing user using OS-specific method
|
// This returns the home dir of the executing user using OS-specific method
|
||||||
// for discovering the home dir. It's not recommended to call this function
|
// for discovering the home dir. It's not recommended to call this function
|
||||||
// when the user has root permission as $HOME depends on what options the user
|
// when the user has root permission as $HOME depends on what options the user
|
||||||
// use with sudo.
|
// use with sudo.
|
||||||
homeDir, err := homedir.Dir()
|
homeDir, err := homedir.Dir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("Cannot determine home directory for the user.")
|
logger.WithError(err).Error("Cannot determine home directory for the user")
|
||||||
|
return "", errors.Wrap(err, "Cannot determine home directory for the user")
|
||||||
}
|
}
|
||||||
return homeDir
|
return homeDir, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,24 +4,30 @@ import (
|
||||||
"github.com/cloudflare/cloudflared/tunneldns"
|
"github.com/cloudflare/cloudflared/tunneldns"
|
||||||
|
|
||||||
"gopkg.in/urfave/cli.v2"
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runDNSProxyServer(c *cli.Context, dnsReadySignal, shutdownC chan struct{}) {
|
func runDNSProxyServer(c *cli.Context, dnsReadySignal, shutdownC chan struct{}) error {
|
||||||
port := c.Int("proxy-dns-port")
|
port := c.Int("proxy-dns-port")
|
||||||
if port <= 0 || port > 65535 {
|
if port <= 0 || port > 65535 {
|
||||||
logger.Fatal("The 'proxy-dns-port' must be a valid port number in <1, 65535> range.")
|
logger.Errorf("The 'proxy-dns-port' must be a valid port number in <1, 65535> range.")
|
||||||
|
return errors.New("The 'proxy-dns-port' must be a valid port number in <1, 65535> range.")
|
||||||
}
|
}
|
||||||
listener, err := tunneldns.CreateListener(c.String("proxy-dns-address"), uint16(port), c.StringSlice("proxy-dns-upstream"))
|
listener, err := tunneldns.CreateListener(c.String("proxy-dns-address"), uint16(port), c.StringSlice("proxy-dns-upstream"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
close(dnsReadySignal)
|
close(dnsReadySignal)
|
||||||
listener.Stop()
|
listener.Stop()
|
||||||
logger.WithError(err).Fatal("Cannot create the DNS over HTTPS proxy server")
|
logger.WithError(err).Error("Cannot create the DNS over HTTPS proxy server")
|
||||||
|
return errors.Wrap(err, "Cannot create the DNS over HTTPS proxy server")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = listener.Start(dnsReadySignal)
|
err = listener.Start(dnsReadySignal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("Cannot start the DNS over HTTPS proxy server")
|
logger.WithError(err).Error("Cannot start the DNS over HTTPS proxy server")
|
||||||
|
return errors.Wrap(err, "Cannot start the DNS over HTTPS proxy server")
|
||||||
}
|
}
|
||||||
<-shutdownC
|
<-shutdownC
|
||||||
listener.Stop()
|
listener.Stop()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
@ -12,8 +13,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
appID = "app_idCzgxYerVD"
|
appID = "app_idCzgxYerVD"
|
||||||
noAutoupdateMessage = "cloudflared will not automatically update when run from the shell. To enable auto-updates, run cloudflared as a service: https://developers.cloudflare.com/argo-tunnel/reference/service/"
|
noUpdateInShellMessage = "cloudflared will not automatically update when run from the shell. To enable auto-updates, run cloudflared as a service: https://developers.cloudflare.com/argo-tunnel/reference/service/"
|
||||||
|
noUpdateOnWindowsMessage = "cloudflared will not automatically update on Windows systems."
|
||||||
)
|
)
|
||||||
|
|
||||||
var publicKey = []byte(`
|
var publicKey = []byte(`
|
||||||
|
@ -98,8 +100,13 @@ func updateApplied() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func isAutoupdateEnabled(c *cli.Context) bool {
|
func isAutoupdateEnabled(c *cli.Context) bool {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
logger.Info(noUpdateOnWindowsMessage)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
if isRunningFromTerminal() {
|
if isRunningFromTerminal() {
|
||||||
logger.Info(noAutoupdateMessage)
|
logger.Info(noUpdateInShellMessage)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ func runApp(app *cli.App, shutdownC chan struct{}) {
|
||||||
|
|
||||||
elog, err := eventlog.Open(windowsServiceName)
|
elog, err := eventlog.Open(windowsServiceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Infof("Cannot open event log for %s", windowsServiceName)
|
logger.WithError(err).Errorf("Cannot open event log for %s", windowsServiceName)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer elog.Close()
|
defer elog.Close()
|
||||||
|
@ -108,12 +108,12 @@ func installWindowsService(c *cli.Context) error {
|
||||||
logger.Infof("Installing Argo Tunnel Windows service")
|
logger.Infof("Installing Argo Tunnel Windows service")
|
||||||
exepath, err := os.Executable()
|
exepath, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Infof("Cannot find path name that start the process")
|
logger.Errorf("Cannot find path name that start the process")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m, err := mgr.Connect()
|
m, err := mgr.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Infof("Cannot establish a connection to the service control manager")
|
logger.WithError(err).Errorf("Cannot establish a connection to the service control manager")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer m.Disconnect()
|
defer m.Disconnect()
|
||||||
|
@ -126,14 +126,14 @@ func installWindowsService(c *cli.Context) error {
|
||||||
config := mgr.Config{StartType: mgr.StartAutomatic, DisplayName: windowsServiceDescription}
|
config := mgr.Config{StartType: mgr.StartAutomatic, DisplayName: windowsServiceDescription}
|
||||||
s, err = m.CreateService(windowsServiceName, exepath, config)
|
s, err = m.CreateService(windowsServiceName, exepath, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Infof("Cannot install service %s", windowsServiceName)
|
logger.Errorf("Cannot install service %s", windowsServiceName)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
err = eventlog.InstallAsEventCreate(windowsServiceName, eventlog.Error|eventlog.Warning|eventlog.Info)
|
err = eventlog.InstallAsEventCreate(windowsServiceName, eventlog.Error|eventlog.Warning|eventlog.Info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Delete()
|
s.Delete()
|
||||||
logger.WithError(err).Infof("Cannot install event logger")
|
logger.WithError(err).Errorf("Cannot install event logger")
|
||||||
return fmt.Errorf("SetupEventLogSource() failed: %s", err)
|
return fmt.Errorf("SetupEventLogSource() failed: %s", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -143,13 +143,13 @@ func uninstallWindowsService(c *cli.Context) error {
|
||||||
logger.Infof("Uninstalling Argo Tunnel Windows Service")
|
logger.Infof("Uninstalling Argo Tunnel Windows Service")
|
||||||
m, err := mgr.Connect()
|
m, err := mgr.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Infof("Cannot establish a connection to the service control manager")
|
logger.Errorf("Cannot establish a connection to the service control manager")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer m.Disconnect()
|
defer m.Disconnect()
|
||||||
s, err := m.OpenService(windowsServiceName)
|
s, err := m.OpenService(windowsServiceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Infof("service %s is not installed", windowsServiceName)
|
logger.Errorf("service %s is not installed", windowsServiceName)
|
||||||
return fmt.Errorf("service %s is not installed", windowsServiceName)
|
return fmt.Errorf("service %s is not installed", windowsServiceName)
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
@ -160,7 +160,7 @@ func uninstallWindowsService(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
err = eventlog.Remove(windowsServiceName)
|
err = eventlog.Remove(windowsServiceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Infof("Cannot remove event logger")
|
logger.Errorf("Cannot remove event logger")
|
||||||
return fmt.Errorf("RemoveEventLogSource() failed: %s", err)
|
return fmt.Errorf("RemoveEventLogSource() failed: %s", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// +build ignore
|
||||||
|
// TODO: Remove the above build tag and include this test when we start compiling with Golang 1.10.0+
|
||||||
|
|
||||||
package tlsconfig
|
package tlsconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
Loading…
Reference in New Issue