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
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=128575
@ -1230,7 +1230,23 @@ the Cisco IOS command:
|
|||||||
.Pp
|
.Pp
|
||||||
.Dl ip verify unicast reverse-path
|
.Dl ip verify unicast reverse-path
|
||||||
.Pp
|
.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
|
.El
|
||||||
.Sh SETS OF RULES
|
.Sh SETS OF RULES
|
||||||
Each rule belongs to one of 32 different
|
Each rule belongs to one of 32 different
|
||||||
|
@ -226,6 +226,7 @@ enum tokens {
|
|||||||
TOK_MAC,
|
TOK_MAC,
|
||||||
TOK_MACTYPE,
|
TOK_MACTYPE,
|
||||||
TOK_VERREVPATH,
|
TOK_VERREVPATH,
|
||||||
|
TOK_VERSRCREACH,
|
||||||
TOK_IPSEC,
|
TOK_IPSEC,
|
||||||
TOK_COMMENT,
|
TOK_COMMENT,
|
||||||
|
|
||||||
@ -338,6 +339,7 @@ struct _s_x rule_options[] = {
|
|||||||
{ "mac", TOK_MAC },
|
{ "mac", TOK_MAC },
|
||||||
{ "mac-type", TOK_MACTYPE },
|
{ "mac-type", TOK_MACTYPE },
|
||||||
{ "verrevpath", TOK_VERREVPATH },
|
{ "verrevpath", TOK_VERREVPATH },
|
||||||
|
{ "versrcreach", TOK_VERSRCREACH },
|
||||||
{ "ipsec", TOK_IPSEC },
|
{ "ipsec", TOK_IPSEC },
|
||||||
{ "//", TOK_COMMENT },
|
{ "//", TOK_COMMENT },
|
||||||
|
|
||||||
@ -1268,6 +1270,10 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
|||||||
printf(" verrevpath");
|
printf(" verrevpath");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case O_VERSRCREACH:
|
||||||
|
printf(" versrcreach");
|
||||||
|
break;
|
||||||
|
|
||||||
case O_IPSEC:
|
case O_IPSEC:
|
||||||
printf(" ipsec");
|
printf(" ipsec");
|
||||||
break;
|
break;
|
||||||
@ -1874,7 +1880,7 @@ help(void)
|
|||||||
" ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
|
" ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
|
||||||
" mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
|
" mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
|
||||||
" setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
|
" setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
|
||||||
" verrevpath\n"
|
" verrevpath | versrcreach\n"
|
||||||
);
|
);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@ -3400,6 +3406,10 @@ add(int ac, char *av[])
|
|||||||
fill_cmd(cmd, O_VERREVPATH, 0, 0);
|
fill_cmd(cmd, O_VERREVPATH, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TOK_VERSRCREACH:
|
||||||
|
fill_cmd(cmd, O_VERSRCREACH, 0, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
case TOK_IPSEC:
|
case TOK_IPSEC:
|
||||||
fill_cmd(cmd, O_IPSEC, 0, 0);
|
fill_cmd(cmd, O_IPSEC, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
@ -95,6 +95,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
|
|||||||
O_TCPOPTS, /* arg1 = 2*u8 bitmap */
|
O_TCPOPTS, /* arg1 = 2*u8 bitmap */
|
||||||
|
|
||||||
O_VERREVPATH, /* none */
|
O_VERREVPATH, /* none */
|
||||||
|
O_VERSRCREACH, /* none */
|
||||||
|
|
||||||
O_PROBE_STATE, /* none */
|
O_PROBE_STATE, /* none */
|
||||||
O_KEEP_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
|
* The 'verrevpath' option checks that the interface that an IP packet
|
||||||
* arrives on is the same interface that traffic destined for the
|
* arrives on is the same interface that traffic destined for the
|
||||||
* packet's source address would be routed out of. This is a measure
|
* packet's source address would be routed out of. The 'versrcreach'
|
||||||
* to block forged packets. This is also commonly known as "anti-spoofing"
|
* option just checks that the source address is reachable via any route
|
||||||
* or Unicast Reverse Path Forwarding (Unicast RFP) in Cisco-ese. The
|
* (except default) in the routing table. These two are a measure to block
|
||||||
* name of the knob is purposely reminisent of the Cisco IOS command,
|
* 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 reverse-path
|
||||||
|
* ip verify unicast source reachable-via any
|
||||||
*
|
*
|
||||||
* which implements the same functionality. But note that syntax is
|
* which implements the same functionality. But note that syntax is
|
||||||
* misleading. The check may be performed on all IP packets whether unicast,
|
* misleading. The check may be performed on all IP packets whether unicast,
|
||||||
* multicast, or broadcast.
|
* multicast, or broadcast.
|
||||||
*/
|
*/
|
||||||
static int
|
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 route ro;
|
||||||
struct sockaddr_in *dst;
|
struct sockaddr_in *dst;
|
||||||
@ -468,10 +474,21 @@ verify_rev_path(struct in_addr src, struct ifnet *ifp)
|
|||||||
|
|
||||||
if (ro.ro_rt == NULL)
|
if (ro.ro_rt == NULL)
|
||||||
return 0;
|
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);
|
RTFREE(ro.ro_rt);
|
||||||
return 0;
|
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);
|
RTFREE(ro.ro_rt);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1911,7 +1928,13 @@ ipfw_chk(struct ip_fw_args *args)
|
|||||||
/* Outgoing packets automatically pass/match */
|
/* Outgoing packets automatically pass/match */
|
||||||
match = ((oif != NULL) ||
|
match = ((oif != NULL) ||
|
||||||
(m->m_pkthdr.rcvif == 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;
|
break;
|
||||||
|
|
||||||
case O_IPSEC:
|
case O_IPSEC:
|
||||||
@ -2546,6 +2569,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
|
|||||||
case O_TCPOPTS:
|
case O_TCPOPTS:
|
||||||
case O_ESTAB:
|
case O_ESTAB:
|
||||||
case O_VERREVPATH:
|
case O_VERREVPATH:
|
||||||
|
case O_VERSRCREACH:
|
||||||
case O_IPSEC:
|
case O_IPSEC:
|
||||||
if (cmdlen != F_INSN_SIZE(ipfw_insn))
|
if (cmdlen != F_INSN_SIZE(ipfw_insn))
|
||||||
goto bad_size;
|
goto bad_size;
|
||||||
|
Loading…
Reference in New Issue
Block a user