Hi,

first of all, feature-ACK, and "structure-ACK" - this is a lightweight
implementation that can go into 2.6 with not much testing, which should
"get the thing done" for most cases.  A more sophisticated implementation
with per-IP hashing (to avoid (ab-)using the rate-limiter to drown-out
legitimate clients) can follwo for 2.7.

This said, most of the code looks good, except for this part:


On Thu, Jan 05, 2023 at 06:56:14PM +0100, Arne Schwabe wrote:
> index ee3783046..cf8622f46 100644
> --- a/src/openvpn/options.c
> +++ b/src/openvpn/options.c
> @@ -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;

... so this is on-by-default...

> @@ -2613,6 +2618,10 @@ options_postprocess_verify_ce(const struct options 
> *options,
>          {
>              msg(M_USAGE, "--connect-freq only works with --mode server 
> --proto udp.  Try --max-clients instead.");
>          }
> +        if (!proto_is_udp(ce->proto) && (options->cf_initial_max || 
> options->cf_initial_per))
> +        {
> +            msg(M_USAGE, "--connect-freq only works with --mode server 
> --proto udp.  Try --max-clients instead.");
> +        }

... and if it is enabled for !UDP modes, we'll refuse cooperation.

But wouldn't that trigger for *all* TCP servers now, since it defaults
to "active"?

Besides that, the "--connect-freq" there is wrong and needs to be 
"--connect-freq-initial" ;-)

[..]
> +    else if (streq(p[0], "connect-freq-initial") && p[1] && p[2] && !p[3])
> +    {
> +        int cf_max, cf_per;
> +
> +        VERIFY_PERMISSION(OPT_P_GENERAL);
> +        cf_max = atoi(p[1]);
> +        cf_per = atoi(p[2]);
> +        if (cf_max < 0 || cf_per < 0)

" < 0 " or " <= 0"?

> +        {
> +            msg(msglevel, "--connect-freq-initial parms must be > 0");
> +            goto err;
> +        }

... because the inverse of ">0" is not "<0"...

> +        options->cf_initial_max = cf_max;
> +        options->cf_initial_per = cf_per;
> +    }

... now we could of course document "0 turns it off", but then the
message needs to be ">= 0".

> +bool
> +reflect_filter_rate_limit_check(struct initial_packet_rate_limit *irl)
> +{
> +    if (now > irl->last_period_reset + irl->period_length)
> +    {
> +        int dropped = max_int(irl->curr_period_counter - 
> irl->max_per_period, 0);
> +        if (dropped > 0)
> +        {
> +            msg(D_TLS_DEBUG_LOW, "Dropped %d initial handshake packets due 
> to "
> +                "--connect-freq-initial %d %d",
> +                dropped, irl->max_per_period, irl->period_length);
> +        }
> +        irl->last_period_reset = now;
> +        irl->curr_period_counter = 0;
> +    }
> +    /* avoid overflow by capping the counter to INT_MAX -1. Still counting
> +     * the number of packets during a period is still useful */
> +    irl->curr_period_counter = min_int(irl->curr_period_counter + 1, INT_MAX 
> - 1);

This looks uglysh.

With a 10-seconds bucket, an (32bit) "int" would overflow at about
430 million packets per seconds - which is, I think, way beyond what
any reasonable system can handle (10G ethernet saturates at 15 Mpps).

But if you are really worried about overflows - why not use a (64bit)
long here?

gert
-- 
"If was one thing all people took for granted, was conviction that if you 
 feed honest figures into a computer, honest figures come out. Never doubted 
 it myself till I met a computer with a sense of humor."
                             Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany                             g...@greenie.muc.de

Attachment: signature.asc
Description: PGP signature

_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to