imbolc / axum-client-ip

A client IP address extractor for Axum
MIT License
43 stars 13 forks source link

Whitelist reverse proxy IPs? #13

Open taladar opened 1 year ago

taladar commented 1 year ago

Other systems that use the X-Forward-For or X-Real-IP headers often allow whitelisting of IPs from which the header is accepted, falling back to the actual TCP peer information instead for requests coming from other sources (or do not include a header of course).

Is there a particular reason this crate does not seem to support this basic security mechanism?

imbolc commented 1 year ago

I'm not sure what you mean by "IPs from which the header is accepted". Checking if the IP we get from a header is whitelisted?

taladar commented 1 year ago

I mean that the header is only accepted if the connection with the request comes from the known IP of the reverse proxy in front of the axum app, so e.g. if I have a varnish running on 1.2.3.4 only requests from 1.2.3.4 would use the IP extracted from the header but all other requests would use the peer IP directly to avoid spoofing.

imbolc commented 1 year ago

Do you mean an app is listening to 0.0.0.0 and we'd like to check if axum::extract::ConnectInfo IP is e.g., 127.0.0.1? Why can't we just make the app listen to 127.0.0.1?

Regarding the implementation, I believe we still have to distinguish between IP extraction and whitelist checking. Let's say we're using the axum_client_ip::XRealIp extractor. The absence of X-Real-IP would mean an error in the proxy configuration, while the absence of the IP in the whitelist would indicate unauthorized access.

The first thing coming to my mind is wrapping the XRealIp extractor into another one. We would also have to keep the whitelist somewhere, in axum::extract::State probably.

taladar commented 1 year ago

Basically I am talking about the trusted proxy settings from e.g.

http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from

https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html#remoteiptrustedproxy

https://github.com/gnif/mod_rpaf ( RPAF_ProxyIPs )

Making the app listen on 127.0.0.1 works for that special case but for anything where you need routing beyond the local host it won't work (e.g. host is reverse proxy for a VM or container, reverse proxy is a load balancer appliance that does SSL termination,...).

The absence of X-Real-IP would mean an error in the proxy configuration

Not necessarily, there could be e.g. monitoring systems checking the app directly to distinguish between failures in different parts of the stack.

imbolc commented 1 year ago

Ok, I think I roughly understand your need. Though I think it's quite specific, as you're mention, most used proxies already have the setting on their level.

Also the topic reaches beyond my area of expertise. So I'm not going to implement this feature by myself. Though However, I'm willing to discuss implementation details and accept a PR if you'd like to work on it.

taladar commented 1 year ago

Oh, these settings are not for use of those servers as proxy but for use behind proxies.

I might have a look at implementing it and creating a PR, thanks for your help so far.