How to ensure that a request is really proxied by CloudFlare? - http-headers

In one of projects we use CloudFlare and its cf-connecting-ip header to get a visitor IP address. But I'm not sure that the info can be fully trusted. For example, a bad user somehow had obtained real IP of our server, and connecting directly to it, putting fake IP address to the cf-connecting-ip header, and pretending that it was a legitimate CF-proxied request.
I examined headers for CF-proxied requests, and saw the cf-request-id header. But it's unique per a request, and I cannot see there any fixed secure key which I can use to verify that the request was legitimate.
How to ensure that a request was really proxied by CF?

You may want to use the Authenticated Origin Pulls feature from Cloudflare:
Authenticated Origin Pulls let origin web servers strongly validate that a web request is coming from Cloudflare.
We use TLS client certificate authentication, a feature supported by most web servers, and present a Cloudflare certificate when establishing a connection between Cloudflare and the origin server.
By validating this certificate in origin server configuration, access can be limited to Cloudflare connections.
You will need to download the client certificate from Cloudflare and configure your webserver to enforce the certificate check.
The referenced page has instructions on how to set up client certificate in Apache and Nginx.

Related

Is it possible to make a cross domain javascript request to HTTP from HTTPS?

There are several questions that relate to this, but they're either very specific, inconclusive or outdated:
Is it possible to make a cross domain request from https to http in IE?
Can IE8 post cross-domain requests from HTTP to HTTPS?
Cross domain HTTP requests
Cross domain request from HTTP to HTTPS aborts immediately
And a few others.
As of now, is it at all possible to make any (GET, PUT, POST...) HTTP request, within JavaScript, to a server that does not have a valid SSL certificate, in a page served from a HTTPS server? Without, of course, asking the user to trust a self-signed cert or disable protections.
I've tried fetch and XMLHttpRequest requests, but they either get blocked by the browser because of CORS or generic "TypeError: NetworkError".
My specific predicament is that I have a home server accessible through a dynamic DNS provider (free tier). I cannot easily obtain an SSL certificate because my ISP blocks HTTP requests to port 80, which makes Let's Encrypt HTTP-01 challenge basically impossible.

How should an HTTP be listed under Google's API when using Cloudflare's shared SSL?

From my research I'm not getting an answer after referencing:
Custom SSL doesn't show when using CloudFlare
How to append SSL Origin Certificate with CloudFlare's Root Certificate?
Assets not loaded when using CloudFlare SSL
Cloudflare SSL issue: Request origin does not match request base_url
CloudFlare SSL refused on HTTP access
Wildcard SSL Certificates, Custom Domain Names, and Cloudflare
In my domain register I point my domain nameservers to Cloudflare and under Cloudflare's Crypto set SSL to Full. When I add the URL under Client ID for web application -> Restrictions -> Authorized JavaScript origins and Authorized redirect URIs should I be using HTTP, HTTPS, or both?
My understanding Cloudflare's SSL is a shared SSL and not a dedicated SSL. From Google's documentation I am unaware or able to find when using the Google Login API if the API will work successfully using a shared SSL.
The app is a web application written in Node using Google's Login API and hosted with a custom domain on Heroku. I am able to get the application to work locally and with Heroku's generated URL but I'd like to also implement Cloudflare I'm just unsure what is the correct way to use a shared SSL.
So to sum up, if I own the domain foobar.com in Google's Restrictions should I be using:
http://foobar.com
http://www.foobar.com
or
https://foobar.com
https://www.foobar.com
if the SSL is a shared SSL from Cloudflare?
It depends how do you want to expose your domain to users. Both protocols http/https can be allowed.
However you are trying to use "Google's Login API" = probably Open ID Connect client (SAML client is different), which needs encryption -> so actually, you need to allow only https protocol and then you will have safe configuration.

Is CloudFlare's free SSL actually secure?

I've just set up CloudFlare on my web app. The free version, since my app isn't generating any revenue right now.
Now all my traffic is routing through CloudFlare's servers, correct? And that connection is "secure" because it's under HTTPS -- Chrome even displays the green padlock.
But CloudFlare is still communicating with my server over HTTP (unsecure connection), are they not?
Doesn't that mean all my client's data is sent in the clear between CloudFlare and my server? And that makes it not really secure at all, despite what Chrome thinks?
No.
The "Flexible" option of the "Crypto / SSL (with SPDY)" setting is not secure. If you read the "Help" text it says:
There is an encrypted connection between your website visitors and CloudFlare, but not from CloudFlare to your server.
You must install an SSL certificate on your own server and then select the "Full SSL (strict)" option to be secure.
You can configure the origin for the CDN (i.e. your servers that provide the original version of the content to be distributed across the CDN) to provide data using HTTPS. With the pro version (which you are not currently using) you can also use the SPDY protocol. HTTPS communication between the CDN and your servers protects that part of the communication path.
Additionally, and optionally, you can use Authenticated Origin Pulls (also available in the free version) to ensure that the CDN and origin (you) are both who you claim to be.

Difference between https protocol and SSL Certificate

What is difference between https protocol and SSL Certificate that we use in web browser?
Aren't both of these used to encrypt communication between client (browser) and server?
HTTPS is HTTP (HyperText Transfer Protocol) plus SSL (Secure Socket Layer). You need a certificate to use any protocol that uses SSL.
SSL allows arbitrary protocols to be communicated securely. It enables clients to (a) verify that they are indeed communicating with the server they expect and not a man-in-the-middle and (b) encrypt the network traffic so that parties other than the client and server cannot see the communication.
An SSL certificate contains a public key and certificate issuer. Not only can clients use the certificate to communicate with a server, clients can verify that the certificate was cryptographically signed by an official Certificate Authority. For example, if your browser trusts the VeriSign Certificate Authority, and VeriSign signs my SSL certificate, your browser will inherently trust my SSL certificate.
There's some good reading here: http://en.wikipedia.org/wiki/Transport_Layer_Security
Two pieces of one solution.
https is the protocol that defines how the client and server are going to negotiate a secure connection.
The SSL Certificate is the document that they will use to agree upon the servers authenticity.
HTPS is the new HTTPS.
HTTPS is highly vulnerable to SSL Stripping / MITM (man in the middle).
to quote adam langley's (google) blog imperial violet:
"HTTPS tends to cause people to give talks mocking certificate security and the ecosystem around it. "
The problem is that the page isn't served over HTTPS. It should have been, but when a user types a hostname into a browser, the default scheme is HTTP. The server may attempt to redirect users to HTTPS, but that redirect is insecure: a MITM attacker can rewrite it and keep the user on HTTP, spoofing the real site the whole time. The attacker can now intercept all the traffic to this perfectly well configured and secure website.
This is called SSL stripping and it's terribly simple and devastatingly effective. We probably don't see it very often because it's not something that corporate proxies need to do, so it's not in off-the-shelf devices. But that respite is unlikely to last very long and maybe it's already over: how would we even know if it was being used?
In order to stop SSL stripping, we need to make HTTPS the only protocol. We can't do that for the whole Internet, but we can do it site-by-site with HTTP Strict Transport Security (HSTS).
HSTS tells browsers to always make requests over HTTPS to HSTS sites. Sites become HSTS either by being built into the browser, or by advertising a header:
Strict-Transport-Security: max-age=8640000; includeSubDomains
The header is in force for the given number of seconds and may also apply to all subdomains. The header must be received over a clean HTTPS connection.
Once the browser knows that a site is HTTPS only, the user typing mail.google.com is safe: the initial request uses HTTPS and there's no hole for an attacker to exploit.
(mail.google.com and a number of other sites are already built into Chrome as HSTS sites so it's not actually possible to access accounts.google.com over HTTP with Chrome - I had to doctor that image! If you want to be included in Chrome's built-in HSTS list, email me.)
HSTS can also protect you, the webmaster, from making silly mistakes. Let's assume that you've told your mother that she should always type https:// before going to her banking site or maybe you setup a bookmark for her. That's honestly more than we can, or should, expect of our users. But let's say that our supererogatory user... ]
because of obstructing/very stupid link-rules for new users on stackoverflow i cannot give you the rest of adam's answer and you'll have to visit adam langley's blog yourself at
https://www.imperialviolet.org/2012/07/19/hope9talk.html
"Adam Langley works on both Google's HTTPS serving infrastructure and Google Chrome's network stack."
HTTPS is an application layer protocol. It can provide non-repudiation of individual requests or responses through digital signatures.
SSL is a lower level protocol and does not have this capability. SSL is a transport level encryption.
HTTPS is more flexible than SSL: an application can configure the level of security it needs. SSL has fewer options so it is easier to setup and administer.

OpenID Over SSL with self signed certificate

I setup my own open id provider on my personal server, and added a redirect to https in my apache config file. When not using a secure connection (when I disable the redirect) I can log in fine, but with the redirect I can't log in with this error message:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
I'm guessing that this is because I am using a self signed certificate.
Can anyone confirm if the self signed certificate is the issue? If not does anyone have any ideas what the problem is?
The primary benefit of using SSL for your OpenID URL is that it gives the relying party a mechanism to discover if DNS has been tampered with. It's impossible for the relying party to tell if an OpenID URL with a self-signed certificate has been compromised.
There are other benefits you get from using SSL on your provider's endpoint URL (easier to establish associations, no eavesdropping on the extension data) which would still hold if you used a self-signed cert, but I would consider those to be secondary.
OpenID is designed in a redirect-transparent way. As long as the necessary key/value pairs are preserved at each redirect, either by GET or POST, everything will operate correctly.
The easiest solution to achieve compatibility with consumers that do not work with self-signed certificates is to use a non-encrypted end-point which redirects checkid_immediate and checkid_setup messages to an encrypted one.
Doing this in your server code is easier than with web server redirects as the former can more easily deal with POST requests, while also keeping code together. Furthermore, you can use the same end-point to handle all OpenID operations, regardless whether or not it should be served over SSL, as long as proper checks are done.
For example, in PHP, the redirect can be as simple as:
// Redirect OpenID authentication requests to https:// of same URL
// Assuming valid OpenID operation over GET
if (!isset($_SERVER['HTTPS']) &&
($_GET['openid_mode'] == 'checkid_immediate' ||
$_GET['openid_mode'] == 'checkid_setup'))
http_redirect("https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
As the openid.return_to value was generated against a plain HTTP end-point, as far as the consumer is concerned, it is only dealing with a non-encrypted server. Assuming proper OpenID 2.0 operation with sessions and nonces, whatever information passed between the consumer and your sever should not reveal exploitable information. Operations between your browser and the OpenID server, which are exploitable (password snooping or session cookie hijacking) are done over an encrypted channel.
Aside from keeping out eavesdroppers, having authentication operations be carried out over SSL allows you to use the secure HTTP cookie flag. This adds yet another layer of protection for checkid_immediate operations, should you wish to allow it.
(Disclaimer: I'm new to OpenID, so I might be wrong here.) The communication between the Open ID Consumer (e.g., StackOverflow) and the Open ID Provider (your server) does not require HTTPS -- it will work just as fine and just as securely over plain HTTP. What you need to do is to configure your server to switch to HTTPS only when it shows you your login page. In that case, only your browser needs to concern itself with the self-signed certificate. You could import the certificate onto your PC and everything will be as secure as with, say, Verisign-issued certificate.
It sounds like it. The client of your OpenID server doesn't trust the root certification authority.