This project is a VPN-server, written in golang, using websockets as a transport. The idea is that multiple-nodes each connect to a central VPN-server, and once connected they can talk to each other securely, regardless of their location.
The following image illustrates the expected setup:
While it is possible to use this software to mask your laptop's IP while traveling, instead showing the IP of the VPN-server as being the source of connections that is not the expected use-case. (Nor is it documented!)
It should be noted that the VPN-server will become a single point of failure if you're using it to join (say) a database-host located at Hetzner with a number of webserver-nodes split between Linode and Digital Ocean, but being a simple service, easy to deploy, it should be trivial to spin up a replacement in a hurry.
There are two ways to install this project from source, which depend on the version of the go version you're using.
Alternatively you can download the latest release from our releases page if you're running upon AMD64-GNU/Linux host. (Unfortunately we use CGO
, and the water-library, which makes our code non-portable for now.)
If you're using go
before 1.11 then the following command should fetch/update the projectl and install it upon your system:
$ go get -u github.com/skx/simple-vpn
If you're using a more recent version of go
(which is highly recommended), you need to clone to a directory which is not present upon your GOPATH
:
git clone https://github.com/skx/simple-vpn
cd simple-vpn
go install
The VPN-server does not implement any kind of encryption itself, nor does it handle access-control beyond the use of a shared-secret. Is this insane? Actually no.
The expectation is that you'll host the VPN-server behind an nginx/apache proxy and you'll add TLS there (i.e. Let's Encrypt). Providing all the clients connect to the server over a TLS/SSL-protected socket then things are secure:
I believe this solution is "secure enough", but if you have concerns you can ensure that all the traffic you send over it uses TLS itself, for example database-connections can use TLS, etc.
Because traffic routed between two nodes on their private IP addresses has to be routed via the VPN-server expect to see approximately 50% overhead.
Configuring a VPN server requires two things:
simple-vpn
binary to be running in server-mode..
A minimal configuration file for using simple-vpn
in server-mode looks like this:
With your configuration-file you can now launch the VPN-server like so:
# simple-vpn server ./server.cfg
To proxy traffic to this server, via nginx
, you could have a configuration file like this:
server {
server_name vpn.example.com;
listen [::]:443 default ipv6only=off ssl;
ssl on;
ssl_certificate /etc/lets.encrypt/ssl/vpn.example.com.full;
ssl_certificate_key /etc/lets.encrypt/ssl/vpn.example.com.key;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
add_header Strict-Transport-Security "max-age=31536000";
proxy_buffering off;
proxy_buffer_size 128k;
proxy_buffers 100 128k;
## VPN server ..
location /vpn {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:9000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
proxy_connect_timeout 43200000;
tcp_nodelay on;
}
}
simple-vpn
.Install the binary upon the client hosts you wish to link, and launch them with the name of a configuration-file:
# simple-vpn client client.cfg
There is a sample client configuration file here:
The configuration file has two mandatory settings:
key
vpn
The server will assign each client which connects the next unused IP address from the range it is configured to serve.
Because each client identifies itself with the hostname of the local system it is possible to map static IP addresses to any remote host, which is useful if you wish to setup DNS entries, etc.
To setup a static IP see the commented-out sections in the server.cfg file.
This repository is configured to run tests upon every commit, and when pull-requests are created/updated. The testing is carried out via .github/run-tests.sh which is used by the github-action-tester action.
Releases are automated in a similar fashion via .github/build, and the github-action-publish-binaries action.