Re: Need stateless NAT
Adam Richards wrote: I need to be able to create *stateless* nat rules for at least 150,000 entries, potentially to grow to 1/2million entries. The reason has to do with being able to work in an asymetric routing environment -- stateless nat must be used because traffic might not egress at the same location it ingressed. In other words I want to do a unidirectional translation and then fahgettaboutit. [...] there are some unique requirements this network brings which make public IP consumption unworkable. [...] table-management operations -- perhaps 10's of operations per second on a table of 500,000 entries/mappings. (operations, like inserts or deletes) Maybe for resilliency, or for ISP cost reasons, you want to take advantage of asymetric routing, or nearest-exit routing, in a unified multi-site network? That is, routing where no Traffic Engineering priciples are used. Clearly stateful tracking inhibits nearest-exit routing by nature. (Side note: to ensure TCP connections are maintained in a stateless enviornment you'd obviously need to enforce 1:1 binat mappings). I'm seeing mixed messages from the above quotes. It's your project, but consider this a friendly thought-check :) You're looking at creating 1:1 mappings from internal IPs to 150-500k public IPs. You talk about a high rate of mapping changes, so clearly you're managing entries dynamically, which is just another way of keeping state. You mention NAT being an impediment to asymmetric routing, but NAT is unrelated to routing, so I can infer some possibilities here: * You want to distribute NAT by implementing it on or near each border. In order for anything bidirectional to function, the mappings must be consistent, so that implies synchronizing state between them. You consider pf's stateful behavior to be ill-suited to this use case, so you're investigating stateless options. * You are implementing routing on the same device that runs pf, and you believe pf's state-keeping will prevent asymmetric routing from taking place. Are either of these correct? If you are trying to do distributed NAT, I would ask if that is actually a design requirement. It may be easier to place NAT near the internal devices instead. In a dynamic environment, it may reduce complexity and failure modes simply by avoiding the synchronization needed for distributed mappings.
Re: match value question
¿anybody knows? -- Thanks, Jordi Espasa Clofent
Re: Need stateless NAT
On Tue, Apr 08, 2008 at 11:59:11PM -0700, Adam Richards wrote: Maybe a pf.conf knob that allows me to turn off stateful tracking for a particular nat on iface ... rule? Ah, you keep mentioning 'nat' and 'rdr', which confused me before, but I guess what you're actually talking about is called 'binat' in pf: binat A binat rule specifies a bidirectional mapping between an external IP netblock and an internal IP netblock. You're right, it should be relatively easy to give binat a 'no state' option... But not for a /18 of arbitrary mappings with a high rate of change. With the current translation code this would require a rule for every mapping, and every packet is going to require a linear search of this ruleset. Fixing this is going to require fairly major changes to how binat works. Are you willing to pay someone to make this happen? BTW: What kind of packet forwarding rate are you hoping to get with this solution? Much of pf's performance comes from the fact that packets matching state entries are not evaluated against the ruleset. -Ryan
Re: Need stateless NAT
On Wed, Apr 09, 2008 at 05:36:57PM +0900, Ryan McBride wrote: You're right, it should be relatively easy to give binat a 'no state' option... Try the attached diff, eg: binat on egress from 192.168.100.1 to any - 10.99.99.99 no state Index: sys/net/pf.c === RCS file: /cvs/src/sys/net/pf.c,v retrieving revision 1.567 diff -u -r1.567 pf.c --- sys/net/pf.c20 Feb 2008 23:40:13 - 1.567 +++ sys/net/pf.c9 Apr 2008 11:41:02 - @@ -3321,7 +3321,8 @@ return (PF_DROP); } - if (!state_icmp (r-keep_state || nr != NULL || + if (!state_icmp (r-keep_state || + (nr != NULL nr-keep_state) || (pd-flags PFDESC_TCP_NORM))) { /* create new state */ struct pf_state *s = NULL; Index: sbin/pfctl/parse.y === RCS file: /cvs/src/sbin/pfctl/parse.y,v retrieving revision 1.536 diff -u -r1.536 parse.y --- sbin/pfctl/parse.y 1 Feb 2008 06:58:45 - 1.536 +++ sbin/pfctl/parse.y 9 Apr 2008 11:41:02 - @@ -439,7 +439,7 @@ %type v.number number icmptype icmp6type uid gid %type v.number tos not yesno %type v.probability probability -%type v.i no dir af fragcache optimizer +%type v.i no dir af fragcache optimizer binatkeep %type v.i sourcetrack flush unaryop statelock %type v.b action nataction natpasslog scrubaction %type v.b flags flag blockspec @@ -3741,6 +3741,7 @@ memset(r, 0, sizeof(r)); r.action = $1.b1; + r.keep_state = 1; r.natpass = $1.b2; r.log = $1.w; r.logif = $1.w2; @@ -3889,8 +3890,12 @@ } ; +binatkeep : /* empty */ { $$ = 1; } + | NO STATE { $$ = 0; } + ; + binatrule : no BINAT natpasslog interface af proto FROM host TO ipspec tag - tagged rtable redirection + tagged rtable redirection binatkeep { struct pf_rule binat; struct pf_pooladdr *pa; @@ -3915,6 +3920,7 @@ binat.log = $3.b2; binat.logif = $3.w2; binat.af = $5; + binat.keep_state = $15; if (!binat.af $8 != NULL $8-af) binat.af = $8-af; if (!binat.af $10 != NULL $10-af) Index: sbin/pfctl/pfctl_parser.c === RCS file: /cvs/src/sbin/pfctl/pfctl_parser.c,v retrieving revision 1.235 diff -u -r1.235 pfctl_parser.c --- sbin/pfctl/pfctl_parser.c 15 Oct 2007 02:16:35 - 1.235 +++ sbin/pfctl/pfctl_parser.c 9 Apr 2008 11:41:02 - @@ -986,6 +986,8 @@ printf( - ); print_pool(r-rpool, r-rpool.proxy_port[0], r-rpool.proxy_port[1], r-af, r-action); + if (!r-keep_state r-action == PF_BINAT) + printf( no state); } }