badvpn(7)

πŸ“¦ version 1.999.130, in arch rolling, fedora 43, nixos 26.05, nixpkgs unstable

✨ badvpn(7) β€” BadVPN, the peer-to-peer VPN system ✨

okay so welcome to the badvpn(7) page from the Miscellaneous Information Manual, bestie β€” this is BadVPN, and we're about to get you fully caught up on what it is and what it does. πŸ’–

πŸ’– NAME πŸ’–

BadVPN β€” peer-to-peer VPN system.

🌸 DESCRIPTION 🌸

BadVPN is a peer-to-peer VPN system. It provides a Layer 2 (Ethernet) network between the peers (VPN network nodes). The peers connect to a central server which acts as a chat server for them to establish direct connections between each other (data connections). These connections are used for transferring network data (Ethernet frames). Periodt.

✨ Features ✨

πŸ¦‹ Data connections πŸ¦‹

Peers can transfer network data either over UDP or TCP. For both there are ways of securing the data (see below). iykyk.

🌈 IPv6 support 🌈

IPv6 can be used for both server connections and data connections, alongside IPv4. Additionally, both can be combined to allow gradual migration to IPv6. Slay.

πŸŽ€ Address selection πŸŽ€

Because NATs and firewalls are widespread, it is harder for peer-to-peer services to operate. In general, for two computers to be able to communicate, one computer must bind to one of its addresses, and the other computer must connect to the computer that binded (both for TCP and UDP). In a network with point-to-point connectivity, the connecting computer can connect to the same address as the binding computer bound to, so it is sufficient for the binding computer to send its address to the connecting computer. However, NATs and firewalls break point-to-point connectivity. When a network is behind a NAT, it is, by default, impossible for computers outside of that network to connect to computers inside the network. This is because computers inside the network have no externally visible IP address, and only communicate with the outside world through the external IP address of the NAT router. It is however possible to manually configure the NAT router to forward a specific port number on its external IP address to a specific computer inside the network. This makes it possible for a computer outside of the network to connect to a computer inside a network, however, it must connect to the external address of the NAT router (rather than the address the computer inside bound to, which is its internal address). So there needs to be some way for the connecting peer to know what address to connect to.

BadVPN solves this problem with so-called address scopes. The peer that binds must have a list of external addresses for each address it can bind to, possibly ordered from best to worst. Each external address has its scope name. A scope name represents part of a network from which an external address can be reached. On the other hand, the peer that connects must have a list of scopes which it can reach. When a peer binds to an address, it sends the other peer a list of external addresses along with scope names. That peer then chooses the first external address whose scope it recognizes and attempts to connect to it (if there is one).

BadVPN also allows a peer to have multiple addresses for binding to. It is possible to specify both an IPv4 and an IPv6 address to work in a multi-protocol environment.

πŸ’… Relaying πŸ’…

BadVPN can be configured to allow pairs of peers that cannot communicate directly (i.e. because of NATs or firewalls) to relay network data through a third peer. Relaying is only attempted if none of the two peers recognize any of the other peer's external addresses (or there are none). For relaying to work, for each of the two peers (P1, other one P2) there must be at least one third peer (R) that P1 is allowed to relay through and can communicate directly with, and all such peers R must be able to communicate directly with P2.

πŸ“ IGMP snooping πŸ“

BadVPN nodes perform IGMP snooping in order to efficiently deliver multicast frames. For example, this makes it possible to use BadVPN as a tunnel into an IPTV network of an Internet Service Provider for you to watch TV from wherever you want (given sufficient link quality). Not me watching TV from anywhere, iconic.

🧚 Code quality 🧚

BadVPN has great focus on code quality and reliability. BadVPN is written in the C programming language. It is a single-threaded event-driven program. This allows for low resource usage and fast response times. Even though C is a relatively low-level language, the programs are made of small, highly cohesive and loosely coupled modules that are combined into a complete program on a high level. Modules are accessed and communicate through small, simple and to-the-point interfaces. It utilizes a flow-based design which greatly simplifies processing of data and input and output of the programs.

πŸ”’ Security features πŸ”’

BadVPN contains many security features, all of which are optional. The included security features are described here.

πŸ” TLS for client-server connections πŸ”

It is possible for the peers to communicate with the chat server securely with TLS. It is highly recommended that this feature is used if any security whatsoever is needed. Not using it renders all other security features useless, since clients exchange keys unencrypted via the server. When enabled, the chat server requires each client to identify itself with a certificate.

BadVPN uses Mozilla's NSS library for TLS support. This means that the required certificates and keys must be available in a NSS database. The database and certificates can be generated with the certutil command. See the examples section on how to generate and distribute the certificates.

πŸ’¬ TLS for peer messaging πŸ’¬

If TLS is being used for client-server connections, it will also be used between each pair of peers communicating via the server, on top of the TLS connections to the server. This secures the messages from the server itself. It is important because the messages may include encryption keys and other private data.

πŸ”₯ TLS for TCP data connections πŸ”₯

If TCP is used for data connections between the peers, the data connections can be secured with TLS. This requires using TLS for client-server connections. The clients need to trust each others' certificates to be able to connect. Additionally, each client must identify to its peers with the same certificates it used for connecting to the server.

🫢 Encryption for UDP data connections 🫢

If UDP is used for data connections, it is possible for each pair of peers to encrypt their UDP packets with a symmetric block cipher. Note that the encryption keys are transmitted through the server unencrypted, so for this to be useful, server connections must be secured with TLS. The encryption aims to prevent third parties from seeing the real contents of the network data being transferred.

⭐ Hashes for UDP data connections ⭐

If UDP is used for data connections, it is possible to include hashes in packets. Note that hashes are only useful together with encryption. If enabled, the hash is calculated on the packet with the hash field zeroed and then written to the hash field. Hashes are calculated and included before encryption (if enabled). Combined with encryption, hashes aim to prevent third parties from tampering with the packets and injecting them into the network.

πŸ’€ One-time passwords for UDP data connections πŸ’€

If UDP is used for data connections, it is possible to include one-time passwords in packets. Note that for this to be useful, server connections must be secured with TLS. One-time passwords are generated from a seed value by encrypting zero data with a block cipher. The seed contains the encryption key for the block cipher and the initialization vector. Only a fixed number of passwords are used from a single seed. The peers exchange seeds through the server. One-time passwords aim to prevent replay attacks.

πŸ‘‘ Control over peer communication πŸ‘‘

It is possible to instruct the chat server to only allow certain peers to communicate. This will break end-to-end connectivity in the virtual network. It is useful in certain cases to improve security, for example when the VPN is used only to allow clients to securely connect to a central service.

Setting up certificates πŸ’–

If you want to use TLS for server connections (which β€” bestie β€” is highly recommended ✨), then the server and all the peers are gonna need certificates. This section is the whole glow-up routine: how to generate and distribute them using NSS command line tools. πŸŽ€

Setting up the Certificate Authority (CA) πŸ‘‘

On the system that's gonna host the CA, you first make a NSS database for the CA, then generate a CA certificate that's valid for 24 months:

vpnca $ certutil -d sql:/home/vpnca/nssdb -N
vpnca $ certutil -d sql:/home/vpnca/nssdb -S -n "vpnca" -s "CN=vpnca" -t
"TC,," -x -2 -v 24
> Is this a CA certificate [y/N]? y
> Enter the path length constraint, enter to skip [<0 for unlimited
path]: > -1
> Is this a critical extension [y/N]? n

Now export the public CA certificate β€” and fr fr, this file is public, so it's the one you can show off to everyone πŸ’…:

vpnca $ certutil -d sql:/home/vpnca/nssdb -L -n vpnca -a > ca.pem

Setting up the server certificate πŸ–₯️✨

Still on the CA system, generate a certificate for the server, valid for 24 months, with TLS server usage context:

vpnca $ certutil -d sql:/home/vpnca/nssdb -S -n "<insert_server_name>"
-s "CN=<insert_server_name>" -c "vpnca" -t ",," -2 -6 -v 24
> 0
> -1
> Is this a critical extension [y/N]? n
> Is this a CA certificate [y/N]? n
> Enter the path length constraint, enter to skip [<0 for unlimited
path]: >
> Is this a critical extension [y/N]? n

Then export the server certificate into a PKCS#12 file. 🫢

🚨 This file must be kept secret. Like, do not post it. It's not a story, it's a credential.
vpnca $ pk12util -d sql:/home/vpnca/nssdb -o server.p12 -n
"<insert_server_name>"

Okay so now hop over to the system that's actually gonna run the server: create a NSS database there and import the CA certificate plus the server cerificate:

vpnserver $ certutil -d sql:/home/vpnserver/nssdb -N
vpnserver $ certutil -d sql:/home/vpnserver/nssdb -A -t "CT,," -n
"vpnca" -i /path/to/ca.pem
vpnserver $ pk12util -d sql:/home/vpnserver/nssdb -i /path/to/server.p12

Setting up peer certificates πŸ¦‹

Back on the CA system again πŸ’« β€” generate a certificate for the peer, valid for 24 months, with both TLS client and TLS server usage contexts:

vpnca $ certutil -d sql:/home/vpnca/nssdb -S -n "peer-<insert_name>" -s
"CN=peer-<insert_name>" -c "vpnca" -t ",," -2 -6 -v 24
> 0
> 1
> -1
> Is this a critical extension [y/N]? n
> Is this a CA certificate [y/N]? n
> Enter the path length constraint, enter to skip [<0 for unlimited
path]: >
> Is this a critical extension [y/N]? n

Export the peer certificate to a PKCS#12 file too:

🚨 Again: this file must be kept secret. Not me stressing this twice but it literally says so. 😭
vpnca $ pk12util -d sql:/home/vpnca/nssdb -o peer-<insert_name>.p12 -n
"peer-<insert_name>"

And finally, on the system that's gonna run the VPN client, create a NSS database and import the CA certificate and the peer cerificate:

vpnclient $ certutil -d sql:/home/vpnclient/nssdb -N
vpnclient $ certutil -d sql:/home/vpnclient/nssdb -A -t "CT,," -n
"vpnca" -i /path/to/ca.pem
vpnclient $ pk12util -d sql:/home/vpnclient/nssdb -i
/path/to/peer-<insert_name>.p12

Setting up TAP devices πŸŽ€

You need to create and configure TAP devices on all the computers that are gonna participate in the virtual network β€” that means every machine running the client program. See badvpn-client(8), section TAP DEVICE CONFIGURATION for all the deets. πŸ‘‘


Example: Local IPv4 network, UDP transport, zero security πŸ’€

Yes bestie, zero security. We're starting with the unhinged version so you can see the shape of it. 🌈

Starting the server:

badvpn-server --listen-addr 0.0.0.0:7000

Starting the peers:

badvpn-client
       --server-addr <insert_server_local_address>:7000
       --transport-mode udp --encryption-mode none --hash-mode none
       --scope local1
       --bind-addr 0.0.0.0:8000 --num-ports 30 --ext-addr
       {server_reported}:8000 local1
       --tapdev tap0

Example: Adding TLS and UDP security πŸ”₯πŸ”’

Now we're adding the glow-up: TLS and UDP security. Iconic.

Starting the server (other options as above):

badvpn-server ...
       --ssl --nssdb sql:/home/vpnserver/nssdb --server-cert-name
       "<insert_server_name>"

Starting the peers (other options as above):

badvpn-client ...
       --ssl --nssdb sql:/home/vpnclient/nssdb --client-cert-name
       "peer-<insert_name>"
       --encryption-mode blowfish --hash-mode md5 --otp blowfish 3000
       2000

Example: Multiple local networks behind NATs, all connected to the Internet πŸŒπŸ¦‹

For each peer in the existing local network, configure the NAT router to forward its range of ports to it β€” assuming their port ranges don't overlap, obviously. πŸ’… The clients also need to know the external IP address of the NAT router. If you don't have a static one, you'll need to discover it before starting the clients. Also forward the server port to the server. No skipping steps, bestie.

Starting the peers in the local network (other options as above):

badvpn-client
       ...
       --scope internet
       ...
       --ext-addr
       <insert_NAT_routers_external_IP>:<insert_start_of_forwarded_port_range>
       internet
       ...

The --ext-addr option applies to the previously specified --bind-addr option, and must come after the first --ext-addr option which specifies a local address. Order matters here, periodt. ✨

Now go do a similar setup in some other local network behind a NAT. But, and this is important:

  • Don't set up a new server β€” instead, make the peers connect to the existing server in the first local network. πŸ”—
  • You can't use {server_reported} for the local address --ext-addr options, because the server would report the NAT router's external address rather than the peer's internal address. Instead, each peer has to know its internal IP address. πŸ™ˆ
  • Use a different scope name for it, e.g. "local2" instead of "local1". 🏷️

If setup correctly, all peers will be able to communicate: those in the same local network will communicate directly through local addresses, and those in different local networks will communicate through the Internet. πŸŽ‰


🌈 PROTOCOL 🌈

The protocols used in BadVPN are described in the source code in the protocol/ directory. That's it, that's the section β€” go read the source, iykyk. πŸ‘‘


πŸ’œ SEE ALSO πŸ’œ


πŸ‘‘ AUTHORS πŸ‘‘

Ambroz Bizjak <ambrop7@gmail.com>


And that's the whole page, bestie! 🫢 This was badvpn(7), dated 6 October 2010 β€” shoutout to the source and version line for holding it down at the bottom of the page. Go set up some tunnels, you've got this. πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from