CakePHP Force SSL - env('HTTPS') always null - php

I've tried quite a few different solutions (here, here, here, here) but almost all of them caused either 404 or infinately loops.
Finally I found this question which seems to get the closest to working; but it also causes an error in Firefox when I try to load one of the actions I wish to require SSL on:
The page isn't redirecting properly
Firefox has detected that the server is redirecting the request for
this address in a way that will never complete.
This problem can sometimes be caused by disabling or refusing to
accept cookies.
Finally through a bunch of debugging I have found that env('HTTPS') always returns null for some reason (as does $this->RequestHandler->isSsl(); and $_SERVER['HTTPS']) even when I'm using an HTTPS connection. I cannot understand why this is happening, since my browser reports that I am SSL secure and my certificate seems to be installed correctly.
More Info
nginx server
listen 80;
listen 443 ssl;
ssl_certificate /etc/ssl/certs/domain.chain.crt;
ssl_certificate_key /etc/ssl/private/domain.key;
...
App Controller
var $secureItems = array('login', 'edit', 'viewDocs');
function beforeFilter() {
$this->Auth->allow('index', 'display');
$this->set('loggedUser', $this->Auth->user());
$this->__checkSSL();
}
__checkSSL() and supporting functions are directly from the previously link question (this one).
Pages load fine in HTTP and HTTPS as long as its not one of the actions I have listed in $secureItems as soon as I go to one of those actions (either HTTP or HTTPS) it infinately redirects.
Any help is appreciated!
Edit:
I am pretty sure the issue is an infinite loop caused by env('HTTPS') always being null. Since its null the check condition is always false and makes it redirect to an HTTPS URL even though its already on one.
Is there another way I can check for HTTPS or can someone tell me why env('HTTPS') is always returning null?

You're edit is a step in the right direction...
It is down to the web server to set environment variables such as $_SERVER['HTTPS'].
If this has a no value, you need look no further than the web server - nginx in your case - or at any web servers inbetween (reverse proxies, etc.)
I don't have any experience with SSL on nginx in particular, but from what I can gather you need to make sure nginx is sending fastcgi_param HTTPS on for connections on port 443.
Adding something like this, perhaps:
server {
listen 443;
server_name example.com;
ssl on;
fastcgi_param HTTPS on;
# ...
}
Search for "nginx fastcgi_param HTTPS" for other config examples.
I also found some other variables that may be of use further down the line.

Related

Communication between two servers for a ddos challenge page?

I need to develop a challenge page much similar to the Cloudflare firewall challenge.
I know how to make the front end and the back end of the challenge app and I know how to set it up on the server.
The problem comes on how to implement it to the website which is on one server, while the challenge app is on another server. How should I make the communication between the servers? Both servers will be Ubuntu 16.4. Thank you all in advance.
I think it's better to solve this issue like cloudflare using nginx server.
Make an nginx reverse proxy with rate limit
if limit hit user will be redirected to error page
integrate your challenge app with the error page.
more about this configuration is here:
https://serverfault.com/questions/645154/how-to-redirect-to-an-other-link-when-excess-request-limit-req-with-nginx
And How to use PHP in error pages is here:
Nginx, PHP + FPM Custom Error Pages
you can run this reverse proxy on third server or you can run it on the challenge app server.
make your domain points to the reverse proxy
then
make nginx config
server {
listen 80 default_server;
server_name *.*;
client_body_timeout 5s;
client_header_timeout 5s;
location / {
proxy_set_header Host $host;
proxy_pass http://00.00.00.00/; #replace with upstream ip
}
}
you have to combine this with custom php error page

There is mismatch between HTTPS indicated on the server and client

This is the warning when I open my phpMyAdmin's login (index) page:
There is mismatch between HTTPS indicated on the server and client.
This can lead to non working phpMyAdmin or a security risk.
Please fix your server configuration to indicate HTTPS properly.
The error should be caused by a loadbalancer in between my client and phpmyadmin itself. SSL terminates on the loadbalancer so the URL being used (that phpmyadmin receives in request headers, I assume) is https://mydomain/phpmyadmin.
The loadbalancer communicates with phpmyadmin via http, so the URL being used between lb and pma is http://mydomain/phpmyadmin (not https).
I found this very fitting article on github: Possibility to deactivate SSL connection #170 which is for Docker containers and describes an env var to be passed to the container called "PMA_ABSOLUTE_URI" to fix the problem.
Which setting would this be in phpmyadmin NON Docker?
Any other solution to my problem is also highly appreciated.
Sidenote: Phpmyadmin works fine after the login. You can log in, there are no warnings after the log in and you can perform all interactions without problems. I am just worried about the warning.
I have exactly the same setup as you are describing. A front load balancer acts as reverse proxy and also as SSL/TLS terminator. The LB talks in plain http with the backend server where phpMyAdmin is running.
When I upgraded from 4.0.4.1 to 4.9.0.1 I got the same warning appearing at the phpMyAdmin login screen as you. I was able to solve this on the reverse proxy by "faking" the protocol from http to https. In my case my reverse proxy is a Nginx web server and just before I'd pass to the backend server, I added X-Forwarded-Proto:
server {
listen 443;
server_name my.phpmyadmin.example.com;
[... log and ssl settings ...]
location / {
include /etc/nginx/proxy.conf;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://backendserver;
}
}
By adding proxy_set_header X-Forwarded-Proto https; this tells the backend server that the client to proxy communication happens over https. Without setting this header, phpMyAdmin probably identifies (not sure, just a guess) that it was loaded on a https:// URL yet the communication (between reverse proxy and phpMyAdmin server) happened over http. Therefore it's a correct warning to be shown.
As soon as Nginx was reloaded, the warning disappared from the phpMyAdmin login screen.

HTTPS/PHP/NGINX: php://input data is NULL when HTTPS is enabled

This is related to this question. I found that when I checked my HTTPRequest on my YII that Yii::app()->request uses either file_get_contents('php://input') or $HTTP_RAW_POST_DATA to get the request from the front-end. This mechanism works when SSL is disabled yet when enabled, the post data disappears. I saw a similar question but there has been no concrete solution though there is an answer that discourages that use of a 302 redirect when forcing http to https. I need this mechanism on my api server to redirect http to https. How can I allow the redirection of http to https without losing post data? My nginx config is found on this link.
I hope this gets resolved once and for all because I've spent more than a week stuck on this problem.
If you want to redirect http to https, you have to update your nginx conf file.
Nginx should listen to http :
server {
listen 80;
server_name api.test.com;
return 301 https://api.test.com$request_uri;
}
server {
listen 443 ssl http2;
server_name api.test.com;
root /var/apps/myapp/current/workspace/api;
...
The http2 is optional

HTTPS Header Redirect Not Working with PHP

I have a load balanced dev site that I'm working out bugs for SSL on and I have ran into one last very annoying issue. On some pages I need to force it to SSL so easy enough, I just wanted to create a
header ("Location: https://www.example.com/mypage.php");
I thought that was easy enough and no worries. However, every time I do this it transforms it back to http. Well as you can figure it creates an endless loop that can't be resolved. I can't figure out how to keep that https in there so that it will pull the secure version of the page. If I navigate directly to the secure page with https it works just fine. The only issue is on this redirect.
Any help would be awesome! I'm using POUND as a load balance proxy. Apache on the web-server nodes. The SSL cert is setup at the Load Balancer.
When loadbalancing, 'internal' SSL usually goes out the door: Clients connect through a load-balancer with which you can do SSL encryption, but behind that in most loadbalancers I've seen is plain 'HTTP'. Try to get your loadbalancer to set a custom header to you indicating that there is a HTTPS connection between loadbalancer & client.
From http://www.apsis.ch/pound/index_html
WHAT POUND IS:
...
an SSL wrapper: Pound will decrypt HTTPS requests from client browsers and pass them as plain HTTP to the back-end servers.
And from more manual pages:
HTTP Listener
RewriteLocation 0|1|2
If 1 force Pound to change the Location: and Content-location:
headers in responses. If they point to the back-end itself or to
the listener (but with the wrong protocol) the response will be
changed to show the virtual host in the request. Default: 1
(active). If the value is set to 2 only the back-end address is
compared; this is useful for redirecting a request to an HTTPS
listener on the same server as the HTTP listener.
redirecting to https pages is no problem.
you can check for the port, scheme or server variable (probably server variable is the best) to see if https is on, and have it as a condition for redirecting
$_SERVER['SERVER_PORT'] == 443
parse_url($_SERVER['REQUEST_URI'],PHP_URL_SCHEME) == 'https'
$_SERVER['HTTPS'] == 'on'
but as you have an infinite loop there must be something else wrong!
try using the load blancer "balance" instead. it only takes about 5 minutes to set up, and instead of proxying, will do "real" load balancing. I would guess your proxy is currently redirecting https requests to the http address. Try making a request without using the balancer. you can do this by setting up the host name in your /etc/hosts file to point directly to a server instead of to the load balancer's IP

Detecting HTTPS requests in PHP

The problem that I am having has to do with the need to keep some urls of a website protected by HTTPS and the rest kicked to HTTP.
Normally, you have $_SERVER['HTTP_HTTPS'] or $_SERVER['HTTPS'] (depending on your flavor of Apache). You also can check the port - it's 80 for normal traffic and 443 for HTTPS.
My problem is that the certificate sits on the loadbalancer, and all these variables are unavailable, and the webserver sees http://www.foo.com on port 80. One way to fix this is to tell the loadbalancer to send the traffic on a different port, but I wonder if there are other ways to detect HTTPS coming from the load balancer?
If anybody has the same issue behind an Amazon AWS Elastic Load Balancer, the solution is simple because the $_SERVER variable will include:
[HTTP_X_FORWARDED_PORT] => 443
[HTTP_X_FORWARDED_PROTO] => https
So, to get the protocol, you could use:
function getRequestProtocol() {
if(!empty($_SERVER['HTTP_X_FORWARDED_PROTO']))
return $_SERVER['HTTP_X_FORWARDED_PROTO'];
else
return !empty($_SERVER['HTTPS']) ? "https" : "http";
}
If the load balancer is the other end of the SSL connection, you cannot get any more info than the load balancer explicitly provides. I would go for adding a http header, it may already be doing that, dump all the HTTP headers and look.
As another solution, you can do the redirection on the load balancer based on URL.
the $_SERVER['HTTP_X_FORWARDED_PROTO'] seems to be a good solution for joomla users because if your loadbalancer does the rediretion and you set the force_ssl setting to 1 or 2 then you will end in an infinite loop because joomla always sees http:

Categories