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.
Related
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.
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
I have found many posts for this error, tried everything but still getting same error.I am trying to connect to mysql on ubuntu server from my remote app and mysql client. Let me post whatever steps I have taken already :
Stop the firewall on ubuntu server : iptables -F. Also tried with sudo service ufw stop.
Commented "bind-address" in /etc/mysql/my.cnf and restarted mysql.
Added user in mysql : CREATE USER 'test'#'%' IDENTIFIED BY 'testpwd';
GRANT ALL PRIVILEGES ON . TO 'test'#'%' IDENTIFIED BY 'testpwd' WITH GRANT OPTION;
FLUSH PRIVILEGES;
I can see the entry of new user by "Select host, user from mysql.user";
restarted mysql again. Still the same error!
Now I thought maybe there is some problem still with firewall, so added :iptables -A INPUT -i eth0 -p tcp --destination-port 3306 -j ACCEPT
Problem still persist.
"Access denied for user 'test'#'ip'(using password: YES)" is a MySQL error.
This means that at the network level everything is working, because to be denied access as a given user, the server must have understood which user you were trying to connect as. So network, firewall, routing, and so on and so forth, must all be working; the server must be listening, etc..
The problem lies "simply" in the authentication.
Try connecting locally to the database (to override the authentication) and inspect the privilege table:
USE mysql;
SELECT User, Host, Password from user WHERE User = 'test';
and remember that the line you're interested in is the one mentioning the IP (since the error message specifies the IP, and not the host name - in which case, it could have been a DNS problem; the host name is the hostname that the server believes you are coming from, not the hostname you are really coming from).
The user/host matching goes from more specific to less specific. So if you already had:
user host password
test 1.2.3.4 foo
and ran,
GRANT... TO test#'%' ... PASSWORD bar
...this grant would work from everywhere except 1.2.3.4, where the password would remain 'foo'.
From the manual (link above):
The server uses sorting rules that order rows with the most-specific
Host values first. Literal host names and IP addresses are the most
specific. (The specificity of a literal IP address is not affected by
whether it has a netmask, so 192.168.1.13 and
192.168.1.0/255.255.255.0 are considered equally specific.) The pattern '%' means “any host” and is least specific. The empty string
'' also means “any host” but sorts after '%'. Rows with the same Host
value are ordered with the most-specific User values first (a blank
User value means “any user” and is least specific). For rows with
equally-specific Host and User values, the order is indeterminate.
You might be forced to do
USE mysql;
DELETE FROM user WHERE User = 'test';
GRANT ALL PRIVILEGES ON database.* TO 'test'#'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
to ensure that there're no spurious lines in the grant table referring to the user 'test'.
(Also, the GRANT should be, I think,
GRANT ALL PRIVILEGES ON databasename.*
)
Security doubt (unrelated to the answer)
The manual above says: The specificity of a literal IP address is not affected by whether it has a netmask, so 192.168.1.13 and 192.168.1.0/255.255.255.0 are considered equally specific.
Now at a very first glance 127.0.0.1/0.0.0.0 seems very specific (and harmless) for localhost. The netmask, if I'm not mistaken, ensures that it is equivalent to %, except that it is incredibly specific and will run first. Therefore
test bar %
test localfoo 127.0.0.1/0.0.0.0
means that the password for test from anywhere it's not "bar" at all, but it is "localfoo".
No one would insert such a grant by mistake, but there's mistake and mistake.
First let's check - it's network/firewall problem or not.
Start MySql server with --skip-grant-tables , then try to connect to it.
I had the same error on my .net core console app, when trying to connect to my MariaDb database.
I finally find that the uid in my connectionstring was not correct because it is case sensitive!
Even if I felt quite stupid, it might help...
I've just tried to create a bunch of users for a (currently local) database but I'm having issues connecting to the database and not too sure what I'm doing wrong.
The users exist after creation but I can't connect to the database with their credentials while using Workbench for connection testing.
I've created my users and then granted them permission straight after as so:
CREATE USER 'username'#'%' IDENTIFIED BY 'password';
GRANT ALL ON DATABASE.* TO 'username'#'%';
If I run SELECT * FROM mysql.user; to see the users, I can see that the users are there.
I've tried flushing privileges but it doesn't seem to make any difference.
When trying to connect to the server via Workbench as one of the users I've created I get re-prompted for my password. It then seems to either hang or tell me the password is wrong.
This is initially local for development purposes but I'll be setting this up on a server once I've got this working. Could this be down to it being ran locally?
As mentioned in the MySQL documentation for adding users, when connecting locally a user must be created #'localhost' as well as to wildcard locations:
Two of the accounts have a user name of monty and a password of
some_pass. Both accounts are superuser accounts with full privileges
to do anything. The 'monty'#'localhost' account can be used only when
connecting from the local host. The 'monty'#'%' account uses the '%'
wildcard for the host part, so it can be used to connect from any
host.
It is necessary to have both accounts for monty to be able to connect
from anywhere as monty. Without the localhost account, the
anonymous-user account for localhost that is created by
mysql_install_db would take precedence when monty connects from the
local host. As a result, monty would be treated as an anonymous user.
The reason for this is that the anonymous-user account has a more
specific Host column value than the 'monty'#'%' account and thus comes
earlier in the user table sort order. (user table sorting is discussed
in Section 6.2.4, “Access Control, Stage 1: Connection Verification”.)
With a user only being denoted with a host name of '%' to allow for connection anywhere MySQL will instead use the anonymous <anonymous>''#'localhost' account because it will attempt to match the localhost location first and then not find the related user name for localhost and so use the <anonymous> user instead.
Alternatively, the anonymous user can be deleted and this should also fix the problem rather than having to duplicate users.
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