Multiple Mysql communication through TCP with TLS based on SNI

If MySQL uses TLS and Traefik can get access to the TLS cert, then you should be able to use HostSNI().

My guess is that there may be some work needed to support mysql SNI routing behind traefik, similar to Postgresql (as @lucasctd mentionned) and I may fire up Wireshark to take a look.

@cotjoey
please explain more, I tried and it didn't work with mysql :face_with_peeking_eye: :face_with_peeking_eye: :face_with_peeking_eye:

Did you use a tcp router, enable TLS and use rule with HostSNI() (doc)?

1 Like

@bluepuma77
before everything, I have to thank you for all your efforts for helping people :innocent:
In your example i can't see any dynamic.yml !!

I tried the HOSTSNI('example.com') for mysql without success :face_with_thermometer:

Thanks :slight_smile:

Static config is in traefik.yml or command:, dynamic config in separate dynamic config file via providers.file or in labels via providers.docker.

Has anybody succeeded with the issue ?

1 Like

After looking into reverse-proxying to multiple MySQL instances using SNI based routing, I seem to have figured out that it is not feasible to do with out-of-the-box solutions.

The reason why this is not possible, is because like Postgres, the connection protocol for MySQL sends packets before the TLS handshake is initiated. The packets between client and server over the raw TCP connection for Postgres are easy to be spoofed, to trick the client into initiating the TLS handshake (where we can then route based on SNI).

Here's an example for Postgres:

  1. TCP connection established
  2. client sends 80877103 (SSLRequest)
  3. server sends S
  4. client sends TLS hello (with SNI)

This is easily intercepted and spoofed by the proxy by watching for that number, and responding to all with an S.

Unfortunately for MySQL, that pre-TLS exchange involves a connection ID and a random string that the client must hash the password with in order to authenticate with the server.

Here's an example:

  1. TCP connection established
  2. server sends packet containing connection ID and random string for pw hashing
  3. client sends packet requesting ssl mode
  4. client sends TLS hello

Since that random string for authentication is generated and sent by the server to the client before the SNI happens, the proxy would need to "know" which server to connect the client to before it ever receives the hostname from the TLS handshake.

In conclusion, you cannot do SNI based reverse-proxy routing to MySQL instances with standard L4 proxies, instead you must do port based routing.