NginxProxyManager / nginx-proxy-manager

Docker container for managing Nginx proxy hosts with a simple, powerful interface
https://nginxproxymanager.com
MIT License
23.45k stars 2.72k forks source link

[Request] Add Fail2Ban #39

Open lordraiden opened 5 years ago

lordraiden commented 5 years ago

Please consider fail2ban https://www.fail2ban.org/wiki/index.php/Main_Page

and a 2 step verification method https://www.authelia.com/  https://github.com/clems4ever/authelia

BTW your software is being a total sucess here https://forums.unraid.net/topic/76460-support-djoss-nginx-proxy-manager/

posta246 commented 3 years ago

SUMMARY: it works, using the suggested config outside the container, on the host. Just need to understand if fallback file are useful

henkiewie commented 2 years ago

SUMMARY: it works, using the suggested config outside the container, on the host. Just need to understand if fallback file are useful

It works for me also. Adding the fallback files seems useful to me. So I added the fallback_.log and the fallback-.log to my jali.d/npm-docker.local. But is the regex in the filter.d/npm-docker.conf good for this? If I test I get no hits. I'm not an regex expert so any help would be appreciated.

henkiewie commented 2 years ago

SUMMARY: it works, using the suggested config outside the container, on the host. Just need to understand if fallback file are useful

It works for me also. Adding the fallback files seems useful to me. So I added the fallback_.log and the fallback-.log to my jali.d/npm-docker.local. But is the regex in the filter.d/npm-docker.conf good for this? If I test I get no hits. I'm not an regex expert so any help would be appreciated.

So why not make the failregex scan al log files including fallback*.log only for Client.<HOST>

if you have all local networks excluded and use a VPN for access. It works form me.

NajibNour commented 2 years ago

The following regex does not work for me could anyone help me with understanding it? UsingRegex:

^<HOST>.+" (4\d\d|3\d\d) (\d\d\d|\d) .+$ ^.+ 4\d\d \d\d\d - .+ \[Client <HOST>\] \[Length .+\] ".+" .+$

Log output from npm:

[20/Jan/2022:19:19:45 +0000] - - 404 - GET https somesite.ca "/wp-login.php" [Client 8.8.8.8] [Length 172] [Gzip 3.21] [Sent-to somesite] "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36" "-"

DISREGARD It Works just fine! My dumbness

TheUntouchable commented 2 years ago

I am currently using NPM with a MACVLAN, therefore the fail2ban container can read the mounted logs and create ip tables on the host, but the traffice from and to NPM is not going to the iptables of the host because of the MACVLAN and so banning does not work. Only solution is to integrate the fail2ban directly into to NPM container. So please let this happen! :)

mwLabs-eu commented 2 years ago

I am currently using NPM with a MACVLAN, therefore the fail2ban container can read the mounted logs and create ip tables on the host, but the traffice from and to NPM is not going to the iptables of the host because of the MACVLAN and so banning does not work. Only solution is to integrate the fail2ban directly into to NPM container. So please let this happen! :)

Same for me, would be really great if it could added.

arsaboo commented 2 years ago

@hugalafutro I tried that approach and it works. However, it has an unintended side effect of blocking services like Nextcloud or Home Assistant where we define the trusted proxies. For example, Nextcloud required you to specify the trusted domains (https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/config_sample_php_parameters.html). Similarly, Home Assistant requires trusted proxies (https://www.home-assistant.io/integrations/http/#trusted_proxies). Did you try this out with any of those?

hugalafutro commented 2 years ago

@arsaboo I use both ha and nextcloud (and other 13-ish services, including mail server) with n-p-m set up with fail2ban as I outlined above without any issue.

I used to have all these on the same vm and it worked then, later I moved n-p-m to vm where my mail server is, and the vm with nextcloud and ha and other stuff is being tunelled via mullvad and everything still seems to work.

I just cobbled the fail2ban "integration" together from various tutorials, with zero understanding of iptables or docker networking etc. It seemed to work (as in I could see some addresses getting banned), for my configuration, but I'm not technically adept enough to say why it wouldn't for you.

edit: for reference in nextcloud I define the trusted proxy like so in config.php:

  'trusted_proxies' => 
  array (
    0 => '192.168.1.142',
  ),

in ha I define it in configuration.yaml like so:

http:
  server_host: 0.0.0.0
  use_x_forwarded_for: true
  cors_allowed_origins:
    - https://google.com
    - https://www.home-assistant.io
  trusted_proxies:
    - 192.168.1.142
  ip_ban_enabled: false
  login_attempts_threshold: 5
captainabloc commented 2 years ago

Hi all, not running on docker, but on a Proxmox LCX I managed to get a working jail watching the access list rules I setup. In addition, being proxied by cloudflare, added also a custom line in config to get real origin IP.

/etc/fail2ban/filter.d/nginx-access.conf

# fail2ban filter configuration for nginx
[Definition]
failregex = ^ \[error\] \d+#\d+: \*\d+ access forbidden by rule, client: <HOST>, server.+$

ignoreregex = ^ \[warn\] .+$

/etc/fail2ban/jail.conf extract:

[nginx-access]
enabled = true
filter   = nginx-access
logpath = /data/logs/proxy-host-*.log
          /data/logs/default-host*.log
maxretry = 3
bantime  = 360
findtime = 60

In NPM Edit Proxy Host added the following for real IP behind Cloudflare in Custom Nginx Configuration: real_ip_header CF-Connecting-IP;

hope this can be useful. Please let me know if any way to improve

TituxMetal commented 2 years ago

This works for me: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/39#issuecomment-955873405

Hello @mastan30, in this file fail2ban/data/jail.d/npm-docker.local filter=npm-docker must be specified otherwise the filter is not applied, in my tests my ip is always found and then banned even for no reason. I also adjusted the failregex in filter.d/npm-docker.conf, here is the file content:

[INCLUDES]

[Definition]

failregex = ^.+ ".*w00tw00t.*" \[Client <HOST>\] \[Length .+\] .+$
  ^.+ (4\d\d|5\d\d) .*- .+ ".*(~|admin|dbadmin|install|myadmin|MyAdmin|mysql|websql|pma|wp-|manager|blackcat|sprawdza).*" \[Client <HOST>\] \[Length .+\] .+$
  ^.+ (5\d\d|4(?!04)\d\d) - .+ \[Client <HOST>\] \[Length .+\] .+$

Thank you it helps me so much!

kmanwar89 commented 1 year ago

Referencing the instructions that @hugalafutro mentions here:

I attempted to follow your steps, however had a few issues:

1) The compose file you mention includes a .env file, however you didn't provide the contents of this file. Is it save to assume it is the default file from the developer's repository?

2) In the volume directive of the compose file, you mention the path as - "../nginx-proxy-manager/data/logs/:/log/npm/:ro". I'm assuming this should be adjusted relative to the specific location of the NPM folder? In my case, my folder is just called "npm" and is within the ~/services directory on my server, so I modified it to be (relative to the f2b compose file) ../npm/data/logs.

3) In your instructions, you mount the NPM files as /data/logs and mount it to /log/npm, but in this blog post, the author specifically mentions "Ensure that you properly bind mount the logs at /data/logs of your NPM reverse proxy into the Fail2ban docker container at /var/log/npm. Otherwise, Fail2ban is not able to inspect your NPM logs!". I've tried both, and both work, so not sure which is the "most" correct.

I followed the above linked blog and (on the second attempt) got the fail2ban container running and detecting my logs, but I do get an error which (I'm assuming) actually blocks any of the ban behavior from taking effect:

f2b | 2023-01-28T16:41:28.094008433Z 2023-01-28 11:41:28,093 fail2ban.actions [1]: ERROR Failed to execute ban jail 'npm-general-forceful-browsing' action 'action-ban-docker-forceful-browsing' info 'ActionInfo({'ip': '75.225.129.88', 'family': 'inet4', 'fid': <function Actions.ActionInfo.<lambda> at 0x7f0d4ec48820>, 'raw-ticket': <function Actions.ActionInfo.<lambda> at 0x7f0d4ec48ee0>})': Error banning 75.225.129.88

But what is interesting is that after 10 minutes, it DID un-ban the IP, though I never saw a difference in behavior, banned or otherwise:

f2b | 2023-01-28T16:51:41.122149261Z 2023-01-28 11:51:41,121 fail2ban.actions [1]: NOTICE [npm-general-forceful-browsing] Unban 75.225.129.88

I then created a separate instance of the f2b container following your instructions, which also seem to work (at least so far).

Additionally, how did you view the status of the fail2ban jails? What command did you issue, I'm assuming, from within the f2b container itself?

I'm curious to get this working, but may actually try CrowdSec instead, since the developers officially support the integration into NPM.

kmanwar89 commented 1 year ago

I followed the guide that @mastan30 posted and observed a successful ban (though 24 hours after 3 tries is a bit long, so I have to figure out how to un-ban myself). Additionally I tried what you said about adding the filter=npm-docker to my file in jail.d, however I observed this actually did not detect the IP's, so I removed that line.

So I have 2 "working" iterations, and need to figure out the best from each and begin to really understand what I'm doing, rather than blindly copying others' logs.

hugalafutro commented 1 year ago

@kmanwar89 edit: most of your issues stem from having different paths / container / filter names imho, set it up exactly as I posted as that works to try it out, and then you can start adjusting paths and file locations and container names provided you change them in all relevant places. i.e. if you name your file instead of npm-docker.local to haha-hehe-hihi.local, you need to put filter=haha-hehe-hihi instead of filter=npm-docker etc.

  1. Yes
  2. Yes this is just relative path of the npm logs you mount read-only into the fail2ban container, you have to adjust accordingly to your path
  3. Doesn't matter at all as long the
    logpath = /log/npm/default-host_*.log
          /log/npm/proxy-host-*.log

    inside the jail definition file matches the path you mounted the logs inside the f2b container

I do not want to comment on others instructions as the ones I posted are the only ones that ever worked for me.


For reference this is my current config that bans ip on 3 different nginx-proxy-manager installations, I have joined the npm and fail2ban containers into 1 compose now:

directory structure

pi@pi-docker:~/docker/nginx-proxy-manager $ find ./ -type d -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
|____
|____data_npm
| |____logs
| |____custom_ssl
| |____letsencrypt-acme-challenge
| | |____.well-known
| | | |____acme-challenge
| |____access
| |____nginx
| | |____default_www
| | |____dead_host
| | |____proxy_host
| | |____temp
| | |____redirection_host
| | |____default_host
| | |____stream
|____data_f2b
| |____db
| |____action.d
| |____jail.d
| |____filter.d
|____letsencrypt
| |____csr
| |____archive
| | |____npm-10
| | |____npm-1
| | |____npm-48
| | |____npm-46
| | |____npm-26
| | |____npm-15
| |____renewal-hooks
| | |____post
| | |____deploy
| | |____pre
| |____keys
| |____renewal
| |____live
| | |____npm-10
| | |____npm-1
| | |____npm-48
| | |____npm-46
| | |____npm-26
| | |____npm-15
| |____accounts
| | |____acme-v02.api.letsencrypt.org
| | | |____directory
| | | | |____b1fc0554c1bcfe0b429559f8bcefaf4b

docker-compose.yml

version: '3'
services:
  nginx-proxy-manager:
    container_name: nginx-proxy-manager_pi-docker
    image: 'jc21/nginx-proxy-manager:latest'
    ports:
      - '10080:80'
      - '10081:81'
      - '10443:443'
    volumes:
      - ./data_npm:/data
      - ./letsencrypt:/etc/letsencrypt
    restart: always
    environment:
      X_FRAME_OPTIONS: "sameorigin"
      DB_SQLITE_FILE: "/data/database.sqlite"
      TZ: "Europe/London"

  fail2ban:
    image: crazymax/fail2ban:latest
    container_name: fail2ban_pi-docker
    network_mode: "host"
    cap_add:
      - NET_ADMIN
      - NET_RAW
    privileged: true
    volumes:
      - "./data_f2b:/data"
      - "./data_npm/logs/:/log/npm/:ro"
    restart: always
    env_file:
      - "./fail2ban.env"
    depends_on:
      - nginx-proxy-manager

data_f2b/jail.d/npm-docker.local

pi@pi-docker:~/docker/nginx-proxy-manager $ cat data_f2b/jail.d/npm-docker.local
[npm-docker]
enabled = true
ignoreip = 127.0.0.1/8 192.168.1.0/24 172.16.0.1/16 192.168.1.1
chain = INPUT
logpath = /log/npm/default-host_*.log
          /log/npm/proxy-host-*.log
maxretry = 3
bantime  = 2419200
findtime = 86400
filter = npm-docker

data_f2b/filter.d/npm-docker.conf

pi@pi-docker:~/docker/nginx-proxy-manager $ cat data_f2b/filter.d/npm-docker.conf
[INCLUDES]

[Definition]
ignoreregex = ^ [warn] .+$

failregex = ^<HOST>.+" (4\d\d|3\d\d) (\d\d\d|\d) .+$
            ^.+ 4\d\d \d\d\d - .+ \[Client <HOST>\] \[Length .+\] ".+" .+$
            ^.+ (4\d\d|5\d\d) .*- .+ ".*(~|admin|dbadmin|install|myadmin|MyAdmin|mysql|websql|pma|wp-|manager).*" \[Client <HOST>\] \[Length .+\] .+$
            ^.+ (5\d\d|4(?!04)\d\d) - .+ \[Client <HOST>\] \[Length .+\] .+$

check current bans

docker exec -it fail2ban_pi-docker fail2ban-client status npm-docker

example output

pi@pi-docker:~/docker/nginx-proxy-manager $ docker exec -it fail2ban_pi-docker fail2ban-client status npm-docker
Status for the jail: npm-docker
|- Filter
|  |- Currently failed: 58
|  |- Total failed:     4661
|  `- File list:        /log/npm/default-host_access.log /log/npm/default-host_error.log /log/npm/proxy-host-3_access.log /log/npm/proxy-host-10_error.log /log/npm/proxy-host-43_error.log /log/npm/proxy-host-22_error.log /log/npm/proxy-host-43_access.log /log/npm/proxy-host-15_error.log /log/npm/proxy-host-3_error.log /log/npm/proxy-host-22_access.log /log/npm/proxy-host-10_access.log /log/npm/proxy-host-1_access.log /log/npm/proxy-host-1_error.log /log/npm/proxy-host-15_access.log
`- Actions
   |- Currently banned: 255
   |- Total banned:     258
   `- Banned IP list:   101.68.211.3 103.72.147.115 104.155.129.44 107.150.126.151 108.194.208.147 109.237.97.180 109.237.98.226 109.249.187.77 109.74.204.123 111.30.107.154 116.203.223.117 118.193.56.146 128.14.188.209 134.122.40.17 134.209.105.9 134.209.172.210 136.33.158.151 137.184.147.18 137.184.214.147 137.184.69.186 138.197.12.104 138.197.147.198 138.197.157.88 139.59.101.36 139.59.190.229 139.59.251.216 139.64.164.73 139.99.120.203 139.99.123.180 141.255.167.130 142.93.240.129 143.110.178.178 143.198.212.64 143.198.220.72 143.198.239.27 143.244.140.48 144.126.236.89 144.91.106.14 146.148.39.73 146.19.24.230 146.190.244.19 146.70.119.3 146.70.119.35 146.70.119.37 146.70.119.67 148.63.28.25 150.129.81.213 152.32.227.68 152.89.196.211 157.245.136.139 157.245.99.223 159.203.35.125 159.223.68.123 159.65.111.248 159.89.107.64 159.89.111.42 161.35.161.99 161.35.188.150 162.142.125.10 162.142.125.210 162.142.125.211 162.142.125.212 162.142.125.213 162.142.125.219 162.142.125.221 162.142.125.7 162.142.125.8 162.142.125.9 164.92.135.200 165.22.54.62 165.22.65.114 165.227.208.24 165.227.212.9 165.232.124.165 165.232.64.133 167.172.103.51 167.172.188.222 167.172.90.80 167.172.93.19 167.248.133.117 167.248.133.120 167.248.133.44 167.248.133.46 167.248.133.60 167.248.133.61 167.248.133.62 167.71.201.171 167.71.73.251 167.71.85.7 167.94.138.119 167.94.138.120 167.94.138.44 167.94.138.46 167.94.138.47 167.94.138.60 167.94.138.61 167.94.138.62 167.94.146.57 167.94.146.58 167.94.146.60 167.99.207.240 170.64.134.42 170.64.148.163 170.64.176.251 170.64.176.7 170.64.180.140 176.65.137.4 179.43.155.157 179.43.177.242 183.106.161.103 183.136.225.32 183.136.225.45 184.105.139.67 184.105.139.70 185.180.143.141 185.180.143.81 185.195.232.131 185.195.232.133 185.195.232.139 185.195.232.140 185.195.232.141 185.195.232.149 185.195.232.152 185.195.232.160 185.195.232.161 185.195.232.169 185.195.232.170 185.195.232.180 185.213.175.253 185.224.128.219 185.225.73.198 185.225.74.45 185.225.74.55 185.248.85.10 185.248.85.31 185.248.85.32 185.248.85.36 185.248.85.4 188.166.232.195 191.254.254.119 193.32.162.159 193.35.18.189 193.35.18.227 193.35.18.228 193.35.18.242 193.38.55.200 194.180.49.233 194.55.186.216 195.133.40.86 195.154.77.190 198.20.69.98 2.57.122.80 20.163.207.204 201.163.190.64 201.23.6.2 207.154.245.167 208.100.26.229 209.126.151.116 209.126.151.117 209.126.151.119 209.126.151.120 209.126.151.122 209.141.33.8 212.18.176.230 213.205.192.74 213.205.196.194 213.205.241.29 213.205.241.92 213.205.242.98 219.85.88.188 23.224.186.225 24.150.82.71 24.199.92.233 34.121.19.107 34.122.44.159 34.135.91.26 34.136.137.67 34.171.253.186 34.172.163.221 34.172.175.164 34.172.209.163 34.173.116.45 34.201.148.42 34.27.133.230 34.29.37.32 34.67.120.116 34.67.167.189 34.67.214.23 34.69.204.32 34.70.93.107 34.71.162.68 35.192.12.146 35.202.182.162 35.202.234.8 35.216.248.122 35.222.78.111 35.224.175.167 35.225.212.38 35.226.241.168 35.226.97.237 35.232.70.169 35.238.41.231 35.239.89.230 37.44.238.144 37.44.238.71 43.134.171.148 43.135.123.64 45.12.253.180 45.61.186.176 45.9.110.186 45.93.201.64 46.19.136.74 47.89.188.40 49.234.150.132 5.188.210.227 5.75.202.224 52.4.28.5 61.147.15.65 61.147.15.67 62.171.128.107 62.210.75.103 64.225.103.50 64.225.18.115 64.225.56.220 65.49.20.66 65.49.20.68 67.222.109.195 68.183.111.90 68.183.12.150 71.6.135.131 72.55.136.154 74.82.47.3 74.82.47.4 77.81.142.251 79.124.59.150 80.94.92.57 82.170.148.96 89.248.165.204 89.248.165.52 89.31.112.234 90.2.97.189 91.107.142.252 92.118.39.29 92.118.39.82 94.62.138.31 185.195.232.165 112.47.34.246 159.89.171.91 35.153.144.36 193.35.18.206 161.35.213.143 134.209.159.229 163.123.181.180 185.195.232.159 34.136.218.224
hugalafutro commented 1 year ago

Apologies if this is offtopic, but if anyone doubts usefulness of adding f2b to npm or whether the method I used is working I'd like to share some statistics from my cloud server with exposed ssh and http(s) ports. Along banning failed attempts for n-p-m I also ban failed ssh log ins. Endlessh is a wonderful little app that sits on the default ssh port and drags out random ssh responses until they time out to waste the script kiddie's time and then f2b bans them for a month. Graphs are from LibreNMS. image I get about twice the amount of bans on my cloud based mailcow mail server, along the bans that mailcow itself facilitates for failed mail logins.

alneven commented 1 year ago

| |____action.d

@hugalafutro : just to make it sure, in a totally new setup, npm and fail2ban: do I need something in this action.d folder? a docker.conf file or something? with definition like

actionstart
actionstop
actioncheck
actionban
actionunban
hugalafutro commented 1 year ago

@alneven In both my setups using n-p-m+f2b the directory ended up empty. I'm not really sure what it's for (every tutorial for implementing f2b whether in docker or on the bare metal I followed only talks about making a filter and a jail).

alneven commented 1 year ago

In both my setups using n-p-m+f2b the directory ended up empty.

thanks for the prompt feedback, I will ignore it as well

JS-E commented 1 year ago

Sorry to bump and old topic but i was considering trying to get this to work- Think it would be great to have another tab on the dashboard that shows you blocked IPs and various stats about fail2ban. Has anyone actually got this working nicely inside the nginx container? I do agree that i think it's better to have it all in one as it's the main entry point to services

gzxiexl commented 1 year ago

I hope to merge the functions of Fail2Ban and make a dashboard to display the banned logs.

JS-E commented 1 year ago

I hope to merge the functions of Fail2Ban and make a dashboard to display the banned logs.

I love to help out where i can and i love the idea of having a dashboard to monitor what's been blocked and why. Maybe with the option to expose it to something like grafana? Just ideas

samwathegreat commented 10 months ago

Add me to the list of people that would be eternally grateful to see fail2ban integration with npm. I use proxmox (LXC containers), so it would be great if this was available using the proxmox script and not just docker.

captainabloc commented 10 months ago

Add me to the list of people that would be eternally grateful to see fail2ban integration with npm. I use proxmox (LXC containers), so it would be great if this was available using the proxmox script and not just docker.

it is! just install Fail2ban on your LXC after NPM install

B0F1B0 commented 7 months ago

``> Hi all, not running on docker, but on a Proxmox LCX I managed to get a working jail watching the access list rules I setup. In addition, being proxied by cloudflare, added also a custom line in config to get real origin IP.

/etc/fail2ban/filter.d/nginx-access.conf

# fail2ban filter configuration for nginx
[Definition]
failregex = ^ \[error\] \d+#\d+: \*\d+ access forbidden by rule, client: <HOST>, server.+$

ignoreregex = ^ \[warn\] .+$

/etc/fail2ban/jail.conf extract:

[nginx-access]
enabled = true
filter   = nginx-access
logpath = /data/logs/proxy-host-*.log
          /data/logs/default-host*.log
maxretry = 3
bantime  = 360
findtime = 60

In NPM Edit Proxy Host added the following for real IP behind Cloudflare in Custom Nginx Configuration: real_ip_header CF-Connecting-IP;

hope this can be useful. Please let me know if any way to improve

For me the /etc/fail2ban/filter.d/nginx-access.conf was not working to ban someone. With this nginx-access.conf it works

nano/etc/fail2ban/filter.d/nginx-access.conf

[INCLUDES]

[Definition]

failregex = ^<HOST>.+" (4\d\d|3\d\d) (\d\d\d|\d) .+$
            ^.+ 4\d\d \d\d\d - .+ \[Client <HOST>\] \[Length .+\] ".+" .+$
github-actions[bot] commented 1 month ago

Issue is now considered stale. If you want to keep it open, please comment :+1:

demlak commented 1 month ago

bad stale-bot! =)