From 5125f1fc310242f6f9d0a847ed7ec14ef08a5a0c Mon Sep 17 00:00:00 2001 From: Federico Paolinelli Date: Mon, 8 Feb 2021 12:10:54 +0100 Subject: [PATCH 1/2] Agnhost: make it possible to pass the addresses to listen on for udp The current udp implementation listens on any for tcp, udp and tcp. There are some cases where it makes sense to listen on specific addresses (especially udp, see https://github.com/kubernetes/kubernetes/issues/95565). This is because UDP is connectionless, and in order to conntrack to work, the application must ensure that the src of the reply is the same as the dest of the request. The easiest way to do that is to bind explicitly on an ip. Here we pass an optional parameter that contains a comma separated list of addresses. Signed-off-by: Federico Paolinelli --- test/images/agnhost/netexec/netexec.go | 54 ++++++++++++++++++++------ 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/test/images/agnhost/netexec/netexec.go b/test/images/agnhost/netexec/netexec.go index 564a3c79b3d..acf4a52aac9 100644 --- a/test/images/agnhost/netexec/netexec.go +++ b/test/images/agnhost/netexec/netexec.go @@ -37,19 +37,23 @@ import ( "github.com/spf13/cobra" utilnet "k8s.io/apimachinery/pkg/util/net" + "k8s.io/apimachinery/pkg/util/sets" ) var ( - httpPort = 8080 - udpPort = 8081 - sctpPort = -1 - shellPath = "/bin/sh" - serverReady = &atomicBool{0} - certFile = "" - privKeyFile = "" - httpOverride = "" + httpPort = 8080 + udpPort = 8081 + sctpPort = -1 + shellPath = "/bin/sh" + serverReady = &atomicBool{0} + certFile = "" + privKeyFile = "" + httpOverride = "" + udpListenAddresses = "" ) +const bindToAny = "" + // CmdNetexec is used by agnhost Cobra. var CmdNetexec = &cobra.Command{ Use: "netexec", @@ -123,6 +127,7 @@ func init() { CmdNetexec.Flags().IntVar(&udpPort, "udp-port", 8081, "UDP Listen Port") CmdNetexec.Flags().IntVar(&sctpPort, "sctp-port", -1, "SCTP Listen Port") CmdNetexec.Flags().StringVar(&httpOverride, "http-override", "", "Override the HTTP handler to always respond as if it were a GET with this path & params") + CmdNetexec.Flags().StringVar(&udpListenAddresses, "udp-listen-addresses", "", "A comma separated list of ip addresses the udp servers listen from") } // atomicBool uses load/store operations on an int32 to simulate an atomic boolean. @@ -162,7 +167,14 @@ func main(cmd *cobra.Command, args []string) { addRoutes(http.DefaultServeMux, exitCh) } - go startUDPServer(udpPort) + udpBindTo, err := parseAddresses(udpListenAddresses) + if err != nil { + log.Fatal(err) + } + + for _, address := range udpBindTo { + go startUDPServer(address, udpPort) + } if sctpPort != -1 { go startSCTPServer(sctpPort) } @@ -539,15 +551,15 @@ func redirectHandler(w http.ResponseWriter, r *http.Request) { } // udp server supports the hostName, echo and clientIP commands. -func startUDPServer(udpPort int) { - serverAddress, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", udpPort)) +func startUDPServer(address string, udpPort int) { + serverAddress, err := net.ResolveUDPAddr("udp", net.JoinHostPort(address, strconv.Itoa(udpPort))) assertNoError(err, fmt.Sprintf("failed to resolve UDP address for port %d", sctpPort)) serverConn, err := net.ListenUDP("udp", serverAddress) assertNoError(err, fmt.Sprintf("failed to create listener for UDP address %v", serverAddress)) defer serverConn.Close() buf := make([]byte, 2048) - log.Printf("Started UDP server on port %d", udpPort) + log.Printf("Started UDP server on port %s %d", address, udpPort) // Start responding to readiness probes. serverReady.set(true) defer func() { @@ -639,3 +651,21 @@ func assertNoError(err error, detail string) { log.Fatalf("Error occurred: %s:%v", detail, err) } } + +func parseAddresses(addresses string) ([]string, error) { + if addresses == "" { + return []string{bindToAny}, nil + } + // Using a set to remove duplicates + res := make([]string, 0) + split := strings.Split(addresses, ",") + for _, address := range split { + netAddr := net.ParseIP(address) + if netAddr == nil { + return nil, fmt.Errorf("parseAddress: invalid address %s", address) + } + res = append(res, address) + } + set := sets.NewString(res...) + return set.List(), nil +} From f6451c93b132236161a17eabd1584cf490848d6a Mon Sep 17 00:00:00 2001 From: Federico Paolinelli Date: Fri, 19 Feb 2021 10:23:40 +0100 Subject: [PATCH 2/2] Bump up agnhost version to 2.29 This is to consume the changes for binding the udp listeners of netexec to specific addresses. Signed-off-by: Federico Paolinelli --- build/dependencies.yaml | 2 +- test/images/agnhost/VERSION | 2 +- test/images/agnhost/agnhost.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/dependencies.yaml b/build/dependencies.yaml index 3376a658746..7e8d07e491a 100644 --- a/build/dependencies.yaml +++ b/build/dependencies.yaml @@ -18,7 +18,7 @@ dependencies: # agnhost: bump this one first - name: "agnhost" - version: "2.28" + version: "2.29" refPaths: - path: test/images/agnhost/VERSION match: \d.\d diff --git a/test/images/agnhost/VERSION b/test/images/agnhost/VERSION index 410158ac6db..072e651358f 100644 --- a/test/images/agnhost/VERSION +++ b/test/images/agnhost/VERSION @@ -1 +1 @@ -2.28 +2.29 diff --git a/test/images/agnhost/agnhost.go b/test/images/agnhost/agnhost.go index 436a5d78768..a02f398ac7d 100644 --- a/test/images/agnhost/agnhost.go +++ b/test/images/agnhost/agnhost.go @@ -51,7 +51,7 @@ import ( func main() { rootCmd := &cobra.Command{ Use: "app", - Version: "2.28", + Version: "2.29", } rootCmd.AddCommand(auditproxy.CmdAuditProxy)