Just for the record, I'm running that pf_table patch for almost a month now 
without any negative impact on my load balancers.

pfsync/carp/relayd

It also solved my problem with relayd.

However I believe some care should also be taken on relayd part
- do not check statistics on disabled redirects
- make redirect respect disabled table

I did posted some patches on tech@, don't know if they are ok but I do also run 
them on my load balancers.
https://marc.info/?l=openbsd-tech&m=168859090917010&w=2
https://marc.info/?l=openbsd-tech&m=168899743827537&w=2

G

On 01/08/2023 02:50, Alexandr Nedvedicky wrote:
> Hello,
>
> the issue has been reported by Gianni Kapetanakis month ago [1]. It took
> several emails to figure out relayd(8) exists after hosts got disabled
> by 'relayctl host dis ...'
>
> The thing is that relayd(8) relies on pf(4) to create persistent
> tables (PFR_TFLAG_PERSIST) as relayd requests that:
>
>  47 void
>  48 init_tables(struct relayd *env)
>  49 {
>  ...
>  62         TAILQ_FOREACH(rdr, env->sc_rdrs, entry) {
>  63                 if (strlcpy(tables[i].pfrt_anchor, RELAYD_ANCHOR "/",
>  64                     sizeof(tables[i].pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
>  65                         goto toolong;
>  66                 if (strlcat(tables[i].pfrt_anchor, rdr->conf.name,
>  67                     sizeof(tables[i].pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
>  68                         goto toolong;
>  69                 if (strlcpy(tables[i].pfrt_name, rdr->conf.name,
>  70                     sizeof(tables[i].pfrt_name)) >=
>  71                     sizeof(tables[i].pfrt_name))
>  72                         goto toolong;
>  73                 tables[i].pfrt_flags |= PFR_TFLAG_PERSIST;
>  74                 i++;
>  75         }
>
> unfortunately it's not the case as further investigation revealed [2].
>
> the issue can be easily reproduced by pfctl(8) which also creates
> persistent tables on behalf of command line:
>
>     pfctl -t foo -T add ...
>
> command above always asks pf(4) to create persistent table, however
> pf(4) does not honor persistent flag when <foo> table exists already.
> One can verify that using commands as follows:
>
>     ## create 'referenced' table only (table exists but has no active flag)
>     # echo 'pass from in <foo> to any' |pfctl -f -
>     # pfctl -sT -vg
>     ----r-- foo
>     # create instance of table <foo> using command line:
>     # pfctl -t foo -T add 192.168.1.0/24
>     1/1 addresses added.
>     # pfctl -sT -vg
>     --a-r-- foo
>     ## create instance of table <bar>, note the table will get 'p' flag
>     # pfctl -t bar -T add 192.168.10.0/24
>     1 table created.
>     1/1 addresses added.
>     # pfctl -sT -vg
>     -pa---- bar
>     --a-r-- foo
>
> one-liner change to sys/net/pf_table.c fixes that it also works for Gianni
> Kapetanakis. I'm also adding tests to regress/sys/net/pf_table/Makefile
> to cover it.
>
> On system which runs current the test fails with error as follows:
>
>     pfctl -a regress/ttest -t instance -T add 192.168.1.0/24
>     1/1 addresses added.
>     pfctl -a regress/ttest -sT -vg | diff table-persist.out -
>     1c1
>     < -pa-r--       instance        regress/ttest
>     ---
>     > --a-r--       instance        regress/ttest
>     *** Error 1 in . (Makefile:96 'flags')
>     FAILED
>
> the failure is expected on system without patch. On system with
> patch applied all tests do pass.
>
> OK to commit?
>
> thanks and
> regards
> sashan
>
>
> [1] https://marc.info/?t=168811270400005&r=1&w=2
>
> [2] https://marc.info/?l=openbsd-bugs&m=168868165801905&w=2
>
> --------8<---------------8<---------------8<------------------8<--------
> diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c
> index 6f23a6f795d..c862c804f84 100644
> --- a/sys/net/pf_table.c
> +++ b/sys/net/pf_table.c
> @@ -1565,8 +1565,10 @@ pfr_add_tables(struct pfr_table *tbl, int size, int 
> *nadd, int flags)
>                       xadd++;
>               } else if (!(flags & PFR_FLAG_DUMMY) &&
>                   !(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
> -                     p->pfrkt_nflags = (p->pfrkt_flags &
> -                         ~PFR_TFLAG_USRMASK) | PFR_TFLAG_ACTIVE;
> +                     p->pfrkt_nflags =
> +                         (p->pfrkt_flags & ~PFR_TFLAG_USRMASK) |
> +                         (n->pfrkt_flags & PFR_TFLAG_USRMASK) |
> +                         PFR_TFLAG_ACTIVE;
>                       SLIST_INSERT_HEAD(&changeq, p, pfrkt_workq);
>               }
>       }
> diff --git a/regress/sys/net/pf_table/Makefile 
> b/regress/sys/net/pf_table/Makefile
> index a71f0190c73..8911e8a1d35 100644
> --- a/regress/sys/net/pf_table/Makefile
> +++ b/regress/sys/net/pf_table/Makefile
> @@ -1,15 +1,26 @@
>  #    $OpenBSD: Makefile,v 1.3 2017/07/07 23:15:27 bluhm Exp $
>  
> -REGRESS_TARGETS=     hit miss cleanup
> -CLEANFILES=          stamp-*
> +REGRESS_TARGETS=     hit miss cleanup flags
> +CLEANFILES=          stamp-* \
> +                     pf-reftab.conf          \
> +                     pf-instance.conf        \
> +                     table-ref.conf          \
> +                     table-pgone.out         \
> +                     table-persist.out       \
> +                     table-ref.out           \
> +                     table-refgone.out
> +
>  
>  stamp-setup:
> +     ${SUDO} pfctl -a regress/ttest -Fa
>       ${SUDO} pfctl -qt __regress_tbl -T add -f ${.CURDIR}/table.in
>       date >$@
>  
>  cleanup:
>       rm -f stamp-setup
>       ${SUDO} pfctl -qt __regress_tbl -T kill
> +     ${SUDO} pfctl -q -a regress/ttest -Fr
> +     ${SUDO} pfctl -q -a regress/ttest -qt instance -T kill
>  
>  hit: stamp-setup
>       for i in `cat ${.CURDIR}/table.hit`; do \
> @@ -27,6 +38,77 @@ miss: stamp-setup
>       done; \
>       exit 0
>  
> -.PHONY: hit miss
> +#
> +# tables <instance> and <reference> are both referenced by rule only
> +#
> +pf-instab.conf:
> +     @echo 'table <instance> { 192.168.1.0/24 }' > $@
> +     @echo 'pass in from <instance> to <reference>' >> $@
> +
> +#
> +# table <instance> is active and referred by rule, table <reference>
> +# is referenced only.
> +pf-reftab.conf:
> +     @echo 'pass in from <instance> to <reference>' > $@
> +
> +#
> +# check persistent flag (p) is gone from table <instance> after
> +# we load pf-instab.conf. Deals with case when persistent table <instance>
> +# exists before pf-instab.conf gets loaded.
> +#
> +table-pgone.out:
> +     @echo '--a-r--  instance        regress/ttest' > $@
> +     @echo '----r--  reference       regress/ttest' >> $@
> +
> +#
> +# verify table <instance> got persistent flag after we
> +# run 'pfctl -t instance -T add ...'
> +#
> +table-persist.out:
> +     @echo '-pa-r--  instance        regress/ttest' > $@
> +     @echo '----r--  reference       regress/ttest' >> $@
> +
> +#
> +# verify tables <instance> and <reference> are created on behalf of
> +# reference by rule after pf-reftab.conf got loaded.
> +#
> +table-ref.out:
> +     @echo '----r--  instance        regress/ttest' > $@
> +     @echo '----r--  reference       regress/ttest' >> $@
> +
> +#
> +# verify reference to <instance> table (persistent) is gone
> +# after rules got flushed
> +#
> +table-refgone.out:
> +     @echo '-pa----  instance        regress/ttest' > $@
> +
> +flags: pf-instab.conf pf-reftab.conf table-pgone.out table-persist.out \
> +    table-ref.out table-refgone.out
> +     @echo 'loading pf-reftab,conf (tables referenced by rules only)'
> +     @cat pf-reftab.conf
> +     ${SUDO} pfctl -a regress/ttest -f pf-reftab.conf
> +     @echo 'tables <reference> and <instance> should both have ----r--'
> +     ${SUDO} pfctl -a regress/ttest -sT -vg | diff table-ref.out -
> +     @echo 'creating <instance> table on command line, flags should be:'
> +     @cat table-persist.out
> +     ${SUDO} pfctl -a regress/ttest -t instance -T add 192.168.1.0/24
> +     ${SUDO} pfctl -a regress/ttest -sT -vg | diff table-persist.out -
> +     @echo 'flushing rules'
> +     ${SUDO} pfctl -a regress/ttest -Fr
> +     @echo 'table <reference> should be gone, table <instance> should stay'
> +     ${SUDO} pfctl -a regress/ttest -sT -vg | diff table-refgone.out -
> +     @echo 'loading pf-instab.conf'
> +     @cat pf-instab.conf
> +     ${SUDO} pfctl -a regress/ttest -f pf-instab.conf
> +     @echo 'table <instance> loses -p- flag:'
> +     @cat table-pgone.out
> +     ${SUDO} pfctl -a regress/ttest -sT -vg | diff table-pgone.out -
> +     @echo 'flusing rules, both tables should be gone'
> +     ${SUDO} pfctl -a regress/ttest -Fr
> +     @echo 'anchor regress/ttest must be gone'
> +     ${SUDO} pfctl -a regress/ttest -sr 2>&1 | grep 'pfctl: Anchor does not 
> exist'
> +
> +.PHONY: hit miss flags
>  
>  .include <bsd.regress.mk>
>
>
>

Reply via email to