{"id":37136440,"url":"https://github.com/grepplabs/reverse-http","last_synced_at":"2026-01-14T15:54:01.256Z","repository":{"id":224552475,"uuid":"763513433","full_name":"grepplabs/reverse-http","owner":"grepplabs","description":"Reverse HTTP proxy over QUIC protocol","archived":false,"fork":false,"pushed_at":"2025-11-05T08:12:30.000Z","size":142,"stargazers_count":5,"open_issues_count":12,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-05T08:34:34.745Z","etag":null,"topics":["edge","go","golang","http","https","quic","reverse-http","reverse-proxy","tunnel"],"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/grepplabs.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-02-26T12:46:37.000Z","updated_at":"2025-11-05T06:54:28.000Z","dependencies_parsed_at":"2024-06-21T13:12:42.595Z","dependency_job_id":"1088e924-0c48-44b0-a5b3-783d6239ee23","html_url":"https://github.com/grepplabs/reverse-http","commit_stats":null,"previous_names":["grepplabs/reverse-http"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/grepplabs/reverse-http","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grepplabs%2Freverse-http","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grepplabs%2Freverse-http/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grepplabs%2Freverse-http/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grepplabs%2Freverse-http/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grepplabs","download_url":"https://codeload.github.com/grepplabs/reverse-http/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grepplabs%2Freverse-http/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28425558,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T15:24:48.085Z","status":"ssl_error","status_checked_at":"2026-01-14T15:23:41.940Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["edge","go","golang","http","https","quic","reverse-http","reverse-proxy","tunnel"],"created_at":"2026-01-14T15:54:00.637Z","updated_at":"2026-01-14T15:54:01.238Z","avatar_url":"https://github.com/grepplabs.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# reverse-http\n[![Build Status](https://github.com/grepplabs/reverse-http/actions/workflows/build.yml/badge.svg)](https://github.com/grepplabs/reverse-http/actions/workflows/build.yml)\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Release](https://img.shields.io/github/v/release/grepplabs/reverse-http?sort=semver)](https://github.com/grepplabs/reverse-http/releases)\n\nReverse HTTP proxy over QUIC protocol ([RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000)).\n\n## Architecture\n\n### Standalone\n\n\u003cp style=\"text-align: center;\"\u003e\u003cimg src=\"docs/reverse-http-arch.svg\" alt=\"Architecture\"\u003e\u003c/p\u003e\n\n* Agent connection process\n  * An agent initiates a connection to the proxy server utilizing the `QUIC` protocol.\n    * The connection between the agent and the proxy is persistent\n  * Upon connection, the proxy server performs an agent authentication\n  * The proxy keeps track of agents' connections\n    * Each agent is uniquely identified by an `agentID`\n    * Multiple agents can simultaneously connect to the proxy.\n    * Only one connection per `agentID` is allowed.\n\n* Client connection process\n  * Clients establish a connection with the HTTP proxy by issuing an `HTTP CONNECT` request. This standard method allows the client to specify the desired destination.\n  * During the connection process, the proxy authenticates the connecting client using basic `Proxy-Authorization`, where the `username` is utilized to specify the `agentID` that the client wishes to connect to.\n  * Once authenticated, the proxy server locates the corresponding agent's `QUIC` connection that is already being tracked.\n  * Proxy opens a new `QUIC` stream to the agent and sends all subsequent data through it\n  * The agent proceeds with the `CONNECT` procedure by establishing a new TCP connection to the requested destination.\n\n### HA setup\n\n\u003cp style=\"text-align: center;\"\u003e\u003cimg src=\"docs/reverse-http-ha.svg\" alt=\"HA\"\u003e\u003c/p\u003e\n\n* Agent connection process\n  * An agent initiates a connection to the UDP load balancer, which in turn establishes a connection with one of the proxy servers\n  * Upon establishing a connection, the proxy server records an entry in `memcached` for an agentID along with its own HTTP proxy address.\n* Client connection process\n  * Clients connect to the TCP load balancer, which then establishes a connection with one of the LB servers.\n  * Upon connection, the LB server retrieves the HTTP proxy address and an agentID from Memcached.\n    * The LB server then sends an `HTTP CONNECT` request to the proxy.\n\n## Install binary release\n\n1. Get latest tag version\n    ```\n    TAG=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/grepplabs/reverse-http/releases/latest | grep -o 'tag/.*' | sed 's/tag\\///')\n    VERSION=$(echo -n $TAG | grep -o 'v[0-9.]*' | sed 's/v//')\n    ```\n2. Download the release\n   * Linux\n     ```\n      curl -Ls https://github.com/grepplabs/reverse-http/releases/download/${TAG}/reverse-http_${VERSION}_linux_amd64.tar.gz | tar xz\n     ```\n   * MacOS Intel\n     ```\n     curl -Ls https://github.com/grepplabs/reverse-http/releases/download/${TAG}/reverse-http_${VERSION}_darwin_amd64.tar.gz | tar xz\n     ```\n\n   * MacOS Apple Silicon\n     ```\n     curl -Ls https://github.com/grepplabs/reverse-http/releases/download/${TAG}/reverse-http_${VERSION}_darwin_arm64.tar.gz | tar xz\n     ```\n\n3. Move the binary to a file location on your system PATH.\n    ```\n    mv ./reverse-http /usr/local/bin/reverse-http\n    ```\n\n## Docker run\n  ```\n  docker run --rm ghcr.io/grepplabs/reverse-http:latest --help\n  ```\n\n## Build\n### build binary\n\n    make clean build\n\n\n## Quick requirements\n\nhttps://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes\n\n```bash\nsudo bash -c 'echo net.core.rmem_max=2500000 \u003e\u003e /etc/sysctl.conf'\nsudo bash -c 'echo net.core.wmem_max=2500000 \u003e\u003e /etc/sysctl.conf'\nsudo sysctl -p\n```\n\n\n\n## Local test standalone\n\n### no auth\n\n```bash\nmake start-proxy\nmake start-agent\ncurl -x \"http://4711:noauth@localhost:3128\" https://httpbin.org/ip\n```\n\n### jwt auth\n\n```bash\nmake start-proxy-jwt\nmake start-agent-jwt\nmake curl-proxy-jwt\n```\n\n## Local test docker-compose\n\n```bash\nmake TEST_AUTH=noauth docker-compose.run\nmake TEST_AGENT_ID=4711 curl-proxy\nmake TEST_AGENT_ID=4712 curl-proxy\n```\n\n## Whitelisting patterns\n\n```\nlocalhost\nlocalhost:80\nlocalhost:1000-2000\n*.zone\n*.zone:80\n*.zone:1000-2000\n127.0.0.1\n127.0.0.1:80\n127.0.0.1:1000-2000\n10.0.0.1/8\n10.0.0.1/8:80\n10.0.0.1/8:1000-2000\n1000::/16\n1000::/16:80\n1000::/16:1000-2000\n[2001:db8::1]/64\n[2001:db8::1]/64:80\n[2001:db8::1]/64:1000-2000\n2001:db8::1\n[2001:db8::1]\n[2001:db8::1]:80\n[2001:db8::1]:1000-2000\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrepplabs%2Freverse-http","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrepplabs%2Freverse-http","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrepplabs%2Freverse-http/lists"}