Sie die request.access_route
attribute nur verwenden, wenn Sie eine Liste der vertraute Proxies definieren.
Das Attribut access_route
verwendet die X-Forwarded-For
header, die auf die REMOTE_ADDR
WSGI-Variable zurückfällt; Letzteres ist in Ordnung, da Ihr Server dies feststellt; die X-Forwarded-For
von nur etwa jeder gesetzt worden sein könnte, aber wenn Sie einen Proxy vertrauen korrekt den Wert einzustellen, verwenden Sie dann die erste (von hinten), die nicht vertraut ist:
trusted_proxies = {'127.0.0.1'} # define your own set
route = request.access_route + [request.remote_addr]
remote_addr = next((addr for addr in reversed(route)
if addr not in trusted_proxies), request.remote_addr)
Auf diese Weise, Selbst wenn jemand den X-Forwarded-For
Header mit fake_ip1,fake_ip2
vortäuscht, fügt der Proxy-Server ,spoof_machine_ip
zum Ende hinzu, und der obige Code setzt remote_addr
auf spoof_machine_ip
, egal wie viele vertrauenswürdige Proxies es zusätzlich zu Ihrem äußersten Proxy gibt.
Dies ist die Whitelist-Herangehensweise, über die Ihr verknüpfter Artikel spricht (kurz, in dem Rails es verwendet) und was Zope implemented over 11 years ago.
Ihr ProxyFix Ansatz funktioniert gut, aber Sie missverstanden, was es tut. Es nur Sätze request.remote_addr
; Das request.access_route
Attribut ist unverändert (der X-Forwarded-For
Header ist nicht angepasst von der Middleware). Aber, würde ich sehr vorsichtig blind von Proxys abzählen.
Anwendung des gleichen Whitelist-Ansatz an die Middleware würde wie folgt aussehen:
class WhitelistRemoteAddrFix(object):
"""This middleware can be applied to add HTTP proxy support to an
application that was not designed with HTTP proxies in mind. It
only sets `REMOTE_ADDR` from `X-Forwarded` headers.
Tests proxies against a set of trusted proxies.
The original value of `REMOTE_ADDR` is stored in the WSGI environment
as `werkzeug.whitelist_remoteaddr_fix.orig_remote_addr`.
:param app: the WSGI application
:param trusted_proxies: a set or sequence of proxy ip addresses that can be trusted.
"""
def __init__(self, app, trusted_proxies=()):
self.app = app
self.trusted_proxies = frozenset(trusted_proxies)
def get_remote_addr(self, remote_addr, forwarded_for):
"""Selects the new remote addr from the given list of ips in
X-Forwarded-For. Picks first non-trusted ip address.
"""
if remote_addr in self.trusted_proxies:
return next((ip for ip in reversed(forwarded_for)
if ip not in self.trusted_proxies),
remote_addr)
def __call__(self, environ, start_response):
getter = environ.get
remote_addr = getter('REMOTE_ADDR')
forwarded_for = getter('HTTP_X_FORWARDED_FOR', '').split(',')
environ.update({
'werkzeug.whitelist_remoteaddr_fix.orig_remote_addr': remote_addr,
})
forwarded_for = [x for x in [x.strip() for x in forwarded_for] if x]
remote_addr = self.get_remote_addr(remote_addr, forwarded_for)
if remote_addr is not None:
environ['REMOTE_ADDR'] = remote_addr
return self.app(environ, start_response)
explizit zu sein: diese Middleware auch nur Sätze request.remote_addr
; request.access_route
bleibt davon unberührt.
Ich denke, ich bin nur verwirrt, warum der sogenannte "ProxyFix" das Problem nicht behoben hat. Soll ich mich mit dem ProxyFix beschäftigen? –
thx wieder Martijn! –