diff --git a/CHANGELOG.md b/CHANGELOG.md index 22512105d..4d3dd2202 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,46 @@ * Enhancement: Add terminator_id and version to service events. If a service event relates to a terminator, the terminator_id will now be included. Service events now also have a version field, which is set to 2. * Enhancement: Don't let identity/service/edge router role attributes start with a hashtag or at-symbol to prevent confusion. * Bug fix: Timeout remaining for onWake/onUnlock will properly report as non-zero after MFA submission +* Enhancement: traceroute support + +## Traceroute + +The Ziti cli and Ziti Golang SDK now support traceroute style operations. In order for this to work the SDK and routers must be at version 0.22.6 or greater. This is currently only supported in the Golang SDK. + +The SDK can perform a traceroute as follows: + +``` +conn, err := ctx.Dial(o.Args[0]) +result, err := conn.TraceRoute(hop, time.Second*5) +``` + +The result structure looks like: + +``` +type TraceRouteResult struct { + Hops uint32 + Time time.Duration + HopType string + HopId string +} +``` +Increasing numbers of hops can be requested until the hops returned is greater than zero, indicating that additional hops weren't available. This functionality is available in the Ziti CLI. + +``` +$ ziti edge traceroute simple -c ./simple-client.json + 1 xgress/edge 1ms + 2 forwarder[n4yChTL3Jy] 0s + 3 forwarder[Yv7BPW0kGR] 0s + 4 xgress/edge 1ms + 5 sdk/golang 0s + +plorenz@carrot:~/work/nf$ ziti edge traceroute simple -c ./simple-client.json + 1 xgress/edge 0s + 2 forwarder[n4yChTL3Jy] 0s + 3 forwarder[Yv7BPW0kGR] 1ms + 4 xgress/edge_transport 0s +``` +>>>>>>> 7d34149 (Update deps/changelog. Add traceroute command to ziti edge CLI) # Release 0.22.5 diff --git a/go.mod b/go.mod index 65dac3f6b..e48107071 100644 --- a/go.mod +++ b/go.mod @@ -34,10 +34,10 @@ require ( github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 github.com/michaelquigley/pfxlog v0.6.1 - github.com/openziti/edge v0.20.88 - github.com/openziti/fabric v0.16.112 - github.com/openziti/foundation v0.15.80 - github.com/openziti/sdk-golang v0.15.103 + github.com/openziti/edge v0.20.93 + github.com/openziti/fabric v0.16.114 + github.com/openziti/foundation v0.15.81 + github.com/openziti/sdk-golang v0.15.105 github.com/pborman/uuid v1.2.0 github.com/pkg/errors v0.9.1 github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 diff --git a/go.sum b/go.sum index e63fa9f66..00accd681 100644 --- a/go.sum +++ b/go.sum @@ -739,14 +739,14 @@ github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e h1:ST9+54UtCr96S5 github.com/openziti/bbolt v1.3.6-0.20210317142109-547da822475e/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= github.com/openziti/dilithium v0.3.3 h1:PLgQ6PMNLSTzCFbX/h98cmudgz/cU6TmjdSv5NAPD8k= github.com/openziti/dilithium v0.3.3/go.mod h1:vsCjI2AU/hon9e+dLhUFbCNGesJDj2ASgkySOcpmvjo= -github.com/openziti/edge v0.20.88 h1:BZbDzZnfwPzIxU9KFZBe6FWAQFfE7P0hKZ68jf3vdRg= -github.com/openziti/edge v0.20.88/go.mod h1:RtPQJT3atx01XoHTSpWne31xyd8Q05yTBe5/BY+fV98= -github.com/openziti/fabric v0.16.112 h1:U2F+aDNhrtrho92iVI+rRCElpdl4/sgLOHFjGl13F+I= -github.com/openziti/fabric v0.16.112/go.mod h1:gT8eZNIN9N3T7fe4D3944E6rfVU6UgycEhVD4a8VKkc= -github.com/openziti/foundation v0.15.80 h1:iFjByd2+pk7OekuykIdhVdfdlz+p9N6isN5rPzTEHoQ= -github.com/openziti/foundation v0.15.80/go.mod h1:ruy6cSHAJ40DIOb9232INkrn4wsWeGmZWLJbTycoNNc= -github.com/openziti/sdk-golang v0.15.103 h1:VFOuHk0hrV0P5wjxfbywPQ2F6Wh7GIr933EjC5lxwm4= -github.com/openziti/sdk-golang v0.15.103/go.mod h1:cNMY4wKP7BBmrddRJFL2C2RYwyMfhFLTyOkrodfhbik= +github.com/openziti/edge v0.20.93 h1:IV8/n+gMqaINEcpYBsxsUQL3+Y9hChH8PuIB7eDZniA= +github.com/openziti/edge v0.20.93/go.mod h1:HtLl7CtcsX0L2P9tTfiUOUob/DyZyf47f3xddVg6CtI= +github.com/openziti/fabric v0.16.114 h1:kSGBSvJtBVXDiPLQSYd1peCKvBbATID1WzkJGYwJ29s= +github.com/openziti/fabric v0.16.114/go.mod h1:23ISF6SAx9y9C3njZv5X1twSKtM4/65dgSdS7bKLzhA= +github.com/openziti/foundation v0.15.81 h1:zQFba0AMFukPSH1tM9WD73rz2XjIr1R3YXgENMSaILc= +github.com/openziti/foundation v0.15.81/go.mod h1:ruy6cSHAJ40DIOb9232INkrn4wsWeGmZWLJbTycoNNc= +github.com/openziti/sdk-golang v0.15.105 h1:CRnb9F74fbjGjYNijK+I4rYv1ze66EmW/qKZRzFcVxM= +github.com/openziti/sdk-golang v0.15.105/go.mod h1:XKVVS/RTYhK+ZMC8Y8EMjRBgsDmSjXWa0w9tD9BABv0= github.com/oracle/oci-go-sdk v24.2.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI= github.com/orcaman/concurrent-map v0.0.0-20210106121528-16402b402231 h1:fa50YL1pzKW+1SsBnJDOHppJN9stOEwS+CRWyUtyYGU= diff --git a/ziti/cmd/ziti/cmd/edge/root.go b/ziti/cmd/ziti/cmd/edge/root.go index 7d64e611e..02e8cb14d 100644 --- a/ziti/cmd/ziti/cmd/edge/root.go +++ b/ziti/cmd/ziti/cmd/edge/root.go @@ -94,6 +94,7 @@ func populateEdgeCommands(f cmdutil.Factory, out io.Writer, errOut io.Writer, cm cmd.AddCommand(enrollment.NewEnrollCommand()) cmd.AddCommand(newTraceCmd(out, errOut)) cmd.AddCommand(newTutorialCmd(p)) + cmd.AddCommand(newTraceRouteCmd(out, errOut)) return cmd } diff --git a/ziti/cmd/ziti/cmd/edge/traceroute.go b/ziti/cmd/ziti/cmd/edge/traceroute.go new file mode 100644 index 000000000..23e6450cb --- /dev/null +++ b/ziti/cmd/ziti/cmd/edge/traceroute.go @@ -0,0 +1,121 @@ +package edge + +import ( + "fmt" + "github.com/openziti/sdk-golang/ziti" + "github.com/openziti/sdk-golang/ziti/config" + "github.com/openziti/ziti/ziti/cmd/ziti/cmd/common" + cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "io" + "math" + "time" +) + +type traceRouteOptions struct { + edgeOptions + skipIntermediate bool + hops uint8 + configFile string + timeout time.Duration +} + +func newTraceRouteCmd(out io.Writer, errOut io.Writer) *cobra.Command { + options := &traceRouteOptions{ + edgeOptions: edgeOptions{ + CommonOptions: common.CommonOptions{Out: out, Err: errOut}, + }, + } + + cmd := &cobra.Command{ + Use: "traceroute ", + Short: "runs a traceroute on the service", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + options.Cmd = cmd + options.Args = args + err := options.Run() + cmdhelper.CheckErr(err) + }, + SuggestFor: []string{}, + } + + // allow interspersing positional args and flags + cmd.Flags().SetInterspersed(true) + + cmd.Flags().StringVarP(&options.configFile, "config-file", "c", "", "Config file path") + cmd.Flags().BoolVarP(&options.skipIntermediate, "skip-intermediate", "s", false, "Skip intermediate hops") + cmd.Flags().Uint8Var(&options.hops, "hops", 0, "Maximum number of hops") + cmd.Flags().DurationVarP(&options.timeout, "timeout", "t", 5*time.Second, "Trace route response timeout") + cmd.Flags().BoolVarP(&options.Verbose, "verbose", "", false, "Enable verbose logging") + + return cmd +} + +// Run implements this command +func (o *traceRouteOptions) Run() error { + var ctx ziti.Context + if o.configFile != "" { + cfg, err := config.NewFromFile(o.configFile) + if err != nil { + return err + } + ctx = ziti.NewContextWithConfig(cfg) + } else { + ctx = ziti.NewContext() + } + + conn, err := ctx.Dial(o.Args[0]) + if err != nil { + return err + } + defer func() { + if err = conn.Close(); err != nil { + logrus.WithError(err).Error("failed to close connection") + } + }() + + hops := uint32(o.hops) + if hops == 0 { + hops = math.MaxUint32 + } + currentHop := uint32(1) + if o.skipIntermediate { + currentHop = hops + } + + routerNameLookupsFailed := false + for currentHop <= hops { + result, err := conn.TraceRoute(currentHop, o.timeout) + if err != nil { + return err + } + + if result.Hops > 0 { + break + } + + hopLabel := result.HopId + if result.HopType == "forwarder" { + hopLabel, err = mapIdToName("transit-routers", result.HopId, o.edgeOptions) + if err != nil { + hopLabel = result.HopId + routerNameLookupsFailed = true + } + } + + if hopLabel == "" { + fmt.Printf("%2v %25v %6v \n", currentHop, result.HopType, result.Time) + } else { + fmt.Printf("%2v %25v %6v \n", currentHop, fmt.Sprintf("%v[%v]", result.HopType, hopLabel), result.Time) + } + + currentHop++ + } + + if routerNameLookupsFailed { + fmt.Println("Router name lookup failed. For this to work you must use ziti edge login first and be an administrator.") + } + return nil +}