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 },

Reply via email to