cloudflare/proxy-everything
Go
Captured source
source ↗cloudflare/proxy-everything
Language: Go
Stars: 7
Forks: 1
Open issues: 0
Created: 2026-01-26T18:19:15Z
Pushed: 2026-04-24T17:01:02Z
Default branch: main
Fork: no
Archived: no
README:
proxyeverything
It's a TPROXY based docker container sidecar to proxy all traffic from a docker container to wherever you want.
It leverages HTTP CONNECT to proxy traffic from the container to the host.
Why do I need this?
This is very useful to do things like "listen to all IP ports that the container connects to". You can implement your own gateway for docker containers like this.
(your gateway) [proxy-everything] [user container]
How to build
GOOS=linux CGO_ENABLED=0 go build .
Attention: Do NOT run proxy-everything on your development machine without isolating it in a docker container or its own network namespace, it will modify your iptables.
You should run it on its own docker container. See "How to use it with Docker".
How to implement your own gateway for proxy-everything to use
A gateway server should:
1. Listen on a TCP port (default: 49121) accessible from the container's Docker bridge network (typically 172.17.0.1:49121).
2. Accept HTTP CONNECT requests. proxy-everything will send requests in this format:
CONNECT : HTTP/1.1 Host: : User-Agent: proxy-everything/0.0.1/ Connection: close X-Forwarded-For: X-Proto: tcp
Optional headers may also be present:
X-Tls-Sni:when outbound TLS traffic exposes SNI.X-Hostname:when outbound HTTP traffic exposes aHostheader and no SNI was available.
3. Parse the destination from the Host header (or request URI) to know where to dial.
4. Establish a connection to the destination (the original target the container wanted to reach).
5. Respond with HTTP status codes:
2xxif the connection to the destination succeeded - the tunnel is now established.400if the connection to the destination failed (e.g., connection refused).- The rest of status codes are treated as errors from the gateway.
6. Relay data bidirectionally between the proxy-everything client and the destination after sending the 200 OK response. The server should:
- Copy data from the proxy connection to the destination connection.
- Copy data from the destination connection back to the proxy connection.
- Handle half-close properly (close write side when read side receives EOF).
See dummyserver.go for a simple reference implementation. If you don't want to implement your own, run proxy-everything's reference implementation like:
SERVER=1 ./proxy-everything
How to use it with Docker
export CONTAINER=mycontainer $ docker build -t proxy-everything:dev . $ docker run \ --add-host=host.docker.internal:host-gateway \ -d --name $(CONTAINER) ubuntu:latest sleep infinity $ docker run \ -it --rm --cap-add=NET_ADMIN \ --network container:$(CONTAINER) \ --name $(CONTAINER)-proxy proxy-everything:dev # In another terminal $ docker exec $(CONTAINER) bash # You can run commands here to check how proxy-everything works
This will make proxy-everything to $(DOCKER_GATEWAY_IP):49121, DOCKER_GATEWAY_IP which usually belongs to 172.17.0.0/16. At startup proxy-everything will use the default DNS resolver of the container to resolve host.docker.internal so it knows which IP to use to proxy traffic.
When you use proxy-everything as a tool that proxies connections to your own host process, you need to make sure you listen in the right IP, usually this can be accomplished by talking to docker and asking the network gateway of the container.
Example:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
...By the default by this example, the TCP address you should be listening in to receive proxy-everything traffic is 172.17.0.1:49121.
TLS interception
Pass -tls-intercept to terminate TLS inside the proxy so the gateway sees plaintext.
docker run \ -it --rm --cap-add=NET_ADMIN \ --network container:$(CONTAINER) \ proxy-everything:dev -tls-intercept
At startup an ephemeral CA is written to /ca/ca.crt and /ca/ca.key. For outbound TLS connections the proxy peeks the SNI from the ClientHello and adds an X-Tls-Sni header to the CONNECT request. If no SNI is present and the payload looks like HTTP, it also peeks the HTTP request headers and adds X-Hostname. The gateway then decides:
- 200 -- terminate TLS. The proxy presents a leaf cert (signed by the ephemeral CA) to the container and forwards plaintext to the gateway.
- 202 -- pass-through. Raw TLS bytes are forwarded as-is; the session stays end-to-end between the container and the origin.
To make the container trust the CA:
docker cp $(CONTAINER)-proxy:/ca/ca.crt /tmp/ca.crt docker cp /tmp/ca.crt $(CONTAINER):/usr/local/share/ca-certificates/proxy-everything.crt docker exec $(CONTAINER) update-ca-certificates
Without -tls-intercept all traffic is forwarded as raw bytes and no CA is generated.
Ingress CONNECT listener
Pass -http-ingress-address= to enable an always-on ingress listener inside proxy-everything. If the flag is empty, no ingress listener is started.
CONNECTrequests are accepted on that listener.X-Dst-Addrmust contain the full destination asIP:port.- If the destination port is closed, the listener returns
400. GET /careturns the PEM-encoded CA certificate (/ca/ca.crt). Only useful when-tls-interceptis enabled. Returns404if the certificate doesn't exist.PUT /egressupdates shared runtime configuration. Supported fields are:port-- updateshttp-egress-portinternet.enabled-- enables or disables internet forwarding for DNS interceptiondns.allowHostnames-- array of hostname globs such as*.google.com,google.com, or*
Example:
# Fetch the CA certificate (requires -tls-intercept)
curl http://127.0.0.1:49122/ca -o ca.crt
curl -X PUT http://127.0.0.1:49122/egress \
-H 'Content-Type: application/json' \
-d '{"port":8080,"internet":{"enabled":true},"dns":{"allowHostnames":["*.google.com","google.com"]}}'
curl -v -x http://127.0.0.1:49122 https://ignored.example \
-H 'X-Dst-Addr: 172.17.0.1:8443'DNS interception
UDP interception is currently limited to DNS on port…
Excerpt shown — open the source for the full document.
Notability
notability 2.0/10Low traction, routine repo