From 0cb83312841ad779186cca0d5cbdb0ddb96f61d1 Mon Sep 17 00:00:00 2001 From: Christian Richter Date: Thu, 24 Oct 2024 09:13:03 +0200 Subject: [PATCH 1/3] avoid 0.0.0.0 & replace by outbound ip Signed-off-by: Christian Richter --- ocis-pkg/checks/checkgrpc.go | 13 +++++++++++-- ocis-pkg/checks/checkhttp.go | 14 ++++++++++++++ ocis-pkg/handlers/checker.go | 18 ++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/ocis-pkg/checks/checkgrpc.go b/ocis-pkg/checks/checkgrpc.go index 5690c67def..20007bf286 100644 --- a/ocis-pkg/checks/checkgrpc.go +++ b/ocis-pkg/checks/checkgrpc.go @@ -3,15 +3,24 @@ package checks import ( "context" "fmt" + "strings" - "google.golang.org/grpc/credentials/insecure" - + "github.com/owncloud/ocis/v2/ocis-pkg/handlers" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) // NewGRPCCheck checks the reachability of a grpc server. func NewGRPCCheck(address string) func(context.Context) error { return func(_ context.Context) error { + if strings.Contains(address, "0.0.0.0") { + outboundIp, err := handlers.GetOutBoundIP() + if err != nil { + return err + } + address = strings.Replace(address, "0.0.0.0", outboundIp, 1) + } + conn, err := grpc.NewClient(address, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return fmt.Errorf("could not connect to grpc server: %v", err) diff --git a/ocis-pkg/checks/checkhttp.go b/ocis-pkg/checks/checkhttp.go index 462749fb87..b0c1f5c45d 100644 --- a/ocis-pkg/checks/checkhttp.go +++ b/ocis-pkg/checks/checkhttp.go @@ -3,13 +3,27 @@ package checks import ( "context" "fmt" + "github.com/owncloud/ocis/v2/ocis-pkg/handlers" "net/http" + "strings" "time" ) // NewHTTPCheck checks the reachability of a http server. func NewHTTPCheck(url string) func(context.Context) error { return func(_ context.Context) error { + if strings.Contains(url, "0.0.0.0") { + outboundIp, err := handlers.GetOutBoundIP() + if err != nil { + return err + } + url = strings.Replace(url, "0.0.0.0", outboundIp, 1) + } + + if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { + url = "http://" + url + } + c := http.Client{ Timeout: 3 * time.Second, } diff --git a/ocis-pkg/handlers/checker.go b/ocis-pkg/handlers/checker.go index 48ee3b12b1..51215f5145 100644 --- a/ocis-pkg/handlers/checker.go +++ b/ocis-pkg/handlers/checker.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "maps" + "net" "net/http" "golang.org/x/sync/errgroup" @@ -113,3 +114,20 @@ func (h *CheckHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { h.conf.logger.Panic().Err(err).Msg("failed to write response") } } + +func GetOutBoundIP() (string, error) { + interfacesAddresses, err := net.InterfaceAddrs() + if err != nil { + return "", err + } + + for _, address := range interfacesAddresses { + if ipNet, ok := address.(*net.IPNet); ok && !ipNet.IP.IsLoopback() { + if ipNet.IP.To4() != nil { + return ipNet.IP.String(), nil + } + } + } + + return "", fmt.Errorf("no IP found") +} From 0dc9e99761475789d197f939c6f094cc97c23179 Mon Sep 17 00:00:00 2001 From: Christian Richter Date: Thu, 24 Oct 2024 09:56:45 +0200 Subject: [PATCH 2/3] tackle ipv6 wildcard binds Signed-off-by: Christian Richter --- ocis-pkg/checks/checkgrpc.go | 4 +++- ocis-pkg/checks/checkhttp.go | 4 +++- ocis-pkg/checks/checktcp.go | 12 ++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ocis-pkg/checks/checkgrpc.go b/ocis-pkg/checks/checkgrpc.go index 20007bf286..ebb22fb29d 100644 --- a/ocis-pkg/checks/checkgrpc.go +++ b/ocis-pkg/checks/checkgrpc.go @@ -13,12 +13,14 @@ import ( // NewGRPCCheck checks the reachability of a grpc server. func NewGRPCCheck(address string) func(context.Context) error { return func(_ context.Context) error { - if strings.Contains(address, "0.0.0.0") { + if strings.Contains(address, "0.0.0.0") || strings.Contains(address, "::") { outboundIp, err := handlers.GetOutBoundIP() if err != nil { return err } address = strings.Replace(address, "0.0.0.0", outboundIp, 1) + address = strings.Replace(address, "::", "["+outboundIp+"]", 1) + address = strings.Replace(address, "[::]", "["+outboundIp+"]", 1) } conn, err := grpc.NewClient(address, grpc.WithTransportCredentials(insecure.NewCredentials())) diff --git a/ocis-pkg/checks/checkhttp.go b/ocis-pkg/checks/checkhttp.go index b0c1f5c45d..1fab4e118b 100644 --- a/ocis-pkg/checks/checkhttp.go +++ b/ocis-pkg/checks/checkhttp.go @@ -12,12 +12,14 @@ import ( // NewHTTPCheck checks the reachability of a http server. func NewHTTPCheck(url string) func(context.Context) error { return func(_ context.Context) error { - if strings.Contains(url, "0.0.0.0") { + if strings.Contains(url, "0.0.0.0") || strings.Contains(url, "::") { outboundIp, err := handlers.GetOutBoundIP() if err != nil { return err } url = strings.Replace(url, "0.0.0.0", outboundIp, 1) + url = strings.Replace(url, "::", outboundIp, 1) + url = strings.Replace(url, "[::]", "["+outboundIp+"]", 1) } if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { diff --git a/ocis-pkg/checks/checktcp.go b/ocis-pkg/checks/checktcp.go index 475ff50e82..d89da356c3 100644 --- a/ocis-pkg/checks/checktcp.go +++ b/ocis-pkg/checks/checktcp.go @@ -2,13 +2,25 @@ package checks import ( "context" + "github.com/owncloud/ocis/v2/ocis-pkg/handlers" "net" + "strings" "time" ) // NewTCPCheck returns a check that connects to a given tcp endpoint. func NewTCPCheck(address string) func(context.Context) error { return func(_ context.Context) error { + if strings.Contains(address, "0.0.0.0") || strings.Contains(address, "::") { + outboundIp, err := handlers.GetOutBoundIP() + if err != nil { + return err + } + address = strings.Replace(address, "0.0.0.0", outboundIp, 1) + address = strings.Replace(address, "::", outboundIp, 1) + address = strings.Replace(address, "[::]", "["+outboundIp+"]", 1) + } + conn, err := net.DialTimeout("tcp", address, 3*time.Second) if err != nil { return err From fd262970b3e4fb950aa1800350760ebbd2c64cfe Mon Sep 17 00:00:00 2001 From: Christian Richter Date: Thu, 24 Oct 2024 10:45:59 +0200 Subject: [PATCH 3/3] simplify code Signed-off-by: Christian Richter --- ocis-pkg/checks/checkgrpc.go | 12 +++--------- ocis-pkg/checks/checkhttp.go | 14 +++++--------- ocis-pkg/checks/checktcp.go | 15 +++++---------- ocis-pkg/handlers/checker.go | 21 ++++++++++++++++++--- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/ocis-pkg/checks/checkgrpc.go b/ocis-pkg/checks/checkgrpc.go index ebb22fb29d..c10b53bbf8 100644 --- a/ocis-pkg/checks/checkgrpc.go +++ b/ocis-pkg/checks/checkgrpc.go @@ -3,7 +3,6 @@ package checks import ( "context" "fmt" - "strings" "github.com/owncloud/ocis/v2/ocis-pkg/handlers" "google.golang.org/grpc" @@ -13,14 +12,9 @@ import ( // NewGRPCCheck checks the reachability of a grpc server. func NewGRPCCheck(address string) func(context.Context) error { return func(_ context.Context) error { - if strings.Contains(address, "0.0.0.0") || strings.Contains(address, "::") { - outboundIp, err := handlers.GetOutBoundIP() - if err != nil { - return err - } - address = strings.Replace(address, "0.0.0.0", outboundIp, 1) - address = strings.Replace(address, "::", "["+outboundIp+"]", 1) - address = strings.Replace(address, "[::]", "["+outboundIp+"]", 1) + address, err := handlers.FailSaveAddress(address) + if err != nil { + return err } conn, err := grpc.NewClient(address, grpc.WithTransportCredentials(insecure.NewCredentials())) diff --git a/ocis-pkg/checks/checkhttp.go b/ocis-pkg/checks/checkhttp.go index 1fab4e118b..48502fe6ac 100644 --- a/ocis-pkg/checks/checkhttp.go +++ b/ocis-pkg/checks/checkhttp.go @@ -3,23 +3,19 @@ package checks import ( "context" "fmt" - "github.com/owncloud/ocis/v2/ocis-pkg/handlers" "net/http" "strings" "time" + + "github.com/owncloud/ocis/v2/ocis-pkg/handlers" ) // NewHTTPCheck checks the reachability of a http server. func NewHTTPCheck(url string) func(context.Context) error { return func(_ context.Context) error { - if strings.Contains(url, "0.0.0.0") || strings.Contains(url, "::") { - outboundIp, err := handlers.GetOutBoundIP() - if err != nil { - return err - } - url = strings.Replace(url, "0.0.0.0", outboundIp, 1) - url = strings.Replace(url, "::", outboundIp, 1) - url = strings.Replace(url, "[::]", "["+outboundIp+"]", 1) + url, err := handlers.FailSaveAddress(url) + if err != nil { + return err } if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { diff --git a/ocis-pkg/checks/checktcp.go b/ocis-pkg/checks/checktcp.go index d89da356c3..693ba255ce 100644 --- a/ocis-pkg/checks/checktcp.go +++ b/ocis-pkg/checks/checktcp.go @@ -2,23 +2,18 @@ package checks import ( "context" - "github.com/owncloud/ocis/v2/ocis-pkg/handlers" "net" - "strings" "time" + + "github.com/owncloud/ocis/v2/ocis-pkg/handlers" ) // NewTCPCheck returns a check that connects to a given tcp endpoint. func NewTCPCheck(address string) func(context.Context) error { return func(_ context.Context) error { - if strings.Contains(address, "0.0.0.0") || strings.Contains(address, "::") { - outboundIp, err := handlers.GetOutBoundIP() - if err != nil { - return err - } - address = strings.Replace(address, "0.0.0.0", outboundIp, 1) - address = strings.Replace(address, "::", outboundIp, 1) - address = strings.Replace(address, "[::]", "["+outboundIp+"]", 1) + address, err := handlers.FailSaveAddress(address) + if err != nil { + return err } conn, err := net.DialTimeout("tcp", address, 3*time.Second) diff --git a/ocis-pkg/handlers/checker.go b/ocis-pkg/handlers/checker.go index 51215f5145..0326c580dc 100644 --- a/ocis-pkg/handlers/checker.go +++ b/ocis-pkg/handlers/checker.go @@ -7,10 +7,10 @@ import ( "maps" "net" "net/http" - - "golang.org/x/sync/errgroup" + "strings" "github.com/owncloud/ocis/v2/ocis-pkg/log" + "golang.org/x/sync/errgroup" ) // check is a function that performs a check. @@ -115,7 +115,22 @@ func (h *CheckHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } -func GetOutBoundIP() (string, error) { +// FailSaveAddress replaces wildcard addresses with the outbound IP. +func FailSaveAddress(address string) (string, error) { + if strings.Contains(address, "0.0.0.0") || strings.Contains(address, "::") { + outboundIp, err := getOutBoundIP() + if err != nil { + return "", err + } + address = strings.Replace(address, "0.0.0.0", outboundIp, 1) + address = strings.Replace(address, "::", "["+outboundIp+"]", 1) + address = strings.Replace(address, "[::]", "["+outboundIp+"]", 1) + } + return address, nil +} + +// getOutBoundIP returns the outbound IP address. +func getOutBoundIP() (string, error) { interfacesAddresses, err := net.InterfaceAddrs() if err != nil { return "", err