diff options
author | andre <andre@FreeBSD.org> | 2004-04-23 14:28:38 +0000 |
---|---|---|
committer | andre <andre@FreeBSD.org> | 2004-04-23 14:28:38 +0000 |
commit | d4f49f008f33c4f8764a222f33a2c7469a2bed19 (patch) | |
tree | 409e5a1193422d7cff37e0eac1786413b8e0b686 /sys/netinet | |
parent | e8723e5528fcaf8fa35c8432a0f4aedfe76cb723 (diff) | |
download | FreeBSD-src-d4f49f008f33c4f8764a222f33a2c7469a2bed19.zip FreeBSD-src-d4f49f008f33c4f8764a222f33a2c7469a2bed19.tar.gz |
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
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_fw.h | 1 | ||||
-rw-r--r-- | sys/netinet/ip_fw2.c | 38 |
2 files changed, 32 insertions, 7 deletions
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index 8e3047d..7258b6c 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -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 */ diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index 7097b20..e440f01 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -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 @@ check_body: /* 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; |