Hello!
I have some dashboards open to internet and I would like to protect them, but I saw that Grafana logs does not take the IP of failed logins.
How can we protect our dashboard from a bruteforce attack?
This is an example of my logs located on: /var/log/grafana/grafana.log
(I rewrite the IPs and emails)
t=2019-10-15T09:11:04+0200 lvl=info msg=“Request Completed” logger=context userId=2 orgId=1 uname=user1 method=GET path=/api/datasources/proxy/1/query status=400 remote_addr=190.720.751.765 time_ms=20 size=77 referer=“https://myserver .com/graf/d/jOI1Ku7Wk/principal-fv?orgId=1&refresh=30s&fullscreen&edit&panelId=40”
t=2019-10-15T15:58:19+0200 lvl=info msg=“Request Completed” logger=context userId=0 orgId=0 uname= method=GET path=/d/jOI1Ku7Wk/principal-fv status=302 remote_addr=190.720.751.765 time_ms=0 size=34 referer=
t=2019-10-15T15:58:43+0200 lvl=eror msg=“Invalid username or password” logger=context userId=0 orgId=0 uname= error=“Invalid Username or Password”
t=2019-10-15T15:58:43+0200 lvl=info msg=“Request Completed” logger=context userId=0 orgId=0 uname= method=POST path=/login status=401 remote_addr=190.720.751.765 time_ms=2 size=42 referer=https://myserver.com/graf/login
t=2019-10-15T15:58:48+0200 lvl=eror msg=“Invalid username or password” logger=context userId=0 orgId=0 uname= error=“Invalid Username or Password”
t=2019-10-15T15:58:48+0200 lvl=info msg=“Request Completed” logger=context userId=0 orgId=0 uname= method=POST path=/login status=401 remote_addr=190.720.751.765 time_ms=0 size=42 referer=https://myserver.com/graf/login
t=2019-10-15T15:58:55+0200 lvl=eror msg=“Invalid username or password” logger=context userId=0 orgId=0 uname= error=“Invalid Username or Password”
t=2019-10-15T15:58:55+0200 lvl=info msg=“Request Completed” logger=context userId=0 orgId=0 uname= method=POST path=/login status=401 remote_addr=190.720.751.765 time_ms=0 size=42 referer=https://myserver.com/graf/login
t=2019-10-15T18:45:58+0200 lvl=info msg=“Request Completed” logger=context userId=0 orgId=0 uname= method=GET path=/d/jOI1Ku7Wk/principal status=302 remote_addr=190.720.751.765 time_ms=0 size=34 referer=
t=2019-10-15T18:46:08+0200 lvl=info msg=“Successful Login” logger=http.server User=user2@gmail .com
torkel
October 16, 2019, 7:29am
2
Grafana has login protection enabled by default (unless disabled).
# used for signing
secret_key = SW2YcwTIb9zpOOhoPsMm
# disable gravatar profile images
disable_gravatar = false
# data source proxy whitelist (ip_or_domain:port separated by spaces)
data_source_proxy_whitelist =
# disable protection against brute force login attempts
disable_brute_force_login_protection = false
# set to true if you host Grafana behind HTTPS. default is false.
cookie_secure = false
# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict" and "none"
cookie_samesite = lax
# set to true if you want to allow browsers to render Grafana in a <frame>, <iframe>, <embed> or <object>. default is false.
allow_embedding = false
think it will block logins for 5m or so after 5 failed attempts from the same IP and user
1 Like
Thanks you, it is great Grafana have an automatic protection, but I can not control it or log that it works.
That’s why I would like to know if is possible log the IP who fail at sign in.
Another option is to put an auth_proxy before Grafana and manage everything you want
1 Like
Thanks a lot, using auth_proxy could be a possible solution, but I prefer use the main login page of Grafana
Grafana Auth Proxy Guide
I think i could open a request on GitHub to able log failed logins. It does not seem difficult
tkohhh
January 1, 2020, 6:45pm
6
Did you end up opening a request? I also would like this, as I am trying to set up fail2ban for all of my websites.
No, I forgive that. Sorry. It is very important.
I will open it and quote you
EDIT: here is the request in GitHub: https://github.com/grafana/grafana/issues/21310
1 Like
tkohhh
March 18, 2020, 1:44am
8
This is now working in 6.7.0-beta1!!! Thank you @castillo92 for your efforts in getting this addressed!
For those interested, this is what I used for my failregex in fail2ban:
^ lvl=[a-zA-z]* msg=\"Invalid username or password\" (?:\S*=(?:\".*\"|\S*) )*remote_addr=<HOST>
I welcome any comments/critique on my regex as I am definitely not a regex expert.
*edit: changed regex to use non-capturing groups instead of capturing groups
1 Like
Thanks you very much @tkohhh
Today, three month later I setup the rules in fail2ban and it is working with a minor modification of your Regex:
My log files has the timestamp at the beggining of each line, so I needed to add .* after ^
Example of logs:
t=2020-04-29T21:41:36+0200 lvl=eror msg=“Invalid username or password” logger=context userId=0 orgId=0 uname= error=“Invalid Username or Password” remote_addr=88.9.13.3
t=2020-04-29T21:41:36+0200 lvl=info msg=“Request Completed” logger=context userId=0 orgId=0 uname= method=POST path=/login status=401 remote_addr=88.9.13.3 time_ms=0 size=42 referer=https://myserver.com/graf/login
So the regex config file has to be: I only changed the beggining:
[Definition]
failregex = ^.*lvl=[a-zA-z]* msg=\"Invalid username or password\" (?:\S*=(?:\".*\"|\S*) )*remote_addr=<HOST>
ignoreregex =
Tried and works in 6.7.1 stable and, after the update, it still works so in 6.7.3 stable.
tkohhh
April 29, 2020, 8:52pm
10
Glad to hear you got it working!
Are you sure it wasn’t working without the .* at the beginning? According to the fail2ban manual :
If the failregex is anchored with a leading ^, then the anchor refers to the start of the remainder of the line, after the timestamp and intervening whitespace.
Did you put a datepattern in your .conf file? I wonder if that makes a difference? Mine looks like this:
[Init]
datepattern = ^t=%%Y-%%m-%%dT%%H:%%M:%%S%%z
In any case, mine works without the leading .* and I think it’s generally a bad idea to have an unlimited match at the beginning of the failregex because it could potentially be abused with an injection-type attack.
tkohhh
April 29, 2020, 8:59pm
11
Just to be clear, here is my whole grafana.conf. It works well for me.
[INCLUDES]
before = common.conf
[Definition]
failregex = ^ lvl=[a-zA-z]* msg=\"Invalid username or password\" (?:\S*=(?:\".*\"|\S*) )*remote_addr=<HOST>
ignoreregex =
[Init]
datepattern = ^t=%%Y-%%m-%%dT%%H:%%M:%%S%%z
Great, but would you be so kind and tell me how can I change this parameter in Grafana in docker?
I guess I have to add something in grafana.env?
Thank You!