Skip to content

Instantly share code, notes, and snippets.

@Morley93
Last active April 28, 2024 08:44
Show Gist options
  • Save Morley93/9697578 to your computer and use it in GitHub Desktop.
Save Morley93/9697578 to your computer and use it in GitHub Desktop.
This is how you can take an openvpn .ovpn config file and extract the certificates/key required to import the profile into NetworkManager.

OpenVPN .ovpn manipulation.

This is how you can take an OpenVPN .ovpn config file and extract the certificates/keys required to import the profile into NetworkManager.

  • Download the .ovpn file. Save it somewhere you can store it permanently (I use ~/.vpn).
  • Copy from between <ca> tags into ca.crt, remove <ca> tags.
  • Copy from between <cert> tags into client.crt, remove <cert> tags.
  • Copy from between <key> tags into client.key, remove <key> tags.
  • Copy from between <tls-auth> tags into ta.key, remove <tls-auth> tags.
  • Remove the line "key-direction 1"
  • Above "# -----BEGIN RSA SIGNATURE-----" insert the following lines.
    • ca ca.crt
    • cert client.crt
    • key client.key
    • tls-auth ta.key 1
  • Import the .ovpn file into NetworkManager and save the profile.
@chb0github
Copy link

chb0github commented May 22, 2016

I actually tracked down the openssl code to find out exactly how it likes these files:

    if ((strncmp(buf, "-----END ", 9) != 0) ||
        (strncmp(nameB->data, &(buf[9]), i) != 0) ||
        (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) {
        PEMerr(PEM_F_PEM_READ_BIO, PEM_R_BAD_END_LINE);
        goto err;
    }

the last line MUST meet these rules:

  1. first 9 characters: "-----END " (5 dashes, "END" and a single space)
  2. The part of the line must have the exact same header name as the "START". So like, "START CERTIFICATE"
  3. The final part of the line must be, exactly 5 dashes and a single "\n" which would be hex byte 0x0A which is default newline for unix

The problem: I was missing 1 single '-' at the end of the file!!

@NickoMas
Copy link

Thank you, good sir, you saved my sanity after sleepless night with your solution.

@alexandervlpl
Copy link

Yeah, thanks man! Just what I needed. 👍

@mcuprojects
Copy link

thanks man, that's helpful

@lattice0
Copy link

@yabbes
Copy link

yabbes commented Nov 15, 2019

I had the same idea but wasn't sure it would work like this so I ended up here :)
In my case it's just <tls-crypt> brackets instead of <tls-auth> but will work the same way.
Starred this gist 👍

@raOne-007
Copy link

raOne-007 commented Jan 2, 2020

Hello Guys ,
I have able to save VPN configuration.
Please tell me how to make the server address variable or get server address and what is the remote identifier for?
Please tell me if anyone worked on VPN Configuration
Here is my code:

    func connectVPN(){
        do {
                 if let file = URL(string: "example.com") {
                let data = try Data(contentsOf: file)
                let json = try JSONSerialization.jsonObject(with: data, options: [])
                if let object = json as? [String: String] {
                // json is a dictionary
                var data_VPN = object["VPN_data"]!
                //print("data:\(data_VPN)")
                let certificate = data_VPN
                let nsdata = certificate.data(using: .utf8)

                let base64EncodedData = nsdata!.base64EncodedData()

                print("base64StoreData:\(nsdata!)")
                print("base64StoreNewData:\(base64EncodedData)")

                var vpnManager = NEVPNManager.shared()

                                    vpnManager.loadFromPreferences { error in

                                        if vpnManager.`protocol` == nil{
                                            let newIPSec = NEVPNProtocolIPSec()

                                            newIPSec.serverAddress = ""
                                            newIPSec.localIdentifier = ""
                                            newIPSec.remoteIdentifier = ""
                                            newIPSec.useExtendedAuthentication = true
                                            newIPSec.identityData = base64EncodedData as! Data
                                            newIPSec.authenticationMethod = NEVPNIKEAuthenticationMethod.certificate
                                            print("VPNDATA:\(newIPSec)")

                                            if #available(iOS 9, *) {
                                            vpnManager.protocolConfiguration = newIPSec
                                            } else {
                                            vpnManager.`protocol` = newIPSec
                                            }

                                            vpnManager.isEnabled = true
                                            vpnManager.saveToPreferences(completionHandler: { (error) -> Void in
                                                if ((error) != nil) {
                                                    print("VPN Preferences error: 2")
                                                }
                                                else {
                                                    vpnManager.loadFromPreferences(completionHandler: { (error) in
                                                        if ((error) != nil) {
                                                            print("VPN Preferences error: 2")
                                                        }
                                                        else {
                                                            var startError: NSError?
                                                            do {
                                                                try vpnManager.connection.startVPNTunnel()
                                                            }
                                                            catch let error as NSError {
                                                                startError = error
                                                                print(startError)
                                                            }
                                                            catch {
                                                                print("Fatal Error")
                                                                fatalError()
                                                            }
                                                            if ((startError) != nil) {
                                                                print("VPN Preferences error: 3")
                                                                let alertController = UIAlertController( title: "Oops..", message: "Something went wrong while connecting to the VPN. Please try again.", preferredStyle: UIAlertControllerStyle.alert)
                                                                alertController.addAction( UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.default,handler: nil))
                                                                self.present(alertController, animated: true, completion: nil)
                                                                print(startError)
                                                            }
                                                            else {
                                                                //VPNStatusDidChange(nil)
                                                                print("Start VPN")
                                                            }
                                                        }
                                                    })
                                                }
                                            })
                }

            } else if let object = json as? [Any] {
                // json is an array
                for anItem in object as! [Dictionary<String, AnyObject>] {
                    let industryName = anItem["VPN_data"] as! String                                               
                }
            } else {
                print("JSON is invalid")
            }
        } else {
            print("no file")
        }
    } catch {
        print(error.localizedDescription)
    }

}

}

@labbots
Copy link

labbots commented May 6, 2020

I have written a bash script that could split or merge OVPN config file. The code can be found at https://github.com/labbots/OVPN-Config-Manipulator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment