pfsync and policy routing states patch
Hi All I'm testing this patch to permit synchronization of states that use route-to or reply-to for policy routing, this patch apply to OpenBSD v4.6 -stable, this is the problem: when pfsync send an state that uses route-to or reply-to option to the other machine, it only sends only current next-hop address in rt_addr member of pfsync_state struct, the peer gets the pfsync data and it will try to insert the state and bind it to ruleset, when the secondary machine gets active and a packet going to pass through pf will try to process pf_route if the state matches with a rule with route/reply option, but the interface information hadn't inserted into the state so the state will has st-rt_kif = NULL then the packet will be droped in pf_route function. To complete the route/reply option of one state and keep compatibility with pfsync_state structure, we can use the data space holding by pad member into pfsync_state_peer, it seems to not be used by other function, so we can free rename it, I rename it as ex_info (extra info), so we can use it to put the info to complete the state. The ex_info data is 6 bytes length so we can't put the st-rt_kif-pfik_name data here. We can put the relative position of the rt_kif into the route/reply pool, this manner we need only 2 bytes to send the integer that represents the relative position into the pool, this position will only tell us where the interface can be found, it no necesary be the exact pool, so when a peer receives the pfsync data it can bind it into the pool if the both ruleset have a checksum match. I made some tests and it is running fine, this patch can be ported to the -current version of cvs, but we need to make a little changes beacuse rpool member of pf_rule struct has a new name: route. The modified functions was: pfsync_state_export, pfsync_state_import and pfsync_in_upd, the pfsync_in_upd was inserted a new state with flags equal to zero, now it insert the new state with the pkt-flags, so if the ruleset checksum matches this state will be attached to the ruleset in pfsync_state_import function === RCS file: src/sys/net/RCS/if_pfsync.c,v retrieving revision 1.127 diff -u -r1.127 src/sys/net/if_pfsync.c --- src/sys/net/if_pfsync.c 2010/01/13 23:06:38 1.127 +++ src/sys/net/if_pfsync.c 2010/01/14 21:45:18 @@ -398,6 +398,9 @@ void pfsync_state_export(struct pfsync_state *sp, struct pf_state *st) { + struct pf_pooladdr *acur = NULL; + struct pf_rule *r = NULL; + int count = 0; bzero(sp, sizeof(struct pfsync_state)); /* copy from state key */ @@ -449,6 +452,20 @@ else sp-nat_rule = htonl(st-nat_rule.ptr-nr); + /* insert the rpool position reference for route-to states */ + if(st-rt_kif) { + if(sp-rule != htonl(-1) ntohl(sp-rule) pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount) + r = pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr_array[ntohl(sp-rule)]; + if(r != NULL) { + TAILQ_FOREACH(acur, r-rpool.list, entries) { + count++; + if(st-rt_kif == acur-kif) + break; + } + } + bcopy(count, sp-dst.ex_info, sizeof(count)); + } + pf_state_counter_hton(st-packets[0], sp-packets[0]); pf_state_counter_hton(st-packets[1], sp-packets[1]); pf_state_counter_hton(st-bytes[0], sp-bytes[0]); @@ -465,6 +482,9 @@ struct pfi_kif *kif; int pool_flags; int error; + struct pf_pooladdr *acur; + int count; + int i; if (sp-creatorid == 0 pf_status.debug = PF_DEBUG_MISC) { printf(pfsync_state_import: invalid creator id: @@ -563,6 +583,19 @@ st-nat_rule.ptr = NULL; st-anchor.ptr = NULL; st-rt_kif = NULL; + /* try to insert the route-to kif for this state */ + if(r != pf_default_rule r-rpool.cur) { + bcopy(sp-dst.ex_info, count, sizeof(count)); + i = 0; + TAILQ_FOREACH(acur, r-rpool.list, entries) { + i++; + if(i == count) { + st-rt_kif = acur-kif; + break; + } + } + } + st-pfsync_time = time_uptime; st-sync_state = PFSYNC_S_NONE; @@ -916,7 +949,7 @@ st = pf_find_state_byid(id_key); if (st == NULL) { /* insert the update */ - if (pfsync_state_import(sp, 0)) + if (pfsync_state_import(sp, pkt-flags)) pfsyncstats.pfsyncs_badstate++; continue; }
pfsync and policy routing states patch
Hi All I'm testing this patch to permit synchronization of states that use route-to or reply-to for policy routing, this patch apply to OpenBSD v4.6 -stable, this is the problem: when pfsync send an state that uses route-to or reply-to option to the other machine, it only sends only current next-hop address in rt_addr member of pfsync_state struct, the peer gets the pfsync data and it will try to insert the state and bind it to ruleset, when the secondary machine gets active and a packet going to pass through pf will try to process pf_route if the state matches with a rule with route/reply option, but the interface information hadn't inserted into the state so the state will has st-rt_kif = NULL then the packet will be droped in pf_route function. To complete the route/reply option of one state and keep compatibility with pfsync_state structure, we can use the data space holding by pad member into pfsync_state_peer, it seems to not be used by other function, so we can free rename, I rename it as ex_info (extra info), so we can use it to put the info to complete the state. The ex_info data is 6 bytes length so we can't put the st-rt_kif-pfik_name data here. We can put the relative position of the rt_kif into the route/reply pool, this manner we need only 2 bytes to send the integer that represents the relative position into the pool, so when a peer receives the pfsync data it can bind it into the pool if the both ruleset have a checksum match. I made some tests and it is running fine, this patch can be ported to the -current version of cvs, but we need to make a little changes beacuse rpool member of pf_rule struct has a new name: route. The modified functions was: pfsync_state_export, pfsync_state_import and pfsync_in_upd, the pfsync_in_upd was inserted a new state with flags equal to zero, now it insert the new state with the pkt-flags, so if the ruleset checksum matches this state will be attached to the ruleset in pfsync_state_import function === RCS file: src/sys/net/RCS/if_pfsync.c,v retrieving revision 1.127 diff -u -r1.127 src/sys/net/if_pfsync.c --- src/sys/net/if_pfsync.c 2010/01/13 23:06:38 1.127 +++ src/sys/net/if_pfsync.c 2010/01/14 21:45:18 @@ -398,6 +398,9 @@ void pfsync_state_export(struct pfsync_state *sp, struct pf_state *st) { + struct pf_pooladdr *acur = NULL; + struct pf_rule *r = NULL; + int count = 0; bzero(sp, sizeof(struct pfsync_state)); /* copy from state key */ @@ -449,6 +452,20 @@ else sp-nat_rule = htonl(st-nat_rule.ptr-nr); + /* insert the rpool position reference for route-to states */ + if(st-rt_kif) { + if(sp-rule != htonl(-1) ntohl(sp-rule) pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount) + r = pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr_array[ntohl(sp-rule)]; + if(r != NULL) { + TAILQ_FOREACH(acur, r-rpool.list, entries) { + count++; + if(st-rt_kif == acur-kif) + break; + } + } + bcopy(count, sp-dst.ex_info, sizeof(count)); + } + pf_state_counter_hton(st-packets[0], sp-packets[0]); pf_state_counter_hton(st-packets[1], sp-packets[1]); pf_state_counter_hton(st-bytes[0], sp-bytes[0]); @@ -465,6 +482,9 @@ struct pfi_kif *kif; int pool_flags; int error; + struct pf_pooladdr *acur; + int count; + int i; if (sp-creatorid == 0 pf_status.debug = PF_DEBUG_MISC) { printf(pfsync_state_import: invalid creator id: @@ -563,6 +583,19 @@ st-nat_rule.ptr = NULL; st-anchor.ptr = NULL; st-rt_kif = NULL; + /* try to insert the route-to kif for this state */ + if(r != pf_default_rule r-rpool.cur) { + bcopy(sp-dst.ex_info, count, sizeof(count)); + i = 0; + TAILQ_FOREACH(acur, r-rpool.list, entries) { + i++; + if(i == count) { + st-rt_kif = acur-kif; + break; + } + } + } + st-pfsync_time = time_uptime; st-sync_state = PFSYNC_S_NONE; @@ -916,7 +949,7 @@ st = pf_find_state_byid(id_key); if (st == NULL) { /* insert the update */ - if (pfsync_state_import(sp, 0)) + if (pfsync_state_import(sp, pkt-flags)) pfsyncstats.pfsyncs_badstate++; continue; } === RCS file: src/sys/net/RCS/pfvar.h,v retrieving revision 1.290 diff -u -r1.290
pfsync'ing route-to, reply-to rules states OpenBSD v4.6 -stable
Hi all, I'm working on a patch to make the rules route-to and reply-to to be synced between two firewalls in HA schema, pfsync breaks the route-to state when the state is imported. This patch will break the pfsync protocol, because the addition of char rt_ifname[IFNAMSIZ] in pfsync_state struct, for this reason other utilities that depends of pfvar.h must be recompiled, one of this application is pfctl that depends of pfsync_state_export to show the currents states: --- pfvar.h 2010/01/14 01:04:54 1.290 +++ pfvar.h 2010/01/14 01:08:05 @@ -841,6 +841,7 @@ struct pfsync_state_peer src; struct pfsync_state_peer dst; struct pf_addr rt_addr; + char rt_ifname[IFNAMSIZ]; u_int32_trule; u_int32_tanchor; u_int32_tnat_rule; --- if_pfsync.c 2010/01/13 23:06:38 1.127 +++ if_pfsync.c 2010/01/14 01:14:22 @@ -415,6 +415,9 @@ /* copy from state */ strlcpy(sp-ifname, st-kif-pfik_name, sizeof(sp-ifname)); bcopy(st-rt_addr, sp-rt_addr, sizeof(sp-rt_addr)); + /* if state has route-to option, export rt interface name too*/ + if(st-rt_kif) + strlcpy(sp-rt_ifname, st-rt_kif-pfik_name, sizeof(sp-rt_ifname)); sp-creation = htonl(time_second - st-creation); sp-expire = pf_state_expires(st); if (sp-expire = time_second) @@ -562,7 +565,12 @@ st-rule.ptr = r; st-nat_rule.ptr = NULL; st-anchor.ptr = NULL; - st-rt_kif = NULL; + /* if the state had mached with ruleset we can bind the + interface for route-to, reply-to rules */ + if(r != pf_default_rule r-rpool.cur) + st-rt_kif = pfi_kif_get(sp-rt_ifname); + else + st-rt_kif = NULL; st-pfsync_time = time_uptime; st-sync_state = PFSYNC_S_NONE; @@ -916,7 +924,7 @@ st = pf_find_state_byid(id_key); if (st == NULL) { /* insert the update */ - if (pfsync_state_import(sp, 0)) + if (pfsync_state_import(sp, pkt-flags)) pfsyncstats.pfsyncs_badstate++; continue; } I found that adding rt_ifname data to pfsync_state is the easiest way to complete the route-to states synchronization. I tested this patch and it seems to work well, the states are keeped on a failover or failback. I will test this (with the required changes) on the -current cvs version. - Romey