Secure Remote Access to iSpy Agent DVR

While evaluating video surveillance solutions, I discovered that many have transitioned to a subscription-based licensing model and depend on cloud services of varying reliability. Pure open-source DVR solutions either appear outdated and visually unappealing, like ZoneMinder, or suffer from significant limitations.

We were seeking a robust and contemporary solution with an active developer base, compatible with our local Debian server, independent of cloud services, and does not require a software subscription. The only solution that fulfilled all these requirements was iSpy Agent DVR.

The iSpy Agent solution proved to be highly stable and efficiently utilized CPU resources. Although there is room for improvement in the user interface, we are completely satisfied with it overall.

The only challenge we faced was establishing secure remote access without utilizing the iSpy cloud offering. However, we developed a solution that might be worth sharing.

Installing iSpy Agent DVR on Debian 11

The installation on Linux could not be easier, it is a one-liner, assuming that curl is available:

bash <(curl -s "https://raw.githubusercontent.com/ispysoftware/agent-install-scripts/main/v2/install.sh")

iSpy Agent has very few software dependencies, which makes it likely to coexist peacefully with other software. Immediately after successful installation, you can access the iSpy Web Management via http://<<iSpyServer>>:8090 and start configuring cameras and storage.

Configuring Live Views

One nice feature of iSpy is a simple API that allows to convert any video stream into MJPG format for direct browser viewing, integration into a smart home server or a website. Just type the following URL into your web browser and view the ad-hoc-conversion of a camera stream:

http://<iSpyServer>:8090/video.mjpg?oids=1&size=1255x706

Remote Access

Theoretically, all that is required for remote access to the iSpy Agent GUI and its video streams is a port forwarding rule within your firewall from the WAN interface to the local iSpy Agent server. But the management GUI uses HTTP, and you would not want unsecured access from the internet. The obvious solution is to use an HTTP proxy server that does SSL encryption. As an additional benefit, it acts as an additional safeguard against brute force and DOS attacks.

Setting up Apache as a reverse proxy

We assume that you already have a running Apache server with certificates and HTTPS enabled. If not, follow the numerous Apache installation tutorials available for your Linux distribution.

When your Apache web server is up and running, edit the site configuration, usually located in /etc/apache2/sites-available/<sitename>.conf, locate the VirtalHost-section serving port 443 and add the two ProxyPass lines like so:

<VirtualHost <ApacheLanIP>:443>
   ProxyPass "/" "http://<iSpyAgentLanIP>:8090/"
   ProxyPassReverse "/" "http://<iSpyAgentLanIP>:8090/"
   ...
   <Directory ...>
     ...
   </Directory>
   ...
</VirtualHost>

After restarting Apache, you will now be able to reach your iSpy Agent Server from the internet via HTTPS and Port 443.

Enabling HTTPS access to iSpy Agent

Unfortunally, in the free license version of iSpy Agent the software contains code that detects that the original request came in via HTTPS and blocks GUI access completely, even though the proxy converts all requests correctly to HTTP. However, there is a "Agent DVR Business License" for US$ 49,- that unlocks the HTTPS feature and allows also the creation of additional users with read-only privileges. This business license offering is somewhat hidden on the iSpy website, so it may take a while to find it. Anyway, USD 49,- this is a fair price for a perpetual server license.

Forward UDP Port 3478 to iSpy Agent

With the licensed Agent server and the Apache, the iSpy GUI can now be accessed via HTTPS, but it is still not possible to log in and view video streams. This is because the remote web browser wants to reach the iSpy Agent via UDP on port 3478. This is not well documented, so simply add a port forwarding rule in your firewall.

Securing Remote Access

With the business license, an Apache reverse proxy and the port forwarding rule, you now have complete remote control of your DVR, protected with an interactive login and multiple user access levels.

But wait, while the iSpy API is now SSL-encrypted as well, the API is publicly open without any authentication! This means that anyone around the globe may now watch all of your camera streams, which is probably not what you want. The root cause for this problem is that GUI and API run over the same port 8090 and use the same URL path. This is not a good implementation because the proxy has no chance to allow selective access to the GUI while blocking API access.

This means we must add another layer of protection within the Reverse Proxy.

Setting up Basic Authentication in Apache

Setting up basic authentication in Apache is straightforward, just execute the following commands:

apt install apache2-utils
htpasswd -c /etc/apache2/htpasswd <username>

The httpasswd command will ask for a password and creates the access control file htpasswd in the given location. Choose any file location that the apache2 process can read, except the webserver's document root, which would make it publicly visible.

Password protecting an Apache directory is straightforward and well documented, but how to password protect a proxy location is less obvious. Extend the apache configuration mentioned above like so:

<VirtualHost <ApacheLanIP>:443>
   # This is essential, otherwise remote login will not function reliably...

   ProxyBadHeader Ignore   

   ProxyPass "/" "http://<iSpyAgentLanIP>:8090/"
   ProxyPassReverse "/" "http://<iSpyAgentLanIP>:8090/"
   <proxy *>
     Order deny,allow
     Authtype Basic
     Authname "iSpy Remote Access"
     AuthUserFile "/etc/apache2/htpasswd"
     <requireAny>
       # Allow unauthorizes acces from within LAN...
       Require ip 192.168.0.0/24
       # Optional, allows unprotected LAN acces when using Port Reflection...
       Require ip <PublicIP>
       # Auth Override for specific internet hosts...
       # Require ip 159.69.68.104
       Require local
       Require valid-user
     </RequireAny>
   </proxy>

   ...
   <Directory ...>
     ...
   </Directory>
   ...
</VirtualHost>

Let's explain these statements:

ProxyBadHeader is needed because iSpy agent seems to send some malformed HTTP headers which the Apache proxy would drop without this statement.

ProxyPass and ProxyPassReverse tell Apache where to forward the external request. "/" means that all paths should be proxied.

<proxy *> is a section identifier that causes the subsequent authentication constraints to be applied to the proxy function and not to normal webpages.

Order deny,allow means that by default everything is denied except what is explicitly allowed in the subsequent process.

Authtype Basic is a simple, yet proved authentication method. Don't be fooled by the fact that Basic Auth uses plain text passwords: Our Apache proxy is configured to listen only on port 443, which means that all traffic is TLS-encrypted, including all passwords.

Authname is an arbitrary name that appears in the web authentication dialog.

AuthUserFile is the access control file that you have created.

<requireAny> is a section identifier meaning that one of the contained requirements are sufficient to grant access.

Require ip 192.168.0.0/24 means that hosts within the local LAN are automatically granted access. Replace this with your LAN network or delete the line if you want that local PCs must authenticate as well.

Require ip <PublicIP> This is needed if you access your iSpy Agent from within the LAN with the same public DNS name as used with remote access. In this case the DNS name resolves to the public IP of your firewall and your firewall must have port reflection enabled to reply correctly. Replace  <PublicIP> with your fixed public internet IP address.

Require ip 159.69.68.104 If you want that requests origination from a specific host should also skip authentication, remove the comment and substitute the sample IP address.

Require local allows local web access to skip authentication, useful if your Linux server has a graphical environment.

Require valid-user Causes to check the AuthUserFile for a user / password match. Note that the file may contain multiple users.

Final Considerations

To simplify external access you may duplicate the relevant user credentials from iSpy into the htpasswd file so that only a single password must be remembered. On the other hand, different passwords offer increased security.

Luckily, The iSpy GUI is fully responsive, which means that it is perfectly usable on mobile devices, with the restriction that at the time of writing only Chrome Browser is supported on Android. If you open the iSpy Agent website in Chrom for the first time, don't forget to set the option to create a start screen app. This will make the website behave somewhat like an app. This prevents that the website is opened multiple times, thereby saving server load and internet bandwidth.

Don't try to use the iSpy mobile app, it works only with a valid subscription and an iSpy cloud account.

This remote solution for iSpy works fo me like a charm, so I hope it is useful for others that share my dislike of subscription licensing and cloud services, that are beyond my control.

 

Martin Kasztantowicz