shadowsocks-go icon indicating copy to clipboard operation
shadowsocks-go copied to clipboard

Unable to connect in World of Warcraft (potentially other apps), while other shadowsocks server/client options works

Open mklnz opened this issue 2 years ago • 9 comments

I'm having some difficulty using shadowsocks-go to connect to World of Warcraft via socks5 + proxifier on Windows. It tries to login but disconnects immediately. Browser and other apps so far seems to be working

The client output doesn't show any errors, I've attached all the configs and last few lines of client output before the disconnection in the game.

If I replace client/server with shadowsocks-rust (with same 2022 ciphers) or shadowsocks-libev I have no issues connecting. I've already tried changing the MTU & TFO options but no avail.

Perhaps there is some low level network code that is causing issues on a lower level? Do you have any suggestions of other options to try, or specific actions to diagnose/debug this issue?

Server config:

{
  "servers": [
    {
      "name": "1",
      "listen": ":10000",
      "protocol": "2022-blake3-aes-128-gcm",
      "enableTCP": true,
      "listenerTFO": true,
      "enableUDP": true,
      "mtu": 1500,
      "psk": "S69XhmQWXDxCQEuJWwEYgA==",
      "uPSKStorePath": "upsk_1.json"
    }
  ],
  "api": {
    "enabled": true,
    "enableTrustedProxyCheck": false,
    "proxyHeader": "X-Forwarded-For",
    "listen": "127.0.0.1:8000"
  }
}

upsk_1.json:

{"user1":"+x+NuBLirqPt/0BQjBsCaA=="}

Client config:

{
    "servers": [
        {
            "name": "socks5",
            "listen": ":1080",
            "protocol": "socks5",
            "enableTCP": true,
            "listenerTFO": true,
            "enableUDP": true,
            "mtu": 1500
        }
    ],
    "clients": [
        {
            "endpoint": "192.168.1.5:10000",
            "protocol": "2022-blake3-aes-128-gcm",
            "enableTCP": true,
            "dialerTFO": true,
            "enableUDP": true,
            "mtu": 1500,
            "psk": "+x+NuBLirqPt/0BQjBsCaA==",
            "iPSKs": [
                "S69XhmQWXDxCQEuJWwEYgA=="
            ]
        }
    ]
}

last logs on client:

2023-05-22T12:04:06.113-0400 INFO service/tcp.go:293 Two-way relay started {"server": "socks5", "listener": 0, "listenAddress": "[::]:1080", "clientAddress": "[::ffff:127.0.0.1]:51126", "username": "", "targetAddress": "137.221.104.184:1119", "client": "", "initialPayloadLength": 147}
2023-05-22T12:04:09.183-0400 INFO service/tcp.go:293 Two-way relay started {"server": "socks5", "listener": 0, "listenAddress": "[::]:1080", "clientAddress": "[::ffff:127.0.0.1]:51129", "username": "", "targetAddress": "24.105.35.138:3724", "client": "", "initialPayloadLength": 1280}
2023-05-22T12:04:09.229-0400 INFO service/tcp.go:324 Two-way relay completed {"server": "socks5", "listener": 0, "listenAddress": "[::]:1080", "clientAddress": "[::ffff:127.0.0.1]:51129", "username": "", "targetAddress": "24.105.35.138:3724", "client": "", "nl2r": 1333, "nr2l": 53}
2023-05-22T12:04:11.491-0400 INFO service/tcp.go:324 Two-way relay completed {"server": "socks5", "listener": 0, "listenAddress": "[::]:1080", "clientAddress": "[::ffff:127.0.0.1]:51126", "username": "", "targetAddress": "137.221.104.184:1119", "client": "", "nl2r": 8003, "nr2l": 7847}

mklnz avatar May 22 '23 16:05 mklnz

If I replace client/server with shadowsocks-rust (with same 2022 ciphers)

Did you mean replacing both client and server, or either of them? Which combinations work and which ones don't?

Do you have any suggestions of other options to try, or specific actions to diagnose/debug this issue?

In this case, I really don't like "initialPayloadLength": 1280. This means the SOCKS5 client probably wrote more bytes than the initial payload buffer can hold. There are test cases for this, so the bug is likely not at shadowsocks-go's side.

Let's get started by adding "disableInitialPayloadWait": true to the client's SOCKS5 server config and see if it resolves the issue.

database64128 avatar May 22 '23 17:05 database64128

Thanks for that, good catch - "disableInitialPayloadWait": true on the client's server section fixed the issue

What are the implications of disabling initial payload wait? Also to clarify, I meant replacing both client and server with shadowsocks-rust and also shadowsocks-libev.

mklnz avatar May 22 '23 17:05 mklnz

fixed the issue

Good. WoW's server is likely the one at fault here. The person who wrote the offending code was probably not familiar with TCP semantics. And they got away with it, at least most of the time, because the actual TCP MSS out in the wild is usually larger than their initial request size.

You can confirm this by using WireShark or any similar tool to capture traffic to the client's SOCKS5 server, and outgoing traffic from your server to 24.105.35.138:3724. The payload content should match, but the first packet with payload captured on the server only has 1280 bytes of payload.

You didn't encounter the same issue with shadowsocks-rust, because it uses 8192 as the size of the initial payload buffer: https://github.com/shadowsocks/shadowsocks-rust/blob/736df148ebb7387741b0745f250748d8cccf1a2e/crates/shadowsocks-service/src/local/utils.rs#L40-L68

Since 1280 is a rather arbitrary default in shadowsocks-go, and it's not like any of us can get Blizzard to fix their code, I'm open to raising the default or making it a configurable option. What do you think?

What are the implications of disabling initial payload wait?

This effectively nullifies the benefits of TFO by not allowing the first write to carry actual payload.

database64128 avatar May 22 '23 18:05 database64128

I think making it a configuration option with an implicit default might be a good idea, I'll let you know if I encounter different init payloads

mklnz avatar May 23 '23 22:05 mklnz

Does the new allowSegmentedFixedLengthHeader: true option allow a workaround to this issue?

mklnz avatar May 25 '23 22:05 mklnz

No, it's unrelated. The option for initial payload buffer size will be added at a later time.

database64128 avatar May 26 '23 01:05 database64128

Done in cb5061f05b572b5be7eb7cca91a9a299405d979b.

database64128 avatar Jun 05 '23 18:06 database64128

I added the config in the socks5 client config by separating the tcp/udp listeners, and bumped up the payload size to a 81920 just to test but still getting the initial payload to be maxed out.

Is there anything to be set on the server side?

I'm wondering if there is some other issue at play because no matter how high I set it, it seems to fill it. The only way I can get it to work is to disable initialpayloadwait entirely.

{
  "clients": [
    {
      "dialerTFO": true,
      "enableTCP": true,
      "enableUDP": true,
      "endpoint": "< redacted >",
      "iPSKs": [
        "<redacted>"
      ],
      "mtu": 1500,
      "protocol": "2022-blake3-aes-128-gcm",
      "psk": "<redacted>"
    }
  ],
  "servers": [
    {
      "mtu": 1500,
      "name": "socks5",
      "protocol": "socks5",
      "tcpListeners": [
        {
          "address": ":12000",
          "fastOpen": true,
          "initialPayloadWaitBufferSize": 81920,
          "network": "tcp"
        }
      ],
      "udpListeners": [
        {
          "address": ":12000",
          "network": "udp"
        }
      ]
    }
  ]
}

ss-go log entry:

{"server": "socks5", "listener": 0, "listenAddress": "[::]:12000", "clientAddress": "[::ffff:127.0.0.1]:57687", "username": "", "targetAddress": "24.105.34.174:3724", "client": "", "initialPayloadLength": 81920}

mklnz avatar Jun 08 '23 22:06 mklnz

Hmm, that's interesting. There are still a few things you could try before the only option we have left is packet capture.

  1. On the client side, lower initialPayloadWaitTimeout. The default (250ms) is quite high and there's a chance that this had triggered a bug in WoW.
  2. On the server side, add a client with the protocol set to direct and dialerTFO set to false. When there are no clients configured, shadowsocks-go adds a default "direct" client:

https://github.com/database64128/shadowsocks-go/blob/16fd811f558201f3110b2aeb292e44f2454e5c1a/service/service.go#L52-L63

The default client has TFO enabled by default. If the remote server misbehaves when a SYN packet with cookie request option is received, this could cause problems.

database64128 avatar Jun 09 '23 01:06 database64128