cpeng 3 Posted December 24, 2019 Posted December 24, 2019 (edited) I wanted to share my fail2ban configuration for people that want to protect against a brute force attack. Fail2ban is a piece of software that will monitor log files for a authentication failures then ban the source ip address after so many attempts to protect against a brute force attack. I searched around for an tutorial or how to on how to implement this for emby and came up short, so I decided to give it a try and got it to work without much trouble at all. I wouldn't consider myself an expert and this is my first how to I have every written so if I made a mistake or I'm wrong let me know, and use my instructions at your own risk. USE AT YOUR OWN RISK THIS PROBABLY WILL NOT WORK IF YOU ARE USING EMBY CONNECT I'm not using emby connect because I think it has some security problems listed here https://emby.media/community/index.php?/topic/80497-log-out-security-hole/ You need to install fail2ban For my setup with ubuntu 18.10 I used, (should be the same for debian but I haven't tested) sudo apt install fail2ban To get fail2ban working with emby there are two parts, filter and jail, they both have their directories (jail.d) (filter.d) in /etc/fail2ban/ cpeng@g5500:~$ cd /etc/fail2ban/ cpeng@g5500:/etc/fail2ban$ ls action.d fail2ban.conf fail2ban.d filter.d jail.conf jail.d paths-arch.conf paths-common.conf paths-debian.conf paths-opensuse.conf The jail controls what happens with an authentication error and the filter tells how to read the log to find the error. Create a filter: cpeng@g5500:/etc/fail2ban$ sudo nano filter.d/emby.conf /etc/fail2ban/filter.d/emby.conf # Fail2Ban for emby # # [Definition] failregex = AUTH-ERROR: <HOST> - Invalid user or password entered ignoreregex = EDIT: New failregex proposed (below) by @@nayr to catch 401 errors and attempts to find valid user names [Definition] failregex = AUTH-ERROR: <HOST> - Invalid user HTTP Response 401 to <HOST>. The failregex tells what the log line will have in it that designates a fail and "<HOST>" designated the actual ip address. That error looked like this: 2019-12-24 11:12:00.326 Warn HttpServer: AUTH-ERROR: 10.9.162.31 - Invalid user or password entered. So I assumed that AUTH-ERROR will be unique to login errors which is why I started the filter with that. Next you have to create the jail in cpeng@g5500:/etc/fail2ban$ sudo nano jail.d/emby.local /etc/fail2ban/jail.d/emby.local [emby] enabled = true filter = emby logpath = /var/lib/emby/logs/embyserver.txt port = 80,443 I use a reverse proxy that uses ports 80,443, but if you aren't doing that then you want to block the default ports 8096,8920 The logpath may vary from distribution, you can find yours in your dashboard under paths. There are other options that you can add, my default ban time was 10 minutes and max number of retries was 5 which is default which seemed fine to me. The last thing you need to do is reload fail2ban so it re reads the files. sudo systemctl reload fail2ban Then test by entering the wrong password into emby and confirm that it blocks you. Check out the fail2ban.log at /var/log/fail2ban.log tail /var/log/fail2ban.log For testing this command might also come in handy: sudo fail2ban-client unban --all Hope this is helpful. P.S. I recently switched from plex to emby for the dvr service and so far I have been very impressed and happy with how it works. I got tired of all the bugs with plex, that would never get fixed, instead we got new "features" and new interfaces. The icing on the cake is how responsiveness the developers are on these forums. Edited January 7, 2020 by cpeng 2
nayr 36 Posted January 4, 2020 Posted January 4, 2020 (edited) Thanks for this, did some testing and it needs tweaking slightly: failregex = AUTH-ERROR: <HOST> - Invalid user There is an inconsistency in the logging.. first message is with an invalid username, second message is with an invalid password for a valid username: 2020-01-03 22:28:18.789 Warn HttpServer: AUTH-ERROR: 192.168.4.20 - Invalid username or password entered. 2020-01-03 22:29:17.998 Warn HttpServer: AUTH-ERROR: 192.168.4.20 - Invalid user or password entered. matching stoping at user will catch both variants.. your original config will not ban hammering of unknown usernames.. which does not provide the desired results. I also put the embyserver logs on a shared resource since my reverse proxy and emby are in different containers, this way my proxy can enact the ban on its side. Edited January 4, 2020 by nayr
nayr 36 Posted January 4, 2020 Posted January 4, 2020 (edited) Got another tweak after even further testing, the following filter will also pickup 401 Unauthorized Errors which is what you see in the logs trying to hit the Emby API's w/Invalid Credentials. Sample Log Entry: 2020-01-04 00:58:15.915 Info HttpServer: HTTP Response 401 to 192.168.4.13. Time: 2ms. http://192.168.4.15:8096/emby/ScheduledTasks/Running/9492d30c70f7f1bec3757c9d0a4feb45 401 Response from Emby API: Access token is invalid or expired. New Regex for Multiple Variants. [Definition] failregex = AUTH-ERROR: <HOST> - Invalid user HTTP Response 401 to <HOST>. Edited January 4, 2020 by nayr
Prototyp 0 Posted January 4, 2020 Posted January 4, 2020 Hey. If there is an api http response, what about https ?
nayr 36 Posted January 4, 2020 Posted January 4, 2020 (edited) I'm using a reverse proxy so IDK if that message changes for built in https.. I cant test it, but regardless of http or https transport.. response 401 is a HTTP Response code and AFIK there's no such thing as a HTTPS response code, https specs fall back to http for that stuff.. https just adds a TLS/SSL transport around HTTP so I would not expect that message to change.. but as we can see, making assumptions about security can be a bad idea. Edited January 4, 2020 by nayr
sfatula 189 Posted January 5, 2020 Posted January 5, 2020 Thanks for reminding me I need to do this, love fail2ban
cpeng 3 Posted January 7, 2020 Author Posted January 7, 2020 (edited) [Definition] failregex = AUTH-ERROR: <HOST> - Invalid user HTTP Response 401 to <HOST>. @@nayr, Thanks for this, I will add it to the OP. Edited January 7, 2020 by cpeng 1
gewbert 2 Posted February 2, 2020 Posted February 2, 2020 Thanks for this! I'm trying to set up fail2ban on my system but running into an issue. My emby log lists 2 ips (see below) because of my reverse proxy I assume. Fail2ban is banning the first IP but not the second so I can still access Emby despite the first being banned. How would I set up my filter to catch this? Log: 2020-02-02 13:44:47.571 Info UserManager: Authentication request for User has been denied. 2020-02-02 13:44:47.571 Warn HttpServer: AUTH-ERROR: XX.XX.XXX.XXX, XXX.XX.XX.XX - Invalid user or password entered. 2020-02-02 13:44:47.571 Error HttpServer: Invalid user or password entered. 2020-02-02 13:44:47.572 Info HttpServer: HTTP Response 401 to XX.XX.XXX.XXX, XXX.XX.XX.XX. Time: 26ms.
cpeng 3 Posted February 3, 2020 Author Posted February 3, 2020 Thanks for this! I'm trying to set up fail2ban on my system but running into an issue. My emby log lists 2 ips (see below) because of my reverse proxy I assume. Fail2ban is banning the first IP but not the second so I can still access Emby despite the first being banned. How would I set up my filter to catch this? Log: 2020-02-02 13:44:47.571 Info UserManager: Authentication request for User has been denied. 2020-02-02 13:44:47.571 Warn HttpServer: AUTH-ERROR: XX.XX.XXX.XXX, XXX.XX.XX.XX - Invalid user or password entered. 2020-02-02 13:44:47.571 Error HttpServer: Invalid user or password entered. 2020-02-02 13:44:47.572 Info HttpServer: HTTP Response 401 to XX.XX.XXX.XXX, XXX.XX.XX.XX. Time: 26ms. Honestly I don't know. I run a reverse proxy as well so maybe the easiest way to fix it is to get the logs to show 1 ip address. This is my nginx reverse proxy server { #root /var/www/emby/html; # Add index.php to the list if you are using PHP #index index.html index.htm index.nginx-debian.html; server_name emby.mydomain.com; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. #try_files $uri $uri/ =404; proxy_pass http://127.0.0.1:8096/; proxy_set_header Range $http_range; proxy_set_header If-Range $http_if_range; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #Next three lines allow websockets #proxy_http_version 1.1; #proxy_set_header Upgrade $http_upgrade; #proxy_set_header Connection "upgrade"; } listen [::]:443 ssl ipv6only=on; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/emby.mydomain.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/emby.mydomain.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot add_header X-Xss-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Strict-Transport-Security "max-age=2592000; includeSubdomains" always; add_header X-Frame-Options "SAMEORIGIN" always; proxy_hide_header X-Powered-By; add_header 'Referrer-Policy' 'no-referrer'; add_header Content-Security-Policy "frame-ancestors emby.mydomain.com;"; } server { if ($host = emby.mydomain.com) { return 301 https://$host$request_uri; } # managed by Certbot listen 80 default_server; listen [::]:80 default_server; server_name emby.mydomain.com; return 404; # managed by Certbot }
gewbert 2 Posted February 3, 2020 Posted February 3, 2020 Much appreciated! I actually figured it out, it was because of Cloudlare which I use as my DNS. Had to do some more tweaking but i got it to work.
Keksebacker 1 Posted February 7, 2020 Posted February 7, 2020 Hi at all, I am running emby within a LXC-container behind an apache2 reverse proxy (another LXC-container) and I have some issues to find the right configs for fail2ban. Filter: [INCLUDES] before = common.conf [Definition] _daemon = emby-server failregex = AUTH-ERROR: <HOST> - Invalid use HTTP Response 401 to <HOST>. ignoreregex = jail.local [emby] enabled = true port = 8096,443,80 protocol = tcp filter = emby maxretry = 3 findtime = 600 bantime = 43200 logpath = /var/lib/emby/logs/embyserver.txt action = %(action_mwl)s %(action_mwl)s # ban & send an e-mail with whois report to the destemail. action_mw = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] %(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"] Banaction will be iptables-multiport Fail2ban bans the right ip but emby is still available. I had a similar problem with nextcloud which uses apache as a web server. I followed the instructions at the following block and now it works but I have no idea how I have to modify the banaction to work properly with emby. https://nerdblog.steinkopf.net/2016/12/fail2ban-schuetzt-owncloud-hinter-reverse-proxy/ Could anybody help me?
nayr 36 Posted February 7, 2020 Posted February 7, 2020 (edited) This is kinda how I'm setup, except its nginx reverse proxy.. What I did was create a shared mount point between my WebServer container and my Emby server that contains the log files then configured fail2ban to process the emby log files inside the WebServer container.. since your behind a proxy, you need to be implementing fail2ban on the proxy itself. There are other ways to do this also, there's an alternatives and addons to fail2ban for cloud environments where an attack on one host will result in bans across multiple hosts.. its a more complicated setup tho and my method of sharing the log files between hosts is a happy path with least effort... If you want to maintain security isolation between the containers, you should mount the log file as read only on your proxy container so the web exposed container has minimal rights/attack surfaces. Edited February 7, 2020 by nayr 1
joelang6126 9 Posted August 5, 2020 Posted August 5, 2020 On 2/7/2020 at 4:09 PM, nayr said: since your behind a proxy, you need to be implementing fail2ban on the proxy itself. How do you go about doing this? Could you share your config files as I too am behind an nginx proxy trying to get fail2ban working with emby.
joelang6126 9 Posted August 5, 2020 Posted August 5, 2020 On 2/3/2020 at 5:52 PM, gewbert said: Much appreciated! I actually figured it out, it was because of Cloudlare which I use as my DNS. Had to do some more tweaking but i got it to work. I too am behind cloudflare. I have fail2ban working however it bans the cloudflare IP instead of the real IP. Any idea how I pass the real IP to emby?
mastrmind11 718 Posted August 5, 2020 Posted August 5, 2020 58 minutes ago, joelang6126 said: How do you go about doing this? Could you share your config files as I too am behind an nginx proxy trying to get fail2ban working with emby. I believe its this part: proxy_set_header Range $http_range; proxy_set_header If-Range $http_if_range; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
joelang6126 9 Posted August 24, 2020 Posted August 24, 2020 (edited) On 8/5/2020 at 2:02 PM, mastrmind11 said: I believe its this part: proxy_set_header Range $http_range; proxy_set_header If-Range $http_if_range; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; Adding that block reveals the correct IP to Emby now however fail2ban is actually failing to ban the IP even though it is detected and added to the ban list. Emby is still reachable. If I remove this block and turn Cloudflare to DNS only fail2ban functions correctly. Clearly theres something not quite right with that block. I'm at a loss to explain this. Any ideas guys? Edited August 24, 2020 by joelang6126
nayr 36 Posted August 26, 2020 Posted August 26, 2020 (edited) If your using cloudfare infront of your server you cant use fail2ban to blackhole these connections locally, because you'd have to do the blocking at cloudflare level.. locally all you can block is cloudfare as those IP's are not making any connections to you that could be blocked. You need a fail2ban action that makes an API request to Cloudfare to add the IP to a block list.. that information is out there. Edited August 26, 2020 by nayr
whiteowl3 2 Posted February 5, 2021 Posted February 5, 2021 I'd like to expand on this to cover the emby image traversal "problem", but I wanted to bounce some questions of you guys before I wasted too much time. We want fail2ban to detect actors which attempt the primary image bruteforce described here: The first question I have before I get started is: can regex do this? The second question is: @Luke, would filtering this behavior be likely to ban good actors? I realize it's a complex question, but, off the top of your head, does this seem doable? How likely is it that a good actor will request a massive incremental sequence of primary image resources? Third question: Does somebody smarter than me have a better approach to this? Are there other ways we could determine that the traversal is occurring? I think this is kinda the more important question because motivated baddies will obscure the iteration. Would looking for a different pattern be more useful? I really appreciate input on this before I zone in on code I don't fully comprehend.
whiteowl3 2 Posted February 5, 2021 Posted February 5, 2021 2 minutes ago, Luke said: Filter what behavior exactly? This, and effectively similar behaviors: http://{public domain}/emby/items/{increment number}/images/primary
Luke 38812 Posted February 5, 2021 Posted February 5, 2021 Just now, whiteowl3 said: This, and effectively similar behaviors: http://{public domain}/emby/items/{increment number}/images/primary Yes that would cause a problem. 1
emvidi 0 Posted October 26, 2021 Posted October 26, 2021 For docker version fail2ban not working have a look at this answer on serverfault.com. Copied from there: [YOUR-JAIL-NAME] chain = DOCKER-USER
mshaik 2 Posted November 9, 2021 Posted November 9, 2021 On 10/31/2021 at 10:22 PM, mshaik said: Finally I am able to ban Ip using fail2ban-docker, npm-docker and emby-docker. 1. Create a folder fail2ban and create the docker-compose.yml adding the following code: ``` version: "3.7" services: fail2ban: image: crazymax/fail2ban:latest container_name: fail2ban_docker network_mode: "host" environment: - TZ=US/Eastern - F2B_LOG_TARGET=STDOUT - F2B_LOG_LEVEL=INFO - F2B_DB_PURGE_AGE=1d cap_add: - NET_ADMIN - NET_RAW volumes: - "path/to/storage/fail2ban/data:/data" - "path/to/storage/fail2ban/log/:/var/log/" - "path/to/storage/nginxproxymanager/AppData/data/logs:/log/npm/:ro" - "path/to/storage/emby/logs:/log/emby/:ro" restart: unless-stopped ``` 2. In the fail2ban/data/ folder you created in your storage, create action.d, jail.d, filter.d folders and copy the files in the corresponding folder of git into them. i.e jail.d will have npm-docker.local,emby.local, filter.d will have npm-docker.conf,emby.conf and filter.d will have docker-action.conf,emby-action.conf respectively . Folder: fail2ban/data/jail.d npm-docker.local ``` [npm-docker] enabled = true ignoreip = 127.0.0.1/8 192.168.1.0/24 logpath = /log/npm/default-host_*.log /log/npm/proxy-host-*.log maxretry = 3 bantime = 86400 findtime = 60 action = docker-action ``` emby.local ``` [emby] enabled = true logpath = /log/emby/embyserver.txt ignoreip = 127.0.0.1/8 192.168.1.0/24 # your local IP subnets maxretry = 3 bantime = 84600 findtime = 60 action = emby-docker-action ``` Folder: fail2ban/data/filter.d emby.conf ``` [INCLUDES] [Definition] failregex = Response.4\d\d.to <HOST>.+ Time AUTH-ERROR: <HOST>.+- ``` npm-docker.conf ``` [INCLUDES] [Definition] failregex = ^<HOST>.+" (4\d\d|3\d\d) (\d\d\d|\d) .+$ ^.+ 4\d\d \d\d\d - .+ \[Client <HOST>\] \[Length .+\] ".+" .+$ ``` Folder: fail2ban/data/action.d docker-action.conf ``` [Definition] actionstart = iptables -N f2b-npm-docker iptables -A f2b-npm-docker -j RETURN iptables -I FORWARD -p tcp -m multiport --dports 0:65535 -j f2b-npm-docker actionstop = iptables -D FORWARD -p tcp -m multiport --dports 0:65535 -j f2b-npm-docker iptables -F f2b-npm-docker iptables -X f2b-npm-docker actioncheck = iptables -n -L FORWARD | grep -q 'f2b-npm-docker[ \t]' actionban = iptables -I f2b-npm-docker -s <ip> -j DROP actionunban = iptables -D f2b-npm-docker -s <ip> -j DROP ``` emby-action.conf ``` [Definition] actionstart = iptables -N f2b-emby iptables -A f2b-emby-docker -j RETURN iptables -I FORWARD -p tcp -m multiport --dports 0:65535 -j f2b-emby actionstop = iptables -D FORWARD -p tcp -m multiport --dports 0:65535 -j f2b-emby iptables -F f2b-emby iptables -X f2b-emby actioncheck = iptables -n -L FORWARD | grep -q 'f2b-emby[ \t]' actionban = iptables -I f2b-emby -s <ip> -j DROP actionunban = iptables -D f2b-emby -s <ip> -j DROP ``` 3. Once these are set, run the docker compose and check if the container is up and running or not Solution: It's setting custom action to ban and unban and also use Iptables forward from forward to f2b-npm-docker, f2b-emby which is more configuring up docker network, my docker containers are all in forward chain network, you can change FOWARD to DOCKER-USER or INPUT according to your docker-containers network. I used following guides to finally come up with this: https://github.com/jc21/nginx-proxy-manager/issues/39#issuecomment-907795521 - setup https://www.the-lazy-dev.com/en/install-fail2ban-with-docker/ - iptable commands etc .. Hope this helps some one like me who is trying to solve the issues they face with fail2ban and docker networks
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now