Fix TLS handshake: add X.509 keyUsage/EKU extensions to all certs

OpenVPN 2.7 + OpenSSL 3.6 strictly checks keyUsage extension.
Client log showed: 'Certificate does not have key usage extension'
→ 'VERIFY KU ERROR' → 'TLS handshake failed'.

Root cause: all certs generated via bare 'openssl req/x509 -req'
without any -extensions/-extfile, so no X.509 v3 extensions at all.

Fix: generate per-cert openssl ext config files:

CA cert (EnsureCA):
  basicConstraints = critical,CA:TRUE
  keyUsage = critical,keyCertSign,cRLSign
  subjectKeyIdentifier = hash
  authorityKeyIdentifier = keyid:always,issuer

Server cert (IssueCert, clientName=='server'):
  basicConstraints = critical,CA:FALSE
  keyUsage = critical,digitalSignature,keyEncipherment
  extendedKeyUsage = serverAuth

Client cert (IssueCert, otherwise):
  basicConstraints = critical,CA:FALSE
  keyUsage = critical,digitalSignature,keyEncipherment
  extendedKeyUsage = clientAuth

Also fix while here:
- .ovpn remote host: strip port from HTTP Host header with
  net.SplitHostPort; prefer ?host= query param from frontend
- Replace deprecated 'persist-key' (OpenVPN 2.7 warns) with just
  'persist-tun' in both server.conf and client .ovpn
- Replace 'cipher X' with 'data-ciphers X:AES-128-GCM' (OpenVPN 2.5+
  negotiation) in server.conf and client .ovpn

Verified: CA/Server/Client certs all show correct keyUsage + EKU via
openssl x509 -text; .ovpn remote shows correct host:port.
This commit is contained in:
cnbugs
2026-08-09 22:39:51 +08:00
parent ae02b60d67
commit 7c0f8cf4d8
2 changed files with 54 additions and 10 deletions
+6
View File
@@ -1,6 +1,7 @@
package api
import (
"net"
"net/http"
"os"
"path/filepath"
@@ -376,7 +377,12 @@ func (s *Server) deleteUser(c *gin.Context) {
func (s *Server) downloadOVPN(c *gin.Context) {
host := c.Query("host")
if host == "" {
// 从 Host 头取 hostname(strip 端口号)
// 用户应在前端 ?host=vpn.example.com 传入真实地址
host = c.Request.Host
if h, _, err := net.SplitHostPort(host); err == nil {
host = h
}
}
p, err := s.Svc.GenerateOVPN(c.Param("uid"), host)
if err != nil {