Security of VpnCloud
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
sysctl
options if you don't know what you are doing
Programming Language
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.
Since version 1.5 VpnCloud is 100% Rust code. That means that all of VpnCloud is guarded by the strong safety guarantees of the Rust language.
"Unsafe" code in VpnCloud
VpnCloud contains a few instances of the "unsafe" keyword to
- to set up and manage virtual interfaces using libc
- use the Epoll methods of libc
- to call a libc method to get the current time (which is faster than via Rust)
Those calls have been reviewed multiple times by me and I consider them safe.
Encryption
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.
In the initialization of a connection, both peers perform a handshake. The messages of the handshake are authenticated so that the receiver can verify the integrity of the message and detect any manipulation or forgery. During the handshake, both peers negotiate an encryption method and common key material. Also they exchange initial peer information for the VpnCloud protocol.
The connection initialization can only be performed by a peer using a key that is listed in the trusted keys of the receiver. Any forgery or tempering is automatically detected and the initialization is aborted. Also all sensitive information in the handshake is already encrypted.
VpnCloud supports 3 different encryption methods: ChaCha20 combined with Poly1305 (see RFC7539) and AES128 and AES256 in GCM mode. All 3 methods are very efficient (with AES128 and 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.
The encryption always affects the whole message (including the VPN payload, if any), except a small header containing a message number. All supported encryption algorithms take a 96 bit nonce, that is initialized with a random value 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. The encryption algorithms calculate a 128 bit tag, that is automatically appended to the message and protects it from alteration.
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. However, VpnCloud contains a protection against replay attacks, that automatically detects and rejects old packets.
The encryption is based on key material that is negotiated on each connection and rotated frequently. The keys that are used are ephemeral (i.e. short-lived, never transmitted nor stored anywhere), in order to provide perfect forward secrecy.
The peer authentication is based on elliptic curve key pairs based on Curve25519. Users can either specify the key pair explicitly 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 pair is never transmitted over the network.
Plain encryption
VpnCloud also supports disabling encryption as an explicit opt-out. If two peers both allow unencrypted connections, their connection will be unencrypted. That means, that they still carry out a handshake with full authentication but then downgrade to an unencrypted connection for the rest of the communication.
In this case all payload as well as any protocol messages can be read and even manipulated by the network. Please note that this also includes information about all other connections of a node (even if those connections are encrypted).
Please only enable this setting if you are aware of all the consequences and are in control of the network between the two nodes.
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 --no-port-forwarding
switch.
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.
Attack Scenarios
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
In order to establish a new connection with any node of the VPN, the attacker would have to perform a connection initialization with any of the nodes. Since this initialization is protected by the elliptic key pairs, this requires either breaking the elliptic encryption algorithm or guessing the private key of one peer, both of which is practically impossible.
The attacker could also try to inject data into an existing connection by manipulating the source address. If the connection is encrypted, the attacker must either break the used encryption algorithm, guess the current ephemeral key or guess the correct authentication tag, all of which is practically impossible.
If the VPN is unencrypted, the attacker can inject data into the connection:
- The attacker can send payload data to the node but not receive a reply.
- The attacker can send a peer list to the node and lead it to initiate a connection with any chosen address. Those connection initializations will still have to be authenticated properly, otherwise they will fail.
- The attacker can terminate the running connection which will cause a short disruption and trigger a reconnect.
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 within a short period of time (i.e. 1-2 seconds). The VpnCloud protocol is resistant to those attacks, as those are effects that also happen in the Internet by chance.
The attacker can not take a message sent by one peer and instead send it using the address of a different peer. This is prevented by the per-connection encryption.
If connections in the VPN are not encrypted, the attacker can read all the payload data and see the inner communication of those connections. 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).
Scenario 3: Attack by a peer
Attacker capabilities & knowledge: The attacker is part of the VPN as a peer. This includes knowledge of one trusted private key and the current encryption key (if any) of at least one connection.
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. Please see CVE-2019-14899 for a common misconfiguration that affects this setting.
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.
Security History
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 measures were taken to avoid similar bugs in the future.
No other security related issues have been reported or observed.