Skip to content

Conversation

@NoOverflow
Copy link

What does this PR do?

This PR aims to add support for L4 Routing for MySQL using SNI.

Motivation

For a while Traefik could not route TCP (w/ TLS) requests for MySQL as both the client and server did not support SNI. The only option was to use a wildcard router ('HostSNI(*') which works fine, until you need enable TLS to host multiple MySQL instances using the same entrypoint on Traefik.

This has since been addressed by MySQL and SNI support has been added as of version 8.1.0 (2023/07)

Adding routing for MySQL would allow multiple databases to be behind a single Traefik instance.

Draft issues

  • Fake handshake packet
  • Figure out how to send a proper handshake packet, as there may be multiple MySQL instances using different configuration values, we can't just send fake values, we also cannot get them from the right server since we don't know at this point which one the client is trying to reach.
  • Find a proper way to identify a MySQL connection, since it uses a client-first protocol. (An example of fingerprinting for Postgresql)

More

  • Fix Draft issues (see above)
  • Added/updated documentation

Additional Notes

Useful links

Closes #10505

@NoOverflow NoOverflow force-pushed the feat-mysql-support-v3.0 branch from 323c2f2 to b7cd4ee Compare July 6, 2024 14:05
@NoOverflow NoOverflow marked this pull request as draft July 6, 2024 14:05
@nmengin
Copy link
Contributor

nmengin commented Jul 8, 2024

Hey @NoOverflow,

Thank you for your contribution.
Could you tell us when your PR will be in a status that allow us to start our review?

Thanks in advance.

@NoOverflow
Copy link
Author

Hey @nmengin,
I wish I could tell you, there are still many problems that need to be fixed. I opened this PR to basically kickstart the work for MySQL support (see #10505 (comment))

@Kwuray
Copy link
Contributor

Kwuray commented Jul 10, 2024

Hello,

Is it really a problem to send a fake initial handshake packet?

We could test each server flag capability and measure the impact of sending a false value?
For example, the predominant encoding is that of the client, and sending a false value does not seem very problematic.

https://dev.mysql.com/doc/refman/8.4/en/charset-connection.html#charset-connection-error-handling

It appears that it is impossible to determine the SNI before sending the initial handshake packet, or even resend it later for correction.

@Kwuray
Copy link
Contributor

Kwuray commented Jul 10, 2024

Hi @NoOverflow

How can I suggest changes? For example to check that it is an SSL request : // TODO: Parse the response and check if the client requested SSL instead of manually checking the username byte

Can I push directly into your fork?
I have never participated in open source projects...

Thanks

@NoOverflow
Copy link
Author

Hello,

Is it really a problem to send a fake initial handshake packet?

We could test each server flag capability and measure the impact of sending a false value? For example, the predominant encoding is that of the client, and sending a false value does not seem very problematic.

https://dev.mysql.com/doc/refman/8.4/en/charset-connection.html#charset-connection-error-handling

It appears that it is impossible to determine the SNI before sending the initial handshake packet, or even resend it later for correction.

Hi @Kwuray, this is a question that needs answering, maybe it will break or not, there are many edge cases to test

Hi @NoOverflow

How can I suggest changes? For example to check that it is an SSL request : // TODO: Parse the response and check if the client requested SSL instead of manually checking the username byte

Can I push directly into your fork? I have never participated in open source projects...

Thanks

You're free to open a PR on my repo targeting the NoOverflow:feat-mysql-support-v3.0 branch 😄

@rtribotte rtribotte modified the milestones: 3.0, 3.1, next Aug 5, 2024
@rtribotte rtribotte changed the base branch from v3.0 to master August 5, 2024 13:23
@kevinpollet kevinpollet modified the milestones: 3.2, next Oct 3, 2024
@umeshkhatiwada1
Copy link

so Any update regarding the PR @NoOverflow

@GMProg
Copy link

GMProg commented Oct 31, 2024

Hey, I've also run into this, as I see it there is not a fine and nice solution, (other than waiting for the change of mysql protocol), but what if we had options when defining the entrypoint that it is a server-first entrypoint and also the protocol, so when receiving a packet on that port we would know what to do with it.
I know this also has it's limitations, like one type of portocol/port, but I think this is better than the current one service/port situation, and not to mention this solution would set the base of other server-first protocols.

@nmengin What do you think, would this type of solution be acceptable by traefik's end?

@Kwuray
Copy link
Contributor

Kwuray commented Oct 31, 2024

@GMProg with your solution we would do the same thing with the request regardless the MySQL service ? So impossible to have various MySQL server (different Charest, version, ...) ? Maybe I did not understand your idea 😅

@GMProg
Copy link

GMProg commented Oct 31, 2024

@GMProg with your solution we would do the same thing with the request regardless the MySQL service ? So impossible to have various MySQL server (different Charest, version, ...) ? Maybe I did not understand your idea 😅

well yes, my suggestion would mean that all mysql servers should have the same configuration, at least to the level that's sent by the server first, and also there's the connection id parameter, which is just, really hard to fake, you're right this not the way either, sadly.

@NoOverflow
Copy link
Author

@GMProg You could indeed do that, but as @Kwuray correctly mentioned, you would be stuck with a single version of MySQL behind your traefik instance since MySQL is a server-first protocol and the first packet (even before STARTTLS negotiation) contain server properties that you cannot "get" as you don't know where the request is heading to yet.

This port-based logic with a forged initial packet would help in (very) specific cases but would not make it into an official Traefik release.

The only way to progress further with this PR is to initiate a talk with the MySQL maintainers and propose a new protocol that would allow SNI routing (way easier said than done though...)

@nmengin
Copy link
Contributor

nmengin commented Nov 22, 2024

Hello @NoOverflow,

@nmengin What do you think, would this type of solution be acceptable by traefik's end?

We have discussed with the other maintainers the opportunity to dedicate an entrypoint to the mysql protocol.
And... We haven't reached any consensus on it!

Even if the proposition is interesting, some maintainers would prefer to manage this mechanism globally.
For this reason, we'd prefer not to go this way until more discussion on this topic.

@kevinpollet kevinpollet modified the milestones: 3.3, next Dec 17, 2024
@kevinpollet kevinpollet removed this from the 3.4 milestone Apr 1, 2025
@kevinpollet
Copy link
Member

Hi @NoOverflow,

We discussed this issue during our triage session, and as mentioned in the previous message, we would like to address this globally, for example by having dedicated entry points. This would allow us to support other protocols without having to have assertions in the connection path to detect them, which can get tricky at some point and introduce incompatibilities.

And as you said, even with dedicated entry points, this may not be possible today.

So we are closing this pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MySQL client cannot connect to database when using SNI routing with TLS

8 participants