From c746cb906517eba4ffa4dd27d3d154da2661d1ee Mon Sep 17 00:00:00 2001 From: Ricardo Pardini Date: Mon, 5 Aug 2024 18:25:06 +0200 Subject: [PATCH] detectPublicIPv4: try to detect ipv4's from interfaces with a default gateway first - adds github.com/vishvananda/netlink to get at the routing tables - if none found, old logic is kept (gets the first IPv4 from the first interface that has one) Signed-off-by: Ricardo Pardini --- cmd/smee/flag.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 4 +++- go.sum | 5 +++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/cmd/smee/flag.go b/cmd/smee/flag.go index fe95f5ff..db241762 100644 --- a/cmd/smee/flag.go +++ b/cmd/smee/flag.go @@ -11,8 +11,11 @@ import ( "text/tabwriter" "time" + "golang.org/x/sys/unix" + "github.com/peterbourgon/ff/v3" "github.com/peterbourgon/ff/v3/ffcli" + "github.com/vishvananda/netlink" ) // customUsageFunc is a custom UsageFunc used for all commands. @@ -172,6 +175,11 @@ func newCLI(cfg *config, fs *flag.FlagSet) *ffcli.Command { } func detectPublicIPv4() string { + ipDgw, err := autoDetectPublicIpv4WithDefaultGateway() + if err == nil { + return ipDgw.String() + } + ip, err := autoDetectPublicIPv4() if err != nil { return "" @@ -200,3 +208,41 @@ func autoDetectPublicIPv4() (net.IP, error) { return nil, errors.New("unable to auto-detect public IPv4") } + +// autoDetectPublicIpv4WithDefaultGateway finds the network interface with a default gateway +// and returns the first net.IP address of the first interface that has a default gateway. +func autoDetectPublicIpv4WithDefaultGateway() (net.IP, error) { + // Get the list of routes from netlink + routes, err := netlink.RouteList(nil, unix.AF_INET) + if err != nil { + return nil, fmt.Errorf("failed to list routes: %v", err) + } + + // Find the route with a default gateway (Dst == nil) + for _, route := range routes { + if route.Dst == nil && route.Gw != nil { + // Get the interface associated with this route + iface, err := net.InterfaceByIndex(route.LinkIndex) + if err != nil { + return nil, fmt.Errorf("failed to get interface by index: %v", err) + } + + // Get the addresses assigned to this interface + addrs, err := iface.Addrs() + if err != nil { + return nil, fmt.Errorf("failed to get addresses for interface %v: %v", iface.Name, err) + } + + // Return the first valid IP address found + for _, addr := range addrs { + if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { + if ipNet.IP.To4() != nil { + return ipNet.IP, nil + } + } + } + } + } + + return nil, fmt.Errorf("no default gateway found") +} diff --git a/go.mod b/go.mod index 9990c604..79cbd2a4 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/prometheus/client_golang v1.20.0 github.com/tinkerbell/ipxedust v0.0.0-20240726225714-c9bd1dd89cc3 github.com/tinkerbell/tink v0.10.0 + github.com/vishvananda/netlink v1.1.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 go.opentelemetry.io/otel v1.28.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 @@ -25,6 +26,7 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/net v0.28.0 golang.org/x/sync v0.8.0 + golang.org/x/sys v0.23.0 google.golang.org/grpc v1.65.0 k8s.io/apimachinery v0.31.0 k8s.io/client-go v0.30.3 @@ -80,6 +82,7 @@ require ( github.com/rs/zerolog v1.33.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect + github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect @@ -88,7 +91,6 @@ require ( golang.org/x/crypto v0.26.0 // indirect golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sys v0.23.0 // indirect golang.org/x/term v0.23.0 // indirect golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.5.0 // indirect diff --git a/go.sum b/go.sum index d7cd0750..f0c87913 100644 --- a/go.sum +++ b/go.sum @@ -174,6 +174,10 @@ github.com/tinkerbell/tink v0.10.0 h1:W34Psx6Yn5o0jILSgyjF8C7Cg6ivDcccUqJ6zG9zGz github.com/tinkerbell/tink v0.10.0/go.mod h1:Dc8PpbvrC8Kfhr8yGhUsWBN6Dq6opRIX655KDTxLUJY= github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg= github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= +github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -225,6 +229,7 @@ golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=