Zero Trust Access to Cameras
- 7 minutes read - 1298 wordsHow to Control Access to Your Cameras
Now that you’ve assembled and configured your cameras, you’ll want to be able to view them from the internet. But how to do that?
Some options you have:
Option | Difficulty | Security Considerations |
---|---|---|
Leave Port(s) open | Easy | Greatest exposure / highest risk |
VPN | Medium | Limits exposure to 1 port |
Cloudflare Teams | Medium | No open ports |
Cloudflare Teams and Tunnel
Cloudflare tunnels is a zero trust service. That’s buzzwordy for you’ll have to authenticate every time you want to connect to view your cameras. Your device isn’t trusted, and there’s no client to trust.
Did I mention it is all free?
How Cloudflare Teams and Tunnel Works
Tunnel is a service that creates a tunnel between a device on your network, and the Cloudflare network. You’ll configure Cloudflare as the DNS server for your domain and it will proxy that traffic to your device.
Teams performs access control using one of several different options for authentication. This is a free service for up to 50 users.
Let’s take a look at the details.
Network Configuration
The diagram shows the traffic flows through the network.
-
The user makes an HTTPS request to
cameras.beckitrue.com
-
Cloudflare resolves the DNS request and sees that it is configured as an application in Cloudflare Teams
-
Cloudflare will require the authentication method you configured in the application policy rules.
-
If you authenticate successfully, it proxies your request to the device running
cloudflared
. In my case, this is a Raspberry Pi. -
motionEyeOS doesn’t run HTTPS, and they recommend using a
nginx
reverse proxy so I configured one that serves a web page listing the hyperlinks to each camera on my network -
The
nginx
server forwards the HTTPS request to the camera
What You’ll Need
-
a domain name
-
a device to install on your network that
-
can reach your camera network
-
running Linux and install
cloudflared
andnginx
-
Let’s Break it Down
This can be a lot to bite off in one go. If you’re new to this, break it down into pieces. The instructions are detailed below, but it’s good to get an idea of the steps we’ll take. Taking it a piece at a time, and testing as we go makes troubleshooting a lot easier.
Cloudflared Tunnel
- Get your cameras working. I’m assuming you’ve already done that. https://blog.beckitrue.com/post/tech/motioneyeos/
- Configure your Pi and then configure a cloudflare tunnel that you test with the
tunnel-test
service. - Use your web browser to test your tunnel by going to
https://tunnel-test.your-domain.com
At this point you know your Cloudflare Tunnel is working, Now configure and test Teams
Cloudflare Teams
- Configure Teams to authenticate requests to your
tunnel-test
service. - Use your web browser to test your tunnel by going to
https://tunnel-test.your-domain.com
When this works, you know your authentication is working with Teams. Now you can move on to serving the webpage listing your cameras.
Webpage
- Create your webpage
- Connect to your webpage from your Pi that’s running the Cloudflare Tunnel
- Test connections to the cameras from your new webpage
At this point you know your webpage works and you can reach your cameras from the Pi that is running a Cloudflare Tunnel. Now you can test the service with Cloudflare Tunnel and Teams.
Webpage with Teams
- Configure the service to your webpage <cameras.my-domain.com> if you haven’t already
- Add the DNS entry for the service
- Configure the authentication method in Teams
- From a computer other than the Pi running the Cloudflare tunnel, go to the URL for your service i.e. https://cameras.beckitrue.com
At this point, you should be prompted to authenticate before reaching the webpage. You will not be able to reach the cameras until you configure and run the nginx reverse proxy.
Nginx
- Configure the nginx reverse proxy
- Start nginx
- From a computer other than the Pi running the Cloudflare tunnel, go to the URL for your service i.e. https://cameras.beckitrue.com
Now when you authenticate, you should be able to see the webpage for your cameras and connect to each one.
The Instructions
Configure DNS in Cloudflare
This all works because Cloudflare proxies the DNS requests to the services you configure in Teams and in the cloudflared config file. So you have to use Cloudflare for the DNS. You dont’ have to register you domain with them, but you will need to create a CNAME record if you don’t.
The instructions for all of that can be found here
Configure Tunnel
You will want to follow the setup guide. I’ve added some clarifications below.
Download and Install cloudflared
Here are the instructions to download and install cloudfared for your platform. You can even run it as a Docker container.
I’m using a Raspberry Pi, so I followed the instructions here. You will need to know if you are using AMD64 or ARM architecture on your Pi.
Run step 2 in the setup guide
cloudflared tunnel login
Configure the Tunnel
Use whatever name you want for the tunnel, but I named mine cameras.
cloudflared tunnel create cameras
From the output of the command, take note of the tunnel’s UUID and the path to your tunnel’s credentials file.
Configure cloudflared
Change the <tunnel-uuid>
below to match your tunnel uuid. I also have a test service so that I can test the tunnel. This is optional, but helpful. You also need to include a 404 service in your tunnel configuration file.
$ vim /home/pi/.cloudflared/config.yaml
tunnel: cameras
credentials-file: /ubuntu/.cloudflared/<tunnel-uuid>.json
ingress:
- hostname: cameras.beckitrue.com
service: http://localhost:80
- hostname: tunnel-test.beckitrue.com
service: hello_world
- service: http_status:404
Start your tunnel and try to connect to your test service. You can follow the instructions here to configure it to run on startup if you’re using a Pi. Your tunnel is working if your test service is working.
Configure Teams
Follow the Tutorial on Self Hosted Applications
Webpage for Camera Links
You’ll want to make a basic webpage with the links to you cameras. This is what nginx will direct the requests to. This is what my index.html
looks like:
<!DOCTYPE html>
<html>
<head>
<title>Welcome Home!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome Home!</h1>
<h2>Basement</h2>
<a href="http://cameras.beckitrue.com/basement">basement</a>
<h2>Front Door</h2>
<a href="http://cameras.beckitrue.com/front-door">front-door</a>
<h2>Garage</h2>
<a href="http://cameras.beckitrue.com/garage">garage</a>
</body>
</html>
Nginx Configuration
Edit the /etc/nginx/nginx.conf
file’s server block to look something like this. What you’re doing is configuring a location and a proxied server. Give this document a read if you find this confusing.
server {
server_name cameras.beckitrue.com;
root /var/www/beckitrue.com;
index index.html;
location /basement {
proxy_pass http://<basement ip>:8081;
}
location /front-door {
proxy_pass http://<front door ip>:8081;
}
location /garage {
proxy_pass http://<garage ip>:8081;
}
}
Start nginx. If you’re using a Pi run the command below. If not, follow the instructions here
sudo systemctl start nginx
Give It A Test
Go to the domain you configured your application to be in your cloudflared config file. You should be prompted for whatever authentication method you configured in Teams. After you authenticate, you should be presented with the webpage you configured nginx
to point to. Assuming you’ve been testing as you configured each part, you should be able to view your cameras. Congratulations!
Wrap Up
I hope this helped you see the value in using Cloudflare’s Tunnel and Teams. You’ll have no open ports coming into your network, but you’ll still be able to reach the devices you want from anywhere in the world - as long as you can authenticate using the rules you set up in Teams.
In this article we used tunnels for HTTP requests to our cameras, but you can also use it to SSH, or RDP, or VNC, and any number of other remote access protocols.
Drop me a comment if you have questions, or if you’d like to link to a project that you used Cloudflare Tunnels and Teams to limit access.