Access HTTP_X_FORWARDED_FOR Header in Apache for Django - django

I want to read client's IP address in Django. When I try to do so now with the HTTP_X_FORWARDED_FOR Header, it fails. The key is not present.
Apparently this is related to configuring my Apache server (I'm deploying with apache and mod_wsgi). I have to configure it as a reverse proxy? How do I do that, are there security implications?
Thanks,
Brendan

Usually these headers are available in request.META. So you might try request.META['HTTP_X_FORWARDED_FOR'].
Are you using Apache as a reverse proxy as well? This doesn't seem right to me. Usually one uses a lighter weight static server like nginx as the reverse proxy to Apache running the app server. Nginx can send any headers you like using the proxy_set_header config entry.

I'm not familiar with mod_wsgi, but usually the client IP address is available in the REMOTE_ADDR environment variable.
If the client is accessing the website through a proxy, or if your setup includes a reverse proxy, the proxy address will be in the REMOTE_ADDR variable instead, and the proxy may copy the original client IP in HTTP_X_FORWARDED_FOR (depending on it's configuration).
If you have a request object, you can access these environment variables like this :
request.environ.get('REMOTE_ADDR')
request.environ.get('HTTP_X_FORWARDED_FOR')
There should be no need to change your Apache configuration or configure a reverse proxy just to get the client's IP address.

Related

Sitecore GEO IP

I have an environment where a few Sitecore servers are behind a firewall & the reverse proxy in different AWS-VPCs (internet & intranet) with AWS Gateway. I need Geo-IP to be enabled and updated to the Sitecore host node for the device analytics dashboard (access via intranet or internet). Any possible suggestion? Thank you.
Reverse proxies typically forward the IP address from the connecting client via an additional http header X-Forwarded-For. See also https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For . You might need to enable this on AWS, I'm unfamiliar with their services.
However, also on the Sitecore end, you then need to enable reading of the header. This has been support for quite a while, and the documentations seems to have changed barely (if at all) since version 9.0:
https://doc.sitecore.com/xp/en/developers/90/sitecore-experience-manager/set-up-sitecore-ip-geolocation.html
The interesting bits are at the bottom, though:
When requests come from a reverse proxy server to your Sitecore instance that you want to track as the valid IP addresses of a client (not as the IP addresses of a proxy), use the following setting.
In Sitecore.Analytics.Tracking.config change the Analytics.ForwardedRequestHttpHeader setting to the value: X-Forwarded-For

Accessing HTTP content from an HTTPS server || HTTP request blocked

My Django application currently runs on HTTPS in the server. Recently i added a new functionality for which it has access another link to get JSON object which is HTTP link.
Its working fine in the localhost but when I deploy it in the server, it is showing the following error.
Site was loaded over HTTPS, but requested an insecure resource http link. This request has been blocked; the content must be served over HTTPS.
Can someone please suggest a workaround to bypass this so that the new functionality runs smooth.
This error comes from the browser, so there is not match you can do on the server side.
Easiest thing would be to enable https to those external resources if you have control over that.
Next workaround would be to add a proxy for your http resources and make this proxy https. In example, you could add a simple nginx server with proxy_pass to your http server and add https on that proxy'ing nginx.
Note, that if this JSON you are talking about contains anything sensitive, security-wise you really should serve it via https and not via proxy-workaround I described above. If nothing sensitive is served, workaround might be ok.
Since you have control over your http server, just allow ssl proxy on the nginx, with configuration that may look something like that:
server {
listen 443;
server_name my.host.name;
ssl_certificate /path/to/cert;
ssl_certificate_key /path/to/key;
location / {
proxy_pass http://localhost:80;
}
}
Note, if you're using something like AWS / GCP / Azure - you can do it on the load balancer side instead of nginx.
Otherwise, you can use letsencrypt to get the actual certificate and do some auto-configuration of nginx for you.

BrowserMob not proxying localhost pages

I'm trying to use BrowserMob to proxy pages with Selenium WebDriver. When the (Python) test case tries to load pages from localhost, BrowserMob fails to proxy them.
Is it possible for BrowserMob to proxy connections to the webserver at localhost?
I had the same problem with Selenium ChromeDriver. It didn't use proxy for localhost.
Setting noProxy attribute of seleniumProxy to "<-loopback>" solved the issue.
val seleniumProxy = ClientUtil.createSeleniumProxy(this)
...
seleniumProxy.noProxy = "<-loopback>"
Take a look at below link for details.
https://chromium.googlesource.com/chromium/src/+/master/net/docs/proxy.md#bypass-rule_subtract-implicit-rules
BrowserMob Proxy will work with localhost, but only in the latest version (2.0.0), and only when defining the bmp.allowNativeDnsFallback Java property when running the proxy. I'm not familiar with the Python wrapper, but it's unlikely that it meets those criteria.
The problem is the DNS resolution that BrowserMob Proxy uses, which essentially ignores the hosts file that defines localhost. If you use 127.0.0.1 instead of localhost when making requests it should work for you.

Restrict RESTful endpoint on tomcat to local webapp

Is there a mechanism built into Tomcat or Apache to differentiate between a local web application calling a local web service vs a direct call to a webservice?
For example, a single server has both apache and tomcat servers with a front end web app deployed to apache and back end services deployed on tomcat. The webapp can call the service via port 80 utilizing mod_proxy, however a direct call to the webservice and examining tomcaat's logs shows the requests to both be identical. For example:
http://127.0.0.1/admin/tools
<Location /admin/tools>
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</Location>
ProxyPass /admin/tools http://localhost:8080/admin/tools
ProxyPassReverse /admin/tools http://localhost:8080/admin/tools
This only blocks (or allows if you remove the deny) all external requests and both requests appear identical in tomcat's log.
Is there a recommended mechanism to differentiate and limit a direct remote service request vs the web application making a service request?
You need to use Tomcat's Remote IP Filter to extract the client IP provided by the proxy in the X-Forwarded-For HTTP header and use it to populate Tomcat's internal data structures. Then you will be able to correctly identify the source of the request.

Is it possible to run Apache and IIS on the same machine with one IP-Address (and different ports ?)

The "main" one should be IIS. Is there an option to address the Apache without typing in the port-number
The reason for this is: I cannot get Django to work on IIS
Any ideas will be appreciated
You could set up Apache on a different port, then use redirects or proxying on IIS to get people to the Apache port without them having to type it.
The only way to avoid typing in the port number is to set up a proxy, which could be either one of the two webservers. That way, the proxy makes the connection on the alternate port and the client doesn't have to know where it is.
I don't know about IIS, but on Apache, you would have to load mod_proxy (and I think, mod_proxy_http) and then do something like this:
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass /foo http://foo.example.com/bar
ProxyPassReverse /foo http://foo.example.com/bar
Also check the docs for mod_proxy online.
You might also want to look at lightweight webservers such as lighttpd, if you're going to have two running. It's a common setup to have a light webserver taking specific tasks away from the main one. (Apache for dynamic and lighttpd for static content is one typical example).
There's also other possibilities, ranging from getting more fancy, such as
Have a third webserver doing only the proxying and the other two on alternate ports
Have them running on the same port but two IPs and hide that fact via your network setup
to attacking the root cause by either
finding somenone who knows how to get Django running on IIS
moving from IIS to another webserver
Of course, I have no clue what might be appropriate for your situation.
If this is a matter of running Django on a server that already needs IIS, you can run django on IIS directly, thanks to efforts like Django-IIS and PyISAPIe. I think it would be preferable to NOT run a second web server when all its going to be doing is proxying requests out to a third server, the Django code.