Class: Mt::Wall::DSL::NatBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/mt/wall/dsl/nat_builder.rb

Overview

Block context for the ‘nat` verb inside a `device` block (Layer B — the box’s own NAT table). Opened by DeviceBuilder#nat. Each verb appends a Model::NatRule. IPv4-only for v1 (see Model::NatRule).

device "edge-1", host: "10.0.0.1" do
  nat do
    # srcnat: hide the LAN behind the WAN address
    masquerade out_interface: "ether1-wan"

    # dstnat: publish an internal service (port-forward)
    dst_nat protocol: :tcp, dst_port: 443,
            to_addresses: "10.0.0.5", to_ports: 8443,
            in_interface: "ether1-wan"
  end
end

CORE verbs only (v1): masquerade / dst_nat / src_nat — one rule each, taking native match keywords (protocol:, dst_port:, src_port:, in_interface:, out_interface:, src:, dst:, comment:) plus SPLIT translation targets (to_addresses:, to_ports:) where the action uses them. ‘src:` / `dst:` reference a Layer-A host/group by name; an unknown name is a fail-fast error at compile time. No `port_forward` helper and no combined “host:port” target string in v1 (YAGNI).

VALIDATION (fail-fast):

* SCOPING IS REQUIRED — a fully-unscoped NAT rule is dangerous and
  rejected: `masquerade` requires `out_interface:`; `dst_nat` requires
  `in_interface:` OR `dst:`. A rule lacking its required scope raises
  ConfigurationError.
* `dst_nat`/`src_nat` require `to_addresses`; `masquerade` must NOT
  carry translation targets;
* ports are 1..65535; addresses parse as IPv4 via IPAddr (an IPv6
  target is rejected in v1).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeNatBuilder

Returns a new instance of NatBuilder.



40
41
42
# File 'lib/mt/wall/dsl/nat_builder.rb', line 40

def initialize
  @rules = []
end

Instance Attribute Details

#rulesArray<Model::NatRule> (readonly)

The Model::NatRule list collected for this device.

Returns:



90
91
92
# File 'lib/mt/wall/dsl/nat_builder.rb', line 90

def rules
  @rules
end

Instance Method Details

#dst_nat(to_addresses:, to_ports: nil, **match) ⇒ void

This method returns an undefined value.

dstnat (port-forward): redirect matched traffic to an internal host. REQUIRES scoping — ‘in_interface:` OR `dst:` must be present (else ConfigurationError) so the rule does not hijack arbitrary traffic.

Parameters:

  • to_addresses (String, Array<String>)

    internal target address(es)

  • to_ports (Integer, Array, Range, nil) (defaults to: nil)

    internal target port(s)



65
66
67
68
69
70
71
72
73
74
# File 'lib/mt/wall/dsl/nat_builder.rb', line 65

def dst_nat(to_addresses:, to_ports: nil, **match)
  normalized, comment = build_match(match)
  unless normalized.key?(:in_interface) || normalized.key?(:dst)
    raise ConfigurationError, "dst_nat requires `in_interface:` or `dst:` scoping"
  end

  addresses = validated_targets(to_addresses, to_ports, verb: "dst_nat")
  @rules << Model::NatRule.new(chain: :dstnat, action: :dst_nat, match: normalized,
                               to_addresses: addresses, to_ports: to_ports, comment: comment)
end

#masquerade(out_interface:, **match) ⇒ void

This method returns an undefined value.

srcnat masquerade. Translation target is implicit (the out-interface address), so to_addresses/to_ports must be omitted. ‘out_interface:` is REQUIRED — an unscoped masquerade would NAT every egress path.

Parameters:

  • out_interface (String)

    the egress (e.g. WAN) interface



51
52
53
54
55
56
57
# File 'lib/mt/wall/dsl/nat_builder.rb', line 51

def masquerade(out_interface:, **match)
  normalized, comment = build_match(match)
  normalized[:out_interface] = Validators.validate_name!(out_interface, label: "out_interface")

  @rules << Model::NatRule.new(chain: :srcnat, action: :masquerade,
                               match: normalized, comment: comment)
end

#src_nat(to_addresses:, to_ports: nil, **match) ⇒ void

This method returns an undefined value.

srcnat to a specific source address (static NAT / one-to-one egress).

Parameters:

  • to_addresses (String, Array<String>)
  • to_ports (Integer, Array, Range, nil) (defaults to: nil)


80
81
82
83
84
85
86
# File 'lib/mt/wall/dsl/nat_builder.rb', line 80

def src_nat(to_addresses:, to_ports: nil, **match)
  normalized, comment = build_match(match)
  addresses = validated_targets(to_addresses, to_ports, verb: "src_nat")

  @rules << Model::NatRule.new(chain: :srcnat, action: :src_nat, match: normalized,
                               to_addresses: addresses, to_ports: to_ports, comment: comment)
end