From patchwork Fri Jan 6 14:38:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2979 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7300:c95:b0:82:e4b3:40a0 with SMTP id p21csp1046138dyk; Fri, 6 Jan 2023 06:39:49 -0800 (PST) X-Google-Smtp-Source: AMrXdXsoRsI+IDHcgmiZrnMutH7QXu9o6XCjdp4OWbPoBLFC1CmCUIGV4zimtoWYsttlkcr0WkcH X-Received: by 2002:a62:1687:0:b0:57a:7b74:4ec5 with SMTP id 129-20020a621687000000b0057a7b744ec5mr58489347pfw.13.1673015988762; Fri, 06 Jan 2023 06:39:48 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1673015988; cv=none; d=google.com; s=arc-20160816; b=Mu3Z6zi8LybpZ/bieJyos9swWqgtQQwtHwD6hi8ZXHJD460M4eBoyJPf/6jaPWNiFc NZvNCXgCuuP3GjL89TaPD4aEo8B7glN9Pl3PHGauE/KhcEhhsmWogdLibowqxkw45vwm on6qgNFBq5F508q+2yRLumW0ITfDDGsMvVMDfxbZuAlHDzb29mYUnrxfep8BPefQ6vhP sUrFLadM+7NxrILKgNS1K8eHWV4EuNxgXpoB3Qfitc5hEOc8yFqWzWP7TBdzNg6nbRQX ISTcDel8wgUA5XxnD+ds4ZkhDilzPtBrsh7IN19efTWBRpCtXb8dZAiLhcyohT+qGtct JnoQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature; bh=L+IfDIjaoYdVE8HUJC1+2VPCE5HvlqLuJaPWC/5CoSo=; b=bf6xF0+leaiZ8ME0Du9f2I+S9Vmu/uG86M3jnygVOd0qzklcmpQPa4FzAge3y3rVVf GloFw4O+Qhx2LHVqlS0ey/b9EM9yT4SzHZNtBeh3FOe3wKQt1dTr/e1IjZQokYM8Qm2Z n10qPo8kWgptOQg1zffwF3u67j7kRZtmRkIWdnB9V87+/E+Tgr4dPi3yQwvRQc5iyCfE j+L1TmKyp0hqL1Ddagk8zXg2IACqfghuyC41nISi7WmhsTNm+2CZo49O0G8Bn0pSsmqs Dn/pdeKe3s/up4WRxxYwWJHjgPBA6E9XC7BqF1Rvbk1XOWQfMfbpGb+wgEgbsxvF3UG5 H2yA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="Ye43/nWr"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=ZzTAv84v; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id w8-20020a63f508000000b004a2d9640cd1si1672780pgh.168.2023.01.06.06.39.48 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 06 Jan 2023 06:39:48 -0800 (PST) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="Ye43/nWr"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=ZzTAv84v; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1pDnry-0007H1-T3; Fri, 06 Jan 2023 14:38:54 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1pDnrx-0007Gu-Ii for openvpn-devel@lists.sourceforge.net; Fri, 06 Jan 2023 14:38:53 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=YIU8XKd22+6zaYsEkCAiPBsoiuXpFwRxe0ZBkmORDfw=; b=Ye43/nWrXi9aEuWQ0K/EUDG6Sm AEooMz85ESiDbv6jprGPCOO3wVTKhwpIE9sqy9V7Mnv5juU7cS89kcaol6LapeIvUHLHeAWq9OMgZ ONB7PPJSLWMeP+M18hmbfHnfyXZvQsOebLz3bQ0N3jaw2AxJ8e6QB6+sh0PHRvreigzg=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=YIU8XKd22+6zaYsEkCAiPBsoiuXpFwRxe0ZBkmORDfw=; b=ZzTAv84vUocziYM+UGLO5JygLr FwNO/lbxKgcHF+3HodV2MRloQtFVChI8FBqeBa3zvruu2/UNJB0/bISIZop9cmnAPLP8pUC0RpUlU qoRLDoJo9hR1HRu078iVza5NH8kr3HKTGCYmPw6oMfKSgCQGtM/vmX/gE+8TgavAE2P8=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1pDnrs-007PvS-PQ for openvpn-devel@lists.sourceforge.net; Fri, 06 Jan 2023 14:38:53 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.95 (FreeBSD)) (envelope-from ) id 1pDnrl-0007MH-FE for openvpn-devel@lists.sourceforge.net; Fri, 06 Jan 2023 15:38:41 +0100 Received: (nullmailer pid 506550 invoked by uid 10006); Fri, 06 Jan 2023 14:38:41 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Fri, 6 Jan 2023 15:38:41 +0100 Message-Id: <20230106143841.506504-1-arne@rfc2549.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230105175614.405385-1-arne@rfc2549.org> References: <20230105175614.405385-1-arne@rfc2549.org> MIME-Version: 1.0 X-Spam-Score: 0.3 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-2.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: This limits the nubmer of packets OpenVPN will respond to. This avoid OpenVPN server being abused for refelection attacks in a large scale as we gotten a lot more efficient with the cookie approach in [...] Content analysis details: (0.3 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-Headers-End: 1pDnrs-007PvS-PQ Subject: [Openvpn-devel] [PATCH v2] Add connect-freq-initial option to limit initial connection responses X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1754206226475479846?= X-GMAIL-MSGID: =?utf-8?q?1754284413835141329?= This limits the nubmer of packets OpenVPN will respond to. This avoid OpenVPN server being abused for refelection attacks in a large scale as we gotten a lot more efficient with the cookie approach in our initial connection approach. The defaults of 100 attempts per 10s should work for most people, esepcially since completed three way handshakes are not counted. So the default will throttle connection attempts on server with high packet loss or that are actually under a DOS. The 100 per 10s are similar in size to the old 2.5 and earlier behaviour where every initial connection attempt would take up a slot of the max-clients sessions and those would only expire after the TLS timeout. This roughly translates to 1024 connection attempts in 60s on an empty server. OpenVPN will announce once per period how many packets it dropped: Dropped 11 initial handshake packets due to --connect-freq-initial 100 10 to inform an amdin about the consequence of this feature. Patch v2: use strtol instead of atoi to be able to differentiate between an error parsing and parsing 0. Use int64_t instead int to avoid overflow errors. Signed-off-by: Arne Schwabe --- Changes.rst | 4 ++ doc/man-sections/server-options.rst | 19 ++++++ src/openvpn/Makefile.am | 1 + src/openvpn/mudp.c | 14 +++++ src/openvpn/multi.c | 4 ++ src/openvpn/multi.h | 2 + src/openvpn/options.c | 21 +++++++ src/openvpn/options.h | 5 ++ src/openvpn/reflect_filter.c | 93 +++++++++++++++++++++++++++++ src/openvpn/reflect_filter.h | 71 ++++++++++++++++++++++ 10 files changed, 234 insertions(+) create mode 100644 src/openvpn/reflect_filter.c create mode 100644 src/openvpn/reflect_filter.h diff --git a/Changes.rst b/Changes.rst index 47933ae09..187d03fcf 100644 --- a/Changes.rst +++ b/Changes.rst @@ -92,6 +92,10 @@ Cookie based handshake for UDP server shake. The tls-crypt-v2 option allows controlling if older clients are accepted. + By default the rate of initial packet responses is limited to 100 per 10s + interval to avoid OpenVPN servers being abused in reflection attacks + (see ``--connect-freq-initial``). + Data channel offloading with ovpn-dco 2.6.0+ implements support for data-channel offloading where the data packets are directly processed and forwarded in kernel space thanks to the ovpn-dco diff --git a/doc/man-sections/server-options.rst b/doc/man-sections/server-options.rst index 99263fff3..cbb2c3c92 100644 --- a/doc/man-sections/server-options.rst +++ b/doc/man-sections/server-options.rst @@ -184,6 +184,25 @@ fast hardware. SSL/TLS authentication must be used in this mode. For the best protection against DoS attacks in server mode, use ``--proto udp`` and either ``--tls-auth`` or ``--tls-crypt``. +--connect-freq-initial args + (UDP only) Allow a maximum of ``n`` initial connection packet responses + per ``sec`` seconds from to clients. + + Valid syntax: + :: + + connect-freq-initial n sec + + OpenVPN starting at 2.6 is very efficient in responding to initial + connection packets. When not limiting the initial responses + an OpenVPN daemon can be abused in reflection attacks. + This option is designed to limit the rate OpenVPN will respond to initial + attacks. + + Connection attempts that complete the initial three-way handshake + will not be counted against the limit. The default is to allow + 100 initial connection per 10s. + --duplicate-cn Allow multiple clients with the same common name to concurrently connect. In the absence of this option, OpenVPN will disconnect a client diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index e80a35abd..35d60a65b 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -113,6 +113,7 @@ openvpn_SOURCES = \ ps.c ps.h \ push.c push.h \ pushlist.h \ + reflect_filter.c reflect_filter.h \ reliable.c reliable.h \ route.c route.h \ run_command.c run_command.h \ diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index c27c6da5b..4ef2f355b 100644 --- a/src/openvpn/mudp.c +++ b/src/openvpn/mudp.c @@ -82,6 +82,16 @@ do_pre_decrypt_check(struct multi_context *m, struct openvpn_sockaddr *from = &m->top.c2.from.dest; int handwindow = m->top.options.handshake_window; + if (verdict == VERDICT_VALID_RESET_V3 || verdict == VERDICT_VALID_RESET_V2) + { + /* Check if we are still below our limit for sending out + * responses */ + if (!reflect_filter_rate_limit_check(m->initial_rate_limiter)) + { + return false; + } + } + if (verdict == VERDICT_VALID_RESET_V3) { /* Extract the packet id to check if it has the special format that @@ -244,6 +254,10 @@ multi_get_create_instance_udp(struct multi_context *m, bool *floated) if (frequency_limit_event_allowed(m->new_connection_limiter)) { + /* a successful three-way handshake only counts against + * connect-freq but not against connect-req-initial */ + reflect_filter_rate_limit_decrease(m->initial_rate_limiter); + mi = multi_create_instance(m, &real); if (mi) { diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 0ba509fa0..1a7f278f7 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -52,6 +52,7 @@ #include "crypto_backend.h" #include "ssl_util.h" #include "dco.h" +#include "reflect_filter.h" /*#define MULTI_DEBUG_EVENT_LOOP*/ @@ -368,6 +369,8 @@ multi_init(struct multi_context *m, struct context *t, bool tcp_mode) */ m->new_connection_limiter = frequency_limit_init(t->options.cf_max, t->options.cf_per); + m->initial_rate_limiter = initial_rate_limit_init(t->options.cf_initial_max, + t->options.cf_initial_per); /* * Allocate broadcast/multicast buffer list @@ -729,6 +732,7 @@ multi_uninit(struct multi_context *m) mbuf_free(m->mbuf); ifconfig_pool_free(m->ifconfig_pool); frequency_limit_free(m->new_connection_limiter); + initial_rate_limit_free(m->initial_rate_limiter); multi_reap_free(m->reaper); mroute_helper_free(m->route_helper); multi_tcp_free(m->mtcp); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 370d795c9..713c63eee 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -39,6 +39,7 @@ #include "mtcp.h" #include "perf.h" #include "vlan.h" +#include "reflect_filter.h" #define MULTI_PREFIX_MAX_LENGTH 256 @@ -170,6 +171,7 @@ struct multi_context { * as external transport. */ struct ifconfig_pool *ifconfig_pool; struct frequency_limit *new_connection_limiter; + struct initial_packet_rate_limit *initial_rate_limiter; struct mroute_helper *route_helper; struct multi_reap *reaper; struct mroute_addr local; diff --git a/src/openvpn/options.c b/src/openvpn/options.c index ee3783046..e756af948 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -480,6 +480,7 @@ static const char usage_message[] = " as well as pushes it to connecting clients.\n" "--learn-address cmd : Run command cmd to validate client virtual addresses.\n" "--connect-freq n s : Allow a maximum of n new connections per s seconds.\n" + "--connect-freq-initial n s : Allow a maximum of n replies for initial connections attempts per s seconds.\n" "--max-clients n : Allow a maximum of n simultaneously connected clients.\n" "--max-routes-per-client n : Allow a maximum of n internal routes per client.\n" "--stale-routes-check n [t] : Remove routes with a last activity timestamp\n" @@ -864,6 +865,8 @@ init_options(struct options *o, const bool init_gc) o->n_bcast_buf = 256; o->tcp_queue_limit = 64; o->max_clients = 1024; + o->cf_initial_per = 10; + o->cf_initial_max = 100; o->max_routes_per_client = 256; o->stale_routes_check_interval = 0; o->ifconfig_pool_persist_refresh_freq = 600; @@ -1555,6 +1558,8 @@ show_p2mp_parms(const struct options *o) SHOW_BOOL(duplicate_cn); SHOW_INT(cf_max); SHOW_INT(cf_per); + SHOW_INT(cf_initial_max); + SHOW_INT(cf_initial_per); SHOW_INT(max_clients); SHOW_INT(max_routes_per_client); SHOW_STR(auth_user_pass_verify_script); @@ -7452,6 +7457,22 @@ add_option(struct options *options, options->cf_max = cf_max; options->cf_per = cf_per; } + else if (streq(p[0], "connect-freq-initial") && p[1] && p[2] && !p[3]) + { + long cf_max, cf_per; + + VERIFY_PERMISSION(OPT_P_GENERAL); + char *e1, *e2; + cf_max = strtol(p[1], &e1, 10); + cf_per = strtol(p[2], &e2, 10); + if (cf_max < 0 || cf_per < 0 || *e1 != '\0' || *e2 != '\0') + { + msg(msglevel, "--connect-freq-initial parameters must be integers and >= 0"); + goto err; + } + options->cf_initial_max = cf_max; + options->cf_initial_per = cf_per; + } else if (streq(p[0], "max-clients") && p[1] && !p[2]) { int max_clients; diff --git a/src/openvpn/options.h b/src/openvpn/options.h index fec1eace5..48315b10e 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -513,8 +513,13 @@ struct options bool push_ifconfig_ipv6_blocked; /* IPv6 */ bool enable_c2c; bool duplicate_cn; + int cf_max; int cf_per; + + int cf_initial_max; + int cf_initial_per; + int max_clients; int max_routes_per_client; int stale_routes_check_interval; diff --git a/src/openvpn/reflect_filter.c b/src/openvpn/reflect_filter.c new file mode 100644 index 000000000..621b0dee6 --- /dev/null +++ b/src/openvpn/reflect_filter.c @@ -0,0 +1,93 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2022 OpenVPN Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#include "syshead.h" + + +#include +#include +#include +#include +#include +#include + +#include "crypto.h" +#include "reflect_filter.h" + + +bool +reflect_filter_rate_limit_check(struct initial_packet_rate_limit *irl) +{ + if (now > irl->last_period_reset + irl->period_length) + { + int64_t dropped = irl->curr_period_counter - irl->max_per_period; + if (dropped > 0) + { + msg(D_TLS_DEBUG_LOW, "Dropped %" PRId64 " initial handshake packets due to " + "--connect-freq-initial %" PRId64 " %d", + dropped, irl->max_per_period, irl->period_length); + } + irl->last_period_reset = now; + irl->curr_period_counter = 0; + } + + irl->curr_period_counter++; + + return irl->curr_period_counter > irl->max_per_period; +} + +void +reflect_filter_rate_limit_decrease(struct initial_packet_rate_limit *irl) +{ + if (irl->curr_period_counter > 0) + { + irl->curr_period_counter--; + } +} + + +struct initial_packet_rate_limit * +initial_rate_limit_init(int max_per_period, int period_length) +{ + struct initial_packet_rate_limit *irl; + + + ALLOC_OBJ(irl, struct initial_packet_rate_limit); + irl->max_per_period = max_per_period; + irl->period_length = period_length; + irl->curr_period_counter = 0; + + return irl; +} + +void +initial_rate_limit_free(struct initial_packet_rate_limit *irl) +{ + free(irl); +} diff --git a/src/openvpn/reflect_filter.h b/src/openvpn/reflect_filter.h new file mode 100644 index 000000000..4d7c0a7da --- /dev/null +++ b/src/openvpn/reflect_filter.h @@ -0,0 +1,71 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2022 OpenVPN Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef REFLECT_FILTER_H +#define REFLECT_FILTER_H + +#include + +/** struct that handles all the rate limiting logic for initial + * responses */ +struct initial_packet_rate_limit { + /** This is a hard limit for packets per seconds. */ + int64_t max_per_period; + + /** period length in seconds */ + int period_length; + + /** Number of packets in the current period. We use int64_t here + * to avoid any potiential issues with overflow */ + int64_t curr_period_counter; + + /* Last time we reset our timer */ + time_t last_period_reset; +}; + + +/** + * checks if the connection is still allowed to connect under the rate + * limit. This also increases the internal counter at the same time + */ +bool +reflect_filter_rate_limit_check(struct initial_packet_rate_limit *irl); + +/** + * decreases the counter of initial respsonses to allow connections that + * successfully completed the three-way handshake to not count against + * the counter of initial connection attempts + */ +void +reflect_filter_rate_limit_decrease(struct initial_packet_rate_limit *irl); + +/** + * allocates and initial the initial packet rate limiter structure + */ +struct initial_packet_rate_limit * +initial_rate_limit_init(int max_per_period, int period_length); + +/** + * free the initial rate limiter structure + */ +void initial_rate_limit_free(struct initial_packet_rate_limit *irl); +#endif /* ifndef REFLECT_FILTER_H */