First of all I understand that the `errorfile` (and related
`errorloc`) are for HAProxy's own generated errors.

However given how powerful the ACL system is, and the availability of
`http-request deny deny_status <code>`, one can leverage all this and
implement a powerful WAF.

For example last week I tried to "hide" some URL's and pretend they
are 404's directly from HAProxy (as it seems that the backend server I
was using doesn't support this feature...)  However when I tried to
use `deny_status 404` it actually replied with a 403 (and the custom
page for that error).  Now this is not a big issue, however it might
give an "attacker" a hint that "something" is at that URL...

----

Therefore I took a look at the `errorfile` related code and how it is
currently implemented:

    
https://github.com/haproxy/haproxy/blob/61ea7dc005bc490ed3e5298ade3d932926fdb9f7/include/common/http.h#L82-L96
    
https://github.com/haproxy/haproxy/blob/61ea7dc005bc490ed3e5298ade3d932926fdb9f7/src/http.c#L218-L231
    
https://github.com/haproxy/haproxy/blob/61ea7dc005bc490ed3e5298ade3d932926fdb9f7/src/http.c#L233
    
https://github.com/haproxy/haproxy/blob/06f5b6435ba99b7a6a034d27b56192e16249f6f0/src/http_rules.c#L106-L111
    
https://github.com/haproxy/haproxy/blob/21c741a665f4c7b354e961267824c81ec44f503f/include/types/proxy.h#L408

At a first glance it implements a sort of "associative-array"
structure, of fixed `HTTP_ERR_SIZE`, with the actual codes being
statically mapped to indices via `http_err_codes`.

There is a global default array `http_err_msgs` (plus the
`http_err_chunks` counterpart) and a per-proxy embedded array
`proxy->errmsg`, both pre-allocated of size `HTTP_ERR_SIZE`.

Therefore adding support for a new status code is quite trivial, just
create the relevant entries in `http_err_codes` and `http_err_msgs`
and a new `HTTP_ERR_*` entry.  The downside is minimal, just a slight
increase of `sizeof (struct buffer)` bytes (32) globally and one for
each proxy, and almost no run-time impact in terms of CPU.

Thus I would suggest adding at least the following:
* 404 -- not-found -- with an obvious use-case;
* 402 -- payment-required -- which might be used as a "soft" 403
alternative, which suggests that although you are "authenticated" and
issued a valid request, you are not-allowed because of some
"accounting" reason;
* 406 -- not-acceptable -- although used for content negotiation, it
could be "abused" as a page indicating to the user that his "browser"
(or agent) is not "compatible" with the generated content;
* 409/410 -- conflict/gone -- alternatives for 403/404 if the user has
need for them;
* 451 -- unavailable-for-legal-reasons -- perhaps useful in these GDPR-days?
* 501 -- not-implemented -- useful perhaps to "hide" some
not-yet-published API endpoints, or other backend-related
"blacklisting";

----

However my proposal would be to allow "user-defined" error codes, the
main use-case being WAF/CDN custom status codes
(https://support.cloudflare.com/hc/en-us/sections/200820298-Error-Pages).

Such a change shouldn't be that involved, although for efficiency the
`proxy->errmsg` should be transformed from an embedded array to an
array pointer of variable size.

Would such a feature be accepted by the HAProxy developers?

----

Moreover, dare I say, this feature could be "abused" to serve a few
"static files" (like `favicon.ico` or `robots.txt`) directly from
HAProxy without requiring Lua.  In fact the most viewed topic on
HAProxy's forum is exactly about this:

  
https://discourse.haproxy.org/t/how-do-i-serve-a-single-static-file-from-haproxy/32

Ciprian.

Reply via email to