TCP and TLS endpoints

Not everything speaks HTTP. A TCP endpoint gives any TCP service — SSH, a database, RDP, a Minecraft Java server — a public address, and a TLS endpoint passes encrypted connections to a service that terminates TLS itself. Both are on paid plans: an open port attracts scanners, which is why ngrok asks for a card first too.

TCP and TLS endpoints are rolling out; the agent says so if they aren’t on for your account yet.

TCP

$ devgate tcp 22

The agent prints an address like tcp://tcp.devgate.run:21734; connect to that host and port. Each run gets a new port — --url tcp:// with no address, or url: tcp:// in a config file, asks for the same. To keep one, reserve a TCP endpoint in the dashboard (Endpoints → Reserve endpoint → protocol TCP) and start it by its address or name:

$ devgate tcp 22 --url tcp://tcp.devgate.run:21734

Limit who can connect with --cidr-allow and --cidr-deny, or a Traffic Policy’s on_tcp_connect rules (restrict-ips, deny); request-level actions don’t apply to raw TCP.

TLS

$ devgate tls 8443 --url tls://app.example.com

devgate reads only the server name from the handshake and sends the connection, still encrypted, to your service on port 8443, which presents its own certificate. TLS endpoints run on your own domains — names under our zones are terminated with our certificate.

The client’s address: PROXY protocol

Connections reach your service from the agent, on your machine, so the service sees the agent’s address, not the client’s. With --proxy-proto, as on ngrok, devgate starts each connection with a PROXY protocol header naming the client — version 1 (text) or 2 (binary) — and the agent passes it through untouched:

$ devgate tcp 5432 --proxy-proto 2
$ devgate tls 8443 --url tls://app.example.com --proxy-proto 1

In a config file it’s upstream.proxy_protocol: 1 or 2. Turn it on only for a service that expects the header — nginx with listen … proxy_protocol, HAProxy with accept-proxy, Traefik, Envoy — since anything else reads it as the start of the client’s data. The agent’s request log shows the client from the header too. HTTP endpoints don’t need it: their requests carry the client in X-Forwarded-For and X-Real-IP.

Billing

TCP and TLS endpoints are metered in connections, apart from HTTP/S requests, as on ngrok: a connection is one however long it stays open, and its bytes count as data transfer. Each plan with TCP includes 5k connections a month; past them they cost $2 per 100k. Agents from 0.21.0 report them on their own; with an older agent the server files what a TCP or TLS endpoint reports as connections, so nothing is counted twice. See usage and limits.

Questions people actually ask

Can I SSH into a machine behind NAT with devgate?

Yes: devgate tcp 22 on that machine gives you tcp://tcp.devgate.run:<port>, and ssh -p <port> user@tcp.devgate.run connects. Reserve a TCP endpoint to keep the same port.

How does my TCP service see the client’s IP address through devgate?

Start the endpoint with --proxy-proto 1 or --proxy-proto 2. devgate then starts every connection with a PROXY protocol header carrying the client’s address, and the agent passes it to your service as it is. nginx (proxy_protocol on a listen), HAProxy and most databases’ proxies read it; a service that doesn’t expect it will see garbage.

What is the difference between a TLS endpoint and an HTTPS one?

An HTTPS endpoint terminates TLS at devgate with our certificate and can run a Traffic Policy on each request. A TLS endpoint passes the encrypted connection through untouched, by its server name: your service holds the certificate and devgate never sees the plaintext.