• This repository has been archived on 13/Sep/2024
  • Stars
    star
    606
  • Rank 73,958 (Top 2 %)
  • Language
    C
  • License
    MIT License
  • Created about 10 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A VPN system over websockets

vpn-ws

A VPN system over websockets

This is the client/server implementation of a layer-2 software switch able to route packets over websockets connections.

The daemon is meant to be run behind nginx, apache, the uWSGI http router or a HTTP/HTTPS proxy able to speak the uwsgi protocol and to manage websockets connections

How it works

A client creates a tap (ethernet-like) local device and connects to a websocket server (preferably over HTTPS). Once the websocket handshake is done, every packet received from the tuntap will be forwarded to the websocket server, and every websocket packet received from the server will be forwarded to the tuntap device.

The server side of the stack can act as a simple switch (no access to the network, only connected nodes can communicate), a bridge (a tuntap device is created in the server itself that can forward packets to the main network stack) a simpe router/gateway (give access to each node to specific networks without allowing communication between nodes) or whatever you can think of. (The server is voluntary low-level to allow all the paradigms supported by the network stack).

Authentication/Authorization and Security

Authentication and Authorization is delegated to the proxy. We believe that battle-tested webservers (like nginx and apache) cover basically every authentication and security need, so there is no need to reimplement them.

By default only HTTPS access (eventually with client certificate authentication) should be allowed, but plain-http mode is permitted for easy debugging.

Virtualhosting

A vpn-ws client is required to send the Host header during the handshake and "should" support SNI. In this way virtualhosting can be easily managed by the proxy server.

Installation from sources

note: see below for binary packages

You need gnu make and a c compiler (clang, gcc, and mingw-gcc are supported).

The server has no external dependancies, while the client requires openssl (except for OSX and Windows where their native ssl/tls implementation is used)

Just run (remember to use 'gmake' on FreeBSD instead of 'make')

make

after having cloned the repository. If all goes well you will end with a binary named vpn-ws (the server) and another named vpn-ws-client (the client)

You can eventually build server or client selectively with

make vpn-ws
make vpn-ws-client

You can build a static binary version too of the server (where supported) with:

make vpn-ws-static

the resulting binary (vpn-ws) will have no library dependancies.

Binary packages

updated to [20141121]

Running the server

by default the server binary takes a single argument, the name of the socket to bind (the one to which the proxy will connect to):

./vpn-ws /run/vpn.sock

will bind to /run/vpn.sock

Now you only need to configure your webserver/proxy to route requests to /run/vpn.sock using the uwsgi protocol (see below)

Nginx

Nginx will be your "shield", managing the authentication/authorization phase. HTTPS + basicauth is strongly suggested, but best setup would be HTTPS + certificates authentication. You can run with plain HTTP and without auth, but please, do not do it, unless for testing ;)

You need to choose the location for which nginx will forward requests to the vpn-ws server:

(we use /vpn)

location /vpn {
  include uwsgi_params;
  uwsgi_pass unix:/run/vpn.sock;
}

this a setup without authentication, a better one (with basicauth) could be:

location /vpn {
  include uwsgi_params;
  uwsgi_pass unix:/run/vpn.sock;
  auth_basic "VPN";
  auth_basic_user_file /etc/nginx/.htpasswd;
}

where /etc/nginx/.htpasswd will be the file containing credentials (you can use the htpasswd tool to generate them)

The Official Client

The official client (vpn-ws-client) is a command line tool (written in C). Its syntax is pretty simple:

vpn-ws-client <tap> <server>

where 'tap' is a (platform-dependent) tap device path, and 'server' is the url of the nginx /vpn path (in the ws://|wss:// form)

Before using the client, you need to ensure you have some form of tun/tap implementation. Linux, FreeBSD and OpenBSD already have it out-of the box.

For OSX you need to install

http://sourceforge.net/projects/tuntaposx/files/tuntap/20141104

while on Windows (ensure to select utils too, when running the installer)

http://swupdate.openvpn.org/community/releases/tap-windows-9.9.2_3.exe

The client must be run as root/sudo (as it requires to create a network interface [TODO: drop privileges after having created the interface).

On linux (you can name devices as you want):

./vpn-ws-client vpn-ws0 wss://foo:[email protected]/vpn

On OSX (you have a fixed number of /dev/tapN devices you can use)

./vpn-ws-client /dev/tap0 wss://foo:[email protected]/vpn

On FreeBSD (you need to create the interface to access the device):

ifconfig tap0 create
./vpn-ws-client /dev/tap0 wss://foo:[email protected]/vpn

On windows (you need to create a tap device via the provided utility and assign it a name, like 'foobar')

./vpn-ws-client foobar wss://foo:[email protected]/vpn

Once your client is connected you can assign it an ip address (or make a dhcp request if one of the connected nodes has a running dhcp server)

The mode we are using now is the simple "switch" one, where nodes simply communicates between them like in a lan.

Server tap and Bridge mode

By default the server acts a simple switch, routing packets to connected peers based on the advertised mac address.

In addition to this mode you can give the vpn-ws server a virtual device too (with its mac address) to build complex setup.

To add a device to the vpn-ws server:

./vpn-ws --tuntap vpn0 /run/vpn.sock

the argument of tuntap is platform dependent (the same rules of clients apply).

The 'vpn0' interface is considered like connected nodes, so once you give it an ip address it will join the switch.

One of the use case you may want to follow is briding the vpn with your physical network (in the server). For building it you need the server to forward packets without a matching connected peers to the tuntap device. This is the bridge mode. To enable it add --bridge to the server command line:

./vpn-ws --bridge --tuntap vpn0 /run/vpn.sock

Now you can add 'vpn0' to a pre-existing network bridge:

# linux example
brctl addbr br0
brctl addif br0 eth0
brctl addif br0 vpn0

Client bridge-mode

This mode allows a client to act as a bridge giving access to its whole network to the vpn (and it clients).

Just add --bridge to the client command line and attach the tuntap device to a bridge.

The main problem is that you still need a route to the vpn server, so the best approach would be having two network interfaces on the client (one for the connection with the server, and the other for the physical bridge).

On linux, you can use the macvlan interface (it is basically a copy of a physical interface with a different mac address):

ip link add link eth0 name virt0 type macvlan
ifconfig virt0 0.0.0.0 promisc up
brctl addif br0 virt0
# add vpn-ws tuntap device to the bridge
ifconfig vpn17 0.0.0.0 promisc up
brctl addif br0 vpn17

The --exec trick

Both the server and client take an optional argument named '--exec '. This option will instruct the server/client to execute a command soon after the tuntap device is created.

As an example you may want to call ifconfig upon connection:

vpn-ws-client --exec "ifconfig vpn17 192.168.173.17 netmask 255.255.255.0" vpn17 wss://example.com/

or to add your server to a tuntap to an already existent bridge:

vpn-ws --exec "brctl addif br0 vpn0" --bridge --tuntap vpn0 /run/vpn.sock

You can chain multiple commands with ;

vpn-ws --exec "brctl addif br0 vpn0; ifconfig br0 192.168.173.30" --bridge --tuntap vpn0 /run/vpn.sock

Required permissions

The server, when no tuntap device is created, does not require specific permissions. If bound to a unix socket, it will give the 666 permission to the scket itself, in this way nginx (or whatever proxy you are using) will be able to connect to it.

If the server needs to create a tap device, root permissions are required. By the way you can drop privileges soon after the device is created (and the --exec option is eventually executed) with the --uid ang --gid options:

vpn-ws --tuntap vpn0 --uid www-data --gid www-data /run/vpn.sock

The client instead requires privileged operations (future releases may allow dropping privileges in the client too)

Client-certificate authentication

Your client can supply a certificate for authenticating to the server.

On OpenSSL-based clients (Linux, FreeBSD) you need a key file and a certificate in pem format:

vpn-ws-client --key foobar.key --crt foobar.crt vpn0 wss://example.com/vpn

On OSX you need to import a .p12 file (or whatever format it support) to the login keychain, then you need to specify the name of the certificate/identity via the --crt option (no --key is involved):

vpn-ws-client --crt "My certificate" /dev/tap0 wss://example.com/vpn

The JSON Control interface

The uwsgi protocol supports a raw form of channel selections using 2 bytes of its header. Thos bytes are called "modifiers". By setting the modifier1 to '1' (by default modifiers are set to 0) you will tell the vpn-ws server to show the JSON control interface. This is a simple way for monitoring the server and for kicking out clients.

When connectin to modifier1, a json blob with the data of all connected clients is shown. Passing a specific QUERY_STRING you can issue commands (currently only killing peers is implemented)

location /vpn {
  include uwsgi_params;
  uwsgi_pass unix:/run/vpn.sock;
  auth_basic "VPN";
  auth_basic_user_file /etc/nginx/.htpasswd;
}

location /vpn_admin {
  include uwsgi_params;
  uwsgi_modifier1 1;
  uwsgi_pass unix:/run/vpn.sock;
  auth_basic "VPN ADMIN";
  auth_basic_user_file /etc/nginx/.htpasswd;
}

You can now connect to /vpn_admin to see a json representation of connected clients. Each peer has an id. you can kick-out that peer/client adding a query string to the bar:

/vpn_admin?kill=n

where n is the id of the specific client.

If needed, more commands could be added in the future.

Example Clients

In the clients/ directory there are a bunch of clients you can run on your nodes or you can use as a base for developing more advanced ones.

Clients must run as root/sudo as they need to create/interact with tuntap devices

  • vpn_linux_tornado.py - a linux-only client based on tornado and ws4py
sudo pip install tornado ws4py python-pytun
sudo python clients/vpn_linux_tornado.py ws://your_server/
  • vpn.pl - more-or-less platform independent perl client (works with OSX and FreeBSD)
sudo cpanm AnyEvent::WebSocket::Client
sudo perl clients/vpn.pl /dev/tap0 ws://your_server/

As the official client you need to ensure a tuntap device implementation is available on the system

then (after having connected to the vpn server) you can assign the ip to it

Remember that we are at layer-2, so if you place a dhcp server on one of those nodes it will work as expected.

Multicast and Broadcast

They are both supported, (yes bonjour, mdns, samba will work !).

You can eventually turn off them selectively adding

  • --no-broadcast
  • --no-multicast

to the server command line

Tutorials

https://github.com/unbit/vpn-ws/blob/master/tutorials/ubuntu_trusty_nginx_bridge_client_certificates.md

Support

https://groups.google.com/d/forum/vpn-ws

(or drop a mail to info at unbit dot it for commercial support)

Twitter

(mainly for announces)

@unbit

Status/TODO/Working on

The server on windows is still a work in progress

The client on windows has no support for SSL/TLS

Grant support for NetBSD, and DragonflyBSD

Investigate solaris/smartos/omnios support

More Repositories

1

uwsgi

uWSGI application server container
C
3,459
star
2

uwsgi-docs

Official uWSGI docs, examples, tutorials, tips and tricks
Python
640
star
3

spockfs

SpockFS is an HTTP based network filesystem
C
307
star
4

foohid

OSX IOKit driver for implementing virtual HID devices (joypads, keyboards, mices, ...) from userspace
C++
264
star
5

django-uwsgi

Django related examples/trick/modules for uWSGI
Python
211
star
6

blastbeat

The BlastBeat server
C
159
star
7

uwsgi.it

The next-generation Unbit hosting platform
Python
77
star
8

uwsgi-docker

uWSGI plugin for integration with Docker
C
66
star
9

sftpclone

A tool for cloning/syncing a local directory tree with an SFTP server
Python
52
star
10

uwsgi-sentry

uWSGI plugin for sentry integration
C
49
star
11

uwsgi-realtime

a uWSGI plugin exposing offloaded realtime features like SSE, socket.io and media streaming
C
38
star
12

pysftpserver

An OpenSSH sftp wrapper in python
Python
36
star
13

uwsgi-consul

uWSGI plugin for consul integration
C
29
star
14

davvy

A Django application for building WebDAV services
Python
25
star
15

uwsgi-sse-offload

uWSGI offload bridge between redis pubsub and server sent events (sse)
C
23
star
16

librethinkdb

a c library for accessing rethinkdb servers
C
23
star
17

uwsgi-phpsgi

uWSGI experimental plugin for implementing a WSGI/PSGI/Rack-like interface for php
C
20
star
18

gitwhoosh

A git repository indexer (using whoosh as the engine)
Python
19
star
19

foohid-py

Python wrapper for the foohid OSX driver
C
18
star
20

spoolgore

A simple mail "spool and send" daemon written in Go
Go
14
star
21

uwsgi-rust

uWSGI and Rust integration plugin
Rust
13
star
22

uwsgi-pgnotify

Maps PostgreSQL notification system to uWSGI signal framework
C
11
star
23

unbit-bars

A Perl Curses::UI interface for uWSGI metrics subsystem
Perl
11
star
24

uwsgi-swift

uWSGI plugin for Apple Swift integration
Objective-C
10
star
25

uwsgi-bonjour

uWSGI plugin for OSX bonjour services integration
C
9
star
26

pydrone

run sandboxed javascript code in your python apps
C
8
star
27

uwsgi-capture

uWSGI plugin for accessing video capture devices
C
8
star
28

uwsgi-eventfd

uWSGI plugin for Linux eventfd() syscall integration
C
7
star
29

uwsgi-influxdb

uWSGI plugin for influxdb integration
C
7
star
30

uwsgi-wstcp

uWSGI plugin mapping websockets to tcp sockets
C
7
star
31

ulver

Unbit Lisp Version
C
7
star
32

uwsgi-node-rpc-server

A simple uwsgi-RPC server written in node.js
JavaScript
7
star
33

dockstrap

Like debootstrap but uses docker registry
Python
6
star
34

uwsgi-datadog

uWSGI plugin for datadog integration
C
6
star
35

uwebsocketconnection

an attempt to run websockets over uwsgi http router using gevent or uGreen
6
star
36

uwsgi-alarm-socket

uWSGI simple plugin for monitoring sockets
C
6
star
37

uwsgi-hetzner

A uWSGI legion action for managing hetzner's failover ip service
6
star
38

uwsgi-pushover

uWSGI plugin for sending pushover notifications (https://pushover.net/)
C
5
star
39

9spock

A high performance, featureful 9p fileserver for containers
5
star
40

uwsgi-apparmor

uWSGI integration with apparmor
C
4
star
41

uwsgi-riemann

uWSGI plugin for riemann integration
C
4
star
42

uwsgi-netlink

uWSGI plugin exposing netlink features
C
4
star
43

uwsgi-ganglia

uWSGI plugin for Ganglia integration
C
4
star
44

uwsgi-cares

uWSGI plugin for integration with the c-ares async dns library
C
3
star
45

uwsgi-gif

uWSGI plugin for dynamic generation of simple gif images
C
3
star
46

uwsgi-qtloop

Qt loop engine for uWSGI
C++
2
star
47

uwsgi-strophe

uWSGI plugin for libstrophe integration (xmpp)
C
2
star
48

uwsgi-java-servlet

experimental uWSGI plugin implementing java servlet 2.5
Java
2
star
49

unbit-docs

Documentazione per deployment su piattaforma Unbit
HTML
2
star
50

unbit.github.com

JavaScript
2
star
51

perl-net-uwsgi

perl module for easy interaction with uWSGI servers
Perl
2
star
52

uwsgi-alarm-chain

uWSGI plugin for mapping multiple alarms to a single event
C
2
star
53

aivengine

AIV Simple Game Engine for first year students
C#
2
star
54

pam-unbit

pam module for attaching to namespaced Emperors via setns()
C
1
star
55

moarvm-uwsgi-skel

A skel/base for building a uWSGI moarvm plugin aimed at NQP
C
1
star
56

uwsgi-opentsdb

uWSGI plugin for OpenTSDB integration
C
1
star
57

nss-unbit

nss module for the uwsgi.it service
C
1
star
58

uwsgi-quota

uWSGI plugin for UNIX quota integration
C
1
star
59

uwsgi-console-broadcast

uWSGI plugin exposing hooks for sending broadcast messages to terminals
C
1
star
60

blastbeat-gem

A Ruby module exporting a bunch of utility for integration with the BlastBeat server
Ruby
1
star
61

uwsgi-etcd

uWSGI plugin for etcd integration
1
star
62

uwsgicc

uWSGI Flask example app using the uwsgi api
Python
1
star