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
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.