Add the option versrcreach to verify that a valid route to the
source address of a packet exists in the routing table. The default route is ignored because it would match everything and render the check pointless. This option is very useful for routers with a complete view of the Internet (BGP) in the routing table to reject packets with spoofed or unrouteable source addresses. Example: ipfw add 1000 deny ip from any to any not versrcreach also known in Cisco-speak as: ip verify unicast source reachable-via any Reviewed by: luigi
This commit is contained in:
parent
b62dccc7e5
commit
22b5770b99
@ -1230,7 +1230,23 @@ the Cisco IOS command:
|
||||
.Pp
|
||||
.Dl ip verify unicast reverse-path
|
||||
.Pp
|
||||
This option can be used to make anti-spoofing rules.
|
||||
This option can be used to make anti-spoofing rules to reject all
|
||||
packets with source addresses not from this interface.
|
||||
.It Cm versrcreach
|
||||
For incoming packets,
|
||||
a routing table lookup is done on the packet's source address.
|
||||
If a route to the source address exists, but not the default route,
|
||||
the packet matches.
|
||||
Otherwise the packet does not match.
|
||||
All outgoing packets match.
|
||||
.Pp
|
||||
The name and functionality of the option is intentionally similar to
|
||||
the Cisco IOS command:
|
||||
.Pp
|
||||
.Dl ip verify unicast source reachable-via any
|
||||
.Pp
|
||||
This option can be used to make anti-spoofing rules to reject all
|
||||
packets whose source address is unreachable.
|
||||
.El
|
||||
.Sh SETS OF RULES
|
||||
Each rule belongs to one of 32 different
|
||||
|
@ -226,6 +226,7 @@ enum tokens {
|
||||
TOK_MAC,
|
||||
TOK_MACTYPE,
|
||||
TOK_VERREVPATH,
|
||||
TOK_VERSRCREACH,
|
||||
TOK_IPSEC,
|
||||
TOK_COMMENT,
|
||||
|
||||
@ -338,6 +339,7 @@ struct _s_x rule_options[] = {
|
||||
{ "mac", TOK_MAC },
|
||||
{ "mac-type", TOK_MACTYPE },
|
||||
{ "verrevpath", TOK_VERREVPATH },
|
||||
{ "versrcreach", TOK_VERSRCREACH },
|
||||
{ "ipsec", TOK_IPSEC },
|
||||
{ "//", TOK_COMMENT },
|
||||
|
||||
@ -1268,6 +1270,10 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
||||
printf(" verrevpath");
|
||||
break;
|
||||
|
||||
case O_VERSRCREACH:
|
||||
printf(" versrcreach");
|
||||
break;
|
||||
|
||||
case O_IPSEC:
|
||||
printf(" ipsec");
|
||||
break;
|
||||
@ -1874,7 +1880,7 @@ help(void)
|
||||
" ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
|
||||
" mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
|
||||
" setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
|
||||
" verrevpath\n"
|
||||
" verrevpath | versrcreach\n"
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
@ -3400,6 +3406,10 @@ add(int ac, char *av[])
|
||||
fill_cmd(cmd, O_VERREVPATH, 0, 0);
|
||||
break;
|
||||
|
||||
case TOK_VERSRCREACH:
|
||||
fill_cmd(cmd, O_VERSRCREACH, 0, 0);
|
||||
break;
|
||||
|
||||
case TOK_IPSEC:
|
||||
fill_cmd(cmd, O_IPSEC, 0, 0);
|
||||
break;
|
||||
|
@ -95,6 +95,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
|
||||
O_TCPOPTS, /* arg1 = 2*u8 bitmap */
|
||||
|
||||
O_VERREVPATH, /* none */
|
||||
O_VERSRCREACH, /* none */
|
||||
|
||||
O_PROBE_STATE, /* none */
|
||||
O_KEEP_STATE, /* none */
|
||||
|
@ -439,21 +439,27 @@ iface_match(struct ifnet *ifp, ipfw_insn_if *cmd)
|
||||
}
|
||||
|
||||
/*
|
||||
* The verify_path function checks if a route to the src exists and
|
||||
* if it is reachable via ifp (when provided).
|
||||
*
|
||||
* The 'verrevpath' option checks that the interface that an IP packet
|
||||
* arrives on is the same interface that traffic destined for the
|
||||
* packet's source address would be routed out of. This is a measure
|
||||
* to block forged packets. This is also commonly known as "anti-spoofing"
|
||||
* or Unicast Reverse Path Forwarding (Unicast RFP) in Cisco-ese. The
|
||||
* name of the knob is purposely reminisent of the Cisco IOS command,
|
||||
* packet's source address would be routed out of. The 'versrcreach'
|
||||
* option just checks that the source address is reachable via any route
|
||||
* (except default) in the routing table. These two are a measure to block
|
||||
* forged packets. This is also commonly known as "anti-spoofing" or Unicast
|
||||
* Reverse Path Forwarding (Unicast RFP) in Cisco-ese. The name of the knobs
|
||||
* is purposely reminiscent of the Cisco IOS command,
|
||||
*
|
||||
* ip verify unicast reverse-path
|
||||
* ip verify unicast source reachable-via any
|
||||
*
|
||||
* which implements the same functionality. But note that syntax is
|
||||
* misleading. The check may be performed on all IP packets whether unicast,
|
||||
* multicast, or broadcast.
|
||||
*/
|
||||
static int
|
||||
verify_rev_path(struct in_addr src, struct ifnet *ifp)
|
||||
verify_path(struct in_addr src, struct ifnet *ifp)
|
||||
{
|
||||
struct route ro;
|
||||
struct sockaddr_in *dst;
|
||||
@ -468,10 +474,21 @@ verify_rev_path(struct in_addr src, struct ifnet *ifp)
|
||||
|
||||
if (ro.ro_rt == NULL)
|
||||
return 0;
|
||||
if ((ifp == NULL) || (ro.ro_rt->rt_ifp->if_index != ifp->if_index)) {
|
||||
|
||||
/* if ifp is provided, check for equality with rtentry */
|
||||
if (ifp != NULL && ro.ro_rt->rt_ifp != ifp) {
|
||||
RTFREE(ro.ro_rt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if no ifp provided, check if rtentry is not default route */
|
||||
if (ifp == NULL &&
|
||||
satosin(rt_key(ro.ro_rt))->sin_addr.s_addr == INADDR_ANY) {
|
||||
RTFREE(ro.ro_rt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* found valid route */
|
||||
RTFREE(ro.ro_rt);
|
||||
return 1;
|
||||
}
|
||||
@ -1911,7 +1928,13 @@ ipfw_chk(struct ip_fw_args *args)
|
||||
/* Outgoing packets automatically pass/match */
|
||||
match = ((oif != NULL) ||
|
||||
(m->m_pkthdr.rcvif == NULL) ||
|
||||
verify_rev_path(src_ip, m->m_pkthdr.rcvif));
|
||||
verify_path(src_ip, m->m_pkthdr.rcvif));
|
||||
break;
|
||||
|
||||
case O_VERSRCREACH:
|
||||
/* Outgoing packets automatically pass/match */
|
||||
match = ((oif != NULL) ||
|
||||
verify_path(src_ip, NULL));
|
||||
break;
|
||||
|
||||
case O_IPSEC:
|
||||
@ -2546,6 +2569,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
|
||||
case O_TCPOPTS:
|
||||
case O_ESTAB:
|
||||
case O_VERREVPATH:
|
||||
case O_VERSRCREACH:
|
||||
case O_IPSEC:
|
||||
if (cmdlen != F_INSN_SIZE(ipfw_insn))
|
||||
goto bad_size;
|
||||
|
Loading…
Reference in New Issue
Block a user