Firewall-tree - request for NAT API naming advice/preference

Hello everyone,

I am currently writing a tree-based firewall library and close to wrapping up the core parts. I would like to ask for preference of naming conventions for NAT from potential users as I am working on the NAT module now.

If you spot any missing NAT types in the list, please do correct me as well so I don’t miss them in the implementation.

I mentioned the library briefly in another thread, you can see the development progress at the repo.


The issue I have stems from the myriad names a type of NAT may have across different vendors (Cisco, Juniper, Linux, etc), and even a “type” of NAT is not very concretely defined in some instances.

Currently I have identified the following major types of NAT

  • Static one source IP to one source IP mapping
    • Aliases
      • Source NAT
      • Static NAT
  • Static one destination IP to one destination IP mapping
    • Aliases
      • Destination NAT
  • Static one destination IP+port to one destination IP+port mapping
    • Aliases
      • Destination NAT
      • Port forwarding
  • Dynamic source IP pool to source IP pool mapping
    • Pools may or may not be of the same size
    • Aliases
      • Source NAT
  • Dynamic destination IP pool to destination IP pool mapping
    • Pools may or may not be of the same size
    • Aliases
      • Destination NAT
      • Dynamic NAT
      • Load balancing
  • Dynamic source IP pool to one source IP mapping
    • Aliases
      • Masquerading (iptables)
      • Overloading NAT
      • Dynamic NAT with Port Address Translation (PAT) overloading

Naming convention of library

A NAT unit would be represented as a node in the firewall tree. The API providing NAT functionality would give you a function to create a NAT node.

Using one source IP to one source IP as an example, this may look like

val make_ipv4_nat_static_single_src_to_single_src :
 (ipv4_addr * ipv4_addr) list -> selecting_modifier

where selecting_modifier is one of the basic node variant in the library.


For each type of the NAT, is there a preferred way/direction that you’d like them to be named?

Directions may be like

  • Lean closer to a given vendor’s terminology
  • Lean closer to the nature of mapping (static one to one, dynamic many to many, dynamic many to one)
  • Lean closer to colloquial terminology (e.g. prefer port forwarding over DNAT)

Thanks for your time,

If the firewall rules were written in OCaml, one could solve this with one or two constructors, which received a callback which made the choice, so I understand the reason to enumerate the various translations may be that it should be possible to load firewall rules from some data source?

I think one additional question to ask in the dynamic cases is what kind of algorithm will be used to decide the result, e.g.:

  • round robin or random choice for load balancing
  • destination based on the hash of the source for load balancing when the same clients use the same server
  • a stateful allocation scheme, e.g. to map source connections to source ports for masquerading
  • a deterministic mapping from address/port range to address/port range

Though this may be implied by the case-by-case analysis, as it allows for a different algorithm in each case.

1 Like

You should probably review the relevant Best Current Practice documents in the IETF Request For Comments (RFC) series, e.g. RFC 7857 and its predecessors. See especially the Terminology section, for starters, but all the various documents introduce additional relevant terms and definitions in the normative text.


That’s partially the reason, yes. Ideally the library can emulate behaviour of either iptables and pf.

The text of yours about underlying algorithm used is a really good point which I didn’t consider, thanks! This reminds me maybe usage of (first class) module to package the algorithms used would be worth exploring later on.

I just wanted to second this as an excellent aspect to consider when designing the library. Having the algorithms and decision mechanisms implemented separately, and then combined to form the specific NAT would be useful. I could imagine having a very different NAT strategy for a home network vs a locked down enterprise network (or indeed, why aren’t our home networks locked down?).

One fun example of dynamic selection might be to use Irmin to do port allocations based on the application state that is requesting the NAT mapping. I wonder if you could combine some aspects of HTTP2 multiplexing with smart IP port reuse across multiple requests.

1 Like

Sorry I’m a bit confused, could you elaborate on what you mean by application state?

I feel like I’ve missed something but I’ll ask anyway - doesn’t HTTP2 multiplexing use the same TCP connection for multiple requests? In that case there would not be need for a different port allocation strategy?