Cloudflare - Issues to be aware of

For anyone trying to setup home assistant behind Cloudflare there are a few gremlins you should be aware of.

  1. You will need to add a page rule to disable Rocket Loader.
  2. Optionally disable Always Online while you’re at it.
  3. If you want to use api.ai you’ll need another page rule to set Browser Integrity Check to Disabled.

In my case I am using:
Cloudflare -> NGINX -> Home Assistant

3 Likes

Any tips or tricks on this one? I just can’t seem to get HA to work behind cloudflare.

Current Setup: Cloudflare -> Apache Reverse Proxy port 8443 -> HA port 8123
I can connect directly to the IP of the Apache Reverse Proxy on port 8443 and everything works perfectly, however when I try to connect through Cloudflare I get a blank page with HA’s trademark blue bar across the top.

I looked through my Cloudflare settings, and websockets are enabled, and I have a page rule set for www.domainname.com:8443/* of Browser Integrity Check: Off, Rocket Loader: Off, Always Online: Off, Cache Level: Bypass

Any ideas are welcome.

1 Like

Hi ve6rah,

I am using Home Assistant using Cloudflare and it took a decent amount of work to set up. I am using haproxy on my router (LEDE/OpenWrt) to manage the connections from external. I have everything coming in on port 443 to my haproxy and pass traffic to the backends using SNI.

This is my configuration with all the private information edited out:

# Global parameters
defaults
    # Slowloris protection
    timeout http-request 5s
    timeout connect 5s
    timeout client 30s
    timeout server 30s
    timeout http-keep-alive 4s

    # Close the backend connection
    option http-server-close
		
global
	log 10.0.0.10 local0
    maxconn 32000
    ulimit-n 65535
    uid 0
    gid 0
    daemon
    nosplice
    tune.ssl.default-dh-param 2048
    ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDH
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
    ssl-default-server-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:EC
    ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets

listen local_health_check
    bind :60000
    mode health

# Frontend for SNI Passthrough
frontend frontend_snipt
    bind *:443
    mode tcp
    log global
    option forwardfor header X-Forwarded-For
    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }
    use_backend backend_snipt_1 if { req_ssl_sni -i 1.domain.com }
    use_backend backend_snipt_2 if { req_ssl_sni -i 2.domain.com }
    use_backend backend_snipt_3 if { req_ssl_sni -i 3.domain.com }
    use_backend backend_snipt_4 if { req_ssl_sni -i 4.domain.com }
    use_backend backend_snipt_5 if { req_ssl_sni -i 5.domain.com }
    default_backend backend_1

# Backend for SNI Passthrough
backend backend_snipt_1
    mode tcp
    server localhost 127.0.0.1:7000 check

backend backend_snipt_2
    mode tcp
    server localhost 127.0.0.1:7001 check

backend backend_snipt_3
    mode tcp
    server localhost 127.0.0.1:7002 check

backend backend_snipt_4
	mode tcp
	server localhost 127.0.0.1:7003 check

backend backend_snipt_5
	mode tcp
	server localhost 127.0.0.1:7004 check
		
# Normal frontend
frontend frontend_1
	bind *:7000 ssl strict-sni crt /etc/ssl/cloudflare/domain.com.pem
	mode http
	use_backend backend_1

frontend frontend_2
	bind *:7001 ssl strict-sni crt /etc/ssl/cloudflare/domain.com.pem
	mode http
	use_backend backend_2
		
frontend frontend_3
	bind *:7002 ssl strict-sni crt /etc/ssl/cloudflare/domain.com.pem
	mode http
	use_backend backend_3

frontend frontend_4
	bind *:7003 ssl strict-sni crt /etc/ssl/cloudflare/domain.com.pem
	mode http
	use_backend backend_4

frontend frontend_5
	bind *:7004 ssl strict-sni crt /etc/ssl/cloudflare/domain.com.pem
	mode tcp
	option clitcpka
	timeout client 3h
	timeout server 3h
	use_backend backend_5

# Normal backend		
backend backend_1
    mode http
    server server01 10.0.0.10:80 check

backend backend_2
    mode http
    server server01 10.0.0.10:8080 check

backend backend_3
    mode http
    server server02 10.0.0.254:80 check

backend backend_4
	mode http
	server server01 10.0.0.10:8081 check

backend backend_5
	mode http
	server server01 10.0.0.10:8082 check

I hope this might help in some way.

2 Likes

Thanks for the reply. I seem to have figured out what’s happening, and a workaround, but not why it’s happening, or how to fix it.

I have HA on my home network using a 192.168.x.x IP, and also on my VPN using a 10.x.x.x IP. Then I have my server hosted on a VPS outside of my home which has a public IP, as well as a connection on the VPN 10.x.x.x subnet. And then I have Cloudflare pointing to the public IP of the server.

If I’m using a device that is not connected to the VPN, and I connect to Cloudflare using port 8443 everything works properly. But as soon as the device I’m on is also connected to the VPN, I can no longer connect by going to port 8443 on cloudflare, and must instead use the 10.x.x.x IP to connect (or if I’m at home, the 192.168.x.x IP works as well).

I have no idea why this is as I have no issues at all accessing any other site on the internet while on the VPN,
including accessing sites that are on port 80 of the same server through the same Cloudflare account, But I’ve learned to live with it.

It’s mostly not an issue as for the most part none of my user devices live on the VPN, and I reserve it for my services (3 permanent hosts on the VPN, the Home Assistant instance, my car, and my web/mail/etc server which is the single point where I can control my home and car automations. I tend to only connect one of my user devices to the VPN when I need to modify settings or do some programming)

1 Like

Is the external FQDN of your server the same internally and externally?

No, they are not.
Internally I connect to host.domain:8123 whereas externally I connect to www.domain:8443
I can connect to www.domain:80 just fine when I’m on the VPN, but if I try to go to www.domain:8443 it doesn’t go and I have to use host.domain:8123 instead
host.domain resolves to 10.x.x.x (IP on the VPN of the RPI running HA)
www.domain resolves to a cloudflare IP which then forwards the traffic to a web server on a VPS which has a second interface on the VPN which then reverse proxies the traffic to the HA instance listed above. This same server has a normal Apache instance running on ports 80 and 443 (HTTP and HTTPS) which work just fine regardless of how I’m connected.
When not connected to the VPN I can go to www.domain:8443 and access HA no problem using the apache reverse proxy.
Of note, my VPN is not setup to route any traffic by default, so only traffic destined for a 10.x.x.x IP should ever end up flowing over the VPN, and no DNS is done over the VPN, it’s all done over the normal internet link and does not change depending on whether the VPN is connected or not.

1 Like

This comment helped me out quite a bit. Home Assistant was only showing the top bar while viewing from Chrome Desktop. It still worked via Chrome on Android, Safari and Firefox.

I had recently changed to a new host behind the reverse proxy, and so I originally thought this was the issue. I spent a good deal of time troubleshooting.

My setup looks like this:
Cloudflare -> Nginx -> Home Assistant on Ubuntu 17.10

Eventually I stumbled across this post, made the Page Rules and it fixed the problem. Thanks for posting.

I spoke too soon. This did not fix my problem.

I use a CNAME record in Cloudflare that points to an A record that is updated on Cloudflare via DDNS. Deleting this CNAME record, and temporarily adding an A record that pointed directly at my IP seemed to fix this issue, whether or not requests were routed through Cloudflare.

This was not an issue while I was running Home Assistant on 16.04. It only seems to have caused problems when I moved my install to a new container (LXC) running on 17.10.

Has anyone else had some experience with this?

What is benefit of placing HA behind cloudflare?

I did this for a couple of reasons.

  1. Hides my public IP
  2. Lets me lock down port 443 on my end to only accept CF traffic based on IP rules.

Granted sure you could still find ways to discover my public IP but I feel its better than not doing anything at all. Oh and its free

EDIT: Also from the hosted DNS front makes renewing my SSL with letsencrypt a snap. I only route external inbound traffic through CF. If we’re hitting a site from inside i.e. HA while I still have the SSL on it this way I still have a valid LetsEncrypt SSL on HA for internally. I could use the cert provided from CF but this is easier. I also have it setup with CF for full-strict encryption so all traffic passed between me and CF is fully encrypted.

Now granted yes CF has the ability to look at the traffic as it passes through them since they decrypt from me and then encrypt it again with the end user, I’m not terribly worried about it as I’m not doing anything crazy here at home :slight_smile:

while I never really had issues with cloudflare in front this was handy, took on your advice and it works even better now… thanks

How did you do that?

I use pfsense as my firewall and CF publishes their IP lists. So I just created a rule to pull that list daily. So I just put that in my source IP field for port 443 and 80.

Thanks for the feedback. I also use pfSense as my firewall and have haproxy as a reverse proxy.

I’ve been experiencing some issues with my new cellphone carrier (Sprint) to remotely connect to HA. I’ll try this approach with CF to see if it solves the problem.

yeah so I just setup a rule inside of PFBlockerNG to go grab the Cloudflare IPs

Then I just did a FW Rule like this

I didn’t put in the destination section but you get it :). Destination IP your IP port 443 etc

2 Likes