Monitor your OpenVPN stats

Over the past couple of weeks, I have come across a huge number of articles with headlines “We raise our VPN” or “Configuring OpenVPN in N steps”. On this wave, I also decided to try to make a VPN for myself and loved ones – such an experience is superfluous (and the VPN itself) definitely won’t. To do this, I bought one of the cheapest VPS with a foreign IP and minimal characteristics. This pleasure cost me ~ 250r per month.

It was decided to deploy the private network itself through OpenVPN. At that time, I had not heard anything about other services, and there were more than enough instructions for setting up OpenVPN (as I found out later, everything can be deployed literally in a couple of lines).

After a couple of hours of fiddling with configs and certificates and fully configuring the VPN, I found in the server control panel that the maximum channel speed is 10Mbps (this was written on the order page, but I overlooked this moment). The technical support explained that this limitation becomes active when the traffic speed exceeds 10Mbps per hour (means that you need to drive about 4.5 GB during this time). It turned out awkward, of course, but I did not plan to use a VPN even to such an extent. However, I became interested in the task of monitoring traffic and the ability to warn myself if suddenly the traffic speed through the VPN approaches the threshold value.

What is already there

First of all, I tried to find ready-made solutions for monitoring OpenVPN, after all, this is a fairly popular implementation, around which there should be a large community.

I have identified 2 solutions for myself:

  • OpenVPN-Admin – a whole combine that serves not only for monitoring, but also for managing certificates and the OpenVPN server itself

  • OpenVPN-Monitor – simple live-time monitoring with a geographic map showing connected clients

The first solution in my case would be too redundant, I would never need 80% of the functionality. In the second case, it turned out that monitoring is carried out only on this momentwhile statistics are not collected – there is no way to see how much the client has downloaded / uploaded in the last hour, and that’s why I was looking for a solution.

Besides these two options, I could not find anything that would meet my requirements or that I could remake to fit my needs.

Task Formulation

So I decided to sketch out my solution over the weekend and practice a few things along the way. What exactly I wanted:

  • Collect VPN usage statistics for each user

  • Track total traffic consumption

  • Warn if traffic exceeds 8-9Mbps in the last hour

  • And also watch all this business in the web interface (for aesthetic purposes) and try to pack everything in Docker (for educational purposes)

parsim, parsim, parsim

To analyze statistics, you must first collect statistics. OpenVPN provides a fairly user-friendly interface for getting traffic usage statistics. The corresponding directive is already included in the default server configuration:

status openvpn-status.log

It allows you to specify a file to which statistics on traffic usage by connected clients will be written. After the file name, you can additionally specify a number – the interval in seconds after which the file will be automatically updated (60 seconds by default).

For an integrated approach and, in my opinion, more humane than file parsing, you can use management-server, for this you need to specify the following directive in the config:

management localhost 7505

Additionally, you can specify a password to connect to the interface (more).

After that, it will be possible to connect to the OpenVPN server via telnet:

OpenVPN management interface
OpenVPN management interface

We collect statistics

OpenVPN kindly gives real-time statistics, but, alas, does not collect or store them. You can only get connected clients and the amount of their traffic in the last session, so you will have to take responsibility for the collection.

To collect statistics, I chose the option using management-interface and for this I wrote small python script. Once every N seconds, it accesses the management interface, requests the status, and creates/updates records in MongoDB for each user:

Data storage scheme
Data storage scheme
Can be better

Already when writing the article, I noticed some of my mistakes. Yes, it was possible to store data much more optimally and get by with just one collection – only segments. You can use it to carry out the entire analysis, practically without adding new fields, and fields with a difference (d_received and d_send) can be calculated dynamically if you do not plan to analyze too long periods of time

To get the total traffic consumption per hour, it is enough to simply select all the records whose time falls within this interval and sum up the traffic for them (or rather, their differences in traffic compared to previous records). For clients, you need the same thing, but with filtering by name.

Now the statistics are being collected, it remains to increase the functionality! In my case, it was only necessary to display it on the web and issue warnings if the traffic speed was exceeded!

We make it convenient

To display on the web, I did a simple web application on Vue and API for it on Flask. There is nothing unusual in it – one page that displays general statistics and cards for each of the users:

This is how the web interface for traffic monitoring looks like
This is how the web interface for traffic monitoring looks like
Oops, forgot to round
Oops, forgot to round

The web interface is great, but what about the traffic speeding notification? Initially, I had thoughts about sending notifications directly to the browser, but I never got to them, because another solution came to my mind – to make a bot in the TG and send messages from it!

Packing in Docker

As a practice, I decided to package everything in Docker. Since I already had MongoDB deployed on another server, I did not deploy it and managed with two Dockerfiles – one for the web and one for the parser. Since both of the microservices are made in Python, their Dockerfiles do not differ much.

# Dockerfile для веба
# Билдим фронтенд
FROM node:16.14-alpine3.14 AS builder

WORKDIR /usr/app/client
COPY ./client /usr/app/client

RUN npm i
RUN npm run build

# Собираем фронтенд и сервер
FROM python:3.10.4-alpine3.14

COPY app.py app.py
COPY requirements.txt requirements.txt
COPY --from=builder /usr/app/client/dist /client/dist

RUN pip install -r requirements.txt

EXPOSE 5000

CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0" ]
# Dockerfile для парсера
FROM python:3.8.13-buster

COPY main.py main.py
COPY OVPNInterface.py OVPNInterface.py
COPY requirements.txt requirements.txt


RUN pip install -r requirements.txt

EXPOSE 5555

CMD [ "python3", "-m", "main" ]

Finally

Thanks for reading! In this article, I just wanted to share my experience in collecting traffic statistics and “integrating” OpenVPN into real life. It is unlikely that my particular solution can be used by someone else, but the possibilities of the same management-interface are much wider, and therefore, there is where to roam!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *