Search code examples
nginxcherrypynginx-reverse-proxy

Get incoming referer domain from cherrypy.request behind nginx reverse proxy


I'm trying to check the website a user just came from to my site against a whitelist of allowed domains:

import cherrypy
import urlparse
referer = cherrypy.request.headers.get('Referer','/').lower()
domain = urlparse.urlparse(referer).netloc
if domain in ('mysite.org','whitelistedsite.com'):
    ... do stuff ...

But my cherrypy is sitting behind NGINX (as a reverse-proxy), so I get nothing back.

 ('X-Forwarded-Host', 'this.org')
 ('Host', 'this.org')

How can I get around this? Or is it impossible without editing NGINX, which I cannot do.

More general information about cherrypy behind NGINX reverse-proxy is here https://www.digitalocean.com/community/tutorials/how-to-deploy-cherrypy-web-applications-behind-nginx-reverse-proxy


Solution

  • Short answer is that Nginx shouldn't me masking the referer. Nginx will mask the Host header, and you need to use the proxy tool in order for cherrypy.request.remote.ip and cherrypy.request.base to be set based on host the original agent sent. But Referer should be passed unchanged.

    It's possible (though seems unlikely) that your hosting provider would remove the referer header.

    For example, I have a service that will echo the request headers with this handler:

    class System: @cherrypy.expose def headers(self): return cherrypy.request.headers

    That server is sitting behind Nginx, and when I make a request to it with a referer, I see it in the output:

    proj master $ curl https://api.tentob.com/system/headers/ -H 'Referer: jaraco did it' {"Remote-Addr": "::1", "Host": "svc.example.com", "X-Real-Ip": "99.99.99.99", "X-Forwarded-For": "99.99.99.99", "X-Forwarded-Host": "svc.example.com", "X-Forwarded-Proto": "https", "Connection": "close", "User-Agent": "curl/7.54.0", "Accept": "*/*", "Referer": "jaraco did it"}

    So your implementation as shown looks like it should work to me.

    You should be careful, though. As you can see, it would be trivially-easy for an attacker to supply any old Referer they wish.