{"id":18663510,"url":"https://github.com/st3iny/snip","last_synced_at":"2025-11-06T08:30:26.500Z","repository":{"id":258250667,"uuid":"778935428","full_name":"st3iny/snip","owner":"st3iny","description":"A tiny TLS pass-through reverse proxy and load balancer based no peeking SNI messages.","archived":false,"fork":false,"pushed_at":"2024-11-15T11:07:31.000Z","size":22,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-27T17:14:21.287Z","etag":null,"topics":["go","load-balancer","pass-through","proxy-protocol","reverse-proxy","server-name-indication","tls","tls-proxy"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/st3iny.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}},"created_at":"2024-03-28T17:42:31.000Z","updated_at":"2024-11-15T11:07:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"7266471b-1927-4198-9805-b5b822bda540","html_url":"https://github.com/st3iny/snip","commit_stats":null,"previous_names":["st3iny/snip"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st3iny%2Fsnip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st3iny%2Fsnip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st3iny%2Fsnip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st3iny%2Fsnip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/st3iny","download_url":"https://codeload.github.com/st3iny/snip/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239487735,"owners_count":19647055,"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","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":["go","load-balancer","pass-through","proxy-protocol","reverse-proxy","server-name-indication","tls","tls-proxy"],"created_at":"2024-11-07T08:18:15.142Z","updated_at":"2025-11-06T08:30:26.460Z","avatar_url":"https://github.com/st3iny.png","language":"Go","readme":"# snip\n\nA tiny TLS pass-through reverse proxy and load balancer based no peeking SNI messages.\nIt also supports proxying to upstreams via\n[PROXY protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) version 2.\n\nPROXY protocol allows to retain a client's remote ip address and is widely supported by all major\nweb servers and reverse proxies, e.g. Apache, Nginx and Caddy.\nIt is like the `X-Forwarded-For` header but for TLS connections.\n\n## Motivation\n\nI was using Nginx as a TLS pass-through reverse proxy in production.\nIt works fine but there is one problem: It does not allow to enable PROXY protocol for some\nupstreams only.\nInstead, the protocol can either be enabled globally for all upstreams or not at all.\n\nAfter a quick research session I discovered that writing a TLS pass-through proxy is actually\nrather simple and Go provides all the TLS and SNI logic out of the box.\nThe two external dependencies are for speaking PROXY protocol to backends and parsing the\nTOML configuration file.\n\n## Usage\n\nCreate a suitable configuration file at `/etc/snip/config.toml` (or anywhere else) and start snip.\nIt currently accepts a single optional flag to set the location of the configuration file via\n`--config`.\n\nValidate the configuration by running the following command: `snip [--config PATH] validate`.\nIt will print some information and the exit code will be adjusted accordingly.\n\nSnip is able to reload its configuration without restarting.\nSend the `USR1` signal to the running program to trigger a reload, e.g. `kill -USR1 $PID`.\nPlease also have a look at the provided Systemd service at `./snip.service`.\n\n## Configuration\n\nPlease have a look at the exemplary configuration file at `./config.toml`.\nIt contains detailed information about each setting and some usage examples.\n\nThere are two main concepts in the architecture of snip: frontends and backends.\nTraffic from clients is routed from a frontend to a backend and then to an upstream server.\n\nThe following chart provides an overview.\n\n```mermaid\nflowchart TD\n    C[Client] --\u003e|example.com:443| F1\n    subgraph snip [snip]\n        F1(\u003cb\u003eFrontend\u003c/b\u003e\u003cbr\u003eexample.com) --\u003e B1(\u003cb\u003eBackend\u003c/b\u003e\u003cbr\u003ecaddy)\n        F2(\u003cb\u003eFrontend\u003c/b\u003e\u003cbr\u003e*.cluster.example.com) --\u003e B2(\u003cb\u003eBackend\u003c/b\u003e\u003cbr\u003ecluster)\n    end\n    B1 --\u003e U1[127.0.0.1:8443]\n    B2 --\u003e U2[node1:443]\n    B2 --\u003e U3[node2:443]\n```\n\n### Frontend\n\nA frontend is an exact domain, a wildcard or a catch-all matcher.\nEach frontend has to specify a backend to route incoming traffic to.\nThe specified backend can either be a named backend, hostname or ip address of an upstream server,\ne.g. `10.0.0.20:443` or `node1:443`.\nA port must be specified if another host or ip address is specified directly.\n\nOtherwise, a named backend will be looked up in the declared backend configuration.\nIn this case a port must not be specified.\nSee below for more information.\n\n### Backend\n\nA backend is an upstream server to which traffic should be proxied.\nIt consists of a unique name, a list of hostnames or ip addresses of upstream servers and some\noptional configuration.\n\nEach upstream should be in the common address and port format, e.g. `10.0.0.20:443` or `node1:443`.\nConnections will be balanced randomly between all upstreams.\nCurrently, there are no health checks implemented, meaning that the connection will be dropped if\nthe first chosen upstream is down.\nIn the future, additional balancing methods and proper health checking may be implemented.\n\nTo enable PROXY protocol, set `proxy_protocol = true` on the backend.\nOptionally, it is also possible to overwrite the global value of `connect_timeout` for each\nbackend.\n\n## Build\n\n1. Install Go \u003e= 1.22\n2. Run `make` or `go build -o bin/snip cmd/snip/main.go`\n3. Use the binary at `bin/snip` and install it to e.g. `/usr/local/bin/snip`.\n\n### Nix and NixOS\n\nRun `nix shell github:st3iny/snip` to build and test the program.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fst3iny%2Fsnip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fst3iny%2Fsnip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fst3iny%2Fsnip/lists"}