Hi,

"route-to" is used with the interface used for the next hop.  But if
it is used with a source address track (sticky-address), it sometimes
output the packet to wrong interface.

Example:

  pass in quick inet proto tcp from any to 192.168.0.10 port 80 \
    keep state (sloppy) route-to <LB> source-hash hogehoge sticky-address

  # pfctl -Tshow -tLB
  127.0.0.1@lo0
  192.168.0.101@em0
  192.168.0.102@em0
  #

pf_test() => pf_route() uses r->route->kif as the output inteface.

If there is no active source address tracking record, r->route->kif is
properly set with the table entry at pfr_pool_get() (called from
pf_map_addr() <= pf_route() <= pf_route()).  But there is an active
source tracking record, pf_map_addr() returns without updating
r->route->kif.

    339 int
    340 pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
    341     struct pf_addr *naddr, struct pf_addr *init_addr, struct 
pf_src_node **sns,
    342     struct pf_pool *rpool, enum pf_sn_types type)
    343 {
    (snip)
    355         if (sns[type] == NULL && rpool->opts & PF_POOL_STICKYADDR &&
    356             (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE &&
    357             pf_map_addr_sticky(af, r, saddr, naddr, sns, rpool, type) 
== 0)
    358                 return (0);

Since pf_map_sticky() doesn't update the kif, kif used previous is
used mistakenly.

ok?

When source address tracking record is used for "route-to", the next
hop interface configured with "route-to" was not used.  Keep the
interface within the pf_src_node and use it when the record is used.

Index: sys/net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.1081
diff -u -p -r1.1081 pf.c
--- sys/net/pf.c        20 Mar 2019 20:07:28 -0000      1.1081
+++ sys/net/pf.c        1 Jul 2019 11:47:36 -0000
@@ -542,7 +542,7 @@ pf_src_connlimit(struct pf_state **state
 int
 pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
     enum pf_sn_types type, sa_family_t af, struct pf_addr *src,
-    struct pf_addr *raddr)
+    struct pf_addr *raddr, struct pfi_kif *kif)
 {
        struct pf_src_node      k;
 
@@ -586,6 +586,7 @@ pf_insert_src_node(struct pf_src_node **
                }
                (*sn)->creation = time_uptime;
                (*sn)->rule.ptr->src_nodes++;
+               (*sn)->kif = kif;
                pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
                pf_status.src_nodes++;
        } else {
@@ -3882,7 +3883,7 @@ pf_test_rule(struct pf_pdesc *pd, struct
 
                if (r->rule_flag & PFRULE_SRCTRACK &&
                    pf_insert_src_node(&ctx.sns[PF_SN_NONE], r, PF_SN_NONE,
-                   pd->af, pd->src, NULL) != 0) {
+                   pd->af, pd->src, NULL, NULL) != 0) {
                        REASON_SET(&ctx.reason, PFRES_SRCLIMIT);
                        goto cleanup;
                }
Index: sys/net/pf_lb.c
===================================================================
RCS file: /cvs/src/sys/net/pf_lb.c,v
retrieving revision 1.63
diff -u -p -r1.63 pf_lb.c
--- sys/net/pf_lb.c     10 Dec 2018 16:48:15 -0000      1.63
+++ sys/net/pf_lb.c     1 Jul 2019 11:47:36 -0000
@@ -329,6 +329,10 @@ pf_map_addr_sticky(sa_family_t af, struc
                pf_print_host(naddr, 0, af);
                addlog("\n");
        }
+
+       if (sns[type]->kif != NULL)
+               rpool->kif = sns[type]->kif;
+
        return (0);
 }
 
@@ -618,7 +622,8 @@ pf_map_addr(sa_family_t af, struct pf_ru
                        pf_remove_src_node(sns[type]);
                        sns[type] = NULL;
                }
-               if (pf_insert_src_node(&sns[type], r, type, af, saddr, naddr))
+               if (pf_insert_src_node(&sns[type], r, type, af, saddr, naddr,
+                   rpool->kif))
                        return (1);
        }
 
Index: sys/net/pfvar.h
===================================================================
RCS file: /cvs/src/sys/net/pfvar.h,v
retrieving revision 1.490
diff -u -p -r1.490 pfvar.h
--- sys/net/pfvar.h     18 Feb 2019 13:11:44 -0000      1.490
+++ sys/net/pfvar.h     1 Jul 2019 11:47:36 -0000
@@ -1712,7 +1712,7 @@ extern int                         pf_state_insert(struct 
pfi
 int                             pf_insert_src_node(struct pf_src_node **,
                                    struct pf_rule *, enum pf_sn_types,
                                    sa_family_t, struct pf_addr *,
-                                   struct pf_addr *);
+                                   struct pf_addr *, struct pfi_kif *);
 void                            pf_remove_src_node(struct pf_src_node *);
 struct pf_src_node             *pf_get_src_node(struct pf_state *,
                                    enum pf_sn_types);

Reply via email to