Home Assistant App Alexa and Brower access secured with CloudFlare

From my reddit post: reddit post

This week I secured my Home Assistants external access with CloudFlare ZTNA and having had to dig through many guides and posts, I thought this could help.

My needs were: external access by browser from any PC (So no VPN), Functioning app without a VPN on phone, and functioning Alexa for WAF. I will link articles and post screenshots where I got stuck.

So:

1 - Browser access from the exterior is secured by a successful Gmail login, then login to HA

2 - Phones need a client certificate so app can access HA + login

3 - Alexa lambda function can bypass authentication, but ONLY that lambda

Steps:

I will assume that you have a cloudflared tunnel already setup, if not : New Add-On: Cloudflared (you need managed tunnel I think)

1 - Create a tunnel and secure with Gmail or another Identity provider:

Follow the guide and Ignore the part about google IP’s?

2 - Create a 2nd tunnel and secure with mTLS for the android app (did not test on iPhone)

I had a problem with the WAF rules so here are mine (In SECURITY/WAF in the website menu):

1 - Create rule, name it, scroll down to “Edit expression” and enter:

 (cf.tls_client_auth.cert_verified) 

Then the action for that rule is “Skip”

2 - Create 2nd rule, name it, scroll down to “Edit expression” and enter while substituting https://yourapp-mtls.yourdomain.com for your domain:

 (not cf.tls_client_auth.cert_verified and http.request.uri.path in {"https://yourapp-mtls.yourdomain.com"}) 

Then action for this is “Block”

3 - Modify Alexa Skill to work with ServiceAuth headers so it will work with ZTNA.

Inspired buy this post: https://www.reddit.com/r/homeassistant/comments/w6hnhz/help_with_alexa_and_cloudflare_tunnel/

and this comment by /u/btoconnor

https://www.reddit.com/r/homeassistant/comments/w6hnhz/comment/ik0fd0u/?utm_source=share&utm_medium=web2x&context=3

1 - follow guide for Alexa access but substitute parts:

2 - Substitute lambda function by function here:

https://gist.githubusercontent.com/btoconnor/796dbcbf2e713cd80bcf1aa28e14392e/raw/177ab86ed85d11f7bdc410f7629ca56156613dd2/existing_file.py

3 - Create a new lambda function with code her:

https://gist.githubusercontent.com/btoconnor/796dbcbf2e713cd80bcf1aa28e14392e/raw/177ab86ed85d11f7bdc410f7629ca56156613dd2/wrapper.py

4 - Create Service Token for ZTNA and add policy to your tunnel

Service tokens · Cloudflare Zero Trust docs.

5 - Add CF_CLIENT and CF_SECRET env Variables to both lambda functions (only the actual keys as values)

6 - Substitute Access Token URI for your wrapper function url + /auth/authorize

7 - Link as usual

Hope this helps somebody

1 Like

I think the reason your WAF rule wasn’t working was because you should be using http.host instead of http.request.uri.path - at least, that works for me. So you should use http.host eq "https://yourapp-mtls.yourdomain.com". Then you don’t need the skip rule.

1 Like

Just wondering, can we do away with ACCESS_ID etc., and insert a custom header in LAMBDA function, and this WAF rule:

(any(http.request.headers["my-client-secret"][*] contains "abcdef"))

It’s working for me and am using Alexa WAF rule before MTLS rule, want to understand security implications if any.