Re: [External] : pf: route-to IPs, not interfaces

2021-01-28 Thread Alexandr Nedvedicky
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

2021-01-28 Thread Alexander Bluhm
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

2021-01-28 Thread David Gwynne
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);
 
-