Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot connect to Discord via websocket #1197

Closed
CompaqDisc opened this issue Oct 31, 2022 · 2 comments
Closed

Cannot connect to Discord via websocket #1197

CompaqDisc opened this issue Oct 31, 2022 · 2 comments
Labels
area-Core This affects CC's core (the Lua runtime, APIs, computer internals). bug A problem or unexpected behaviour with the mod.

Comments

@CompaqDisc
Copy link

CompaqDisc commented Oct 31, 2022

Minecraft Version

1.19.x

Version

1.100.10

Details

Logs:
latest.log
debug.log

Root Cause

I've found out by fiddling with curl that this is caused by ComputerCraft/Netty adding an origin header to the request.


Action Performed:
I tried connecting to the Discord Gateway API using http.websocket(url, headers)

The Lua code for which was:

local api_base = "https://discord.com/api/v10"
local default_headers = {
    ["User-Agent"] = "DiscordBot (https://compaqdisc.com/, 1.0)"
}

-- Get gateway websocket uri
function get_gateway()
    resp = http.get(api_base .. "/gateway", default_headers)
    return textutils.unserializeJSON(resp.readAll())["url"]
end

function open_discord_ws(gateway_uri)
    return http.websocket(gateway_uri, default_headers)
end

gateway = get_gateway()
print("Discord gateway URI: " .. gateway)
ws, error = open_discord_ws(gateway ..  "/?v=10&encoding=json")
if ws == false then
    print(error)
    return
end
print(ws.receive())
ws.close()

Expected Result:
The connection would succeed and I would receive the expected WebSocket message, in the same manner as the tool wscat, invoked as per the following (and run from the same PC/IP address):

wscat -H "User-Agent: DiscordBot (https://compaqdisc.com/, 1.0)" --connect "wss://gateway.discord.gg/?v=10&encoding=json"

Actual Result:
My connection is disconnected with the error: Invalid handshake response getStatus: 403 Forbidden, which results from Cloudflare dropping the connection with a HTTP 403 / Cloudflare 1020.

Additionally:
The existing code works correctly if I instead try to connect to wss://api.kashall.dev/socket, which the author @kashalls has told me is written in NodeJS and is also behind Cloudflare. So my primary concern is if behind the scenes something odd is done that would result in such behaviour.

Requests (captured from Wireshark)
Successful (with wscat, it actually returns 301, because for testing I did this over http):

Transmission Control Protocol, Src Port: 33366, Dst Port: 80, Seq: 1, Ack: 1, Len: 302
Hypertext Transfer Protocol
    GET /?v=10&encoding=json HTTP/1.1\r\n
    Sec-WebSocket-Version: 13\r\n
    Sec-WebSocket-Key: 7QGr6iUbtzcY3l1PZ1Tk2w==\r\n
    Connection: Upgrade\r\n
    Upgrade: websocket\r\n
    User-Agent:  DiscordBot (https://compaqdisc.com/, 1.0)\r\n
    Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n
    Host: gateway.discord.gg\r\n
    \r\n
    [Full request URI: http://gateway.discord.gg/?v=10&encoding=json]
    [HTTP request 1/1]
    [Response in frame: 461]

Unsuccessful (ComputerCraft):

Transmission Control Protocol, Src Port: 57448, Dst Port: 80, Seq: 1, Ack: 1, Len: 399
Hypertext Transfer Protocol
    GET /?v=10&encoding=json HTTP/1.1\r\n
    User-Agent: DiscordBot (https://compaqdisc.com/, 1.0)\r\n
    host: gateway.discord.gg\r\n
    upgrade: websocket\r\n
    connection: upgrade\r\n
    sec-websocket-key: dnJmguIrvsyIKHB3ZSFxEA==\r\n
    origin: http://gateway.discord.gg\r\n
    sec-websocket-version: 13\r\n
    sec-websocket-extensions: permessage-deflate;client_no_context_takeover;client_max_window_bits,deflate-frame,x-webkit-deflate-frame\r\n
    \r\n
    [Full request URI: http://gateway.discord.gg/?v=10&encoding=json]
    [HTTP request 1/1]
    [Response in frame: 26]
@CompaqDisc CompaqDisc added the bug A problem or unexpected behaviour with the mod. label Oct 31, 2022
@SquidDev
Copy link
Member

Thank you for the detailed report, that's very useful! Maybe I need a separate issue label for websockets, the bugs are always so nasty >_>.

In this case, it looks to be an instance of netty/netty#9673. I think the easiest thing to do here is subclass WebSocketClientHandshaker13, override newHandshakeRequest and then remove the Origin header from the request if it's not present in the user-supplied custom headers.

Will have a look at that this evening. Should be easy, just unfortunate it needs to be done at all!

@CompaqDisc
Copy link
Author

I'm happy that I was able to get things into the right hands!

Luckily this can be worked around in-game (at least in this particular situation) by defining the origin header content as an empty string like so:

local my_headers = {
    ["X-Foo"] = "bar",
    ["Origin"] = ""
}

@SquidDev SquidDev added the area-Core This affects CC's core (the Lua runtime, APIs, computer internals). label Oct 31, 2022
SquidDev added a commit that referenced this issue Oct 31, 2022
Technically this removes Sec-Websocket-Origin, as that's what the
current version of Netty uses. We'll need to change this on 1.18+.

Closes ##1197.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Core This affects CC's core (the Lua runtime, APIs, computer internals). bug A problem or unexpected behaviour with the mod.
Projects
None yet
Development

No branches or pull requests

2 participants