Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance mDNS Functionality #733

Merged
merged 3 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions cmd/serf/command/agent/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ func (c *Command) readConfig() *Config {
"tag pair, specified as key=value")
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")
Expand Down Expand Up @@ -176,6 +179,24 @@ func (c *Command) readConfig() *Config {
return nil
}

if config.MDNS.Interface != "" {
DanStough marked this conversation as resolved.
Show resolved Hide resolved
if config.Discover == "" {
c.Ui.Error("mDNS interface specified without enabling mDNS discovery")
return nil
}

if _, err := net.InterfaceByName(config.MDNS.Interface); err != nil {
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'
if config.Role != "" {
c.Ui.Output("Deprecation warning: 'Role' has been replaced with 'Tags'")
Expand Down Expand Up @@ -432,10 +453,12 @@ func (c *Command) startAgent(config *Config, agent *Agent,
local := agent.Serf().Memberlist().LocalNode()

// Get the bind interface if any
iface, _ := config.NetworkInterface()
iface, _ := config.MDNSNetworkInterface()

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
Expand Down Expand Up @@ -734,7 +757,12 @@ Options:
-bind if the interface is known but not the address.
If both are provided, then Serf verifies that the
interface has the bind address that is provided. This
flag also sets the multicast device used for -discover.
flag also sets the multicast device used for -discover,
if mdns-iface is not specified.
-mdns-iface Network interface to use for mDNS. If not provided, the
-iface value is used.
badrabubker marked this conversation as resolved.
Show resolved Hide resolved
-mdns-disable-ipv4 Disable IPv4 for mDNS.
-mdns-disable-ipv6 Disable IPv6 for mDNS.
-advertise=0.0.0.0 Address to advertise to the other cluster members
-config-file=foo Path to a JSON file to read configuration from.
This can be specified multiple times.
Expand Down
35 changes: 34 additions & 1 deletion cmd/serf/command/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ func DefaultConfig() *Config {

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"`
DisableIPv4 bool `mapstructure:"disable_ipv4"`
DisableIPv6 bool `mapstructure:"disable_ipv6"`
}

// Config is the configuration that can be set for an Agent. Some of these
// configurations are exposed as command-line flags to `serf agent`, whereas
// many of the more advanced configurations can only be set by creating
Expand Down Expand Up @@ -154,10 +162,12 @@ type Config struct {
// allows Serf agents to join each other with zero configuration.
Discover string `mapstructure:"discover"`

MDNS MDNSConfig `mapstructure:"mdns"`

// Interface is used to provide a binding interface to use. It can be
// used instead of providing a bind address, as Serf will discover the
// address of the provided interface. It is also used to set the multicast
// device used with `-discover`.
// device used with `-discover`, if `mdns-iface` is not set
Interface string `mapstructure:"interface"`

// ReconnectIntervalRaw is the string reconnect interval time. This interval
Expand Down Expand Up @@ -292,6 +302,16 @@ func (c *Config) NetworkInterface() (*net.Interface, error) {
return net.InterfaceByName(c.Interface)
}

func (c *Config) MDNSNetworkInterface() (*net.Interface, error) {
if c.MDNS.Interface == "" && c.Interface == "" {
return nil, nil
} else if c.MDNS.Interface != "" {
return net.InterfaceByName(c.MDNS.Interface)
} else {
return net.InterfaceByName(c.Interface)
}
}

// DecodeConfig reads the configuration from the given reader in JSON
// format and decodes it into a proper Config structure.
func DecodeConfig(r io.Reader) (*Config, error) {
Expand Down Expand Up @@ -436,6 +456,19 @@ func MergeConfig(a, b *Config) *Config {
if b.Interface != "" {
result.Interface = b.Interface
}

if b.MDNS.Interface != "" {
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
}
Expand Down
43 changes: 25 additions & 18 deletions cmd/serf/command/agent/mdns.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(&params); err != nil {
m.logger.Printf("[ERR] agent.mdns: Failed to poll for new hosts: %v", err)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/hashicorp/go-msgpack/v2 v2.1.2
github.com/hashicorp/go-syslog v1.0.0
github.com/hashicorp/logutils v1.0.0
github.com/hashicorp/mdns v1.0.4
github.com/hashicorp/mdns v1.0.5
github.com/hashicorp/memberlist v0.5.1
github.com/mitchellh/cli v1.1.5
github.com/mitchellh/mapstructure v1.5.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iP
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.4 h1:sY0CMhFmjIPDMlTB+HfymFHCaYLhgifZ0QhjaYKD/UQ=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/mdns v1.0.5 h1:1M5hW1cunYeoXOqHwEb/GBDDHAFo0Yqb/uz/beC6LbE=
github.com/hashicorp/mdns v1.0.5/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.5.1 h1:mk5dRuzeDNis2bi6LLoQIXfMH7JQvAzt3mQD0vNZZUo=
github.com/hashicorp/memberlist v0.5.1/go.mod h1:zGDXV6AqbDTKTM6yxW0I4+JtFzZAJVoIPvss4hV8F24=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
Expand Down
Loading