Drop-in proxy for Discord gateway connections and sessions allowing for zero downtime deploys

Overview

gateway-proxy

This is a very hacky project, so it might stop working if Discord changes their API core. This is unlikely, but keep that in mind while using the proxy.

This is a proxy for Discord gateway connections - clients can connect to this proxy instead of the Discord Gateway and interact with it just like they would with the Discord Gateway.

The proxy connects to Discord instead of the client - allowing for zero-downtime client restarts while the proxy keeps its connections to the gateway open. The proxy won't invalidate your sessions or disconnect you (exceptions below).

How?

It connects all shards to Discord upfront and mimics to be the actual API gateway.

When a client sends an IDENTIFY payload, it takes the shard ID specified and relays all events for that shard to the client.

It also sends you self-crafted, but valid READY and GUILD_CREATE/GUILD_DELETE payloads at startup to keep your guild state up to date, just like Discord does, even though it doesn't reconnect when you do internally.

Because the IDENTIFY is not actually controlled by the client side, activity data must be specified in the config file and will have no effect when sent in the client's IDENTIFY payload.

It uses a minimal algorithm to replace the sequence numbers in incoming payloads with fake sequence numbers that are valid for the clients, but does not need to parse the JSON for that.

Configuration

Create a file config.json and fill in these fields as you wish:

{
  "log_level": "info",
  "token": "",
  "intents": 32511,
  "port": 7878,
  "activity": {
    "type": 0,
    "name": "with kubernetes"
  },
  "status": "idle",
  "backpressure": 100,
  "cache": {
    "channels": false,
    "presences": false,
    "emojis": false,
    "members": false,
    "roles": false,
    "stage_instances": false,
    "stickers": false,
    "users": false,
    "voice_states": false
  }
}

If you have a fixed shard count, set shards to the amount of shards. If you're using twilight's HTTP-proxy, set twilight_http_proxy to the ip:port of the HTTP proxy.

Take special care when setting cache flags, only enable what you actually need. The proxy will tend to send more than Discord would, so double check what your bot depends on.

Running

Compiling this from source isn't the most fun, you'll need a nightly Rust compiler with the rust-src component installed. Then run cargo build --release --target=MY_RUSTC_TARGET, where MY_RUSTC_TARGET is probably x86_64-unknown-linux-gnu.

Instead, I recommend running the Docker images that are prebuilt by CI.

docker.io/gelbpunkt/gateway-proxy:latest requires a Haswell-family CPU or newer (due to AVX2) and will perform best, docker.io/gelbpunkt/gateway-proxy:sandybridge requires a Sandy Bridge-family CPU or newer and will perform slightly worse.

To run the image, mount the config file at /config.json, for example:

docker run --rm -it -v /path/to/my/config.json:/config.json docker.io/gelbpunkt/gateway-proxy:latest

Connecting

Connecting is fairly simple, just hardcode the gateway URL in your client to ws://localhost:7878. Make sure not to ratelimit your connections on your end.

Important: The proxy detects zlib-stream query parameters and compress fields in your IDENTIFY payloads and will encode packets if they are enabled, just like Discord. This comes with CPU overhead and is likely not desired in localhost networking. Make sure to disable this if so.

Metrics

The proxy exposes Prometheus metrics at the /metrics endpoint. They contain event counters, cache size and shard latency histograms specific to each shard.

Caveats

RESUMEs will always result in a session invalidation because the proxy doesn't really track session IDs. Just reidentify, it's free.

Known Issues / TODOs

  • Maybe adhere to this: When initially connecting, if you don't have the GUILD_PRESENCES Gateway Intent, or if the guild is over 75k members, it will only send members who are in voice, plus the member for you (the connecting user). Otherwise, if a guild has over large_threshold members (value in the Gateway Identify), it will only send members who are online, have a role, have a nickname, or are in a voice channel, and if it has under large_threshold members, it will send all members. (though I think this is already wrong documentation from Discord, a 30k member guild above threshold already only sends the bot member)
You might also like...
Reliable p2p network connections in Rust with NAT traversal
Reliable p2p network connections in Rust with NAT traversal

Reliable p2p network connections in Rust with NAT traversal. One of the most needed libraries for any server-less, decentralised project.

A simple API gateway written in Rust, using the Hyper and Reqwest libraries.

API Gateway A simple API gateway written in Rust, using the Hyper and Reqwest libraries. This gateway can be used to forward requests to different bac

RDE1 (Rusty Data Exfiltrator) is client and server tool allowing auditor to extract files from DNS and HTTPS protocols written in Rust. 🦀
RDE1 (Rusty Data Exfiltrator) is client and server tool allowing auditor to extract files from DNS and HTTPS protocols written in Rust. 🦀

Information: RDE1 is an old personal project (end 2022) that I didn't continue development on. It's part of a list of projects that helped me to learn

A Prometheus Aggregation Gateway for FAAS applications

Gravel Gateway Gravel Gateway is a Prometheus Push Gateway for FAAS applications. In particular it allows aggregation to be controlled by the incoming

A Prometheus Aggregation Gateway for FAAS applications

Gravel Gateway Gravel Gateway is a Prometheus Push Gateway for FAAS applications. In particular it allows aggregation to be controlled by the incoming

A rust-based command line tool to serve as a gateway for a Internet Computer replica.

icx-proxy A command line tool to serve as a gateway for a Internet Computer replica. Contributing Please follow the guidelines in the CONTRIBUTING.md

The registration server for WebThings Gateway.

Registration Server This server exposes an HTTP API that lets you register a WebThings Gateway for tunneling support. When combined with a PowerDNS se

WireGuard gateway with SNI for portable connectivity.

Gateway This is a daemon that controls gateway servers. Gateway servers are servers that fulfil three major purposes: facilitating connectivity betwee

A library-first, lightweight, high-performance, cloud-native supported API gateway🪐 by RUST

Preview version, will not guarantee the stability of the API! Do NOT use in production environment! A library-first, lightweight, high-performance, cl

Comments
  • Add self cache

    Add self cache

    Hello, it would be nice to be able to have the proxy cache self members (the member instance for the bot itself) without having to cache all members. This member has useful data such as permissions and role hierarchy.

    enhancement 
    opened by Fabricio20 1
  • Improve logging

    Improve logging

    Logging output should be more consistent:

    • Prefix it with the shard ID and if not known yet, client IP
    • Don't log packets in debug, only in trace
    • More info logs
    enhancement 
    opened by Gelbpunkt 0
  • Add JDA Example

    Add JDA Example

    Adds a JDA example to the repository, this example was tested on Java 16 but should be compatible starting with Java 8. I added a proper README as well with instructions on how to run it.

    The example bot simply logs all messages received and shard status changes, by default TRACE logging is enabled for JDA so raw payloads are shown.

    JDA 4 has a limitation that it relies on the private_channels field being present in the READY payload, this example takes care of it by No-Oping the part of the code that uses it. This should be fixed in JDA 5.

    opened by Fabricio20 0
  • Voice support

    Voice support

    Hey, thanks for making great lib !

    I have several question:

    • If client connect to this proxy and connected to voice, when client disconnected from proxy will that make the voice session became invalid?

    I have tested this proxy with lavalink and when the client disconnected from the proxy. discord sent invalid session to voice gateway. i dont know is it my problem or this proxy problem.

    help wanted question 
    opened by KagChi 1
Owner
Jens Reidel
I love high-performance code, Rust, Python and Discord Bots.
Jens Reidel
A fast, stable, efficient, and lightweight intranet penetration, port forwarding tool supports multiple connections, cascading proxy, and transmission encryption

A fast, stable, efficient, and lightweight intranet penetration, port forwarding tool supports multiple connections, cascading proxy, and transmission encryption

editso 1.3k Dec 30, 2022
Checks Neos VR sessions to see if they're up

Checks Neos VR sessions to see if they're up

Michael Ripley 1 Nov 14, 2021
UDP proxy with Proxy Protocol and mmproxy support

udppp UDP proxy with Proxy Protocol and mmproxy support. Features Async Support Proxy Protocol V2 SOCKET preserve client IP addresses in L7 proxies(mm

b23r0 10 Dec 18, 2022
Web3-proxy: a fast caching and load balancing proxy for web3 (Ethereum or similar) JsonRPC servers.

web3-proxy Web3-proxy is a fast caching and load balancing proxy for web3 (Ethereum or similar) JsonRPC servers. Signed transactions (eth_sendRawTrans

null 55 Jan 8, 2023
Proxy sentry request to a sentry server using a tunnel/proxy endpoint

Sentry Tunnel This is a proxy that forwards tunneled sentry requests to the real sentry server. The implementation is based on the explanation provide

Paul FLORENCE 14 Dec 20, 2022
Lightweight proxy that allows redirect HTTP(S) traffic through a proxy.

Proxyswarm Proxyswarm is a lightweight proxy that allows redirect HTTP(S) traffic through a proxy. WARNING: This app isn't recomended for download lar

Jorge Alejandro Jimenez Luna 4 Apr 16, 2022
A TCP proxy using HTTP - Reach SSH behind a Nginx reverse proxy

?? TCP over HTTP ?? The Questions ?? What does it do? You can proxy TCP traffic over HTTP. A basic setup would be: [Your TCP target] <--TCP-- [Exit No

Julian 185 Dec 15, 2022
Easy-to-use wrapper for WebRTC DataChannels peer-to-peer connections written in Rust and compiling to WASM.

Easy-to-use wrapper for WebRTC DataChannels peer-to-peer connections written in Rust and compiling to WASM.

null 58 Dec 11, 2022
A library for easily creating WebRTC data channel connections in Rust

Cyberdeck A library for easily creating WebRTC data channel connections in Rust.

RICHΛRD ΛNΛYΛ 34 Nov 10, 2022
Reliable p2p network connections in Rust with NAT traversal

Reliable p2p network connections in Rust with NAT traversal. One of the most needed libraries for any server-less / decentralised projects

MaidSafe-Archive 948 Dec 20, 2022