package config import ( "fmt" "net" ) // StaticNAT defines a one-to-one NAT mapping between an external and internal address. // All traffic to the external address is forwarded to the internal address and vice versa. // DNAT rules take precedence over static NAT rules. type StaticNAT struct { // External IP address. Must not be the primary address of the interface. // DNS names are not allowed. External string `yaml:"external"` // Interface that has the external address. Interface string `yaml:"interface"` // Internal IP address. DNS names are not allowed. Internal string `yaml:"internal"` // If true, NAT is effective from all hosts (not just those on the named interface). AllInterfaces bool `yaml:"all_interfaces,omitempty"` // If true, NAT is effective from the firewall system itself. Local bool `yaml:"local,omitempty"` Comment string `yaml:"comment,omitempty"` } func (c *Config) validateStaticNAT() error { for i, n := range c.StaticNAT { if n.External == "" { return fmt.Errorf("nat[%d]: external address required", i) } if net.ParseIP(n.External) == nil { return fmt.Errorf("nat[%d]: external must be an IP address, not a DNS name", i) } if n.Interface == "" { return fmt.Errorf("nat[%d]: interface required", i) } ifaceFound := false for _, iface := range c.Interfaces { if iface.Interface == n.Interface || iface.PhysicalName() == n.Interface { ifaceFound = true break } } if !ifaceFound { return fmt.Errorf("nat[%d]: interface %q not defined in interfaces", i, n.Interface) } if n.Internal == "" { return fmt.Errorf("nat[%d]: internal address required", i) } if net.ParseIP(n.Internal) == nil { return fmt.Errorf("nat[%d]: internal must be an IP address, not a DNS name", i) } } return nil }