Page MenuHomeFreeBSD

D32134.diff
No OneTemporary

D32134.diff

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1382,7 +1382,8 @@
enum pf_syncookies_mode {
PF_SYNCOOKIES_NEVER = 0,
PF_SYNCOOKIES_ALWAYS = 1,
- PF_SYNCOOKIES_MODE_MAX = PF_SYNCOOKIES_ALWAYS
+ PF_SYNCOOKIES_ADAPTIVE = 2,
+ PF_SYNCOOKIES_MODE_MAX = PF_SYNCOOKIES_ADAPTIVE
};
#ifdef _KERNEL
@@ -1402,6 +1403,8 @@
bool keep_counters;
enum pf_syncookies_mode syncookies_mode;
bool syncookies_active;
+ uint64_t syncookies_inflight[2];
+ uint32_t states_halfopen;
};
#endif
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -500,6 +500,15 @@
s->dst.state = newstate;
if (which == PF_PEER_DST)
return;
+ if (s->src.state == newstate)
+ return;
+ if (s->creatorid == V_pf_status.hostid &&
+ s->key[PF_SK_STACK] != NULL &&
+ s->key[PF_SK_STACK]->proto == IPPROTO_TCP &&
+ !(TCPS_HAVEESTABLISHED(s->src.state) ||
+ s->src.state == TCPS_CLOSED) &&
+ (TCPS_HAVEESTABLISHED(newstate) || newstate == TCPS_CLOSED))
+ atomic_add_32(&V_pf_status.states_halfopen, -1);
s->src.state = newstate;
}
@@ -1931,6 +1940,11 @@
s->timeout = PFTM_UNLINKED;
+ /* Ensure we remove it from the list of halfopen states, if needed. */
+ if (s->key[PF_SK_STACK] != NULL &&
+ s->key[PF_SK_STACK]->proto == IPPROTO_TCP)
+ pf_set_protostate(s, PF_PEER_BOTH, TCPS_CLOSED);
+
PF_HASHROW_UNLOCK(ih);
pf_detach_state(s);
@@ -4035,6 +4049,7 @@
pf_set_protostate(s, PF_PEER_SRC, TCPS_SYN_SENT);
pf_set_protostate(s, PF_PEER_DST, TCPS_CLOSED);
s->timeout = PFTM_TCP_FIRST_PACKET;
+ atomic_add_32(&V_pf_status.states_halfopen, 1);
break;
case IPPROTO_UDP:
pf_set_protostate(s, PF_PEER_SRC, PFUDPS_SINGLE);
diff --git a/sys/netpfil/pf/pf_syncookies.c b/sys/netpfil/pf/pf_syncookies.c
--- a/sys/netpfil/pf/pf_syncookies.c
+++ b/sys/netpfil/pf/pf_syncookies.c
@@ -106,6 +106,8 @@
struct callout keytimeout;
uint8_t oddeven;
uint8_t key[2][SIPHASH_KEY_LENGTH];
+ uint32_t hiwat; /* absolute; # of states */
+ uint32_t lowat;
};
VNET_DEFINE_STATIC(struct pf_syncookie_status, pf_syncookie_status);
#define V_pf_syncookie_status VNET(pf_syncookie_status)
@@ -242,7 +244,24 @@
if (pd->pf_mtag && (pd->pf_mtag->tag & PF_TAG_SYNCOOKIE_RECREATED))
return (0);
- return (V_pf_status.syncookies_mode);
+ if (V_pf_status.syncookies_mode != PF_SYNCOOKIES_ADAPTIVE)
+ return (V_pf_status.syncookies_mode);
+
+ if (!V_pf_status.syncookies_active &&
+ atomic_load_32(&V_pf_status.states_halfopen) >
+ V_pf_syncookie_status.hiwat) {
+ /* We'd want to 'pf_syncookie_newkey()' here, but that requires
+ * the rules write lock, which we can't get with the read lock
+ * held. */
+ callout_reset(&V_pf_syncookie_status.keytimeout, 0,
+ pf_syncookie_rotate, curvnet);
+ V_pf_status.syncookies_active = true;
+ DPFPRINTF(LOG_WARNING,
+ ("synflood detected, enabling syncookies\n"));
+ // XXXTODO V_pf_status.lcounters[LCNT_SYNFLOODS]++;
+ }
+
+ return (V_pf_status.syncookies_active);
}
void
@@ -257,6 +276,9 @@
iss, ntohl(pd->hdr.tcp.th_seq) + 1, TH_SYN|TH_ACK, 0, mss,
0, 1, 0);
counter_u64_add(V_pf_status.lcounters[KLCNT_SYNCOOKIES_SENT], 1);
+ /* XXX Maybe only in adaptive mode? */
+ atomic_add_64(&V_pf_status.syncookies_inflight[V_pf_syncookie_status.oddeven],
+ 1);
}
uint8_t
@@ -272,11 +294,17 @@
ack = ntohl(pd->hdr.tcp.th_ack) - 1;
cookie.cookie = (ack & 0xff) ^ (ack >> 24);
+ /* we don't know oddeven before setting the cookie (union) */
+ if (atomic_load_64(&V_pf_status.syncookies_inflight[cookie.flags.oddeven])
+ == 0)
+ return (0);
+
hash = pf_syncookie_mac(pd, cookie, seq);
if ((ack & ~0xff) != (hash & ~0xff))
return (0);
counter_u64_add(V_pf_status.lcounters[KLCNT_SYNCOOKIES_VALID], 1);
+ atomic_add_64(&V_pf_status.syncookies_inflight[cookie.flags.oddeven], -1);
return (1);
}
@@ -290,13 +318,22 @@
CURVNET_SET((struct vnet *)arg);
/* do we want to disable syncookies? */
- if (V_pf_status.syncookies_active) {
+ if (V_pf_status.syncookies_active &&
+ ((V_pf_status.syncookies_mode == PF_SYNCOOKIES_ADAPTIVE &&
+ (atomic_load_32(&V_pf_status.states_halfopen) +
+ atomic_load_64(&V_pf_status.syncookies_inflight[0]) +
+ atomic_load_64(&V_pf_status.syncookies_inflight[1])) <
+ V_pf_syncookie_status.lowat) ||
+ V_pf_status.syncookies_mode == PF_SYNCOOKIES_NEVER)
+ ) {
V_pf_status.syncookies_active = false;
- DPFPRINTF(PF_DEBUG_MISC, ("syncookies disabled"));
+ DPFPRINTF(PF_DEBUG_MISC, ("syncookies disabled\n"));
}
/* nothing in flight any more? delete keys and return */
- if (!V_pf_status.syncookies_active) {
+ if (!V_pf_status.syncookies_active &&
+ atomic_load_64(&V_pf_status.syncookies_inflight[0]) == 0 &&
+ atomic_load_64(&V_pf_status.syncookies_inflight[1]) == 0) {
memset(V_pf_syncookie_status.key[0], 0,
PF_SYNCOOKIE_SECRET_SIZE);
memset(V_pf_syncookie_status.key[1], 0,
@@ -305,8 +342,10 @@
return;
}
+ PF_RULES_WLOCK();
/* new key, including timeout */
pf_syncookie_newkey();
+ PF_RULES_WUNLOCK();
CURVNET_RESTORE();
}
@@ -316,11 +355,13 @@
{
PF_RULES_WASSERT();
+ MPASS(V_pf_syncookie_status.oddeven < 2);
V_pf_syncookie_status.oddeven = (V_pf_syncookie_status.oddeven + 1) & 0x1;
+ atomic_store_64(&V_pf_status.syncookies_inflight[V_pf_syncookie_status.oddeven], 0);
arc4random_buf(V_pf_syncookie_status.key[V_pf_syncookie_status.oddeven],
PF_SYNCOOKIE_SECRET_SIZE);
callout_reset(&V_pf_syncookie_status.keytimeout,
- PF_SYNCOOKIE_SECRET_LIFETIME, pf_syncookie_rotate, curvnet);
+ PF_SYNCOOKIE_SECRET_LIFETIME * hz, pf_syncookie_rotate, curvnet);
}
/*

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 10, 7:14 PM (7 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16582263
Default Alt Text
D32134.diff (5 KB)

Event Timeline