Ferron 3.0.0-beta.10 released

Published on:

Today, we’re releasing Ferron 3.0.0-beta.10, the tenth beta version of what it would be Ferron 3. This release involves security hardening, HTTP/3 stabilization, correctness for your services, and more.

Breaking changes

But first, let’s talk about the breaking changes.

First, Ferron 3 uses a linear-time regular expression engine instead of a backtracking one, which means that backtracking regex patterns are no longer supported. This change was made to avoid potential ReDoS and catastrophic backtracking issues. If you are using syntax such as (?= ...), (?! ...), (?<= ...), (?<! ...), or \1, you need to rewrite the regexes.

Also, following symlinks during static file resolution from webroot is now disabled by default for symlink attack prevention. Check if web application uses symlinks (if it uses, use disable_symlinks false or a similar setting).

Also we reduced the DNS provider support for automatic TLS DNS-01 challenge to a minimal set of providers, to keep Ferron lightweight and lean. Supported providers are now rfc2136, route53, bunny, digitalocean, cloudflare, dnsimple, googlecloud, ovh, spaceship, porkbun, and desec. We’ve also added command provider for custom DNS update code.

Finally, tls { ocsp { enabled true } } and basic_auth { brute_force_protection { enabled true } } are no longer effective and are replaced with tls { ocsp } and basic_auth { brute_force_protection } respectively, to improve consistency across configuration directives (that use flag syntax like cache false).

HTTP/3 stabilization

Ferron 3 now has HTTP/3 support no longer declared experimental (backed by our zincio-http implementation instead of experimental h3). We have now also enabled HTTP/3 by default during the stabilization.

HTTP/3 addresses head-of-line blocking by using QUIC, which is built on top of UDP (in comparison to HTTP/2, which uses TCP), improving website performance on unstable networks like mobile or satellite.

Also, after seeing a GitHub issue after HTTP/3 issues with curl, we fixed the HTTP/3 stream reset errors.

QUIC packet loss fixes

Going from HTTP/3 to QUIC, we found that the routing logic introduced in Ferron 3.0.0-beta.9 introduced packet loss due to improper routing of packets by the QUIC transport.

This has been fixed to improve packet routing (via IP hashing when initializing and connection ID hashing later on) and reduce packet loss.

This should improve reliability of QUIC and HTTP/3 connections.

Reverse proxy resilience

When using Ferron as a reverse proxy and then a backend fails while HTTP request is sent, if the request method is idempotent and body is not sent yet, Ferron will now retry the request (once by default) instead of bailing out.

You can configure this:

example.com
    proxy {
        upstream http://localhost:3000/

        max_retries_per_upstream 2
    }
}

HTTP cache Vary correctness

We have found that a bug (which has been introduced in Ferron 3.0.0-beta.9) led to some header names in Vary header values (If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Range) being ignored by the cache. This led to wrong 304 responses being served occasionally, which would be seen by website visitors as broken websites and blank pages.

This has been fixed by not ignoring the specified header values

h2c listener support

Ferron 3.0.0-beta.10 adds support for h2c (HTTP/2 cleartext) listeners on top of existing HTTP/1.x and HTTP/2 support.

This could be useful when hosting microservices or applications that use gRPC (built on top of HTTP/2) in some way.

We didn’t add h2c upgrade support (only h2c with prior knowledge), as this has been deprecated from the current HTTP/2 specification (RFC 9113).

This can be enabled using this configuration:

{
    http {
        protocols h2c # Note: HTTP/1.x cannot be used here
    }
    default_https_port false
}

api.example.com {
    location /api/some {
        proxy {
            upstream http://somemicroservice:3000/
            http2_only # Use HTTP/2 only to allow gRPC proxying
        }
    }
}

Many correctness fixes

Ferron 3.0.0-beta.10 contains multiple correctness fixes, such as:

  • IPv4 host blocks never matching: fixed IPv4 host never matching due to IP address canonicalization issues and IPv4-mapped IPv6 addresses.
  • Stray } fix: earlier, stray } characters in ferron.conf files could cause an infinite loop. These are now properly handled by erroring out.
  • High-cardinality metric removed: the ferron.proxy.lb.selections with high-cardinality ferron.proxy.lb.score attribute has been removed to prevent exhaustion of metric storage.
  • Fixed deny_ips bypass using non-canonical IP representations: previously, deny_ips could be bypassed using non-canonical IP address representations (such as 0x7f.0.0.1 or 2130706433). This has been fixed to normalize the IP addresses first.
  • Ranges beyond the end correctness: the server now returns 416 Range Not Satisfiable when a range request start exceeds the available content length.
  • Configured HTTP responses after HTTP -> HTTPS redirects: HTTP responses configured to be served after the https_redirect stage will now only be served after a successful HTTP-to-HTTPS redirection. This ensures that these responses are not served before the client is redirected, which could lead to unexpected behavior or security issues.

Looking ahead

Ferron 3 beta is still improving when it comes to correctness and stability for your web services. The remaining beta versions will focus on final polish, stabilizing the ecosystem, and preparing for our first release candidate.

As always, feedback, bug reports, and testing results are welcome.

Full changelog

You can see the complete changelog for Ferron 3.0.0-beta.10 in the release notes.

Try it

Install Ferron 3 using the installer:

sudo bash -c "$(curl -fsSL https://get.ferron.sh/v3)"