{"id":22912005,"url":"https://github.com/opencoff/ovpn-tool","last_synced_at":"2025-05-09T01:33:38.864Z","repository":{"id":52595923,"uuid":"202475735","full_name":"opencoff/ovpn-tool","owner":"opencoff","description":"OpenVPN PKI tools and client/server configuration generator - better than easy-rsa","archived":false,"fork":false,"pushed_at":"2024-12-24T20:25:37.000Z","size":103,"stargazers_count":14,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-31T20:39:13.094Z","etag":null,"topics":["openssl-tools","openvpn","openvpn-cl","openvpn-configuration","openvpn-ser","tls-certificate-management"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opencoff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-15T04:47:27.000Z","updated_at":"2024-12-24T20:25:39.000Z","dependencies_parsed_at":"2023-12-20T10:33:43.629Z","dependency_job_id":"1cc81eef-c7af-413b-97cc-a2ff217c2ba4","html_url":"https://github.com/opencoff/ovpn-tool","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opencoff%2Fovpn-tool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opencoff%2Fovpn-tool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opencoff%2Fovpn-tool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opencoff%2Fovpn-tool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opencoff","download_url":"https://codeload.github.com/opencoff/ovpn-tool/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253174352,"owners_count":21865851,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["openssl-tools","openvpn","openvpn-cl","openvpn-configuration","openvpn-ser","tls-certificate-management"],"created_at":"2024-12-14T04:19:33.158Z","updated_at":"2025-05-09T01:33:38.846Z","avatar_url":"https://github.com/opencoff.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## TL;DR\nThis is an opinionated single-file OpenVPN TLS certificate manager and OpenVPN\nconfiguration generator. It has _no_ dependencies on any other external tool\nsuch as openssl. It is a replacement for and an enhancement to easy-rsa\n(typically bundled with OpenVPN).\n\n## IMPORTANT\n* v0.9.x is a breaking change from the previous version:\n   - `pki/` code is moved to its own repository\n   - boltdb code refactored (e.g., use AEAD for storing DB key)\n* If you are using v0.8.x, please export the database and import it.\n  See the section on importing below.\n\n## Features\n* Uses a single [boltdb](https://github.com/etcd-io/bbolt) instance to store the\n  certificates and keys.\n* All data stored in the database is encrypted with keys derived from a user\n  supplied CA passphrase.\n* To support automation, the master password can be supplied via a\n  user defined environment variable. All commands support\n  `--env-password=E` option to support this feature.\n* Support for arbitrary chain of intermediate CAs\n* The certificates and keys are opinionated:\n   * Secp521r1 used for CA certificates\n   * Secp256k1 EC certificate private keys\n   * \"SSL-Server\" attribute set on server certificates (nsCertType)\n   * \"SSL-Client\" attribute set on client certificates (nsCertType)\n   * ECDSA with SHA512 is used as the signature algorithm\n* The generated OpenVPN configuration for client or server uses inline\n  certificates, keys *and* runs with an opinionated set of defaults:\n   * `TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256` for\n      TLS control channel\n   * `AES-256-GCM` for data encryption\n   * TLS 1.2 is the minimum version negotiation\n   * Client verifies the X509 Common-Name of the server\n   * Uses \"tun\" mode\n   * Server pushes its tunnel address as the default gateway for all\n     client traffic\n   * Server pushes its tunnel address as the DNS server so that all\n     DNS lookups on the client can be handled inside the tunnel. The\n     server will need additional software such as `unbound` to provide\n     DNS server/cache functionality.\n   * The Client and Server configurations uses the `tls-crypt` option\n     to ensure that the server is protected with an additional layer\n     of encryption to thwart DoS attacks.\n* Ability to export DB contents as a JSON file; ability to import\n  JSON from a previous export.\n\n## Building ovpn-tool\nYou will need a fairly recent golang toolchain (\u003e1.10):\n\n    $ git clone https://github.com/opencoff/ovpn-tool\n    $ cd ovpn-tool\n    $ ./build -s\n\nThe build script puts the binary in a platform specific directory:\n\n* macOS: `bin/darwin-amd64`\n* Linux: `bin/linux-amd64`\n* OpenBSD: `bin/openbsd-amd64`\n\nAnd so on. The build script can generate a fully standalone\nstatically-linked binary on platforms that support it. To build\nstatically linked binaries, use `build -s`.\n\nYou can also do cross-platform builds for any supported OS, Arch\ncombination supported by the golang toolchain. e.g., on macOS,\nto build a statically linked binary for linux-amd64 architecture:\n\n    $ ./build -s --arch linux-amd64\n\n## Invoking ovpn-tool\nThe common pattern for invoking ovpn-tool is:\n\n    ovpn-tool DB CMD [options] [arguments]\n\nWhere:\n* *DB* is the name of the certificate store (database). This is a\n  [boltdb](https://github.com/etcd/bbolt) instance.\n\n* *CMD* is a command - one of `init`, `server`, `client`, `export`,\n  `list`, `delete`, `crl`, `passwd`.\n\nThe tool writes the certificates, keys into an encrypted boltdb instance.\n\nThe tool comes with builtin help:\n\n    $ ./bin/openbsd-amd64/ovpn-tool --help\n\nEvery subcommand comes with its own help; but, requires you to at least\nsupply a database name as the first argument. e.g.,\n\n    $ ./bin/openbsd-amd64/ovpn-tool foo.db server --help\n\n## Common Workflows\nIn what follows, we will assume that you have built ovpn-tool and\ninstalled somewhere in your `$PATH`.\n\n### Initialize a new CA\nBefore any certificates are generated, one must first create a CA and\ninitialize the certificate DB:\n\n    $ ovpn-tool -v foo.db init my-CA\n\nYou can see the generated CA certificate via two ways:\n\n1. Using `-v` for the ovpn-tool's global options\n2. Using the `list` command with the `--ca` option.\n\nIn general, using the `-v` global option when generating the CA, server\nor client certificates will print the certificate to stdout at the end.\n\nThe CA can be initialized with additional data such as Organization Name,\nOrganization Unit Name etc. See `init --help` for additional details.\n\nThe default lifetime of the CA is 5 years; you can change this via\nthe `-V` (`--validity`) option to \"init\".\n\nOne can also use a user defined environment variable to provide the\ndatabase master password:\n\n    $ abcdef=myDBPassword45879 ovpn-tool -v foo.db init -E abcdef my-CA\n\nThe example invocation above uses the DB password from the\nenvironment variable `abcdef` to find the passphrase\n`myDBPassword45879`.\n\n### Initialize a new CA by Importing from a JSON file\nIf you are using any version of ovpn-tool **prior** to v0.9.x, you\nmust first export the DB into a JSON file *using the v0.8.x version\nof the tool*. Assuming the DB dump is in *db.json*, then you can\ninitialize a new CA instance like so:\n\n    $ ovpn-tool -v foo.db init --from-json db.json\n\nYou will be prompted for the DB passphrase; this passphrase is for\nthe **new** database (and NOT the old database).\n\n### Creating an intermediate CA\nOften, it's useful to have an intermediate CA for issuing server or\nclient certificates. These intermediate CAs can be arbitrarily\nchained.\n\n    $ ovpn-tool -v foo.db inter client-ca\n\nOnce created, this intermediate CA can be used to issue new leaf\ncertificates:\n\n    $ ovpn-tool -v foo.db user -s client-ca user@example.com\n\n### Create an OpenVPN server certificate \u0026 key pair\nAn OpenVPN server needs a few things:\n* A server common name - so client can either address it by DNS Name.\n* An IP Address - so that the server config can use it to listen on\n  an IP:Port.\n* The IP Address has the additional benefit (or drawback) of not\n  requiring the client to do a DNS lookup.\n\nCreating a new server certificate/key pair:\n\n    $ ovpn-tool -v foo.db server -i IP.ADDR.ES server.domain.name\n\nOf course, you should use the appropriate values for `IP.ADDR.ES`\nand `server.domain.name` for your setup.\n\nThe IP Address and Server FQDN show up in the certificate as\nCertificate.IPAddress and Certificate.Subject.CommonName.\nAdditionally, the server FQDN also shows up in Certificate.DNSNames.\n\nYou can also set a custom OpenVPN port for this server via the `-p`\nflag. You can request the server certificate to have a different\nvalidity via the `V` (`--validity`) option; this option takes the\nvalue in units of years.\n\nYou can of course create as many server certificates as needed. But,\nwhen you export a *client* configuration, you must select the correct\nserver name this client will connect to. See example below.\n\n### Create an OpenVPN client (user) certificate \u0026 key pair\nAn OpenVPN client certificate is quite simple - it just needs a\ncommon name. For convenience, you may use the email address as the\ncommon Name.\n\n    $ ovpn-tool -v foo.db client user@domain.name\n\nYou can ask the client private key to be encrypted with a user\nsupplied passphrase by using the `-p` or `--password` option to the\n`client` command.  You can request the client certificate to have\na different validity via the `V` (`--validity`) option; this option\ntakes the value in units of years.\n\n### Delete an OpenVPN user from the Cert Database\nOnce in a while you will want to delete users and prevent them from\nconnecting to the OpenVPN server. E.g.,\n\n    $ ovpn-tool -v foo.db delete user@domain.name user2@domain\n\nThis only deletes the users from the certificate DB. You still need\nto generate a new CRL (Certificate Revocation List) and push it to\nyour server. See the next workflow.\n\n### Generate a CRL from Revoked Certificates\nOnce a user is deleted from the system, you will need to generate a\nnew CRL and push it to the server. The command to generate a new\nCRL:\n\n    $ ovpn-tool -v foo.db crl -o crl.pem\n\nThis write the PEM encoded CRL to `crl.pem`. You must copy this file\nto the OpenVPN server and reload (or restart) it.\n\nYou can also just view a full list of revoked users:\n\n    $ ovpn-tool foo.db crl --list\n\n### See list of certificates managed by this CA\nTo see a list of certificates in the database:\n\n    $ ovpn-tool foo.db list\n\n## Revoking CAs or Leaf Certificates\novpn-tool enables you to revoke intermediate CAs or leaf\ncertificates. To revoke a user/server cerfificate:\n\n    $ ovpn-tool foo.db del NAME\n\nwhere `NAME` is the common-name of the certificate you want to\nrevoke. **Note** you should generate a new CRL once you revoke any\ncertificate:\n\n    $ ovpn-tool foo.db crl -v 7 -o crl.pem\n\nThis generates a CRL with a 7 day validity (you should regenerate\nthe CRLs regularly).\n\n### Exporting a Server Configuration\nWhile the tool manages certificates, what we are really after are\nOpenVPN server \u0026 client configurations for the server \u0026 client\nrespectively. To export a server configuration:\n\n    $ ovpn-tool foo.db export server.domain.name\n\nThis prints the server configuration to stdout. To save this to a\nfile:\n\n    $ ovpn-tool foo.db export server.domain.name -o server.conf\n\nNote the configuration uses certain private IP address blocks and\nsuch. Please edit the configuration file to suit your environment.\n\n*At a minimum* you have to edit the user/group information\nparticular to your OS for dropping privilege of the OpenVPN daemon.\ne.g., on Alpine Linux, the preferred user and group for the daemon\nis \"openvpn\". On OpenBSD it is \"\\_openvpn\"; on macOS it is \"nobody\".\n\nThe server configuration uses a template baked into ovpn-tool. You\nhave the option of providing your own template. The easiest way is\nto export the template and edit it. You can then feed the modified\ntemplate back to the export command:\n\n    $ ovpn-tool foo.db export --print-server-template \u003e s.template\n    $ vi s.template\n    $ ovpn-tool foo.db export -t s.template -o s.conf server.domain.name\n\n### Exporting a Client Configuration\nClient configuration is typically associated with one OpenVPN\nserver. However, this is optional and you can take an unassociated\nconfiguration and make manual changes as needed. A typical\ninvocation is:\n\n    $ ovpn-tool foo.db export -s server.domain.name -o client.conf user@domain.name\n\nYou can export the default client configuration template like so:\n\n    $ ovpn-tool foo.db export --print-client-template \u003e c.template\n\n### Replacing the user passphrase on a DB\nIf you desire to change the DB passphrase, you can do so with the\n`passwd` command:\n\n    $ ovpn-tool foo.db passwd\n\nThis merely changes the way the encrypted DB key is stored on disk.\n\nThis command also supports getting the old and new passphrases via\nuser defined environment variables. e.g.,:\n\n    $ oldpw=myDBPassword45879 newpw=newDBPwd112233 ovpn-tool foo.db \\\n        passwd -E oldpw -N newpw\n\nThis mode of getting the password from the environment is highly\ndiscouraged - as it can leave traces in the user's shell history.\nUse with care!\n\n## Template variables available for customization\nThe following template parameters are available for use in your\ncustom configuration templates:\n\n* `.CommonName` - Certificate common name\n* `.Date` - Today's date and time (UTC)\n* `.Tool` - ovpn-tool build information (version, etc.)\n* `.Cert` - PEM encoded certificate\n* `.Key`  - PEM encoded private key\n* `.Ca`   - PEM encoded CA certificate\n* `.TlsCrypt` - Base64 encoded OpenVPN \"tls-crypt\" key\n* `.ServerCommonName` - Common name of the server\n* `.Host` - Server DNS name from the server certificate\n* `.IP`   - Server IP address from the server certificate\n* `.Port` - OpenVPN server port number provided when server\n  certificate was created\n\n## Getting the DB Password from the Environment\nAll command support the option to get the password from the\nenvironment variable of user's choice. This capability is helpful to\nautomate certain operations - but is **NOT recommended** from a good\nsecurity practice perspective.\n\nIf you do choose to use this feature, please remember to turn-off\nshell history otherwise your history will hold a permanent record of\nyour DB password.\n\n# Development Notes\nIf you wish to hack on this, notes here might be useful.\n\nThe code is organized as a library \u0026 command line frontend for that library.\n\n* We use go module support; you will need go 1.10+ or later\n\n* The common PKI creation \u0026 storage is in the `pki/` library. This\n  library can be used by external callers. e.g., see\n  https://github.com/opencoff/certik\n\n* The script `build` is a shell script to build the program.\n  It does two very important things:\n    * Puts the binary in an OS+Arch specific directory\n    * Injects a git version-tag into the final binary (\"linker resolved symbol\")\n\n  Additionally, it makes cross compilation and static builds\n  possible (for supported platforms). Try `./build --help` for more\n  details.\n\n* The OpenVPN server \u0026 client configuration templates are in `src/export.go`.\n  It uses golang's `text/template` syntax.\n\n* Database encryption:\n    * User passphrase is first expanded to 64 bytes by hashing it via SHA-512.\n    * The DB is associated with a random 32-byte encryption key and a random 32-byte\n      salt. This key is protected with a Key-encryption-key (KEK) derived from\n      the expanded passphrase.\n    * The salt and expanded passphrase are fed into Argon2i to derive the KEK.\n    * The DB encryption key is stored on disk as an AEAD encrypted blob (AES-256-GCM).\n      The salt and KEK is stored in the DB.\n    * In pseudo code, the above looks like so:\n      ```python\n\n          expanded  = SHA512(passphrase)\n          salt      = randombytes(32)\n          dbkey     = randombytes(32)\n          kek       = KDF(expanded, salt)\n          enc_dbkey = AES-256-GCM(kek, salt)\n      ```\n\n    * Database entries are individually encrypted in AEAD (AES-256-GCM) mode.\n      The AEAD nonce size is 16 bytes (instead of the golang default of 12 bytes).\n    * Each AEAD encrypt instance uses a separate salt and key extracted via HKDF.\n    * The HKDF salt is used as additional data in the AEAD construction.\n    * Database bucket keys are entangled with the expanded passphrase and the DB\n      salt via HMAC-SHA256. We don't use any kind of AEAD here because we need a\n      quick and easy way to map user CN's to actual keys.  See how `d.key()` is\n      used in *db.go*.\n\n## Guide to Source Code\n* The bulk of the code for PKI management is in\n  [go-pki](https://github.com/opencoff/go-pki).\n\n* The ovpn-tool command line code is in the `src/` directory.\n  Each command is in its own file.\n\n* `internal/utils`: Misc utilities for asking interactive password\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopencoff%2Fovpn-tool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopencoff%2Fovpn-tool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopencoff%2Fovpn-tool/lists"}