Problem connecting to external mysql database - mysql

My problem is this command produces an error when I tried to connect from our server to another external server :
mysql -h db.hostname.com -u username -pP#ssword database_name
And this is the error :
ERROR 1044 (42000): Access denied for user 'username'#'%' to database 'database_name'
I already asked the external server admin to add our IP in their firewall but to no avail..
Has this something to do with GRANTing privileges to the 'username'

It's not a problem with firewall, since MySQL is denying the connection. As you suspect, it is a problem with the privileges granted for the user. You need to execute this on the mysql server (you might need to tweak this a bit if you don't want to grant all privileges to the db):
GRANT ALL ON database_name.* TO 'username'#'%' IDENTIFIED BY 'P#ssword';
Also note that if you always connect from a specific host/ip, it's a better idea to specify that host/ip, instead of using a wildcard %, which would allow connections from anywhere.

It sounds like the password is wrong, or that the username you are trying to use is not allowed to connect from your computer's IP address.
as you know, the mysql administrator at the remote site can specify which IP's are allowed to connect using any given user account. Bear in mind that your computer's IP address may be routed through all kinds of routers and firewalls on your company's end before you reach the external database. As a result, your IP may appear different to you than to the external database.
In that case, it doesn't help if the external database admin adds YOUR IP to the 'allowed' list, they should add the 'outside world' IP address instead.
The easiest way to find out if this applies to you, is as follows:
visit www.whatismyip.com and write down the IP address on screen. This is your IP as seen from the 'outside world'. It is very likely that this IP is actually the outside IP of a firewall or router within your company's network, and not your computer's IP at all.
Next, (assuming you're on Windows) go to Start > run. Type cmd and hit enter. Type ipconfig and hit enter. You can now see your local IP address.
If these two IP's don't match, tell the remote admin to add your outside world IP to the 'allowed' list as well.
also - once you go to production, and move your code to another server, the IP fun starts again. You might as well fix this right away

Related

phpmyadmin share specific DB with more machines

I'm doing a web project and im using wamppserver to take care of the server and database. And now I'm facing a problem, I have to share the project. So it would be useful if i could share the specific DB that I use in the project, so that other people can access from their machines and get all the data previously stored in the DB. Is it possible to do it? How?
If you need to grant access to other machines to one database on local mysql server, you need to do some things:
You need to open MySQL to network interface: Check my.cnf, and do this:
Comment the line skip-networking.
Change the line bind-address to hold your LAN IP address / WAN IP address (if the machine itself have the WAN IP) / 0.0.0.0 (for all IPv4 addresses of the machine) / :: (for all IPv4 and IPv6 addresses of the machine). After reconfigure, restart MySQL server.
Check / configure your firewall for port 3306 opened (You can configure firewall for accept connections only from the required IPs) (Configuration for doing this will depend on your firewall software).
Grant access to the user(s) from the IPs you will need.
You can give access to one user from all IPs, for doing this, execute command [1] on MySQL cli or phpmyadmin, with a user with SUPER privileges (usually root).
You can give access to one user from one IP. Execute command [2].
[1]: GRANT ALL PRIVILEGES ON database.* TO 'user'#'%' IDENTIFIED BY 'password';
[2]: GRANT ALL PRIVILEGES ON database.* TO 'user'#'host' IDENTIFIED BY 'password';
You need to replace database with the name of the database to give privileges, user with the username accessing, host with the IP address of the client accessing, and password, with the desired password.
You can also, repeat command [2] if you want the same username to have access from two different IPs for example. Also, you can use a combination of [1] and [2], using a host with this example format: #'192.168.0.%', for giving access to these user from all computers on the 192.168.0.0/24 network.
Also, you can give really fine privileges, for example, changing GRANT ALL PRIVILEGES with GRANT SELECT, INSERT, these user only can do SELECT and INSERT statements, but not UPDATE or DELETE ones for example. You can check MySQL doc or StackOverflow for more info about this.

How does mysql do reverse resolution of IP addresses?

We rebooted a machine running mysql, and we're having some odd issues. Most processes from other machines are able to connect to without issue. We can also connect locally if we connect through the loopback address explicitly.
This works:
mysql -hlocalhost -utest_user -psecret_password
When we run the command:
mysql -h192.168.1.10 -utest_user -psecret_password
locally on the machine we get the following error:
ERROR 1045 (28000): Access denied for user `test_user`#`SERVER_123`
We had the following users:
test_user#localhost
test_user#%
We have fixed the issue by adding the following user:
test_user#SERVER_123
Where SERVER_123 is the unqualified name of the machine.
We don't know why we had to add that additional user, and we don't want to keep it, but we also don't know why adding it fixed the issue.
Why does connecting from the local machine, via IP (i.e. mysql -ha.b.c.d -utest_user -ppsswd) fail to match the test_user#% user, but will match test_user#machine_name, where machine_name is the unqualified name of the machine?
Here is the user table
anonymous %
anonymous SERVER_123
anonymous localhost
test_user_2 %
test_user_3 %
root ::1
root 127.0.0.1
root SERVER_123
root localhost
Note: Figured out the issue. Somehow rebooting the machine must have changed how 192.168.1.10 resolved so that it resolved to SERVER_123. That then caused logins from 192.168.1.10 to match test_user#SERVER_123.
I would take a look at the sorting rules in this section of the MySQL documentation: https://dev.mysql.com/doc/refman/5.7/en/connection-access.html
It is possible for the client host name and user name of an incoming connection to match more than one row in the user table.
It could be that your user is identified as another user with a different password. What other entries are present in your user table?
Update based on new information: Your login was identified as the ''#'%' user. This user either has different credentials, or is missing the necessary permissions.
You can follow the MySQL documentation here, which talks about the DNS lookup optimization and also the process how this is achieved. To point out one point from the documentation is the following:
The MySQL server maintains a host cache in memory that contains information about clients: IP address, host name, and error information. The server uses this cache for nonlocal TCP connections. It does not use the cache for TCP connections established using a loopback interface address (127.0.0.1 or ::1), or for connections established using a Unix socket file, named pipe, or shared memory.
And there is another point that help you resolve this is with the introduction of the following parameter:
skip-name-resolve
You can follow the article here that suggests that MySQL authenticates based on IP addresses or Hostnames - Article link here.
By default MySQL grants authentication on users based on IP address or hostnames. When there is a connection from a particular host, MySQL does a reverse DNS lookup and compares the hostname and IP address.
Hope this helps to answer your question!
First of all remember only 127.0.0.1, ::1, localhost etc... are considered as loopback addresses not 192.168.1.10 or SERVER_123 as you may be accepting.
Yes! 192.168.1.10 should match for wildcard host %, but unfortunately beside test_user_2 and test_user_3 I don't see test_user entry in provided user table data.
In addition on Linux you may use /etc/hosts file to map ip address to hostname
Found the issue. There is an anonymous user which is matching before the specific user. I'm not sure what happened during the reboot that caused reverse resolution to change, but we had a user ''#'SERVER_123' which must have started matching. Removing the anonymous user fixed the issue, and we no longer need to have privileges for test_user#SERVER_123.

What does it mean on mysql grant command?

I am creating my own PHP development environtment and I am setting mysql.
I need to grant to my root user all the privileges so I use:
GRANT ALL ON *.* TO 'root'#'%';
Why It use 'root'#'%'?
I understand that these are user and host, but in this case that I am in a development environment why I have to put a host?
In case of a production server I understand that it is to grant only the database hosted by an specified host, right?
Thanks.
'%' is a wildcard fall-back. The login attempt tries the most specific and then moves toward the wildcard (moving toward more general) until it finds a user/host combo account if you will to authenticate. If it can't find such an account, the login fails.
So when you have 'root'#'localhost' (call it acct or user 1), that is all fine and dandy when you are sitting at localhost. But when you attach from a different client, say '192.168.10.103', you are no longer 'localhost'. You now need either an explicit 'root'#'192.168.10.103' (user or acct if you will), or for sanity we swing for the wildcard with '%'. Why, because there is no way you want to litter your mysql.user with all the permutations.
What users you have can be seen with
select user,host from mysql.user;
It is not uncommon to have 3 users for root
'root'#'localhost'
'root'#'127.0.0.1'
'root'#'%'
Giving them all the same rights. The 3rd one above is a security risk, naturally. That is so because '%' means from any host anywhere.
And that is why 'root'#'localhost' is recommended to be the only root user in your system. You achieve root by either sitting at that box, or using ssh with a secure connection to become localhost if you will.
You need to understand that it is all about security, and the way, for better or worse, MySQL chose to implement what a user is. A user is the username, plus the hostname coming in as. The hostname could be an IP Address, or a DNS hostname like casper.comcastbusiness.net. When MySQL receives the connection request, it bubbles up from most-specific toward '%' until it can or cannot authenticate the request.
As one use case, I have a server that I want to authenticate as root but not have a 'root'#'%' user in the system for security reasons. So I explicitly created a user like 'root'#'casper.comcastbusiness.net'. Another layer of course is the firewall but that is a separate issue. But to touch on it lightly, AWS ec2 has a Security Groups area to have it such that only certain IP Addresses are able to connect to port 3306. So the firewall is another layer, of what I am saying is that the whole thing is about securing your server.
Administrating it is a pain. But it is what is and we have to live with it.

Can't connect remotely without bind-address, can't connect locally with it

I'm having an issue with mysql. I am trying to allow remote access. I found that if I write in my.cnf:
bind-address=my.ip.address
It works remotely, but using a php script that tries to access the database using the same ip doesn't work anymore!
If I remove this line, I can connect locally, but not remotely.
I tried setting it to 0.0.0.0, which has the same effect as if it were not there at all.
I saw that you can't bind to multiple addresses unfortunately. Any way to resolve?
MYSQL User accounts have 2 parts
The userid
The domain from which they can connect to this MYSQL Server instance
EG 'root'#'localhost'
So you need to create a new user account, you dont want to give access to the root id externally, and make this new userid allowed to connect from either a specific ip address (more secure) or any ip address
From the command line mysql.exe processor you woudl do this
CREATE USER 'somone'#'11.22.33.44' IDENTIFIED BY 'mypass';
for a specific ip address
Or
CREATE USER 'somone'#'%' IDENTIFIED BY 'mypass';
To allow access from any ip adddress in the universe, so better make the password a good strong one
Then you allocate privilages to one or more databases to this new account
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
ON database_name.*
TO 'someone'#'%';
References
CREATE USER http://dev.mysql.com/doc/refman/5.7/en/create-user.html
Grant http://dev.mysql.com/doc/refman/5.7/en/adding-users.html

determining the IP from which an mysql connect (PDO) request came from

I want one Linux server to get or put data to the MySQL server on another Linux machine. I want to avoid granting
GRANT ALL PRIVILEGES ON *.* TO root#% IDENTIFIED BY 'password';
but instead would like to do:
GRANT ALL PRIVILEGES ON *.* to root#123.123.123.123 ..
where 123.. is the IP of the server that is making the request. Where would I go to get a log of the request made on the receiving database end, to know what IP is being queried from? I don't know enough about networking to know this, or to be sure which IP is being used.
Also, would it be OK to use a hostname of the querying server, or is that slower due to DNS lookup time?
If you want to know what IP you're connecting from:
SHOW PROCESSLIST
This will show the originating IP. You can tighten your rules accordingly.
As per my comment to #tadman, the problem turned out to be that I had
bind = 127.0.0.1
in the my.conf file found in /etc/mysql.
Well, once I disabled and restarted mysql, mysql came back and said "permission denied to root#____" - but then I was able to know the IP address. Predictably I guess, it was the primary DNS IP for that server. But problem solved because I was able to set that permission on the remote.