OpenVPN

Das EPEL-Repo stellt für gewöhnlich eine sehr aktuelle OpenVPN-Version bereit.

OpenVPN ist nicht multi-threaded. Damit ist die maximale Bandbreite durch die Leistungsfähigkeit eines CPU-Cores begrenzt.

Die Systemd-Unit-Files erwarten, dass die (Server-)Konfigurationsdateien auf .conf statt auf .ovpn enden. Beispielkonfigurationen für OpenVPN finden sich in /usr/share/doc/openvpn*.

OpenVPN-Client installieren und konfigurieren

Eine zum hier gezeigten Server passende Konfigurationsdatei:

auth SHA384
auth-nocache
client
data-ciphers-fallback AES-256-GCM
dev tun98
keepalive 10 60
nobind
persist-key
persist-tun
pkcs12 /etc/openvpn/myself.p12 # use double slashes on Windows clients, for example c://path//to//myself.p12
proto udp
remote vpn.example.com 12345
remote-cert-tls server
tls-cipher TLS-RSA-WITH-AES-256-GCM-SHA384:TLS-RSA-WITH-AES-256-CBC-SHA256:TLS-RSA-WITH-AES-256-CBC-SHA
tls-version-min 1.2
verb 1
verify-x509-name vpn.example.com name

Client unter RHEL installieren und starten:

# from EPEL-Repository
dnf -y install openvpn
openvpn --config /etc/openvpn/client.ovpn &

Client unter Windows:

Client unter Apple macOS:

OpenVPN-Server installieren und konfigurieren

IP-Forwarding aktivieren:

echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p

Dann:

# from EPEL-Repository
dnf -y install openvpn

Diffie Hellmann-Parameter erstellen:

openssl dhparam -out /etc/openvpn/dh4096.pem 4096
chmod 0400 /etc/openvpn/server/server.p12

Auf gehärteten Maschinen (z.B. CIS), oder bei Erscheinen der Fehlermeldung „RTNETLINK answers: Operation not permitted“ im openvpn.log:

cat > /etc/sudoers.d/openvpn << EOF
openvpn ALL=(ALL) NOPASSWD: /sbin/ip
Defaults:openvpn !requiretty
EOF

Konfiguration eines OpenVPN-Servers, der auf Port 12345 hört, ein VPN-Netz „192.0.2.0“ anbietet, und dieses ins interne Netz „10.80.109.0“ routet:

/etc/openvpn/server/server.conf
auth SHA384
cipher AES-256-GCM
# crl file (or directory) is read every time a peer connects,
# and it has to contain at least one item
#crl-verify /etc/openvpn/server/crl.pem
#client-config-dir /etc/openvpn/ccd
daemon
dev tun
dh /etc/openvpn/dh4096.pem
#duplicate-cn
group openvpn
keepalive 10 60
log-append /var/log/openvpn.log
persist-key
persist-tun
pkcs12 /etc/openvpn/server/server.p12
port 12345
proto udp

push "route 10.80.109.0 255.255.255.0"
server 192.0.2.0 255.255.255.0

status /var/log/openvpn-status.log
syslog
tls-cipher TLS-RSA-WITH-AES-256-GCM-SHA384:TLS-RSA-WITH-AES-256-CBC-SHA256:TLS-RSA-WITH-AES-256-CBC-SHA
tls-server
tls-version-min 1.2
topology subnet
user openvpn
verb 4
semanage port -a -t openvpn_port_t -p udp 12345

OpenVPN-Server starten:

# if config file is named "linuxfabrik.conf", run "...@linuxfabrik":
systemctl enable --now openvpn-server@server

Eine Firewall muss, wenn sie Regeln auf das VPN-Interface anwenden möchte, auf dieses beim Hochfahren warten. Ausserhalb von Systemd lässt sich das so umsetzen:

### Wait for OpenVPN interface ###
device="tun0"
t=60

while [[ $t -gt 0 ]]; do
    if [[ $(ip link show $device 2> /dev/null) ]]; then
        break
    else
        ((t-=1));
        sleep 1;
    fi
done

if [[ $t -le 0 ]]; then
    echo "Cannot find $device."
    logger "Cannot find $device."
    exit 1;
fi

echo "$device found."
logger "$device found."

Logrotate:

cat >/etc/logrotate.d/openvpn << EOF
/var/log/openvpn.log {
    # The log is kept open *even if* I send a
    # SIGUSR1 or SIGHUP signal to the OpenVPN process.
    # Also, if I move away the logfile it is never
    # recreated, just because the
    # daemon keeps writing on the renamed file.
    # The copytruncate fixes this.
    compress
    copytruncate
    daily
    dateext
    missingok
    rotate 14
    size 1
}
EOF

Clients fixe IP zuweisen (CCD)

Auf einem Server mit gesetzter Client Config Dir-Option (CCD) hat es sich bewährt, die CCDs von hinten anfangen zu lassen, damit der IP-Adresspool (Angabe server) sich nicht so schnell mit den statischen IPs aus ccd überschneidet. Die Dateinamen im ccd-Verzeichnis müssen denen des CommonName im Client-Zertifkat entsprechen.

/etc/openvpn/server/server.conf
client-config-dir /etc/openvpn/ccd

Im Beispiel erhält der Client mit dem Zertifikat „myhost“ bei der Einwahl die statische IP „192.0.2.47“:

mkdir -p /etc/openvpn/ccd

cat > /etc/openvpn/ccd/myhost << EOF
ifconfig-push 192.0.2.47 255.255.255.0
EOF

TUN vs. TAP

  • TUN = Punkt-zu-Punkt Netzwerkgerät, sendet und empfängt IP-Pakete auf Layer 3. Routed Network.

  • TAP = virtuelle Ethernet-Schnittstelle, sendet und empfängt Ethernet-Frames auf Layer 2, ist also unabhängig vom verwendeten Protokoll (IP, IPX, etc.). In erster Linie Bridged Network (Routing wäre auch möglich). TAP benötigt Netzwerkkarten im Promiscuous Mode.

Schlüsselstärken

Liste verfügbarer Chiffren anzeigen:

openvpn --show-ciphers

Liste möglicher TLS-Ciphers:

openvpn --show-tls

Liste unterstützter Message Authentications (HMACs):

openvpn --show-digests

Troubleshooting

VPN-Client: „Authenticate/Decrypt packet error: missing authentication info“

Liegt an einer der folgenden fehlenden Client-Settings: nobind, remote-cert-tls server - oder meist an der veralteten Einstellung „ns-cert-type server“ statt „remote-type-tls“. Wird letztere durch „remote-cert-tls server“ ersetzt, ist der Client auch in der Lage, „extended key usage“ der Zertifikate zu validieren.

VPN-Client: Server-Maschine hinter dem VPN-Server ist nicht erreichbar, VPN-Server aber schon

Rückroute auf der Server-Maschine hinter dem OpenVPN-Server fehlt. Entweder auf dem zentralen Gateway die Route hin zum OpenVPN-Server eintragen, oder jedem per VPN zu erreichenden System einzeln.

Built on 2022-10-19