From 5f9541ecbd6d0c1a0c336ebad68cebed8aac76a7 Mon Sep 17 00:00:00 2001 From: Andre Oppermann Date: Mon, 9 Aug 2004 16:12:10 +0000 Subject: [PATCH] New ipfw option "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. Usage example: ipfw add deny ip from any to any not antispoof in Manpage education by: ru --- sbin/ipfw/ipfw.8 | 40 ++++++++++++++++++++++++++++++++++++++-- sbin/ipfw/ipfw2.c | 12 +++++++++++- sys/netinet/ip_fw.h | 1 + sys/netinet/ip_fw2.c | 11 +++++++++++ 4 files changed, 61 insertions(+), 3 deletions(-) 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;