{"id":29799920,"url":"https://github.com/0x4d31/finch","last_synced_at":"2025-08-03T14:03:06.185Z","repository":{"id":306840714,"uuid":"1027297090","full_name":"0x4D31/finch","owner":"0x4D31","description":"Fingerprint‑aware TLS reverse proxy: allow, deny, route or deceive traffic via JA3, JA4 (+QUIC), JA4H, HTTP/2 fingerprints, and other request metadata.","archived":false,"fork":false,"pushed_at":"2025-07-27T23:07:38.000Z","size":2423,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-28T00:25:49.321Z","etag":null,"topics":["deception","fingerprint","fingerprinting","go","honeypot","ja3","ja4","reverse-proxy","security","security-tools"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0x4D31.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-27T18:16:58.000Z","updated_at":"2025-07-27T23:19:43.000Z","dependencies_parsed_at":"2025-07-28T00:44:01.480Z","dependency_job_id":null,"html_url":"https://github.com/0x4D31/finch","commit_stats":null,"previous_names":["0x4d31/finch"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/0x4D31/finch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0x4D31%2Ffinch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0x4D31%2Ffinch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0x4D31%2Ffinch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0x4D31%2Ffinch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0x4D31","download_url":"https://codeload.github.com/0x4D31/finch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0x4D31%2Ffinch/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267488891,"owners_count":24095786,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deception","fingerprint","fingerprinting","go","honeypot","ja3","ja4","reverse-proxy","security","security-tools"],"created_at":"2025-07-28T08:50:13.973Z","updated_at":"2025-07-28T08:50:15.860Z","avatar_url":"https://github.com/0x4D31.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"docs/images/finch.png\" alt=\"Finch logo\" width=\"200\"\u003e\u003c/p\u003e\n\n# Fingerprint‑Aware TLS Reverse Proxy\n\nFinch is a lightweight reverse proxy written in Go. It inspects TLS handshakes and HTTP requests to extract JA3, JA4, JA4H, and Akamai HTTP/2 fingerprints, then evaluates them—alongside the rest of the request metadata—against flexible, hot‑reloadable rules written in HCL. On a per‑request basis, Finch can:\n\n- **allow** legitimate traffic  \n- **deny** or **tarpit** scanners  \n- **route** clients to alternate upstreams  \n- **deceive** attackers with on‑the‑fly, LLM‑generated responses via [Galah](https://github.com/0x4D31/galah)\n\nFinch also offers an authenticated admin API for live configuration and rule updates, a real‑time SSE feed for observability, Suricata HTTP rule matching, and an echo mode for testing or dataset collection. Experimental HTTP/3 and QUIC fingerprinting support is included. Use Finch to block scrapers and other unwanted traffic, slow down scanners, or deploy dynamic honeypots.\n\n\u003e **Status: v0.1.0 – not production‑ready.**  \n\u003e Finch is under active development and may contain bugs or breaking changes.\n\u003e Please test thoroughly before deploying, and open an issue or pull request if you find a problem or can contribute improvements.\n\n### Key Features\n\n- **Fingerprint extraction** – Capture [JA3](https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967/), [JA4](https://github.com/FoxIO-LLC/ja4/blob/main/technical_details/JA4.md), [JA4H](https://github.com/FoxIO-LLC/ja4/blob/main/technical_details/JA4H.md), and [Akamai HTTP/2](https://www.blackhat.com/docs/eu-17/materials/eu-17-Shuster-Passive-Fingerprinting-Of-HTTP2-Clients-wp.pdf) fingerprints for every request, providing high‑fidelity identification of client libraries and TLS stacks.\n- **Flexible rule engine** – Define policies using [HCL](https://github.com/hashicorp/hcl) that evaluate fingerprints, HTTP methods and paths, header values, source‑IP ranges, and Suricata alert messages. Rules can nest `when all` / `when any` blocks and decide whether to `allow`, `deny`, `route`, or `deceive` each request. See the [Rule Schema](docs/rule-schema.md) for details.\n- **Suricata HTTP rules** – Finch loads Suricata `.rules`, evaluates requests against them, hot‑reloads rules on changes, logs matches, and exposes each matched rule’s `msg` to your HCL policies—no Suricata installation needed.\n- **Deception mode** – Trigger the `deceive` action to serve LLM‑generated honeypot responses via [Galah](https://github.com/0x4D31/galah) or slow scanners with a configurable tarpit.  \n- **Live event feed** – Stream structured JSON events over Server‑Sent Events (SSE) for immediate visibility.  \n- **Echo mode** – Run a standalone server that echoes fingerprint data—ideal for testing and dataset collection.\n- **Multiple listeners \u0026 hot reloads** – Define multiple listeners, each with its own upstream, TLS certificate, rule file, and log. Finch hot‑reloads configuration and rule files automatically whenever they change or when it receives `SIGHUP`.  \n- **HTTP/3 \u0026 QUIC support** (experimental) – Parse QUIC Initial packets to generate JA4 fingerprints and apply the rule engine to HTTP/3 traffic.  \n\n\n## Installation\n\n### Building from source\n\nFinch requires Go 1.24 or newer. Clone the repository and build:\n\n```bash\ngit clone https://github.com/0x4D31/finch.git\ncd finch\ngo build -o finch ./cmd/finch\n# or embed a version string at compile time\nexport VERSION=v0.1.0\ngo build -ldflags \"-X main.version=${VERSION}\" -o finch ./cmd/finch\n```\n\nA `Makefile` defines tasks like building (`make build`), running unit tests (`make test`), running [golangci‑lint](https://golangci-lint.run/) (`make lint`) and building a Docker image (`make docker-build`).  `make build` injects the current Git tag as the version.\n\n### Docker\n\nBuild the container image:\n\n```bash\ndocker build --build-arg VERSION=v0.1.0 -t finch:v0.1.0 .\n```\n\nThe container listens on port 8443. Configure listeners and upstreams via environment variables (e.g. `FINCH_LISTEN`, `FINCH_UPSTREAM`) or flags. When running in a container, publish port 8443 and mount your configuration and rule files. Do not mix `FINCH_LISTEN`/`--listen` with `--config`.\n\n## Quick Start\n\nRun Finch without a configuration file using quick‑mode flags:\n\n```bash\nfinch serve --listen :8443 --rule-file my.rules.hcl \\\n            --upstream http://localhost:8080\n```\n\nFor production, provide an HCL config:\n\n```bash\nfinch serve --config configs/finch.hcl\n```\n\nUseful flags include:\n\n| Flag                            | Purpose                                                        |\n| ------------------------------- | -------------------------------------------------------------- |\n| `--listen`                      | Bind address for quick mode (repeatable).                      |\n| `--upstream`                    | Default upstream URL for proxying requests.                    |\n| `--rule-file`                   | Path to the HCL rule file when using quick mode.               |\n| `--access-log`                  | Path to the JSONL access log.                                  |\n| `--log-level`                   | Set log level (`debug`, `info`, `warn`, `error`).              |\n| `finch validate --config FILE`  | Validate a main config file.                                   |\n| `finch validate --rules FILE`   | Validate a rule file only.                                     |\n| `finch echo --listen ADDR`      | Run an echo server                                             |\n| `--upstream-ca-file`            | PEM file containing CAs trusted for upstream HTTPS.            |\n| `--upstream-skip-tls-verify`    | Skip verification of upstream certificates (use with caution). |\n| `--admin-addr`/`--enable-admin` | Enable and configure the admin API.                            |\n| `--sse-addr`/`--enable-sse`     | Enable and configure the SSE feed.                             |\n| `--admin-token`                 | Bearer token required for the admin API.                       |\n\nFinch automatically reloads its configuration and rule files when they change or when it receives a `SIGHUP`.\n\n## Configuration\n\nFor complex deployments write a configuration file in HCL. A top‑level `defaults` block provides inherited settings for listeners. Relative paths are resolved relative to the config file’s directory. Command‑line flags and environment variables override fields in the `defaults` block or top‑level `admin`/`sse` settings, but cannot override per‑listener fields when `--config` is provided.\n\nExample configuration:\n\n```hcl\ndefaults {\n  rule_file        = \"/etc/finch/default.rules.hcl\"\n  access_log       = \"/var/log/finch/events.jsonl\"\n  default_action   = \"deny\"\n}\n\nsuricata {\n  enabled   = true\n  rules_dir = \"/etc/suricata/rules\"\n}\n\nadmin {\n  enabled = true\n  addr    = \"127.0.0.1:9035\"\n  token   = \"super‑secret\"\n}\n\nsse { enabled = true }\n\nlistener \"public\" {\n  id       = \"public\"\n  bind     = \"0.0.0.0:8443\"\n  upstream = \"http://localhost:8080\"\n  tls {\n    cert = \"/path/to/cert.pem\"\n    key  = \"/path/to/key.pem\"\n  }\n  access_log = \"/var/log/finch/public.jsonl\"\n}\n\nlistener \"honeypot\" {\n  id        = \"hp\"\n  bind      = \"0.0.0.0:9443\"\n  upstream  = \"http://localhost:8081\"\n  rule_file = \"/etc/finch/hp.rules.hcl\"\n}\n```\n\nSee [Configuration](docs/configuration.md) for a detailed description of every field and configuration precedence.\n\n## Rule Engine\n\nRules are written in HCL and define an `action` (`allow`, `deny`, `route` or `deceive`), optional metadata (e.g. `upstream`, `strip_prefix`, `expires`, `deception_mode`) and a `when` block containing conditions. The top‑level `when` block can be labelled `when all` (AND) or `when any` (OR); omitting the label implies `all`.\n\nCondition fields include TLS and HTTP fingerprints, HTTP methods and paths, header maps, client IP ranges and Suricata messages. Prefix (`^`), exact (`=`) and regex (`~`) matching operators are supported. See [Rule Schema](docs/rule-schema.md) for full details and examples.\n\nExample ruleset:\n```hcl\n# Block a known scanner by JA3 fingerprint\nrule \"block-scanner-ja3\" {\n  action = \"deny\"\n\n  when {\n    tls_ja3 = [\"3518c438fe56bd7dba3f6e28example\"]  # ZMap TLS fingerprint\n  }\n}\n\n# Deceive anything that matches an evasive JA4 profile\nrule \"deception-rule\" {\n  action         = \"deceive\"\n  deception_mode = \"tarpit\"        # or \"galah\" for AI‑generated responses\n\n  when any {                       # match if any field is true\n    tls_ja4   = [\"q13d0312h3_55b375c5d22e_c183556c78e2\"]\n    http_ja4h = [\"^ bad-ja4h\"]\n  }\n}\n\n# Block requests with a suspicious header value\nrule \"block-bad-header\" {\n  action = \"deny\"\n\n  when {\n    http_header = {\n      \"user-agent\" = [\"^ EvilBot/\"]\n    }\n  }\n}\n```\n\n## Echo Mode\n\n`finch echo` starts a server that returns fingerprint information instead of proxying. Endpoints include:\n\n* `/` – returns an HTML page showing the user agent and generated fingerprints.\n* `/fp/` – returns a compact JSON object of fingerprints.\n* `/fp/detail` – returns a detailed JSON object including TLS ClientHello fields, HTTP headers, HTTP/2 frame data and fingerprints.\n\nEcho mode disables the SSE feed and rule evaluation.\n\n![echo](docs/images/echo.png \"echo\")\n\n## Suricata HTTP Rule Support\n\nIf the `suricata` block is enabled and a `rules_dir` is specified, Finch watches all `.rules` files in that directory and reloads them automatically. Matched Suricata messages can be referenced in Finch rules via the `suricata_msg` field. Currently, only a subset of Suricata’s HTTP keywords are supported, and PCRE handling is limited. For a list of supported keywords and additional details, refer to the Galah [Suricata package](https://github.com/0x4D31/galah/tree/main/docs/SURICATA.md) documentation.\n\n## Server‑Sent Events\n\nWhen enabled (via `--enable-sse`/`sse.enabled`) Finch exposes a live SSE feed at `/events` on the address specified by `--sse-addr` (default `:9036`). Each event is a JSON object identical to the access log entries. See [sse-client](docs/sse-client.html) for a simple client example.\n\n## Admin API\n\nThe admin API (experimental) listens on the address provided via `--admin-addr` or `admin.addr`.  Set `--enable-admin=false` or `admin.enabled = false` to disable it. If a bearer token is configured (`--admin-token` or `admin.token`), requests must include `Authorization: Bearer \u003ctoken\u003e` (case‑sensitive). Endpoints include:\n\n* `GET /config` – return the active configuration as formatted JSON, with an `ETag` header.\n* `POST /load` – replace the configuration with the request body (HCL or JSON).  Requires an `If-Match` header containing the current `ETag`.\n* `POST /stop` – gracefully stop Finch.\n* `GET /rulesets` – list rule files with IDs and listeners referencing them.\n* `GET /rulesets/{id}` / `POST /rulesets/{id}` / `DELETE /rulesets/{id}` – retrieve, update or delete rule files at runtime.\n* `PUT /config/listeners/{name}/ruleset?id=\u003cid\u003e` – switch a listener to a different rule file.\n\nAll relative paths in configurations loaded via the admin API are resolved against Finch’s current working directory.\n\n## Additional Tools\n\nFinch ships an auxiliary CLI tool: **quic‑chdump** – extracts QUIC ClientHello messages from PCAPs or live traffic and logs the SNI and JA3/JA4 fingerprints. See [cmd/quic-chdump](cmd/quic-chdump/README.md) and [docs/http3-quic.md](docs/http3-quic.md) for more information.\n\n## Testing and Linting\n\nRun unit tests with:\n\n```bash\ngo test ./...\n```\n\nSome proxy integration tests require open network sockets and are guarded by the build tag `skipproxy`. To run the full suite including proxy tests, add `-tags skipproxy`.\n\nStatic analysis is performed via [golangci‑lint](https://golangci-lint.run/) – run `make lint` to ensure code quality.\n\n## Contributing\n\nContributions, bug reports and feature requests are welcome! Please open an issue or pull request. Ensure tests pass and `golangci‑lint` reports no warnings before submitting patches.\n\n## License\n\nFinch is developed by Adel \"0x4D31\" Ka and licensed under the [Apache License 2.0](LICENSE). It uses the [fingerproxy](https://github.com/wi1dcard/fingerproxy) package, also under the Apache‑2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0x4d31%2Ffinch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0x4d31%2Ffinch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0x4d31%2Ffinch/lists"}