VPN

Contents

VPN#

A Virtual Private Network is a technology that creates a secure, encrypted connection over the internet, allowing a device to appear as if it is part of a private network. It enables users to securely access network resources and protect their online activity from eavesdropping, even when using public networks.

Minimal setup#

This section shows the simplest example of a VPN, it shows the ideas behind the definition of a Virtual Private Network. It is based on the Static Key Mini-HOWTO tutorial.

We will set up VPN server in a Docker container, connect to it from the host, and show what has happened to the host’s network configuration as a result.


The following cell starts the Docker container and installs the necessarry compoments.

docker run --name server -itd --name vpn_server --privileged --rm ubuntu:24.04
docker exec vpn_server bash -c "apt update && apt install -y openvpn" &> /dev/null
b12ef9318d36d1d29206d323c18d7dad21b83f36676c5f09edab733463687dc3

To start the openvpn server you need to create a config in the /usr/share/doc/openvpn/server.conf path and generate a key, in this case it would be static.key.

Note the ifconfig directive in the configuraion, it sets up the ip to the computers in the virtual network.

docker exec -i vpn_server tee /usr/share/doc/openvpn/server.conf > /dev/null << EOF
dev tun
ifconfig 10.8.0.1 10.8.0.2
secret static.key
cipher AES-256-CBC
EOF

docker exec vpn_server openvpn --genkey --secret static.key &> /dev/null

docker exec -d vpn_server openvpn /usr/share/doc/openvpn/server.conf &> /dev/null

Host is almost the same, but we’ll load a key generated in the sever.

container_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' vpn_server)
cat << EOF > /tmp/client.conf
remote ${container_ip}
dev tun
ifconfig 10.8.0.2 10.8.0.1
secret /tmp/static.key
cipher AES-256-CBC
EOF

docker cp vpn_server:/static.key /tmp/static.key

openvpn /tmp/client.conf &> /dev/null &
process_id=$!
Successfully copied 2.56kB to /tmp/static.key
[1] 20276

Finally, you can ping the address of the vpn server, in the virtual network, and it would work.

ping -c 5 10.8.0.1
PING 10.8.0.1 (10.8.0.1): 56 data bytes
64 bytes from 10.8.0.1: seq=0 ttl=64 time=0.386 ms
64 bytes from 10.8.0.1: seq=1 ttl=64 time=0.921 ms
64 bytes from 10.8.0.1: seq=2 ttl=64 time=0.898 ms
64 bytes from 10.8.0.1: seq=3 ttl=64 time=0.912 ms
64 bytes from 10.8.0.1: seq=4 ttl=64 time=1.024 ms

--- 10.8.0.1 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.386/0.828/1.024 ms

Note that a new network interface has appeared in the client configuration - it organises interaction with the virtual network.

ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 1e:9d:ec:67:b4:c4 brd ff:ff:ff:ff:ff:ff link-netnsid 0
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 02:42:af:62:f0:42 brd ff:ff:ff:ff:ff:ff
19: vethac27a55@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default 
    link/ether 5a:81:82:16:7c:f9 brd ff:ff:ff:ff:ff:ff link-netnsid 1
20: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN mode DEFAULT group default qlen 500
    link/none 
kill $process_id
docker stop vpn_server
vpn_server
[1]+  Done                    openvpn /tmp/client.conf &> /dev/null