Re: [External] : pf: route-to IPs, not interfaces
Hello David, thanks for nice wrap up of the story... > > this change does the following: > > - stores the route info in the state instead of the pf rule > > this allows route-to to keep working when the ruleset changes, and > allows route-to info to be sent over pfsync. there's enough spare bits > in pfsync messages that the protocol doesnt break. > > the caveat is that route-to becomes tied to pass rules that create > state, like rdr-to and nat-to. > > - the argument to route-to etc is a destination ip address > > it's not limited to a next-hop address (thought a next-hop can be a > destination address). this allows for the failover and load balancing > referred to above. > > - deprecates the address@interface host syntax in pfctl > > because routing is done entirely by IPs, the interface is derived from > the route lookup, not pf. I think this requires a notion in changelog. > > this change does not affect some other stuff discussed in the thread: > > - it keeps the current semantic where when route-to changes which > interface the packet is travelling over, it runs pf_test again. > > that's a separate change for broader discussion. > OK sashan
Re: pf: route-to IPs, not interfaces
On Thu, Jan 28, 2021 at 10:54:30PM +1000, David Gwynne wrote: > this is the diff from the "pf route-to issues" thread, but on it's own. I think we should make progress and commit something. > the caveat is that route-to becomes tied to pass rules that create > state, like rdr-to and nat-to. Maybe we should mention that in the man page. But let's discuss that separately. > that's a separate change for broader discussion. Yes. No more topics on top of uncomitted diffs. > ok? OK bluhm@ > Index: sbin/pfctl/parse.y > === > RCS file: /cvs/src/sbin/pfctl/parse.y,v > retrieving revision 1.708 > diff -u -p -r1.708 parse.y > --- sbin/pfctl/parse.y12 Jan 2021 00:10:34 - 1.708 > +++ sbin/pfctl/parse.y28 Jan 2021 11:45:58 - > @@ -276,6 +276,7 @@ struct filter_opts { > struct redirspec nat; > struct redirspec rdr; > struct redirspec rroute; > + u_int8_t rt; > > /* scrub opts */ > int nodf; > @@ -284,15 +285,6 @@ struct filter_opts { > int randomid; > int max_mss; > > - /* route opts */ > - struct { > - struct node_host*host; > - u_int8_t rt; > - u_int8_t pool_opts; > - sa_family_t af; > - struct pf_poolhashkey *key; > - }route; > - > struct { > u_int32_t limit; > u_int32_t seconds; > @@ -372,7 +364,7 @@ void expand_label(char *, size_t, cons > struct node_port *, u_int8_t); > int expand_divertspec(struct pf_rule *, struct divertspec *); > int collapse_redirspec(struct pf_pool *, struct pf_rule *, > - struct redirspec *rs, u_int8_t); > + struct redirspec *rs, int); > int apply_redirspec(struct pf_pool *, struct pf_rule *, > struct redirspec *, int, struct node_port *); > void expand_rule(struct pf_rule *, int, struct node_if *, > @@ -518,7 +510,6 @@ int parseport(char *, struct range *r, i > %typeipspec xhost host dynaddr host_list > %typetable_host_list tablespec > %typeredir_host_list redirspec > -%typeroute_host route_host_list routespec > %type os xos os_list > %typeportspec port_list port_item > %type uids uid_list uid_item > @@ -975,7 +966,7 @@ anchorrule: ANCHOR anchorname dir quick > YYERROR; > } > > - if ($9.route.rt) { > + if ($9.rt) { > yyerror("cannot specify route handling " > "on anchors"); > YYERROR; > @@ -1843,37 +1834,13 @@ pfrule: action dir logquick interface > decide_address_family($7.src.host, &r.af); > decide_address_family($7.dst.host, &r.af); > > - if ($8.route.rt) { > - if (!r.direction) { > + if ($8.rt) { > + if ($8.rt != PF_DUPTO && !r.direction) { > yyerror("direction must be explicit " > "with rules that specify routing"); > YYERROR; > } > - r.rt = $8.route.rt; > - r.route.opts = $8.route.pool_opts; > - if ($8.route.key != NULL) > - memcpy(&r.route.key, $8.route.key, > - sizeof(struct pf_poolhashkey)); > - } > - if (r.rt) { > - decide_address_family($8.route.host, &r.af); > - if ((r.route.opts & PF_POOL_TYPEMASK) == > - PF_POOL_NONE && ($8.route.host->next != > NULL || > - $8.route.host->addr.type == PF_ADDR_TABLE || > - DYNIF_MULTIADDR($8.route.host->addr))) > - r.route.opts |= PF_POOL_ROUNDROBIN; > - if ($8.route.host->next != NULL) { > - if (!PF_POOL_DYNTYPE(r.route.opts)) { > - yyerror("address pool option " > - "not supported by type"); > - YYERROR; > -
pf: route-to IPs, not interfaces
this is the diff from the "pf route-to issues" thread, but on it's own. the summary of why i wanted to do this is: - route-to, reply-to, and dup-to do not work with pfsync this is because the information about where to route-to is stored in rules, and it is hard to have a ruleset synced 100% between firewalls. - i can make my boxes panic when i try to use it in certain situations yeah... - the configuration and syntax for route-to rules are confusing. the argument to route-to and co is an interace name with an optional ip address. there are several problems with this. one is that people tend to think about routing as sending packets to peers by their address, not by the interface they're reachable on. another is that we currently have no way to synchronise interface topology information between firewalls, so using an interface to say where packets go means we can't do failover of these states with pfsync. another is that a change in routing topology means a host may become reachable over a different interface. tying routing policy to interfaces gets in the way of failover and load balancing. this change does the following: - stores the route info in the state instead of the pf rule this allows route-to to keep working when the ruleset changes, and allows route-to info to be sent over pfsync. there's enough spare bits in pfsync messages that the protocol doesnt break. the caveat is that route-to becomes tied to pass rules that create state, like rdr-to and nat-to. - the argument to route-to etc is a destination ip address it's not limited to a next-hop address (thought a next-hop can be a destination address). this allows for the failover and load balancing referred to above. - deprecates the address@interface host syntax in pfctl because routing is done entirely by IPs, the interface is derived from the route lookup, not pf. this change does not affect some other stuff discussed in the thread: - it keeps the current semantic where when route-to changes which interface the packet is travelling over, it runs pf_test again. that's a separate change for broader discussion. id like to thank sashan@, bluhm@, and sthen@ for working through this stuff with me. i've got a lot out of it so far. ok? Index: sbin/pfctl/parse.y === RCS file: /cvs/src/sbin/pfctl/parse.y,v retrieving revision 1.708 diff -u -p -r1.708 parse.y --- sbin/pfctl/parse.y 12 Jan 2021 00:10:34 - 1.708 +++ sbin/pfctl/parse.y 28 Jan 2021 11:45:58 - @@ -276,6 +276,7 @@ struct filter_opts { struct redirspec nat; struct redirspec rdr; struct redirspec rroute; + u_int8_t rt; /* scrub opts */ int nodf; @@ -284,15 +285,6 @@ struct filter_opts { int randomid; int max_mss; - /* route opts */ - struct { - struct node_host*host; - u_int8_t rt; - u_int8_t pool_opts; - sa_family_t af; - struct pf_poolhashkey *key; - }route; - struct { u_int32_t limit; u_int32_t seconds; @@ -372,7 +364,7 @@ void expand_label(char *, size_t, cons struct node_port *, u_int8_t); int expand_divertspec(struct pf_rule *, struct divertspec *); int collapse_redirspec(struct pf_pool *, struct pf_rule *, - struct redirspec *rs, u_int8_t); + struct redirspec *rs, int); int apply_redirspec(struct pf_pool *, struct pf_rule *, struct redirspec *, int, struct node_port *); voidexpand_rule(struct pf_rule *, int, struct node_if *, @@ -518,7 +510,6 @@ int parseport(char *, struct range *r, i %type ipspec xhost host dynaddr host_list %type table_host_list tablespec %type redir_host_list redirspec -%type route_host route_host_list routespec %typeos xos os_list %type portspec port_list port_item %type uids uid_list uid_item @@ -975,7 +966,7 @@ anchorrule : ANCHOR anchorname dir quick YYERROR; } - if ($9.route.rt) { + if ($9.rt) { yyerror("cannot specify route handling " "on anchors"); YYERROR; @@ -1843,37 +1834,13 @@ pfrule : action dir logquick interface decide_address_family($7.src.host, &r.af); decide_address_family($7.dst.host, &r.af); -