diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index e985fa920c7c..e01ac72b1bfc 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -1,7 +1,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 9, 2004 +.Dd August 9, 2004 .Dt IPFW 8 .Os .Sh NAME @@ -1264,12 +1264,14 @@ the Cisco IOS command: .Pp This option can be used to make anti-spoofing rules to reject all packets with source addresses not from this interface. +See also the option +.Cm antispoof . .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 or a blackhole/reject route, the packet matches. -Otherwise the packet does not match. +Otherwise, the packet does not match. All outgoing packets match. .Pp The name and functionality of the option is intentionally similar to @@ -1279,6 +1281,23 @@ the Cisco IOS command: .Pp This option can be used to make anti-spoofing rules to reject all packets whose source address is unreachable. +.It Cm antispoof +For incoming packets, the packet's source address is checked if it +belongs to a directly connected network. +If the network is directly connected, then the interface the packet +came on in is compared to the interface the network is connected to. +When incoming interface and directly connected interface are not the +same, the packet does not match. +Otherwise, the packet does match. +All outgoing packets match. +.Pp +This option can be used to make anti-spoofing rules to reject all +packets that pretend to be from a directly connected network but do +not come in through that interface. +This option is similar to but more restricted than +.Cm verrevpath +because it engages only on packets with source addresses of directly +connected networks instead of all source addresses. .El .Sh LOOKUP TABLES Lookup tables are useful to handle large sparse address sets, @@ -2055,6 +2074,23 @@ system on the wrong interface. For example, a packet with a source address belonging to a host on a protected internal network would be dropped if it tried to enter the system from an external interface. +.Pp +The +.Cm antispoof +option could be used to do similar but more restricted anti-spoofing +by adding the following to the top of a ruleset: +.Pp +.Dl "ipfw add deny ip from any to any not antispoof in" +.Pp +This rule drops all incoming packets that appear to be coming from another +directly connected system but on the wrong interface. +For example, a packet with a source address of +.Li 192.168.0.0/24 +, configured on +.Li fxp0 +, but coming in on +.Li fxp1 +would be dropped. .Ss DYNAMIC RULES In order to protect a site from flood attacks involving fake TCP packets, it is safer to use dynamic rules: diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index cf45a508085a..1030e39aaec7 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -232,6 +232,7 @@ enum tokens { TOK_MACTYPE, TOK_VERREVPATH, TOK_VERSRCREACH, + TOK_ANTISPOOF, TOK_IPSEC, TOK_COMMENT, @@ -345,6 +346,7 @@ struct _s_x rule_options[] = { { "mac-type", TOK_MACTYPE }, { "verrevpath", TOK_VERREVPATH }, { "versrcreach", TOK_VERSRCREACH }, + { "antispoof", TOK_ANTISPOOF }, { "ipsec", TOK_IPSEC }, { "//", TOK_COMMENT }, @@ -1290,6 +1292,10 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth) printf(" versrcreach"); break; + case O_ANTISPOOF: + printf(" antispoof"); + break; + case O_IPSEC: printf(" ipsec"); break; @@ -1897,7 +1903,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 | versrcreach\n" +" verrevpath | versrcreach | antispoof\n" ); exit(0); } @@ -3439,6 +3445,10 @@ add(int ac, char *av[]) fill_cmd(cmd, O_VERSRCREACH, 0, 0); break; + case TOK_ANTISPOOF: + fill_cmd(cmd, O_ANTISPOOF, 0, 0); + break; + case TOK_IPSEC: fill_cmd(cmd, O_IPSEC, 0, 0); break; diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index d66335a07cb2..62e743d7da49 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -96,6 +96,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */ O_VERREVPATH, /* none */ O_VERSRCREACH, /* none */ + O_ANTISPOOF, /* none */ O_PROBE_STATE, /* none */ O_KEEP_STATE, /* none */ diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index de6abf336754..30e63092e914 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -2211,6 +2211,16 @@ ipfw_chk(struct ip_fw_args *args) verify_path(src_ip, NULL)); break; + case O_ANTISPOOF: + /* Outgoing packets automatically pass/match */ + if (oif == NULL && hlen > 0 && + in_localaddr(src_ip)) + match = verify_path(src_ip, + m->m_pkthdr.rcvif); + else + match = 1; + break; + case O_IPSEC: #ifdef FAST_IPSEC match = (m_tag_find(m, @@ -2844,6 +2854,7 @@ check_ipfw_struct(struct ip_fw *rule, int size) case O_ESTAB: case O_VERREVPATH: case O_VERSRCREACH: + case O_ANTISPOOF: case O_IPSEC: if (cmdlen != F_INSN_SIZE(ipfw_insn)) goto bad_size;