Last week I was trying to understand how to establish a secure connection with a webcam streaming server. The idea was to setup a kind of small homemade surveillance system to be used when I’m away.
I knew of mjpg-streamer and I used it years ago, but I’ve never tried to encrypt the communication channel before, so I thought it was time to go a step further.
After a quick search I found that several people talk well about stunnel, a proxy which provides TLS encryption for both client and server.
The combination of these two tools allowed me to reach my goal and now I will briefly show you a step-by-step guide to configure all the needed.
Server-side configuration
For the server side I used an old pc equipped with a full clean installation of Slackware64, at which I connected a Trust Spotlight USB webcam.
Let’s start by installing the mjpg-streamer and noip2 packages. This operation can be accomplished by using sbotools (as root):
# sboinstall mjpg-streamer noip2
The first one provides the video streaming service, the second one allows the server to be visible from outside the local network.
No-IP client setup
In order to use the No-IP service you’ve to register a free account. Once you have it, sign in, add a new host name and then logout.
Now we configure our server via noip2 (as root):
root@darkstar:/home/cristiano# noip2 -C Auto configuration for Linux client of no-ip.com. Please enter the login/email string for no-ip.com myusername Please enter the password for user 'myusername' ******** Only one host [myserver.ddns.net] is registered to this account. It will be used. Please enter an update interval:[30] Do you wish to run something at successful update?[N] (y/N) n New configuration file '/usr/local/etc/no-ip2.conf' created.
Ok, the job is done. The last thing to do is to launch noip2 (as root):
# noip2
You can easily check that noip2 is running in background by using the command ps -A | grep noip2
Create the cerificates using OpenSSL
We want to create a self-signed certificate valid for two years. We can do this using OpenSSL:
mkdir stunnel && cd stunnel openssl req -x509 -sha256 -nodes -days 730 -newkey rsa:2048 -keyout key.pem -out cert.pem
The last command requires a certain number of fields to be filled with some informations. Feel free to enter what you prefer except for the field Common Name which must be filled with myserver.ddns.net.
At the end of the procedure you will find two files called key.pem and cert.pem in the current directory.
Stunnel
Let’s create a configuration file called stunnel.conf with the following content:
key = key.pem cert = cert.pem client = no debug = 7 verify = 2 CAfile = cert.pem sslVersion = all [mjpg-streamer] accept = 4567 connect = 192.168.1.50:8000
The parameter verify = 2 tells stunnel to require and verifiy the certificate. A detailed explanation can be found here.
Now we can start stunnel (as root):
# stunnel stunnel.conf
Also in this case we can check that stunnel is running with ps -A | grep stunnel
Mjpg-streamer
We can launch the streaming service with the following command (as user):
mjpg_streamer -i "input_uvc.so -d /dev/video0 -n -q 80 -y -f 15 -r 640x480" -o "output_http.so -p 8000 -w /var/mjpg-www -c myuser:mypass"
For the input_uvc.so plugin we have the following parameters:
- -d <device>: the video device to use (/dev/video0 in this case)
- -n: don’t initialize dynamic controls of Linux-UVC driver
- -q <quality>: the quality of the JPG compression to use (-q 80)
- -y: use this if your camera doesn’t support MJPG, pictures will be captured in YUVY
- -f <framerate>: the framerate in frames per second (-f 15)
- -r <resolution>: the resolution (-r 640×480)
For the output_http.so plugin the parameters used are:
- -p <port>: the port at which the service is available (-p 8000)
- -w <path>: folder that contains webpages in flat hierarchy (no subfolders) (-w /var/mjpg-www)
- -c <credentials>: protect the access with username and password (-c myuser:mypass)
When launched, mjpg-streamer should show you an output like this one below:
MJPG Streamer Version: svn rev: Unversioned directory i: Using V4L2 device.: /dev/video0 i: Desired Resolution: 640 x 480 i: Frames Per Second.: 15 i: Format............: YUYV i: JPEG Quality......: 80 i: TV-Norm...........: DEFAULT o: www-folder-path...: /var/mjpg-www/ o: HTTP TCP port.....: 8000 o: username:password.: myuser:mypass o: commands..........: enabled
And if you point your web browser to the local IP address of the server (i.e. 192.168.1.50:8000), you should see mjpg-streamer in action ;-)
Final remarks
What we have done until now is valid for a Slackware machine, but what if we want to use an embedded platform like the Raspberry Pi instead?
The steps to do are almost the same, but there are some small details we have to bear in mind.
First of all, here you can find the instructions to install the No-IP client on the Raspberry Pi.
To install stunnel, just do:
sudo apt-get install stunnel4
Regarding mjpg-streamer, the instructions to install it are listed here below:
sudo apt-get update sudo apt-get upgrade sudo apt-get install git cmake libjpeg8-dev git clone https://github.com/jacksonliam/mjpg-streamer.git cd mjpg-streamer/mjpg-streamer-experimental mkdir build && cd build cmake .. make sudo make install cd ..
To launch the video streaming service, just do the following:
export LD_LIBRARY_PATH=. mjpg_streamer -o "output_http.so -w ./www -p 8000 -c myuser:mypass" -i "input_raspicam.so -quality 80 -fps 15 -r 640x480"
Just a note: here I used a Raspberry Pi 1 model B with the Raspberry Pi Camera v1.3, but I think you can certainly obtain better performances by using a more recent model, for example the Raspberry Pi 3.
Router configuration
In order to be able to communicate from outside your home network, you need to enable the port forwarding.
Depending on the router model, an appropriate configuration may be the following:
- Service name: mjpg-streamer (choose the name you like)
- External port: 4567 [TCP]
- Internal port: 4567 [TCP]
- Internal IP address: 192.168.1.50 (the server)
Client-side configuration
Now we consider the client-side configuration by analyzing two different cases.
Slackware (on the laptop)
In this case I used my laptop with Slackware64. I have installed stunnel, as explained above, and then I have configured it as shown here below:
key = key.pem cert = cert.pem client = yes debug = 7 sslVersion = all [mjpg-streamer] accept = 127.0.0.1:8081 connect = myserver.ddns.net:4567
key.pem and cert.pem must be the same of those stored on the server.
We can launch stunnel (as root):
# stunnel stunnel.conf
And then we can point the web browser to 127.0.0.1:8081 to see the video flow!
Android (on the smartphone)
But in most cases, when you’re around, you don’t have your laptop with you. It’s more likely you bring with you a smartphone with an internet connection.
Here below I explain you with a short video how you can access your webcam using a smartphone.
You need to install Termux from the Google Play Store before to try it.
Ok, that’s all for now :-)
As usual, remarks and suggestions are welcome!
hi,
thank you detailed explanations!
How can we secure credentials transfering through url name?
Is it true that creds snooping is possible by capturing http packets or dns queries?
Hi Alihan,
thank you for your comment.
As far as I know, HTTP packets without any protection are obviously traceable, but when you use stunnel the entire HTTP traffic should be obfuscated.
Someone trying to inspect the HTTP traffic will not recognize anything!