Is your feature request related to existing pfSense functionality that is missing from the API? Please describe.
Yes — Services > HAProxy > Settings > Frontend > <edit> > Access Control Lists, expression types "SSL SNI matches" / "Host matches" (and presumably the sibling ssl_sni_contains/ssl_sni_starts_with/ssl_sni_ends_with/ssl_sni_regex/host_* variants, only the two above were directly tested). The REST API exposes the identical field (ha_acls[].expression on /api/v2/services/haproxy/frontend, and the dedicated /api/v2/services/haproxy/frontend/acl sub-resource) and accepts/stores these values without error — but this isn't a missing field, it's a field that's accepted and echoed back correctly by GET yet doesn't actually work.
Is your feature request related to a problem? Please describe.
I'm always frustrated when I configure a TCP-mode SNI-passthrough frontend (the standard pfSense-HAProxy recipe for routing multiple HTTPS backends off one WAN IP without terminating TLS on pfSense) entirely through the REST API, and it silently fails to actually work. Repro:
POST /api/v2/services/haproxy/frontend — TCP-mode frontend with a default backend.
POST /api/v2/services/haproxy/frontend/acl — {"parent_id": <id>, "name": "my_acl", "expression": "ssl_sni_matches", "value": "example.com"}.
POST /api/v2/services/haproxy/frontend/action — {"parent_id": <id>, "action": "use_backend", "acl": "my_acl", "backend": "other_backend"}.
POST /api/v2/services/haproxy/apply — returns 200/{"applied": false}, no error surfaced to the caller.
- HAProxy actually fails to reload. The only place the failure shows up is
/var/log/system.log:
[ALERT] : config : parsing [.../haproxy.cfg:N] : error detected while parsing switching rule : no such ACL : 'my_acl'.
[ALERT] : config : Fatal errors found in configuration file
The generated config contains the use_backend ... if my_acl switching line but never the acl my_acl ... declaration it depends on — so the ACL is silently dropped somewhere between stored config and rendered haproxy.cfg, only for these expression types. A source_ip-expression ACL added the identical way (same frontend, same nested/sub-resource creation paths tried both ways) rendered and reloaded correctly, so this isn't a general "ACLs aren't wired up" issue.
Describe the solution you'd like
Fix whatever translates a stored ACL's expression enum value into the corresponding acl <name> <fetch> line in haproxy.cfg so it covers ssl_sni_matches/ssl_sni_contains/ssl_sni_starts_with/ssl_sni_ends_with/ssl_sni_regex and the host_* family the same way it already correctly covers source_ip and (presumably) other working expression types.
Describe alternatives you've considered
expression: "custom" with the raw HAProxy fetch syntax as value (e.g. "req.ssl_sni -i example.com" for SNI, "hdr(host) -i example.com" for Host) — this renders correctly and is the workaround I'm using, but it means the friendlier typed expression options are unusable for the single most common HAProxy-on-pfSense use case (SNI/Host-based backend routing).
Additional context
- Versions: pfSense 2.9.0-RELEASE (FreeBSD 16.0-CURRENT), pfSense-pkg-RESTAPI 2.10_2, pfSense-pkg-haproxy 0.65.7 (haproxy 3.2.19).
- Reproduced on a stock install with only pfSense-pkg-haproxy installed via
POST /api/v2/system/package {"name": "pfSense-pkg-haproxy"}, no other HAProxy config present beforehand.
- Tried both ACL-creation paths (inline
ha_acls/a_actionitems arrays in the frontend's own POST/PATCH body, and the dedicated /frontend/acl + /frontend/action sub-resource endpoints) — both produce the same broken render, and GET on the frontend correctly echoes the ACL back with the right parent_id either way, confirming it's stored correctly and the bug is specifically in the config-file renderer.
- Happy to provide full request/response payloads and
system.log excerpts on request.
Is your feature request related to existing pfSense functionality that is missing from the API? Please describe.
Yes —
Services > HAProxy > Settings > Frontend > <edit> > Access Control Lists, expression types "SSL SNI matches" / "Host matches" (and presumably the siblingssl_sni_contains/ssl_sni_starts_with/ssl_sni_ends_with/ssl_sni_regex/host_*variants, only the two above were directly tested). The REST API exposes the identical field (ha_acls[].expressionon/api/v2/services/haproxy/frontend, and the dedicated/api/v2/services/haproxy/frontend/aclsub-resource) and accepts/stores these values without error — but this isn't a missing field, it's a field that's accepted and echoed back correctly byGETyet doesn't actually work.Is your feature request related to a problem? Please describe.
I'm always frustrated when I configure a TCP-mode SNI-passthrough frontend (the standard pfSense-HAProxy recipe for routing multiple HTTPS backends off one WAN IP without terminating TLS on pfSense) entirely through the REST API, and it silently fails to actually work. Repro:
POST /api/v2/services/haproxy/frontend— TCP-mode frontend with a default backend.POST /api/v2/services/haproxy/frontend/acl—{"parent_id": <id>, "name": "my_acl", "expression": "ssl_sni_matches", "value": "example.com"}.POST /api/v2/services/haproxy/frontend/action—{"parent_id": <id>, "action": "use_backend", "acl": "my_acl", "backend": "other_backend"}.POST /api/v2/services/haproxy/apply— returns200/{"applied": false}, no error surfaced to the caller./var/log/system.log:use_backend ... if my_aclswitching line but never theacl my_acl ...declaration it depends on — so the ACL is silently dropped somewhere between stored config and renderedhaproxy.cfg, only for these expression types. Asource_ip-expression ACL added the identical way (same frontend, same nested/sub-resource creation paths tried both ways) rendered and reloaded correctly, so this isn't a general "ACLs aren't wired up" issue.Describe the solution you'd like
Fix whatever translates a stored ACL's
expressionenum value into the correspondingacl <name> <fetch>line inhaproxy.cfgso it coversssl_sni_matches/ssl_sni_contains/ssl_sni_starts_with/ssl_sni_ends_with/ssl_sni_regexand thehost_*family the same way it already correctly coverssource_ipand (presumably) other working expression types.Describe alternatives you've considered
expression: "custom"with the raw HAProxy fetch syntax asvalue(e.g."req.ssl_sni -i example.com"for SNI,"hdr(host) -i example.com"for Host) — this renders correctly and is the workaround I'm using, but it means the friendlier typed expression options are unusable for the single most common HAProxy-on-pfSense use case (SNI/Host-based backend routing).Additional context
POST /api/v2/system/package {"name": "pfSense-pkg-haproxy"}, no other HAProxy config present beforehand.ha_acls/a_actionitemsarrays in the frontend's own POST/PATCH body, and the dedicated/frontend/acl+/frontend/actionsub-resource endpoints) — both produce the same broken render, andGETon the frontend correctly echoes the ACL back with the rightparent_ideither way, confirming it's stored correctly and the bug is specifically in the config-file renderer.system.logexcerpts on request.