Alex,
> Please correct me if I'm wrong. So for a product which implements IP
> services and uses IPF internally to secure itself, the only way to
> correctly deal with fragmented udp traffic is to have IPF set up with smth
> like "pass all proto udp with frags", which now will pass all frags no
> matter which order they arrive, but loosen security on udp level
> (technically, it means no udp security).
When the UDP server sends out reverse ordered packets, yes.
> Or, maybe there is a way to set up the following behaviour: pass all udp
> frags where offset > sizeof(udp header). For frags where offset=0 and
> size >= sizeof(udp header), run it through firewall rules to make a
> decision. This should give a better work-around for udp frags coming in
> wrong order, because all frags but first will sit in IP stack and not be
> reassembled and passed to application layer until first frag arrives, and
> first frag is contolled by firewall fules. I could not figure out by
> documentation if smth like this is possible.
For this, I can give you a patch to work with IPFilter 4.1.
It changes the "fragtail" flag to be "fragbody" and allows you to write
rules like this:
block in quick all with short
pass in proto udp all with frag-body
pass in proto udp from .. port ... to ... port ...
And that should work for you.
Darren
Index: fil.c
===================================================================
RCS file: /devel/CVS/IP-Filter/fil.c,v
retrieving revision 2.243.2.40
diff -c -r2.243.2.40 fil.c
*** fil.c 2004/11/10 22:59:19 2.243.2.40
--- fil.c 2004/11/12 22:09:57
***************
*** 632,639 ****
frag = fin->fin_dp;
fin->fin_off = frag->ip6f_offlg & IP6F_OFF_MASK;
fin->fin_off <<= 3;
! if (!(frag->ip6f_offlg & IP6F_MORE_FRAG))
! fin->fin_flx |= FI_FRAGTAIL;
fin->fin_dp = (char *)fin->fin_dp + sizeof(*frag);
fin->fin_dlen -= sizeof(*frag);
--- 632,639 ----
frag = fin->fin_dp;
fin->fin_off = frag->ip6f_offlg & IP6F_OFF_MASK;
fin->fin_off <<= 3;
! if (fin->fin_off != 0)
! fin->fin_flx |= FI_FRAGBODY;
fin->fin_dp = (char *)fin->fin_dp + sizeof(*frag);
fin->fin_dlen -= sizeof(*frag);
***************
*** 1228,1237 ****
off &= IP_MF|IP_OFFMASK;
if (off != 0) {
fi->fi_flx |= FI_FRAG;
- if ((off & IP_MF) == 0)
- fi->fi_flx |= FI_FRAGTAIL;
off &= IP_OFFMASK;
if (off != 0) {
off <<= 3;
if (off + fin->fin_dlen > 0xffff) {
fi->fi_flx |= FI_BAD;
--- 1228,1236 ----
off &= IP_MF|IP_OFFMASK;
if (off != 0) {
fi->fi_flx |= FI_FRAG;
off &= IP_OFFMASK;
if (off != 0) {
+ fin->fin_flx |= FI_FRAGBODY;
off <<= 3;
if (off + fin->fin_dlen > 0xffff) {
fi->fi_flx |= FI_BAD;
Index: ip_nat.c
===================================================================
RCS file: /devel/CVS/IP-Filter/ip_nat.c,v
retrieving revision 2.195.2.21
diff -c -r2.195.2.21 ip_nat.c
*** ip_nat.c 2004/11/05 23:15:25 2.195.2.21
--- ip_nat.c 2004/11/12 22:10:12
***************
*** 2568,2574 ****
ip_t *oip;
void *dp;
! if ((fin->fin_flx & (FI_SHORT|FI_FRAGTAIL)))
return NULL;
/*
* nat_icmperrorlookup() will return NULL for `defective' packets.
--- 2568,2574 ----
ip_t *oip;
void *dp;
! if ((fin->fin_flx & (FI_SHORT|FI_FRAGBODY)))
return NULL;
/*
* nat_icmperrorlookup() will return NULL for `defective' packets.
***************
*** 3422,3428 ****
ft = &np->in_tuc;
if (!(fin->fin_flx & FI_TCPUDP) ||
! (fin->fin_flx & (FI_SHORT|FI_FRAGTAIL))) {
if (ft->ftu_scmp || ft->ftu_dcmp)
return 0;
return 1;
--- 3422,3428 ----
ft = &np->in_tuc;
if (!(fin->fin_flx & FI_TCPUDP) ||
! (fin->fin_flx & (FI_SHORT|FI_FRAGBODY))) {
if (ft->ftu_scmp || ft->ftu_dcmp)
return 0;
return 1;
Index: ip_state.c
===================================================================
RCS file: /devel/CVS/IP-Filter/ip_state.c,v
retrieving revision 2.186.2.18
diff -c -r2.186.2.18 ip_state.c
*** ip_state.c 2004/11/05 23:15:23 2.186.2.18
--- ip_state.c 2004/11/12 22:10:16
***************
*** 795,801 ****
int out;
if (fr_state_lock ||
! (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGTAIL|FI_BAD)))
return NULL;
if ((fin->fin_flx & FI_OOW) && !(fin->fin_tcpf & TH_SYN))
--- 795,801 ----
int out;
if (fr_state_lock ||
! (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGBODY|FI_BAD)))
return NULL;
if ((fin->fin_flx & FI_OOW) && !(fin->fin_tcpf & TH_SYN))
***************
*** 2453,2459 ****
u_int pass;
if (fr_state_lock || (ips_list == NULL) ||
! (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGTAIL|FI_BAD)))
return NULL;
is = NULL;
--- 2453,2459 ----
u_int pass;
if (fr_state_lock || (ips_list == NULL) ||
! (fin->fin_flx & (FI_SHORT|FI_STATE|FI_FRAGBODY|FI_BAD)))
return NULL;
is = NULL;
Index: tools/ipf_y.y
===================================================================
RCS file: /devel/CVS/IP-Filter/tools/ipf_y.y,v
retrieving revision 1.69.2.20
diff -c -r1.69.2.20 ipf_y.y
*** ipf_y.y 2004/11/02 08:08:54 1.69.2.20
--- ipf_y.y 2004/11/12 22:13:09
***************
*** 118,124 ****
%token IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE
%token IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL
IPFY_FRAG
%token IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN
IPFY_NOICMPERR
! %token IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE
IPFY_SYNC
%token IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP
%token IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR
%token IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO
--- 118,125 ----
%token IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE
%token IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL
IPFY_FRAG
%token IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN
IPFY_NOICMPERR
! %token IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE
! %token IPFY_SYNC IPFY_FRAGBODY
%token IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP
%token IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR
%token IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO
***************
*** 1131,1136 ****
--- 1132,1138 ----
| IPFY_BADSRC { $$ = FI_BADSRC; }
| IPFY_LOWTTL { $$ = FI_LOWTTL; }
| IPFY_FRAG { $$ = FI_FRAG; }
+ | IPFY_FRAGBODY { $$ = FI_FRAGBODY; }
| IPFY_FRAGS { $$ = FI_FRAG; }
| IPFY_MBCAST { $$ = FI_MBCAST; }
| IPFY_MULTICAST { $$ = FI_MULTICAST; }
***************
*** 1402,1407 ****
--- 1404,1410 ----
{ "first", IPFY_FIRST },
{ "flags", IPFY_FLAGS },
{ "frag", IPFY_FRAG },
+ { "frag-body", IPFY_FRAGBODY },
{ "frags", IPFY_FRAGS },
{ "from", IPFY_FROM },
{ "ge", YY_CMP_GE },
***************
*** 1567,1572 ****
--- 1570,1576 ----
{ "dstopts", IPFY_IPV6OPT_DSTOPTS },
{ "esp", IPFY_ESP },
{ "frag", IPFY_FRAG },
+ { "frag-body", IPFY_FRAGBODY },
{ "hopopts", IPFY_IPV6OPT_HOPOPTS },
{ "ipv6", IPFY_IPV6OPT_IPV6 },
{ "none", IPFY_IPV6OPT_NONE },