Security of VpnCloud
Note: This page refers to VpnCloud version 1.x and has not yet been adapted to version 2.x.
This page will explain the security concepts of VpnCloud. This should serve two purposes:
- It should give users a good idea of how secure VpnCloud is
- It should simplify the process of auditing the software However, this is not a formal review or security audit of the software.
TL;DR: VpnCloud should be pretty secure if you
- use a strong key for encryption
- only add trusted nodes to the VPN
- don't mess with
sysctloptions if you don't know what you are doing
Before diving into how the code is written, let's first take a look into what language it is written in. VpnCloud is written in the Rust programming language, which has been invented by Mozilla to be both efficient and secure - properties, that I wanted for VpnCloud. While Rust programs achieve similar performance to programs written in C or C++, the language is fundamentally more secure. Rust has strong guarantees for memory safety. As long as there is no bug in the compiler, programs written in Rust should be free from most memory-related security problems that are well known from C and C++.
Since the safety guarantees of Rust come with some restrictions, sometimes one needs to circumvent those restrictions. Rust has a built-in mechanism to do so: "unsafe" code. Rust allows developers to write code that Rust can not guarantee to be safe and mark that code as unsafe. Whenever this code is called, the caller must make sure that the usage is actually safe and wrap the call in an unsafe block. This mechanism allows developers to combine automatic safety guarantees of the language with manually-checked code.
C code in VpnCloud
The code of VpnCloud is 99.9% Rust. However, setting up the virtual networking devices is something, that requires system calls that are not available in Rust (as time of writing). Therefore this code had to be written in C. The C code is 27 lines, of which half are comments, empty lines and includes. None of that code is dealing with memory allocation or using pointer arithmetic, the two main sources of security related bugs in C.
"Unsafe" code in VpnCloud
VpnCloud contains 7 instances (as of writing) of the "unsafe" keyword:
- 2 blocks are used to call the C code to set up virtual interfaces
- 4 blocks are required to call the Epoll methods of libc
- 1 block is used to call a libc method to get the current time (which is faster than via Rust)
Those blocks have been reviewed multiple times by me and I consider them safe.
The "magic header" is a 4 byte sequence right at the start of each message that is used to identify packets of the same network and sort out stray packets. While it is not primarily a security feature, it also provides some security.
Users can set this 4 bytes to any value they like (even have them derived from a hash function). Packets with the wrong magic header are sorted out at the earliest possible stage in packet parsing and do not reach any further logic. The attack surface is therefore minimized.
VpnCloud uses the library ring to provide encryption. Ring is written in Rust but also contains lots of hand-written assembler code for performance reasons. The library provides low-level cryptographic methods that are used in VpnCloud to encrypt protocol and payload data.
VpnCloud offers two different encryption methods: ChaCha20 combined with Poly1305 (see RFC7539) and AES256 in GCM mode. Both methods are very efficient (with AES256 even being accelerated by modern CPUs) and widely considered secure. The usage of the methods to encrypt and decrypt messages is the same regardless of the method used.
Although VpnCloud supports two encryption methods, there is no negotiation of encryption methods. The method to be used is configured statically and all messages with the wrong method in the header are dropped automatically.
The encryption always affects the whole message (including the VPN payload, if any), except a small header containing the magic header, the encryption method and the message type. This header is included in the encryption as additional data (see AEAD) and is therefore protected against modification.
The encryption works in a single message mode. Each message is encrypted and decrypted on its own without relation to previous messages. Any scheme that relates message encryption to earlier messages would be more complex as messages could be lost, duplicated or reordered during transmission.
Both encryption algorithms take a 96 bit nonce, that is randomly selected on VpnCloud startup and incremented each time when encrypting a message. The nonce is added to the message in front of the encrypted data and sent along in the message. Both encryption algorithms calculate a 128 bit tag, that is automatically appended to the message and protects it from alteration.
The encryption is based on a shared key (of 256 bits for both methods). Users can either specify the key directly as hexadecimal or have it derived from a passphrase. When deriving the key from a passphrase, VpnCloud uses PBKDF2_HMAC_SHA256 with 4096 iterations and a salt unique to VpnCloud. The key is never transmitted over the network.
Port Forwarding and NAT Routers
Most NAT routers allow nodes inside the NAT to request ports on the public IP address to be redirected to a port on an internal IP address (the ports do not have to be the same). Otherwise most NAT routers only assign ephemeral ports during address translation and only keep them open for a certain IP (or IP range) for limited time in order to receive a reply.
In order for VpnCloud to connect nodes behind NAT routers reliably, it supports establishing port forwardings using the IGD Protocol. A VpnCloud instance will first detect a NAT router and then request the forwarding of a port to its address. After receiving the port forwarding grant, the instance will periodically extend the grant to keep the port open. This default behavior can be disabled using the
Since the IGD protocol is relatively complex and requires supporting the HTTP protocol it opens up a bigger attack surface. Although also the library used for the IGD protocol is written in Rust and therefore less likely to have critical bugs, users that do not trust their network router, should disable this feature.
In general, nodes inside the NAT can not be reached directly by nodes on the Internet. By using a VPN, this restriction can be overcome, so that specific nodes can reach the nodes inside the NAT. Users should be aware that the NAT provides a layer of security that the VPN circumvents. Using the VPN, specific nodes inside the NAT can now be reached by specific nodes from the Internet, which opens them up to attacks from those nodes.
The following scenarios explain the security concepts and attack vectors in different situations with the attacker having different knowledge and capabilities matching some common scenarios.
Scenario 1: Ordinary attacks from the internet
** Attacker capabilities & knowledge: ** The attacker can send packets to at least one peer of a VPN
If the VPN setup includes a non-standard magic header, the attacker would have to guess the correct magic header in order to get past the very first stage of packet parsing. While it is possible to guess the 4-byte value via brute force, it still takes some time depending on the network connectivity, considering that each value has to be tested by a separate UDP packet that could potentially get lost if the sending rate is too high.
Since packets with a wrong magic header are dropped very early, this also serves as a protection against denial-of-service attacks. Of course it is still possible to execute denial-of-service attacks by simply overflowing the whole node on a network level.
If the VPN is encrypted, all packets are protected using a 16 byte tag that is practically impossible to guess. Any packets with a wrong tag are sorted out at an early stage of packet parsing and do not reach the main parsing logic. If the VPN has a non-standard magic header and is encrypted, the attacker has to guess both the magic header and the tag at the same time in order to get a reply that confirms his magic header guess was correct. Only packets with a correct magic header even reach the decryption stage.
If the VPN has the standard magic header and is not encrypted, there is nothing that stops the attacker from joining the VPN as a peer:
- The attacker will learn the addresses of all other peers.
- The attacker can send payload packets and communicate with services within the VPN.
- The attacker will be able to perform attacks as a peer (see scenario 3).
Scenario 2: Attack by the network
** Attacker capabilities & knowledge: ** The attacker can manipulate the whole network traffic, i.e.
- Reading all packets sent by some peers
- Suppressing and delaying packets
- Manipulating packets
- Forging packets and sending them using the address of a peer
Being able to suppress packets of peers, the attacker is able to remove peers from the VPN by suppressing all of their packets. Also the attacker can execute a denial of service by dropping all or some selected packets of the VPN. The attacker can also split the network into two or more networks by dropping all packets between the peers of different split networks.
If the VPN is encrypted, the attacker is not able to read the communication within the network without breaking the encryption or guessing the encryption key. Also the attacker can not send or manipulate data within the VPN as the encryption contains tags that prevent forging or manipulation of messages. Since the encryption is based on single messages, the attacker can suppress, delay, and duplicate messages.
- The VpnCloud protocol is resistant to those attacks, as those are effects that also happen in the Internet by chance.
- The attacker can potentially execute replay attacks on the communication inside the VPN. This is however complicated as the attacker can not read the encrypted payload. TCP based protocols are protected by their random initial sequence numbers. To run a successful replay attack, the attacker would have to repeat the attack until the communication partner randomly chooses the same initial sequence number as in the recorded communication.
The attacker can take a message sent by one peer and instead send it using the address of a different peer. This way, the attacker can manipulate the forwarding logic of the VPN if it is configured to learn addresses. The attacker can use this to redirect traffic from one peer to a different peer.
If the VPN is not encrypted, the attacker can read all the payload data and see the inner communication in the VPN. It can also manipulate the payload, or forge payload packets and send them using any source address.
- The network within the VPN then should be considered as insecure. Depending on the protocols spoken inside the VPN, this might or might not be a security problem. A lot of protocols like SSL encrypted ones (e.g. HTTPS and SSH) do not trust the network anyways and can be used securely over an insecure network.
- The attacker also is able to communicate inside the VPN like a peer, even without actually joining as a peer (see scenario 3).
- The attacker can carry out replay attacks on the communication within the VPN, with full knowledge of the payload.
Scenario 3: Attack by a peer
** Attacker capabilities & knowledge: ** The attacker is part of the VPN as a peer. This includes knowledge of the magic header and the encryption key (if any).
The attacker will learn the addresses of all other peers (by the peer list exchange) and the addresses used within the VPN (either by IP claims of the peers or by listening to the ARP protocol). This information can be used for further attacks on peers and their provided services.
Being a peer, the attacker can send VpnCloud protocol messages to other nodes. In this case, the attack surface is the whole packet forwarding and message parsing code in VpnCloud. However, this code has been written with security in mind in a language that is built to provide safety guarantees. Thus, the likelihood of there being a bug that allows the attacker to send specially crafted VpnCloud messages to execute arbitrary code on the peer is very very low. Nevertheless, VpnCloud supports parameters to drop privileges after setting up the interface and to run as a unprivileged user from there on. The service definition of VpnCloud restricts the service even further, e.g. disallowing most filesystem accesses.
Using the VpnCloud protocol, the attacker can claim any address within the VPN and if necessary steal that address from another peer. The attacker can redirect selected traffic within the VPN to itself.
- The attacker can use this to get access to services that are not available to the public.
- The attacker can take over addresses in order to trick clients to send credentials to the attacker instead of the proper server. Since this is a very common attack, most protocols add additional security like SSL certificates or challenge response mechanisms when submitting credentials.
- The attacker could try to take over an established TCP connection but this requires guessing the TCP sequence number.
The attacker can send forged packets within the VPN with any source IP address. This is not restricted to addresses within in VPN network. Under default settings, Linux filters out any packets received on a networking interface with a source address that would not be routed via that interface. This behavior is called "reverse path filtering" and can be disabled by the "rp_filter" option of the interface. If this setting is disabled at a node, packets with forged source addresses ("martian packets") can be sent by the attacker.
The attacker can send packets to peers with any destination IP address. Under default settings, Linux will not forward packets with destination addresses that do not belong to the node. This behavior can be changed by the "ip_forward" option of a network interface. If enabled, the node will forward packets with any destination address to that address via routing. The attacker can use this to reach and attack addresses via the peer that it could not reach directly. In most cases however, the attacker will not be able to receive replies from the destination as that would require additional routing settings at the destination.
Some of those attacks could be prevented by applying iptables rules to the virtual interfaces that restrict communication based on IP address ranges. Also VpnCloud nodes should only change the default interface options if necessary.
Since the start of the project in 2015, VpnCloud had only one security related issue. The problematic code was pushed to the codebase but removed 2 days later before the next release, so no release version was affected. Nevertheless a security announcement was issued and meassures were taken to avoid similar bugs in the future.
No other security related issues have been reported or observed.