Code Monkey home page Code Monkey logo

furlongm / openvpn-monitor Goto Github PK

View Code? Open in Web Editor NEW
950.0 61.0 290.0 1.12 MB

openvpn-monitor is a web based OpenVPN monitor, that shows current connection information, such as users, location and data transferred.

Home Page: http://openvpn-monitor.openbytes.ie

License: GNU General Public License v3.0

Python 100.00%
openvpn-server python openvpn-monitor html openvpn openvpn-admin openvpn-status openvpn-client openvpn-configuration

openvpn-monitor's Introduction

openvpn-monitor

Summary

openvpn-monitor is a simple python program to generate html that displays the status of an OpenVPN server, including all current connections. It uses the OpenVPN management console. It typically runs on the same host as the OpenVPN server, however it does not necessarily need to.

Supported Operating Systems

  • Ubuntu 20.04 LTS (focal)
  • Debian 10 (buster)
  • CentOS/RHEL 8

Source

The current source code is available on github:

https://github.com/furlongm/openvpn-monitor

Install Options

N.B. all CentOS/RHEL instructions assume the EPEL repository has been installed:

dnf -y install epel-release

If selinux is enabled the following changes are required for host/port to work:

dnf -y install policycoreutils-python-utils
semanage port -a -t openvpn_port_t -p tcp 5555
setsebool -P httpd_can_network_connect=1

virtualenv + pip + gunicorn

# apt -y install python3-virtualenv geoip-database geoip-database-extra # (debian/ubuntu)
# dnf -y install python3-virtualenv geolite2-city                       # (centos/rhel)
mkdir /srv/openvpn-monitor
cd /srv/openvpn-monitor
virtualenv -p python3 .
. bin/activate
pip install openvpn-monitor gunicorn
gunicorn openvpn-monitor -b 0.0.0.0:80

See configuration for details on configuring openvpn-monitor.

apache

Install dependencies and configure apache

Debian / Ubuntu
apt -y install git apache2 libapache2-mod-wsgi python3-geoip2 python3-humanize python3-bottle python3-semantic-version geoip-database geoip-database-extra
echo "WSGIScriptAlias /openvpn-monitor /var/www/html/openvpn-monitor/openvpn-monitor.py" > /etc/apache2/conf-available/openvpn-monitor.conf
a2enconf openvpn-monitor
systemctl restart apache2
CentOS / RHEL
dnf -y install git httpd mod_wsgi python3-geoip2 python3-humanize python3-bottle python3-semantic_version geolite2-city
echo "WSGIScriptAlias /openvpn-monitor /var/www/html/openvpn-monitor/openvpn-monitor.py" > /etc/httpd/conf.d/openvpn-monitor.conf
systemctl restart httpd

Checkout openvpn-monitor

cd /var/www/html
git clone https://github.com/furlongm/openvpn-monitor.git

See configuration for details on configuring openvpn-monitor.

docker

docker run -p 80:80 ruimarinho/openvpn-monitor

Read the docker installation instructions for details on how to generate a dynamic configuration using only environment variables.

nginx + uwsgi

Install dependencies

# apt -y install git gcc nginx uwsgi uwsgi-plugin-python3 virtualenv python3-dev libgeoip-dev geoip-database geoip-database-extra  # (debian/ubuntu)
# dnf -y install git gcc nginx uwsgi uwsgi-plugin-python3 virtualenv python3-devel geoip-devel geolite2-city                       # (centos/rhel)

Checkout openvpn-monitor

cd /srv
git clone https://github.com/furlongm/openvpn-monitor.git
cd openvpn-monitor
virtualenv -p python3 .
. bin/activate
pip install -r requirements.txt

uWSGI app config

Create a uWSGI config: /etc/uwsgi/apps-available/openvpn-monitor.ini

[uwsgi]
base = /srv
project = openvpn-monitor
logto = /var/log/uwsgi/app/%(project).log
plugins = python3
chdir = %(base)/%(project)
virtualenv = %(chdir)
module = openvpn-monitor:application
manage-script-name = true
mount=/openvpn-monitor=openvpn-monitor.py

Nginx site config

Create an Nginx config: /etc/nginx/sites-available/openvpn-monitor

server {
    listen 80;
    location /openvpn-monitor/ {
        uwsgi_pass unix:///run/uwsgi/app/openvpn-monitor/socket;
        include uwsgi_params;
    }
}

Enable uWSGI app and Nginx site, and restart services

ln -s /etc/uwsgi/apps-available/openvpn-monitor.ini /etc/uwsgi/apps-enabled/
systemctl restart uwsgi
ln -s /etc/nginx/sites-available/openvpn-monitor /etc/nginx/sites-enabled/
rm /etc/nginx/sites-enabled/default
systemctl restart nginx

See configuration for details on configuring openvpn-monitor.

deb / rpm

TBD

Configuration

Configure OpenVPN

Add the following line to your OpenVPN server configuration to run the management console on 127.0.0.1 port 5555, with the management password in /etc/openvpn/pw-file:

management 127.0.0.1 5555 pw-file

To run the management console on a socket, with the management password in /etc/openvpn/pw-file:

management socket-name unix pw-file

Refer to the OpenVPN documentation for further information on how to secure access to the management interface.

Configure openvpn-monitor

Copy the example configuration file openvpn-monitor.conf.example to the same directory as openvpn-monitor.py.

cp openvpn-monitor.conf.example openvpn-monitor.conf

In this file you can set site name, add a logo, set the default map location (latitude and longitude). If not set, the default location is New York, USA.

Once configured, navigate to http://myipaddress/openvpn-monitor/

Note the trailing slash, the images may not appear without it.

Debugging

openvpn-monitor can be run from the command line in order to test if the html generates correctly:

cd /var/www/html/openvpn-monitor
python3 openvpn-monitor.py

Further debugging can be enabled by specifying the --debug flag:

cd /var/www/html/openvpn-monitor
python3 openvpn-monitor.py -d

License

openvpn-monitor is licensed under the GPLv3, a copy of which can be found in the COPYING file.

Acknowledgements

Flags are created by Matthias Slovig ([email protected]) and are licensed under Creative Commons License Deed Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0). See http://flags.blogpotato.de/ for more details.

openvpn-monitor's People

Contributors

dekan avatar dependabot[bot] avatar dondiego avatar exeba avatar furlongm avatar hexedpackets avatar jamie- avatar kingy444 avatar limhud avatar meisterschueler avatar pyup-bot avatar quantifiedcode-bot avatar raoulmahtani avatar ruimarinho avatar scomoletti avatar tobiasnix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

openvpn-monitor's Issues

Error: 500 Internal Server Error (Synology NAS)

VPN server on Synology DS 214
OpenVPN : 1.3.5-2757 (most up to date version in the package center)
Monitor Tool: A VM on the same VPN (10.10.22.14)

Seeing the following errors. Looks like the IP has some extra characters maybe due to the Synology flavor of OpenVPN?

DEBUG:
=== begin split line
deque([u'TITLE', u'OpenVPN 2.3.11 armle-unknown-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [MH] [IPv6] built on Jan 13 2017'])
=== end split line
DEBUG:
=== begin split line
deque([u'TIME', u'Thu Mar 2 23:59:30 2017', u'1488517170'])
=== end split line
DEBUG:
=== begin split line
deque([u'HEADER', u'CLIENT_LIST', u'Common Name', u'Real Address', u'Virtual Address', u'Bytes Received', u'Bytes Sent', u'Connected Since', u'Connected Since (time_t)', u'Username'])
=== end split line
DEBUG:
=== begin split line
deque([u'CLIENT_LIST', u'user', u'::ffff:71.230.XXX.XX(1194)', u'10.10.22.18', u'452352', u'529252', u'Thu Mar 2 23:38:23 2017', u'1488515903', u'user'])
=== end split line
Traceback (most recent call last):
File "openvpn-monitor.py", line 746, in
main()
File "openvpn-monitor.py", line 723, in main
monitor = OpenvpnMgmtInterface(cfg, **kwargs)
File "openvpn-monitor.py", line 170, in init
self.collect_data(vpn)
File "openvpn-monitor.py", line 182, in collect_data
vpn['sessions'] = self.parse_status(status, self.gi, vpn['semver'])
File "openvpn-monitor.py", line 346, in parse_status
remote_ip = ip_address(remote)
File "/usr/lib/python2.7/dist-packages/ipaddr.py", line 78, in IPAddress
address)
ValueError: u'::ffff:71.230.XXX.XX(1194)' does not appear to be an IPv4 or IPv6 address

[Thu Mar 02 23:55:58.982122 2017] [core:notice] [pid 9503] AH00094: Command line: '/usr/sbin/apache2'
[Thu Mar 02 23:57:17.333137 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] Traceback (most recent call last):
[Thu Mar 02 23:57:17.333199 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] File "/usr/lib/python2.7/dist-packages/bottle.py", line 862, in _handle
[Thu Mar 02 23:57:17.333206 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] return route.call(**args)
[Thu Mar 02 23:57:17.333210 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] File "/usr/lib/python2.7/dist-packages/bottle.py", line 1737, in wrapper
[Thu Mar 02 23:57:17.333215 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] rv = callback(*a, **ka)
[Thu Mar 02 23:57:17.333219 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 771, in get_slash
[Thu Mar 02 23:57:17.333224 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] return render()
[Thu Mar 02 23:57:17.333228 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 784, in render
[Thu Mar 02 23:57:17.333233 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] main(**kwargs)
[Thu Mar 02 23:57:17.333237 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 723, in main
[Thu Mar 02 23:57:17.333242 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] monitor = OpenvpnMgmtInterface(cfg, **kwargs)
[Thu Mar 02 23:57:17.333246 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 170, in init
[Thu Mar 02 23:57:17.333251 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] self.collect_data(vpn)
[Thu Mar 02 23:57:17.333255 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 182, in collect_data
[Thu Mar 02 23:57:17.333260 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] vpn['sessions'] = self.parse_status(status, self.gi, vpn['semver'])
[Thu Mar 02 23:57:17.333264 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 346, in parse_status
[Thu Mar 02 23:57:17.333269 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] remote_ip = ip_address(remote)
[Thu Mar 02 23:57:17.333273 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] File "/usr/lib/python2.7/dist-packages/ipaddr.py", line 78, in IPAddress
[Thu Mar 02 23:57:17.333277 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] address)
[Thu Mar 02 23:57:17.333282 2017] [wsgi:error] [pid 9508] [client 192.168.1.53:14497] ValueError: '::ffff:71.230.162.47(1194)' does not appear to be an IPv4 or IPv6 address
[Thu Mar 02 23:57:25.320587 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] Traceback (most recent call last):
[Thu Mar 02 23:57:25.320649 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] File "/usr/lib/python2.7/dist-packages/bottle.py", line 862, in _handle
[Thu Mar 02 23:57:25.320656 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] return route.call(**args)
[Thu Mar 02 23:57:25.320660 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] File "/usr/lib/python2.7/dist-packages/bottle.py", line 1737, in wrapper
[Thu Mar 02 23:57:25.320665 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] rv = callback(*a, **ka)
[Thu Mar 02 23:57:25.320683 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 771, in get_slash
[Thu Mar 02 23:57:25.320688 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] return render()
[Thu Mar 02 23:57:25.320691 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 784, in render
[Thu Mar 02 23:57:25.320695 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] main(**kwargs)
[Thu Mar 02 23:57:25.320699 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 723, in main
[Thu Mar 02 23:57:25.320703 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] monitor = OpenvpnMgmtInterface(cfg, **kwargs)
[Thu Mar 02 23:57:25.320707 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 170, in init
[Thu Mar 02 23:57:25.320711 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] self.collect_data(vpn)
[Thu Mar 02 23:57:25.320715 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 182, in collect_data
[Thu Mar 02 23:57:25.320719 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] vpn['sessions'] = self.parse_status(status, self.gi, vpn['semver'])
[Thu Mar 02 23:57:25.320723 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 346, in parse_status
[Thu Mar 02 23:57:25.320727 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] remote_ip = ip_address(remote)
[Thu Mar 02 23:57:25.320731 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] File "/usr/lib/python2.7/dist-packages/ipaddr.py", line 78, in IPAddress
[Thu Mar 02 23:57:25.320735 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] address)
[Thu Mar 02 23:57:25.320738 2017] [wsgi:error] [pid 9506] [client 192.168.1.53:14499] ValueError: '::ffff:71.230.162.47(1194)' does not appear to be an IPv4 or IPv6 address
[Thu Mar 02 23:57:29.512802 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] Traceback (most recent call last):
[Thu Mar 02 23:57:29.512856 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] File "/usr/lib/python2.7/dist-packages/bottle.py", line 862, in _handle
[Thu Mar 02 23:57:29.512861 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] return route.call(**args)
[Thu Mar 02 23:57:29.512865 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] File "/usr/lib/python2.7/dist-packages/bottle.py", line 1737, in wrapper
[Thu Mar 02 23:57:29.512869 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] rv = callback(*a, **ka)
[Thu Mar 02 23:57:29.512873 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 771, in get_slash
[Thu Mar 02 23:57:29.512877 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] return render()
[Thu Mar 02 23:57:29.512881 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 784, in render
[Thu Mar 02 23:57:29.512885 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] main(**kwargs)
[Thu Mar 02 23:57:29.512889 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 723, in main
[Thu Mar 02 23:57:29.512893 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] monitor = OpenvpnMgmtInterface(cfg, **kwargs)
[Thu Mar 02 23:57:29.512897 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 170, in init
[Thu Mar 02 23:57:29.512901 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] self.collect_data(vpn)
[Thu Mar 02 23:57:29.512904 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 182, in collect_data
[Thu Mar 02 23:57:29.512923 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] vpn['sessions'] = self.parse_status(status, self.gi, vpn['semver'])
[Thu Mar 02 23:57:29.512928 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 346, in parse_status
[Thu Mar 02 23:57:29.512932 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] remote_ip = ip_address(remote)
[Thu Mar 02 23:57:29.512935 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] File "/usr/lib/python2.7/dist-packages/ipaddr.py", line 78, in IPAddress
[Thu Mar 02 23:57:29.512939 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] address)
[Thu Mar 02 23:57:29.512943 2017] [wsgi:error] [pid 9509] [client 192.168.1.53:14514] ValueError: '::ffff:(1194)' does not appear to be an IPv4 or IPv6 address

getting Error

File "openvpn-monitor.py", line 34, in
from collections import OrderedDict
ImportError: cannot import name OrderedDict

centos 6

How to install it on CentOS 7

I am having toruble installing it as mod_python is not available on centos7. I downloaded and compiled mod_python but it turns out that it is version 3.5 and 2.7 is needed. Cant find it. Any solutions?

Cropped output

The output is cropped:
openvpn_cropped_output

Last rows in the html are:

<tr>
<td>EDNC</td>
<td>10.8.0.61</td>
<td>91.15.155.167</td>
<td>41217</td>

Problem with python

Dear furlong!

With Ubuntu 16.04.1 LTS apache shutting down.

/var/log/apache2/error.log

[Thu Feb 02 12:28:17.846459 2017] [mpm_event:notice] [pid 2186:tid 140591778240384] AH00491: caught SIGTERM, shutting down
[Thu Feb 02 12:28:18.876525 2017] [wsgi:warn] [pid 2344:tid 140365205100416] mod_wsgi: Compiled for Python/2.7.11.
[Thu Feb 02 12:28:18.876585 2017] [wsgi:warn] [pid 2344:tid 140365205100416] mod_wsgi: Runtime using Python/2.7.12.
[Thu Feb 02 12:28:18.877273 2017] [mpm_event:notice] [pid 2344:tid 140365205100416] AH00489: Apache/2.4.18 (Ubuntu) mod_wsgi/4.3.0 Python/2.7.12 configured -- resuming$
[Thu Feb 02 12:28:18.877300 2017] [core:notice] [pid 2344:tid 140365205100416] AH00094: Command line: '/usr/sbin/apache2'

Regards,
David.

Logging Feature

It would be great to access the log directly off the page :)

Add - Delete - Update - Ban/Block

I suggest adding CRUD feature on the system will become handy. Ban/Unban button users to prevent from reconnecting to server, client openvpn gui has the feature to auto reconnect after disconnection on few seconds.

example: master list of all clients in row.

[column for client username] [column for update password button] [column for delete button] [column for ban button]

below the row - ADD USER button

anyway your work is awesome.

Images loading, Ping Errors

Hey Guys,

The python script was unable to load the images from the images folder (not sure why, they were also not directly available through the URL although permissions were correct). I ended up moving the flags folder out of the images directory and to the /openvpn-monitor/ directory then changed line 651 to "output('{1!s} '.format(flag, full_location))" to resolve the issue.

Unfortunately the "last ping" will just return errors. I've checked the networking and reach-ability to both the WAN, and Client cert ip's from both the Tap int, and the web-server, and they are reachable. I can see from the logs, that the management interface running version, state, status 3 , and quit commands, which I do not see yielding that information.

Cannot see client connections details

I cannot see client connection only count of connection and bytes in and bytes out:
2015-10-06_12-02

When i'm running script in debug mode i see information that is collected by the script about client connections but generated empty html file.

Thanks!
Log:
root@raspberrypi:/var/www/openvpn# ./openvpn-monitor.py -d
=== begin section
{'maps': 'False', 'site': ''}
=== end section
=== begin section
{'host': '192.168.1.1', 'port': '1150', 'name': 'VPN'}
=== end section
=== begin raw data
1444084336,CONNECTED,SUCCESS,192.168.2.1,
END

=== end raw data
=== begin split line
['1444084336', 'CONNECTED', 'SUCCESS', '192.168.2.1', '']
=== end split line
=== begin split line
['END']
=== end split line
=== begin raw data
SUCCESS: nclients=1,bytesin=7430387,bytesout=5210173

=== end raw data
=== begin split line
['nclients=1', 'bytesin=7430387', 'bytesout=5210173\r\n']
=== end split line
=== begin raw data
TITLE,OpenVPN 2.3.6 arm-unknown-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [MH] [IPv6] built on Jun 10 2015
TIME,Wed Oct 7 22:04:52 2015,1444244692
HEADER,CLIENT_LIST,Common Name,Real Address,Virtual Address,Bytes Received,Bytes Sent,Connected Since,Connected Since (time_t),Username
CLIENT_LIST,client,1.1.1.1:49157,192.168.2.2,637356,172249,Wed Oct 7 12:03:00 2015,1444208580,UNDEF
HEADER,ROUTING_TABLE,Virtual Address,Common Name,Real Address,Last Ref,Last Ref (time_t)
ROUTING_TABLE,192.168.2.2,client,1.1.1.1:49157,Wed Oct 7 21:34:37 2015,1444242877
GLOBAL_STATS,Max bcast/mcast queue length,0
END

=== end raw data
=== begin split line
['TITLE', 'OpenVPN 2.3.6 arm-unknown-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [MH] [IPv6] built on Jun 10 2015']
=== end split line
=== begin split line
['TIME', 'Wed Oct 7 22:04:52 2015', '1444244692']
=== end split line
=== begin split line
['HEADER', 'CLIENT_LIST', 'Common Name', 'Real Address', 'Virtual Address', 'Bytes Received', 'Bytes Sent', 'Connected Since', 'Connected Since (time_t)', 'Username']
=== end split line
=== begin split line
['CLIENT_LIST', 'client', '1.1.1.1:49157', '192.168.2.2', '637356', '172249', 'Wed Oct 7 12:03:00 2015', '1444208580', 'UNDEF']
=== end split line
=== begin split line
['HEADER', 'ROUTING_TABLE', 'Virtual Address', 'Common Name', 'Real Address', 'Last Ref', 'Last Ref (time_t)']
=== end split line
=== begin split line
['ROUTING_TABLE', '192.168.2.2', 'client', '1.1.1.1:49157', 'Wed Oct 7 21:34:37 2015', '1444242877']
=== end split line
=== begin split line
['GLOBAL_STATS', 'Max bcast/mcast queue length', '0']
=== end split line
=== begin split line
['END']
=== end split line
Content-Type: text/html

<!doctype html>

<title> OpenVPN Status Monitor</title> <style type="text/css"> body { font-family: sans-serif; font-size: 12px; background-color: #FFFFFF; margin: auto; } h1 { color: #222222; font-size: 20px; text-align: center; padding-bottom: 0; margin-bottom: 0; } table { margin: auto; width:900px; border-collapse: collapse; } td.left {text-align: left; color: #232355; font-weight: bold; font-size: 14px; } td.right {text-align: right; color: #656511; font-weight: bold; font-size: 14px; } th { background: #555555; color: white; text-align: left; padding-left: 10px;} td { padding: 10px 10px 5px 5px; } div { padding: 7px 4px 6px 6px; margin: 0px auto; text-align: center; } div.footer { text-align: center; } </style>

OpenVPN Status Monitor


VPN - Connection up, pingable. 1 clients, 7430387 bytes in, 5210173 bytes out [ 192.168.2.1 tun ]
Username / Hostname VPN IP Address Remote IP Address Port Location Recv Sent Connected Since Last Ping Time Online


=== begin vpns {'VPN1': {'stats': {'nclients': '1', 'bytesout': '5210173\r\n', 'bytesin': '7430387'}, 'name': 'VPN', 'sessions': {}, 'state': {'type': 'tun', 'identifier': '1444084336', 'connected': 'CONNECTED', 'success': 'SUCCESS', 'local_ip': '192.168.2.1'}, 'socket_connect': True, 'host': '192.168.1.1', 'port': '1150'}} === end vpns
Page automatically reloads every 5 minutes.
Last update: Wed 07/10/2015 22:04:52

sort doesn't work on other panel except the first one

as the title goes, I have multiple vpn servers and connected to this openvpn-monitor, the first panel seems fine no bugs at all but the second, third and so on doesn't have sorting feature. Your work is awesome mate :)

How to show the IPv6 address in the web?

Hi Furlong, I already use your tool for managing my OpenVPN for IPv6 tunnel broker in my project and it works great.
Is it possible for me to show the IP version 6 as well when there are clients connection ? As your program now only show the IP version 4 in the client VPN IP column.
To illustrate, I use command in my OpenVPN Management Interface:
status
OpenVPN CLIENT LIST
Updated,Fri Dec 29 14:01:24 2017
Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
android, A.B.C.D:F,335532,1561398,Fri Dec 29 14:00:21 2017 (note: i change the IPv4 and port address here for security reasons)
ROUTING TABLE
Virtual Address,Common Name,Real Address,Last Ref
AAAA:BBBB:C:DDDD:EF::1111,android,A.B.C.D:F,Fri Dec 29 14:01:24 2017 (note: i change the IPv4 and port address also IPv6 address here for security reasons)
10.8.0.101,android,A.B.C.D:F,Fri Dec 29 14:01:24 2017 (note: i change the IPv4 and port address here for security reasons)
GLOBAL STATS
Max bcast/mcast queue length,0
END

While in your web-based tool the client status shown as below:
image

As you can see it only shows the local IPv4 address : 10.8.0.101 while the IPv6 address: AAAA:BBBB:C:DDDD:EF::1111 can't be shown.
Hopefully, You can show me which part of the code that I need to add, to be able to show the IPv6 address part in the web.

Thank you in advance.
Note: I'm using OpenVPN 2.3.2 for the tunnel server

Password protected management interface

It looks like I can add multiple VPNs so I want to monitor some remote ones but obviously don't want to expose the management console to the internet completely. Is there a way to incorporate a password answer for a file defined in the openvpn server.conf?

Clients who have disconnected appear as connected

Hello. Thanks for the software, it is very useful. I have noticed some unexpected behaviour in that it takes 1 or 2 minutes for a client to disappear from the monitor after it has disconnected. Is this expected?

Cheers.

Feature request - Disconnect client if tx+trbigger then amount

Dear furlong!

This would be awesome for me, but hope useful for others too:

Ability to automatically disconnect an user if exceeded an amount of transfer (run script every 5 min by cron) (download+upload > amount in GB -> kick)
Set this amount at conf file (or to 0 if somebody dont want to use this feature) then the sytem disconnects this user.

Then:
If the user is disconnected trigger an event. For example send a specific URL to a GET request with it's username.

Regards,
csib

Ubuntu 14.04

Traceback (most recent call last):
File "openvpn-monitor.py", line 31, in
from humanize import naturalsize
ImportError: No module named humanize

Having issues trying to work out how to install python-humanize, i installed python3-humanize

Feature request: sorted output

My VPN is growing and for a better overview I need a sorted output for "Username / Hostname" or "VPN IP Address". At the moment the output is not sorted at all, right? As a first step you could introduce a default sorting for "Username / Hostname". In a second step you could introduce a user defined sorting.

Feature request - Disconnect clients

Hello I think your tool is awesome. However, I think it would be even better if you could disconnect active clients.

I managed to add this feature in my own hacky way by creating a button to a php script. But it would be great if this was native to your python program? What do you think?

Here are the changes I made

--- openvpn-monitor/openvpn-monitor.py  2016-10-06 18:18:11.476953625 -0400
+++ openvpn-monitor.py  2016-10-06 18:38:04.430057188 -0400
@@ -444,7 +444,7 @@
         output('<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">')
         output('<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">')
         output('<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>')
-        output('<body>')
+        output('</head><body>')


         output('<nav class="navbar navbar-inverse">')
         output('<div class="container-fluid">')
@@ -489,7 +489,7 @@

         server_headers = ['Username / Hostname', 'VPN IP Address',
                           'Remote IP Address', 'Port', 'Location', 'Bytes In',
-                          'Bytes Out', 'Connected Since', 'Last Ping', 'Time Online']
+                          'Bytes Out', 'Connected Since', 'Last Ping', 'Time Online', 'Action']
         client_headers = ['Tun-Tap-Read', 'Tun-Tap-Write', 'TCP-UDP-Read',
                           'TCP-UDP-Write', 'Auth-Read']

@@ -609,6 +609,7 @@
         else:
             output('<td>ERROR</td>')
         output('<td>{0!s}</td>'.format(total_time))
+        output('<td><a href="/cgi-bin/kill.php?vpnclient={0!s}:{1!s}"><button type="button" >Disconnect</button></a> </td>'.format(session['remote_ip'], session['port']))

     def print_session_table(self, vpn_mode, sessions):
         for key, session in list(sessions.items()):

Here's my crappy PHP

<?php

$vpnclient=$_GET[vpnclient];

$fp = fsockopen("localhost", 5555, $errno, $errstr, 30);

if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "kill $vpnclient\r\n";
    $out .= "quit\r\n";
    fwrite($fp, $out);
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }
    fclose($fp);
}

        echo "<html> <head> <meta http-equiv='refresh' content='3;/monitor/' /> </head> <body>";
        echo "<h1>$vpnclient disconnected</h1>";
        echo "</body></html>";
?>

And a screenshot of how it looks

screenshot from 2016-10-06 18 29 43

ImportError: No module named semantic_version

Hi,

I followed the instructions to install openvpn-monitor, during the debugging process I find an error like this.

python openvpn-monitor.py 
Traceback (most recent call last):
   File "openvpn-monitor.py", line 35, in <module>
     from semantic_version import Version as semver
 ImportError: No module named semantic_version

I use:
Ubuntu 14.04 LTS
Apache 2.4.7 (Ubuntu)
Python 2.7.6

I hope you can help me. Thanks.

ipv6 error

Hi there,
i like your monitor and use it quite often. Today I updated it and now i get this error:
[Thu Feb 25 19:14:37 2016] [error] [client 10.0.0.200] Traceback (most recent call last): [Thu Feb 25 19:14:37 2016] [error] [client 10.0.0.200] File "/var/www_ui/vpn/openvpn-monitor.py", line 29, in <module> [Thu Feb 25 19:14:37 2016] [error] [client 10.0.0.200] from humanize import naturalsize [Thu Feb 25 19:14:37 2016] [error] [client 10.0.0.200] ImportError: No module named humanize [Thu Feb 25 19:14:37 2016] [error] [client 10.0.0.200] Premature end of script headers: openvpn-monitor.py

Befor that I had to change the code a little to support IPv6 Addresses. I changed it, so it showed all remote ip addresses as 127.0.0.1. Not a good solution, but it worked so far.Perhaps you find time to fix that.

grettings.

Rename openvpn-monitor.conf

Please rename openvpn-monitor.conf to openvpn-monitor.conf.example
It will allow to update the local version from a repository.

Bug fix / Enhancement - mgmt state format change in openvpn v2.4.2

Looks like 2.4.2 changed the output of the state command from 5 fields to 8. Docs at openvpn.net still show the 2.4.1 behavior. Below is output from a few of my test systems.

2.4.13 client
time,state,opt desc,local tun/tap ip,remote ip
1491408625,CONNECTED,SUCCESS,10.0.0.2,172.16.0.1

2.4.13 server:
time,state, opt desc,local tun/tap ip,
1500864651,CONNECTED,SUCCESS,10.0.0.1,

2.4.2 client:
time,state,opt desc,local tun/tap ipaddr,remote ip,remote port,local outbound ip,local outbound port
1500865657,CONNECTED,SUCCESS,10.0.0.2,172.16.0.1,1194,10.1.1.1,39962

2.4.3 server:
time,state,opt desc,local tun/tap ipaddr,,,local listen ip,local listen port
1499703301,CONNECTED,SUCCESS,10.0.0.1,,,172.16.0.1,1194

Really no impact right now as the client vs server logic still works with the parts[4] still being empty on a server.

I may update parse_state to check version, split the line correctly, and add the local port for the tun/tap and the listen ip/port to the page. So I guess we can mark this as an enhancement.

Not displaying flags and logos

I'm using apache and centos 7

/etc/httpd/conf.d/openvpn-monitor.conf:
WSGIScriptAlias / /var/www/html/openvpn-monitor/openvpn-monitor.py

I put logo.png in /var/www/html/openvpn-monitor folder and set logo option in openvpn-monitor.conf:

[OpenVPN-Monitor]
...
logo=logo.png
...

But logo not showing in interface. If try open url http://myserver/logo.png, then i get 404 error. Flags also not displayed

"GET /flags/ru.png HTTP/1.1" 404 736 "http://myserver/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0"

"GET /logo.png HTTP/1.1" 404 732 "http://myserver/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0"

Restrict Viewing

Is it possible to restrict it so that you can only view the monitor if you are connected to the VPN?

Connection Refused

Hi all,

I have a openvpn running on port 1194 and the management running on 5555 (lsof, nstat, telnet: everything is ok).

Some details: /etc/openvpn/server.conf contains: management 127.0.0.1 5555

openvpn.log contains: MANAGEMENT: TCP Socket listening on [AF_INET]127.0.0.1:5555

lsof -i :5555
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
openvpn 14028 nobody 3u IPv4 31776 0t0 TCP localhost:personal-agent (LISTEN)

telnet 127.0.0.1 5555
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
INFO:OpenVPN Management Interface Version 1 -- type 'help' for more info

but running the container:

docker run -d -e OPENVPNMONITOR_DEFAULT_DATETIMEFORMAT="%%d/%%m/%%Y" -e OPENVPNMONITOR_DEFAULT_LATITUDE=10 -e OPENVPNMONITOR_DEFAULT_LONGITUDE=9 -e OPENVPNMONITOR_DEFAULT_MAPS=True -e OPENVPNMONITOR_DEFAULT_SITE='Test' -e OPENVPNMONITOR_SITES_0_ALIAS=UDP -e OPENVPNMONITOR_SITES_0_HOST=127.0.0.1 -e OPENVPNMONITOR_SITES_0_NAME=VPN -e OPENVPNMONITOR_SITES_0_PORT=5555 -p 80:80 ruimarinho/openvpn-monitor

I can only see: Could not connect to 127.0.0.1:5555 (Connection refused)

What I am doing wrong? Can you pls help me?

Thanks!

Location not correct?

Hello,

I got everything working ๐Ÿ‘

The only problem i encounter is that the location is not correct, its show my location and friends that live in my city that they are almost 6 or 7 kilometer from their real location

Did i do something wrong or is this because of privacy reasons ??

Kind Regards

Sovjet

README install update

The install instructions for CentOS 6 are incorrect.

yum install -y python-GeoIP python-ipaddr python-humanize python-bottle python-semantic_version httpd mod_wsgi git wget

python-semantic_version does not exist in the repo. To install, use pip:

yum install python-pip
pip install semantic_version

Location section not showing flag logo and ping error

Hi there

Just installed and looks really cool. However I have two issues:

  1. Where it shows your location in the table its not giving me the flag icon

  2. Under ping I see only error yet the server this is hosted on can manually ping the remote client ips that are connected, does it try to ping the remote vpn ip?
    vpnmonitorerror

Can you advise please?

Many thanks

Andy

Connection Refused

I'm i missing something?

Wich IP need i use from :
image

Monitor is in the same server as OpenVpn, just trying to reach it from my web browser:
image

Internal Server Error 500

Error: 500 Internal Server Error

Sorry, the requested URL 'http://xxx.xxx.xxx.xxx/openvpn-monitor/' caused an error:

From apache log:

  File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 323, in parse_status
[Thu Dec 29 15:40:39.819552 2016] [wsgi:error] [pid 1063] [client xxx.xxx.xxx.xxx:53087]     if parts[8] != 'UNDEF':
[Thu Dec 29 15:40:39.819555 2016] [wsgi:error] [pid 1063] [client xxx.xxx.xxx.xxx:53087] IndexError: list index out of range
[Thu Dec 29 15:42:03.960098 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142] Traceback (most recent call last):
[Thu Dec 29 15:42:03.960133 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]   File "/usr/lib/python2.7/dist-packages/bottle.py", line 862, in _handle
[Thu Dec 29 15:42:03.960137 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]     return route.call(**args)
[Thu Dec 29 15:42:03.960141 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]   File "/usr/lib/python2.7/dist-packages/bottle.py", line 1737, in wrapper
[Thu Dec 29 15:42:03.960145 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]     rv = callback(*a, **ka)
[Thu Dec 29 15:42:03.960148 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]   File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 723, in root
[Thu Dec 29 15:42:03.960152 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]     main()
[Thu Dec 29 15:42:03.960155 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]   File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 673, in main
[Thu Dec 29 15:42:03.960159 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]     monitor = OpenvpnMonitor(cfg)
[Thu Dec 29 15:42:03.960162 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]   File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 150, in __init__
[Thu Dec 29 15:42:03.960166 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]     self.collect_data(vpn)
[Thu Dec 29 15:42:03.960169 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]   File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 161, in collect_data
[Thu Dec 29 15:42:03.960173 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]     vpn['sessions'] = self.parse_status(status, self.geoip_data)
[Thu Dec 29 15:42:03.960176 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]   File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 323, in parse_status
[Thu Dec 29 15:42:03.960180 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142]     if parts[8] != 'UNDEF':
[Thu Dec 29 15:42:03.960183 2016] [wsgi:error] [pid 1117] [client xxx.xxx.xxx.xxx:53142] IndexError: list index out of range

What I have done to accomplish this error?
Just writes 10.20.0.10 for host. With my other server's address this is working, but that was a public address.

Checked, the connection between this server and 10.20.0.10 is perfect, management interface also works fine.

Update: I had an older OpenVPN on that server, which caused the error somehow. After an OpenVPN upgrade, it is working

Feature Request โ€” Client History Logs

this is not a necessary feature but it would be great if it will be added to openvpn-monitoring since admins of openvpn is not 24/7 online so they can't always trace or see if there are client who shares their account and use it at the same time. :)

image

reference from Chocobozzz
:)

show vpn server in map

could be interesting to add different color pin in map where the server (by reading external ip) is located

Suggestion - Date format

Since I live in the United States, the date format is sometimes confusing for my junior team members.

The US uses Month/Day/Year and this tool uses Day/Month/Year. Without being aware of the date format some folks get confused for example 10/12/2016 in Australia is December 10th but the US it's October 12th.

I really have no issues making the localized modifications, Perhaps you might want to consider a localization option or using ISO 8601 (YYYY-MM-DD) by default .

Keep up the great work

Getting 404 error on monitoring page after install

When I render the monitoring page in my terminal, everything works perfectly but when the URL in the documentation is visited in the browser an error 404 appears. Has anyone had a similar problem?
Attached is server.conf and openvpn-monitor.conf along with the terminal and web page renders:

useme2
useme3
useme
useme1

GeoIP extension build fails during setup

Ubuntu 16.10
While repeating "Quick steps":

py_GeoIP.c:23:19: fatal error: GeoIP.h: No such file or directory
     #include "GeoIP.h"
                       ^
    compilation terminated.
    error: command 'arm-linux-gnueabihf-gcc' failed with exit status 1

Screenshot

Openvpn-monirtor instalaltion issue

Hi,

I am getting below error while installing it on ubuntu 14.04 . Plz guide for solution.

pip install openvpn-monitor gunicorn
Downloading/unpacking openvpn-monitor
Could not find a version that satisfies the requirement openvpn-monitor (from versions: 1.0.0rc19, 1.0.0rc19.linux-x86_64)
Cleaning up...
No distributions matching the version for openvpn-monitor
Storing debug log for failure in /root/.pip/pip.log

an idea for the map.

We got many OpenVPN server around the world.
We will love to have an option to have multible OpenVPN Server output.
(NOT as a folder for each server, as we tryed)
Maybe change the map to Google earth or a zoom-scrolling map-location,
since we got VPNservers and clients all over the world.

semantic_version does not load ! Completely Hopeless

Traceback (most recent call last):
File "/var/www/html/openvpn-monitor/openvpn-monitor.py", line 36, in
from semantic_version import Version as semver
ImportError: No module named semantic_version
[Wed Apr 26 13:22:07.726903 2017] [cgid:error] [pid 8431:tid 140082247436032] [client 172.31.7.187:54704] End of script output before headers: openvpn-monitor.py

prompt@IT-OpenVPN-Server:/var/www/html/openvpn-monitor# pip install semantic_version
Requirement already satisfied: semantic_version in /usr/local/lib/python2.7/dist-packages
prompt@IT-OpenVPN-Server:/var/www/html/openvpn-monitor# apt-get install python-semantic_version
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package python-semantic_version
prompt@IT-OpenVPN-Server:/var/www/html/openvpn-monitor# apt-get install python-semantic-version
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package python-semantic-version
prompt@IT-OpenVPN-Server:/var/www/html/openvpn-monitor# apt-get install python_semantic_version
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package python_semantic_version

Feature request - web login.

There are so many features that could be implemented for this project, as you know.

However, I think that it is especially important that there is some kind of authorisation for the web interface, so that at least to a primitive extent, access to it could be controlled.

GeoIP 2 support on Amazon Linux

Do you plan to implement GeoIP2 support? Also, I cant seem to get this to work on Amazon Linux. Perhaps someone else had luck.

Thank you kindly

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.