jlesage/docker-nginx-proxy-manager

[Feature request] Real client IP to final host

xeviff opened this issue · 11 comments

xeviff commented

Idea

Hello. I have a serious issue:
All external traffic (hackers included) is represented as coming from the same IP and as a local one! (the NPM docker one), like 192.168.80.2 and then, when I receive a brute force attack, my NAS blocks the IP, leaving myself and all my users unable to access anymore to any of my services (all DNS requests are blocked) until I unblock it manually, opening the door again to the next hacker try.
I was thinking about solving this issue making the network_mode="host", and probably the NAS will have the real visibility to the external IPs (not sure, though), but it's not feasible anyways because the ports would need to be 443 and 80, instead of different ones.

How the NAS blocks the IP ? I assume it's based on the content of a log file ?

but it's not feasible anyways because the ports would need to be 443 and 80, instead of different ones.

Why not feasible ? You still need to do port forwarding on your router.

xeviff commented

Hello. I define a security rule on the NAS based on number attempts per time. For example in my case I set it to block an IP where tries more than two wrong logins in the course of 1 hour.

image

That's why identifing the real IP on the NAS point of view is critic. In my case all attacks pointing to my IP, the real source IP is identified, but all pointing to my domain are identified as 192.168.80.2 as you can see on the image:

image

On the other hand, it's true that if I configure the router to port forwarding 4443->443 I could try the network_mode="host" trick, but in my case I want to reach my services in the same way either if I'm at home or outside, for example I want to point to myservice.mydomain.com always (port 443) rather to remember changing the port when I'm at home (using LAN), like myservice.mydomain.com:4443
(I use a local DNS server to reach the LAN IP when I point to my domain).
Thanks for yout attention!

but in my case I want to reach my services in the same way either if I'm at home or outside

This can be done with a router feature called NAT loopback/reflection/hairpin.

xeviff commented

The reason was to run Nginx as non-root by using unprivileged ports.

xeviff commented

Ok. Finally I run it as network=host and did the test. Here's the result when I fail some login from my phone connected by satelite (outsite LAN):
image

The expected was to see some random IP of the phone company, but it's even worse than I though because the identified IP is 192.168.1.22, the NAS IP (!!!), I don't want to imagine what would happen if the NAS blocks itself :-)

Then, the issue is maybe more complex to fix than it seems. Right now I don't have any idea on how to solve it. I guess it's a common issue to all people using NPM on a NAS applying some security rule as IP blocking.

@xeviff you need to tell the NAS that the connection is from a proxy:
image

Put something like this, the IP should be your NPM proxy internal IP address:
image

xeviff commented

Thanks for the comment @jeremysherriff !
I guess this avoid blocking the IP but also opens the door to infinite login attempts from hackers, right?

I guess this avoid blocking the IP but also opens the door to infinite login attempts from hackers, right?

It shouldn't, no. It's not saying "always allow this proxy to be used, at all times, for any purpose", its saying "look for the extra info in the header to apply appropriate security rules". So the X-FORWARDED-FOR header is very important.

xeviff commented

ok, finally solved. Here the concrete details.
As this is a already existing feature, I close the issue. Thanks agani for your time!!

xeviff commented

A final note.
I enabled NAT loopback in my router (didn't know it had the feature, I'm sourprised honestly). It works but now if I fail logins from LAN, the IP identified is my public IP:
User [admin] from [83.xx.xx.228] failed to sign in to [DSM] via [password] due to authorization failure.
I guess at the end of the day, this may have negative impact to the users, and I'm not sure what benefits brings the fact of runnning Nginx as non-root by using unprivileged ports. I guess is not mandatory, as the official image works with 80:80 and 443:443 (I must say though, I always liked more this one because of the no need of having a separated DB docker)