Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109807101
D32134.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D32134.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D32134: pf: implement adaptive mode
Attached
Detach File
Event Timeline
Log In to Comment