Introduction
Requirements
Software, Hardware and Network design
Camera Configuration
Blue Iris Server Configuration
pfSense Configuration
External access
I’ve been asked numerous times for details of my security camera system that I hinted at in my pfSense baseline configuration guide. It’s taken some time to create this guide primarily because I tried to create a detailed step-by-step guide but couldn’t find a way to cover all the potential systems and use cases. I decided to focus on producing an intermediate guide that will cover higher level design and configuration requirements to steer readers. Please share your feedback to help me iterate and make this guide more useful.
This guide will build upon my pfSense baseline configuration guide and cover configuration of infrastructure and performance related components that to a greater extent will influence the reliability and performance of your system. Configuration and optimisation of the video cameras themselves, including motion detection, is outside the scope of this guide.
The requirements for the system I intended to create included
I selected Blue Iris security software for its combination of affordability, support and feature set. The primary downside was the need for a Windows licence but this in itself wasn’t prohibitive. There are also native mobile clients for Android and iOS as well as a great web based interface for remote viewing. I use a Windsows Server 2016 virtual machine under ESXi with 4 vCPU and 4GB RAM allocated on a Xeon-d 1541 processor based system.
Your own camera selection will be highly dependant on your physical needs, for example focal range and lighting will largely influence your decision. I deployed six Dahua IPC-HDW5231R-Z 2MP Starlight cameras around the perimeter of my home cabled with CAT-5 cable utilising power over ethernet (PoE) from my Juniper switch. These cameras have excellent night time performance thanks to the Sony ‘Starvis’ sensor as well as a motorized lens which simplified purchasing and fine tuning during installation. My cameras are configured to provide video on primary (1920x1080) and sub stream (640x480) broadcasts and update at 15fps which is sufficient to track movement whilst reducing network load and storage requirements. I use the camera’s image manipulation hardware to apply the timestamp to the video feed before it arrives at Blue Iris, this prevents Blue Iris having to do a lot of decoding, re-encoding just to add a timestamp to the video.
Remote access is supported from web browsers or mobile Blue Iris clients via a Traefik reverse proxy which enforces HTTPS access from clients preventing eavesdropping. This reverse proxy prevents the need to establish secure OpenVPN connections prior to connecting and reduces complexity for my less technical users to something manageable. Remote access is monitored by Fail2ban and other means to prevent unauthorized intrusion or brute-forcing of passwords.
I segmented the cameras and Blue Iris video system into its own VLAN to reduce the traffic pfSense needs to process as well as help prevent unauthorized access. Segmenting the network like this also allowed me to easily prevent the cameras from accessing the internet preventing any possibility of leaking information or providing access for a Command & Control Botnet. The only connectivity the cameras are permitted is to get their time from my pfSense based NTP server. Cameras are blocked from initiating any form of communication other than NTP requests from my pfSense NTP server.
To reduce persistent load on my spinning disk storage array, I added two HGST 8TB disks in a mirrored configuration providing some redundancy for when theres a hardware failure. These disks are hosted on an OmniOS system configured with Napp-it. This level of redundancy isn’t mandatory but if you have the means to implement it, it could be beneficial someday. The two disks record the cameras video streams 24x7 and provide around 4 weeks worth of recordings. The maximum duration you can retain will be dictated by available storage capacity and affected by image resolution, image quality, format and encoding. I found storage requirements can be tricky to predict accurately ahead of time and needed to upgrade my disks to achieve my desired duration.
To solve the need the for several permanent camera displays around the home, I use several Raspberry Pi’s attached to 20” monitors. As their native resolution is 1280x960 and the Raspberry Pi’s processor or network card isn’t exactly optimum for processing large pixel counts, I make use of a substream broadcast from each camera to provide several 640 x 480 streams @ 15fps. This reduced resolution provides enough detail to identify visitors to our property as well as enable six cameras to fit on screen at once. Initially I tried wireless connections to the Raspberry Pi’s but not surprisingly it wasn’t robust enough for reliable operation. Since moving to wired Cat5 connections I’ve experienced uptime in the region of 200 days + so far.
Log into each cameras web portal in turn and configure their settings as follows.
This enables a primary stream at 1920x1080 @ 15fps and a substream at 640x480 @ 15fps. I make use of the cameras ability to overlay time to prevent Blue Iris having to perform this duty later on in the video chain.
Encode Mode: H.264H
Smart codec: Off
Resolution: 1920 x 1080 (1080p)
Frame rate (FPS): 15
Bit Rate Type: CBR (Constant bit rate)
Bit Rate: 6144Kb/s
I Frame internal: 30fps
Enable = [√]
Encode Mode: H.264H
Resolution: 640 x 480 (VGA)
Frame Rate (FPS): 15
Bit Rate Type: CBR (Constant bit rate)
Bit Rate: 1280Kb/s
I Frame Interval: 30fps
Time Title: Enable
Channel Title: Enable if required.
Audio enabled on primary stream but disabled on the substream.
Enable = [√]
Encode Mode = G.711A
Sampling Frequency: 16k
Enable = [ ]
I disable everything except ONVIF support.
Mode: DHCP
IP Version: IPv4
PPPoE: Disable
DDNS: Disable
SMTP Server: None
UPnP: Disable
SNMP: Disable (enable if you use SNMP monitoring)
Bonjour: Disable
Multicast: Disable
802.1x: Disable
Access Platform, P2P : Disable
Access Platform, Onvif: Enable
I don’t currently make use of onboard SD card recording.
Local: None
FTP: Disable
NAS: Disable
Name: As appropriate
NTP: [√]
Server: 192.168.50.1
Port: 123
Interval: 5 minutes
SSH: Disable
Multicast/Broadcast: Disable
Password Reset: Disable
CGI Service: Disable
Onvif Service: Enable
Genetec Service: Disable
Audio & Video Translation: Disable
Mobile Push: Disable
Auto Reboot: Disable
Auto delete old files: Disable
Physical hardware may be preferable but I’ve had good results with a adequately provisioned and well configured VM running under ESXi 6.7 with the following settings. This supports my six 1080p cameras with direct-to-disk recording running under Windows Server 2016 at 60% RAM use and 30% CPU when interacting with Blue Iris. When running as a background service utilisation is sub 10%. This graph illustrates memory consumption and processor load when Blue iris is active as well as running minimized.
My Blue Iris VM records to a CIFS file share mounted in Windows providing 8TB of storage on mirrored ZFS volume. I didn’t find any noticeable performance difference between Western Digital RED 5400rpm drives and HGST 7200rpm drives I upgraded to later to extend recording time.
Create and configure a new virtual machine as follows
Feel free to use any recent version of Windows, my preference is for Server 2016 as it reduces bloat, run ‘leanly’ and doesn’t randomly upgrade/restart due to upgrades.
I’m not going into a full on how-to guide as steps needed would depend on exactly which OS you used. These are the core settings I adjust on my new installs.
If you haven’t already, download Blue Iris from here. Be aware that direct-to-disk recording only works in the licenced version and this may affect performance if evaluating a trial.
Click on the cog icon in the top-left of the screen to enter settings, apply the following.
Support and Software Updates
Database Path: c:/BlueIris/db (Keep the database on the local disk to optimise performance)
Compact/repair DB each day at: 02:00 AM
Folders Set as per your local system
New = \fs01\NVRdata\BlueIris\New
Do not monitor free space = [ ]
Limit size = 6144GB set as per your storage availability
Limit Clip Age = [ ]
Previous data: Delete
Stored = \fs01\NVRdata\BlueIris\Stored
Do not monitor free space = [ ]
Limit size = 256GB
Limit Clip Age = [ ]
Previous data: Delete
Alerts = \fs01\NVRdata\BlueIris\Alerts
Do not monitor free space = [ ]
Limit size = 10GB
Limit Clip Age = [ ]
Previous data: Delete
Create local users as per your needs
I have access to my Blue Iris camera system by two mechanisms, OpenVPN and a reverse proxy. Arguably OpenVPN is the more secure method, but I’m comfortable with the security I have around my reverse proxy setup to expose it. It certainly makes things easier for non-technical family members to check in on any alerts remotely.
Enable = [√]
Port: 8181
Virtual = /
Use new UI3 preview = [√]
Local/LAN access
LAN: 192.168.50.10:8181
Interfaces: 192.168.50.10
Remote/WAN access
Usually auto populated
Stunnel installed = [ ]
Advanced
All connections: Use secure session keys & login page = [√]
Autoban IP after unsuccessful attempts = [3]
Release banned IP after minutes = [10]
Use x-forwarded headers = [√]
Send Strict-Transport-Security header = [√]
Log ALL connections = [√]
Window: Quiet (minimized & no-splash)
Run as windows service = [√]
Require run as administrator = [ ]
Blue Iris window always om top = [ ]
Force display monitor to remain active at all times = [√]
Prevent power management putting PC to sleep = [√]
Configure Blue Iris for each physical camera you have installed.
Type: Network
[√] Enable audio
[√] Enable motion detection
[√] Direct to disc recording (no re-encoding)
Name: as appropriate
Short name: as appropriate
Address: http://192.168.50.x I use 200-205
username: as appropriate
password: as appropriate
Click Find/Inspect to pull configuration data from your camera, here’s my event log for reference.
Opening 192.168.50.200 port 80...
HTTP Get / request...
OK
ONVIF GetSystemDateAndTime
2018-09-13T16:18:56.000Z
Requesting device information...
Manufacturer: General
Model: IP Camera
FirmwareVersion: 2.640.0000002.0.R, Build Date 2018-05-23
GetCapabilities...
Querying services
Has Imaging services: /onvif/imaging_service
Has media services: /onvif/media_service
Has RTP_RTSP_TCP, requesting profiles
first profile is MediaProfile000
first source is 000
requesting URI for profile MediaProfile000
RTSP URI: /cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
Has Event services: /onvif/event_service
Has WSPullPointSupport
RelayOutputs: 0
InputConnectors: 0
Has Device IO services: /onvif/deviceIO_service
AudioOutputs: 0
Has PTZ service: /onvif/ptz_service
Done
This populates the following fields, in my case
Make: Generic
Model: Main RTSP H.264/H.265/MJPG/MPEG4
Path: /cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
Port: 554
Discovery/ONVIF: 80
Receive Buffer: 6MB
Use RTP/UDP ports: [ ]
Send RSTP keep alives = [√]
Use RTSP/tream timecode = [√]
Skip Initial HTTP DNS reachability tests = [ ]
Decoder compatibility mode = [ ]
Get events with PullPointSubscription = [ ]
Click OK and configure the rest of the tabs as follows
Hardware accelerated decode: Intel + VPP
Limit decoding unless required = [√]
Enable overlays = [ ] we use camera’s overlays instead to reduce Blue Iris’ processing load
Max rate: 15fps
Enable Audio
IP camera stream = [√]
Advise to setup motion sensing but this is beyond the scope of this guide.
Video: Continuous
Folder: New
[√] Create alert list image when triggered
Combine or cut video each 8 hrs / 4GB
Pre trigger video buffer = 5s
Video file format
Format: BVR, with FLAC audio compression
Video compression: Direct to disc H264
[√] Enable: Adjust encoder settings
[ ] Add camera text/overlays
Now we can move onto creating the VLAN and Interface on pfSense. Your new VLAN will need adding to your switches trunks and access ports depending on how and where you have your Blue Iris host.
The firewall configuration will enable
Navigate to Interfaces > Assign > VLAN
Click ‘+’
Parent Interface: Your preferred parent interface, in my case, IX0
VLAN Tag: 50
VLAN Priority: 0
Description: VL50_CAMERAS
Save
Navigate to Interfaces > Assign
Select ‘VLAN50 on IX0’ from the available network ports
Click ‘Add’
I like to match the third octet of my IP address to the VLAN ID as this makes remembering which is which easier, so VLAN id 50 = 192.168.50.0
Click on the label next to ‘VL50_CAMERAS’, its likely to be labeled ‘OPT’
Configure this interface as follows:-
General Configuration
Static IPv4 configuration
Private Networks
Click Save & Apply changes.
To increase security we will only grant IP addresses to devices we explicitly configure in the reserved entries, although we’ll still need to define a range it won’t be used.
Navigate to Services > DHCP Server
Select VL50_CAMERAS tab and set the DHCP server as follows:-
Add DHCP Static Mappings for this Interface
Add a reservation for each device that will be on this subnet, I’ve configured static address for my Blue Iris server, my Raspberry Pi display devices and my cameras.
Save & Apply
Ensure NTP is service all the devices on the VL50_CAMERAS subnet.
Navigate to Services > NTP
DNS will be served by our DNS Resolver
NAT is needed to convert your camera subnet’s private local IP addresses to the global registered address space.
Navigate to Firewall > NAT > Outbound
Click ‘↴+’
We are going to create a few aliases which we will use in the creation of the firewall rules later. These simplify the job of making changes in future especially as we add more interfaces and functionality to our network.
Navigate to Firewall > Aliases > IP and edit LOCAL_SUBNETS
Add
- 192.168.50.0 / 24 “VL50_CAMERAS”
We will create a list of ports to define what traffic is permitted to traverse between our local subnets. You will need to amend this alias as per your own networks requirements but this should get you started. Reviewing the Firewall logs will illustrate which ports are being blocked.
Navigate to Firewall > Aliases > Ports and edit the Allowed_OUT_ports_LAN alias
Add the following ports
- 554 : Media / video / RTSP port
- 8181 : BlueIris web server
- 8999 : Discovery / OVFIF port
- 37777 : TCP Port
- 37778 : UDP Port
Navigate to Firewall > Aliases
Click +Add
Add an entry for each of your cameras, for example. These addresses need to corrospond to the DHCP reservation you make for them also.
Your aliases should look like this when complete
Firewall rules are applied in a top to bottom order and we make use of that aspect here so make sure your order matches mine when complete.
Navigate to Firewall > Rules > VL50_CAMERAS and create the following rules.
This is used for Windows activation, updates, Raspberry Pi updates etc.
When you are done, your interface should look like this.
In order to be able to access our Blue Iris server from outside our network you will need to register a domian name and point it at your WAN address. If you are on a residential connection its likely you will have a dynamic address from your ISP which you will need to sync with your domain name, you can do this with pfSense’s Dynamic DNS service. If you followed my remote access guide you may already have a DNS entry pointed at your WAN interface you could use.
If you don’t have a domain name registered, I recommend namecheap.com. Find a domain name you like and register it.
In pfSense, navigate to Services > Dynamic DNS and configure a dynamic update entry for the domain you just registered at namecheap. pfSense will keep this update as and when your WAN interface changes ensuring you can always access your Blue Iris install remotely via this domain name.
If you wish to access your network via OpenVPN, take a look at my inbound OpenVPN guide here.
I’ve previously used NGINX to handle my reverse proxy needs but recently I’ve been transitioning to Traefik which also handles Lets Encrypt SSL certificates automatically and is has tighter integration with docker that I’ve been experimenting with.
You’ll need to create a pfSense port forward to your reverse proxy to enable this method. I’ve included the pertinent sections from my traefik.toml
file below which is used to generate and manage the HTTPS certificate and handle the redirect through my WAN interface.
defaultEntryPoints = ["https","http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[entryPoints.https.proxyProtocol]
trustedIPs = ["192.168.0.0/16", "127.0.0.1"]
[acme]
email = "letsencrypt@mydomainaddress.com"
storage = "acme.json"
entryPoint = "https"
OnHostRule = true
[acme.httpChallenge]
entryPoint = "http"
[file]
[backends]
[backends.blueiris]
[backends.blueiris.servers.server1]
url = "http://192.168.50.10:8181"
[frontends]
[frontends.blueiris]
backend = "blueiris"
entrypoints = ["https"]
passHostHeader = true
[frontends.blueiris.routes.blueiris_1]
rule = "Host:blueiris.mydomainaddress.com"
Download Blue Iris from the Apple or Android stores, Configuration is straightforward. This will provide access to real time camera streams as well as previous clips & alerts.