MySQL access denied error when connecting via SSH tunnel

In MySQL, the localhost keyword is reserved for connection using the MySQL socket and you should use the ip-address 127.0.0.1 for TCP connections to the MySQL network port on 127.0.0.1. This means that both the server must grant privileges to users from specifically 127.0.0.1, and the client must use -h 127.0.0.1 to go through the tunnel instead of connecting to a local socket.

To allow you access using the SSH port forwarding you need something like:

GRANT SELECT ON *.* TO user@`127.0.0.1`

and then run

FLUSH PRIVILEGES;

and possibly

FLUSH QUERY CACHE;

If it still doesn't work, restart the server process.

In error messages 127.0.0.1 after a reverse DNS lookup gets translated to localhost making debugging difficult.

As the manual describes it:

On Unix, MySQL programs treat the host name localhost specially, in a way that is likely different from what you expect compared to other network-based programs. For connections to localhost, MySQL programs attempt to connect to the local server by using a Unix socket file. This occurs even if a --port or -P option is given to specify a port number. To ensure that the client makes a TCP/IP connection to the local server, use --host or -h to specify a host name value of 127.0.0.1, or the IP address or name of the local server. You can also specify the connection protocol explicitly, even for localhost, by using the --protocol=TCP option. For example:

shell> mysql --host=127.0.0.1
shell> mysql --protocol=TCP

The --protocol option enables you to establish a particular type of connection even when the other options would normally default to some other protocol.