From 67197861d8d3bd83a6e35c4ffb721b099a91f283 Mon Sep 17 00:00:00 2001 From: Badreddin Aboubakr Date: Mon, 1 Jul 2024 18:33:50 +0200 Subject: [PATCH] feat(mdns): add option to disable either IPv4 or IPv6 stack allow the user to disable v4 or v6 if needed. This solves the issue when a user is using discover option but having only one IP stack --- cmd/serf/command/agent/command.go | 10 ++++++- cmd/serf/command/agent/config.go | 12 ++++++++- cmd/serf/command/agent/mdns.go | 43 ++++++++++++++++++------------- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/cmd/serf/command/agent/command.go b/cmd/serf/command/agent/command.go index 9579dbd1f..d35defe4d 100644 --- a/cmd/serf/command/agent/command.go +++ b/cmd/serf/command/agent/command.go @@ -89,6 +89,8 @@ func (c *Command) readConfig() *Config { cmdFlags.StringVar(&cmdConfig.Discover, "discover", "", "mDNS discovery name") cmdFlags.StringVar(&cmdConfig.Interface, "iface", "", "interface to bind to") cmdFlags.StringVar(&cmdConfig.MDNS.Interface, "mdns-iface", "", "interface to use for mDNS") + cmdFlags.BoolVar(&cmdConfig.MDNS.DisableIPv4, "mdns-disable-ipv4", false, "disable IPv4 for mDNS") + cmdFlags.BoolVar(&cmdConfig.MDNS.DisableIPv6, "mdns-disable-ipv6", false, "disable IPv6 for mDNS") cmdFlags.StringVar(&cmdConfig.TagsFile, "tags-file", "", "tag persistence file") cmdFlags.BoolVar(&cmdConfig.EnableSyslog, "syslog", false, "enable logging to syslog facility") @@ -182,6 +184,12 @@ func (c *Command) readConfig() *Config { c.Ui.Error(fmt.Sprintf("Invalid mDNS network interface: %s", err)) return nil } + + // Check for a valid mdns ip mode + if config.MDNS.DisableIPv4 && config.MDNS.DisableIPv6 { + c.Ui.Error("Invalid mDNS configuration: both IPv4 and IPv6 are disabled") + return nil + } } // Backward compatibility hack for 'Role' @@ -445,7 +453,7 @@ func (c *Command) startAgent(config *Config, agent *Agent, c.logger.Printf("[INFO] agent: Starting mDNS listener on interface %s", iface.Name) _, err := NewAgentMDNS(agent, logOutput, config.ReplayOnJoin, - config.NodeName, config.Discover, iface, local.Addr, int(local.Port)) + config.NodeName, config.Discover, iface, local.Addr, int(local.Port), config.MDNS) if err != nil { c.Ui.Error(fmt.Sprintf("Error starting mDNS listener: %s", err)) return nil diff --git a/cmd/serf/command/agent/config.go b/cmd/serf/command/agent/config.go index 25a12c2f9..4eacdadda 100644 --- a/cmd/serf/command/agent/config.go +++ b/cmd/serf/command/agent/config.go @@ -48,7 +48,9 @@ type dirEnts []os.FileInfo type MDNSConfig struct { // Interface is used to provide a binding interface to use for mDNS. // if not set, iface will be used. - Interface string `mapstructure:"interface"` + Interface string `mapstructure:"interface"` + DisableIPv4 bool `mapstructure:"disable_ipv4"` + DisableIPv6 bool `mapstructure:"disable_ipv6"` } // Config is the configuration that can be set for an Agent. Some of these @@ -459,6 +461,14 @@ func MergeConfig(a, b *Config) *Config { result.MDNS.Interface = b.MDNS.Interface } + if b.MDNS.DisableIPv4 == true { + result.MDNS.DisableIPv4 = true + } + + if b.MDNS.DisableIPv6 == true { + result.MDNS.DisableIPv6 = true + } + if b.ReconnectInterval != 0 { result.ReconnectInterval = b.ReconnectInterval } diff --git a/cmd/serf/command/agent/mdns.go b/cmd/serf/command/agent/mdns.go index 6ee6f5f4d..57407500f 100644 --- a/cmd/serf/command/agent/mdns.go +++ b/cmd/serf/command/agent/mdns.go @@ -21,18 +21,21 @@ const ( // AgentMDNS is used to advertise ourself using mDNS and to // attempt to join peers periodically using mDNS queries. type AgentMDNS struct { - agent *Agent - discover string - logger *log.Logger - seen map[string]struct{} - server *mdns.Server - replay bool - iface *net.Interface + agent *Agent + discover string + logger *log.Logger + seen map[string]struct{} + server *mdns.Server + replay bool + iface *net.Interface + ipModes []string + disableIPv4 bool + disableIPv6 bool } // NewAgentMDNS is used to create a new AgentMDNS func NewAgentMDNS(agent *Agent, logOutput io.Writer, replay bool, - node, discover string, iface *net.Interface, bind net.IP, port int) (*AgentMDNS, error) { + node, discover string, iface *net.Interface, bind net.IP, port int, MDNSConfig MDNSConfig) (*AgentMDNS, error) { // Create the service service, err := mdns.NewMDNSService( node, @@ -60,13 +63,15 @@ func NewAgentMDNS(agent *Agent, logOutput io.Writer, replay bool, // Initialize the AgentMDNS m := &AgentMDNS{ - agent: agent, - discover: discover, - logger: log.New(logOutput, "", log.LstdFlags), - seen: make(map[string]struct{}), - server: server, - replay: replay, - iface: iface, + agent: agent, + discover: discover, + logger: log.New(logOutput, "", log.LstdFlags), + seen: make(map[string]struct{}), + server: server, + replay: replay, + iface: iface, + disableIPv4: MDNSConfig.DisableIPv4, + disableIPv6: MDNSConfig.DisableIPv6, } // Start the background workers @@ -123,9 +128,11 @@ func (m *AgentMDNS) run() { // poll is invoked periodically to check for new hosts func (m *AgentMDNS) poll(hosts chan *mdns.ServiceEntry) { params := mdns.QueryParam{ - Service: mdnsName(m.discover), - Interface: m.iface, - Entries: hosts, + Service: mdnsName(m.discover), + Interface: m.iface, + Entries: hosts, + DisableIPv4: m.disableIPv4, + DisableIPv6: m.disableIPv6, } if err := mdns.Query(¶ms); err != nil { m.logger.Printf("[ERR] agent.mdns: Failed to poll for new hosts: %v", err)