Prevent denial of service using bogus fragmented IPv4 packets.
A attacker sending a lot of bogus fragmented packets to the target (with different IPv4 identification field - ip_id), may be able to put the target machine into mbuf starvation state. By setting a upper limit on the number of reassembly queues we prevent this situation. This upper limit is controlled by the new sysctl net.inet.ip.maxfragpackets which defaults to 200, as the IPv6 case, this should be sufficient for most systmes, but you might want to increase it if you have lots of TCP sessions. I'm working on making the default value dependent on nmbclusters. If you want old behaviour (no upper limit) set this sysctl to a negative value. If you don't want to accept any fragments (not recommended) set the sysctl to 0 (zero). Obtained from: NetBSD MFC after: 1 week
This commit is contained in:
parent
06740f7b41
commit
690a6055ff
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=77665
@ -125,6 +125,12 @@ SYSCTL_INT(_net_inet_ip, IPCTL_KEEPFAITH, keepfaith, CTLFLAG_RW,
|
||||
&ip_keepfaith, 0,
|
||||
"Enable packet capture for FAITH IPv4->IPv6 translater daemon");
|
||||
|
||||
static int ip_nfragpackets = 0;
|
||||
static int ip_maxfragpackets = 200;
|
||||
SYSCTL_INT(_net_inet_ip, OID_AUTO, maxfragpackets, CTLFLAG_RW,
|
||||
&ip_maxfragpackets, 0,
|
||||
"Maximum number of IPv4 fragment reassembly queue entries");
|
||||
|
||||
/*
|
||||
* XXX - Setting ip_checkinterface mostly implements the receive side of
|
||||
* the Strong ES model described in RFC 1122, but since the routing table
|
||||
@ -865,6 +871,15 @@ ip_reass(m, head, fp)
|
||||
* If first fragment to arrive, create a reassembly queue.
|
||||
*/
|
||||
if (fp == 0) {
|
||||
/*
|
||||
* Enforce upper bound on number of fragmented packets
|
||||
* for which we attempt reassembly;
|
||||
* If maxfrag is 0, never accept fragments.
|
||||
* If maxfrag is -1, accept all fragments without limitation.
|
||||
*/
|
||||
if ((ip_maxfragpackets >= 0) && (ip_nfragpackets >= ip_maxfragpackets))
|
||||
goto dropfrag;
|
||||
ip_nfragpackets++;
|
||||
if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)
|
||||
goto dropfrag;
|
||||
fp = mtod(t, struct ipq *);
|
||||
@ -1013,6 +1028,7 @@ ip_reass(m, head, fp)
|
||||
TAILQ_REMOVE(head, fp, ipq_list);
|
||||
nipq--;
|
||||
(void) m_free(dtom(fp));
|
||||
ip_nfragpackets--;
|
||||
m->m_len += (IP_VHL_HL(ip->ip_vhl) << 2);
|
||||
m->m_data -= (IP_VHL_HL(ip->ip_vhl) << 2);
|
||||
/* some debugging cruft by sklower, below, will go away soon */
|
||||
@ -1054,6 +1070,7 @@ ip_freef(fhp, fp)
|
||||
}
|
||||
TAILQ_REMOVE(fhp, fp, ipq_list);
|
||||
(void) m_free(dtom(fp));
|
||||
ip_nfragpackets--;
|
||||
nipq--;
|
||||
}
|
||||
|
||||
@ -1081,6 +1098,20 @@ ip_slowtimo()
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If we are over the maximum number of fragments
|
||||
* (due to the limit being lowered), drain off
|
||||
* enough to get down to the new limit.
|
||||
*/
|
||||
for (i = 0; i < IPREASS_NHASH; i++) {
|
||||
if (ip_maxfragpackets >= 0) {
|
||||
while (ip_nfragpackets > ip_maxfragpackets &&
|
||||
!TAILQ_EMPTY(&ipq[i])) {
|
||||
ipstat.ips_fragdropped++;
|
||||
ip_freef(&ipq[i], TAILQ_FIRST(&ipq[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
ipflow_slowtimo();
|
||||
splx(s);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user