Four bugs prevented OpenVPN from actually listening on its UDP port:
1. server.conf line 'server 10.8.0.0/24' — OpenVPN 2.5 rejects CIDR.
Fix: cidrToServerDirective() converts CIDR to 'NETWORK NETMASK'
(e.g. '10.8.0.0 255.255.255.0') using net.ParseCIDR.
2. push_dns '1.1.1.1 8.8.8.8' was emitted as a single push directive
instead of multiple 'push dhcp-option DNS x' lines.
Fix: split space-separated IPs into individual push directives;
pass through if already 'dhcp-option ...' form.
3. client-config-dir referenced a ccd/ directory that was never created.
Fix: CreateInstance now MkdirAll(ccd); WriteServerConf also
defensively MkdirAll(extraDir) before writing the directive.
4. dh.pem generated with 1024-bit DH params → OpenSSL 3.0 refuses
with 'dh key too small'. Fix: use 'dh none' in server.conf so
OpenVPN 2.4+ uses ECDHE key exchange — no DH params needed at all.
Removed the slow openssl dhparam generation from EnsureCA.
Verified: instance starts, OpenVPN parses config successfully,
now fails only at TUNSETIFF (expected: requires root/CAP_NET_ADMIN).