Replace nginx with HAProxy and introduce new rule syntax#1
Merged
Conversation
Migrate the proxy layer from nginx (stream + http modules) to HAProxy, enabling unified TCP/HTTP filtering in a single process with iptables REDIRECT. Domain allowlists are replaced with regex-based rules (ALLOWED_HTTPS_RULES, ALLOWED_HTTP_RULES, ALLOWED_IP_RULES) that match against host:port pairs for more flexible control.
…locking Add edge-case test coverage for infrastructure-level blocking behaviors: - DNS resolution failure (NXDOMAIN) for both HTTP and HTTPS - TLS ClientHello without SNI extension - HTTP request without Host header - Direct IP access blocking (restrict mode assertion) These cases are blocked even in audit mode since they represent protocol/infrastructure errors rather than policy decisions.
hdr(host) -m found returns true even when the Host header is present but empty (e.g., "Host: "). Add hdr_len(host) gt 0 check to also block requests with empty Host header values.
Docker log driver may not have captured all HAProxy output when docker compose logs runs immediately. Add a 500ms delay to ensure logs are fully available.
Change EXTERNAL_RESOLVER from space-delimited with inline "valid=301s" parameter to simple comma-separated IP format (e.g. "1.1.1.1,8.8.8.8"). Move "hold valid 300s" and "accepted_payload_size 8192" into the HAProxy config template as static values, eliminating the need for parsing mixed tokens in entrypoint.sh.
Replace the monolithic entrypoint.sh with s6-overlay process supervisor to manage dnsmasq, haproxy, and initialization tasks as discrete services with proper dependency ordering via s6-rc.
Introduce setup/rules.mjs providing a rule parser that converts user-facing allow rules (wildcard patterns, ~regex, IP addresses) into HAProxy-compatible regex strings. Add unit tests with regex behavior verification, and a make test_unit target to run them.
…ted rules Replace legacy domain-based parameters (allowed_https_domains, allowed_http_domains, https_ports, http_ports) with new unified rule parameters (allowed_https_rules, allowed_http_rules) that support per-rule port specification. Legacy parameters are kept as deprecated with automatic conversion. Switch the internal delimiter from comma to whitespace. Add E2E test cases for nested subdomain blocking and HTTP wildcard matching.
…restrict mode In audit mode, display blocked connections (e.g., protocol errors) in the report and emit a notice instead of failing the step. The fail_on_blocked parameter now only applies to restrict mode. Remove the now-unnecessary || true from test_audit_mode target.
Add docs/rules.md as a rule syntax reference covering wildcards, regex, IP addresses, and migration from deprecated parameters. Update README.md, development guide, and example workflow to reflect the new allowed_https_rules / allowed_http_rules parameters.
Separate IP address rules into a dedicated `allowed_ip_rules` input
instead of auto-detecting them from HTTPS/HTTP rule inputs. Add
wildcard port `*` syntax to match any port (e.g., `example.com:*`).
Refactor main.mjs into structured functions with dependency injection
and simplify rule parsing by removing `{…}` block preservation.
Remove stale comment referencing removed {…} block syntax and replace
empty HAPROXY_AUDIT_ACCEPT value with a descriptive HAProxy comment for
restrict mode.
Reject blocked domains before do-resolve to avoid unnecessary DNS queries for connections that will be denied.
Add setup/convert-rules.mjs so Makefile can accept wildcard syntax instead of requiring hand-written regex. Move rules.mjs and its tests into setup/lib/ for better organization.
Keep stdin open with sleep after printf to prevent BusyBox nc from closing the connection before HAProxy processes the HTTP request in the backend. Also remove unnecessary 500ms delay from report script.
- Fix test mock targeting console.warn instead of console.log in buildLegacyRules empty portsInput test - Guard against whitespace-only portsInput by trimming before fallback - Validate regex syntax in ~-prefixed rules to fail early instead of crashing HAProxy at startup
- Reorder sections logically: Network Isolation → DNS → Proxy → Direct IP - Clarify DNS redirect, HTTP proxy, and iptables descriptions - Add missing Host header rejection to proxy control section - Split Direct IP section into traffic redirection and IP allowlist check - Fix variable names and add audit mode link
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
not-allowed,dns-failed,missing-sni,missing-host-header,ip-not-allowed)entrypoint.shto s6-overlay for proper service supervision (dnsmasq, HAProxy, init scripts)allowed_https_rules,allowed_http_rules, andallowed_ip_rulesinputs, supporting wildcard patterns (*,**,?), wildcard port (example.com:*), and regex (~-prefixed) — replacing the deprecatedallowed_*_domains/*_portsinputssetup/main.mjsinto structured functions with dependency injection for better testabilityfail_on_blockedto restrict mode onlyTest plan
make testto execute restrict mode and audit mode integration testsallowed_*_domains/*_portsinputs still work with deprecation warnings