Source code for netjsonconfig.backends.openvpn.openvpn

from ...schema import X509_FILE_MODE
from ..base.backend import BaseVpnBackend
from . import converters
from .parser import OpenVpnParser, config_suffix, vpn_pattern
from .renderer import OpenVpnRenderer
from .schema import schema


class OpenVpn(BaseVpnBackend):
    """
    OpenVPN 2.x Configuration Backend
    """

    schema = schema
    converters = [converters.OpenVpn]
    parser = OpenVpnParser
    renderer = OpenVpnRenderer
    list_identifiers = ["name"]
    # BaseVpnBackend attributes
    vpn_pattern = vpn_pattern
    config_suffix = config_suffix

[docs] @classmethod def auto_client( cls, host, server, ca_path=None, ca_contents=None, cert_path=None, cert_contents=None, key_path=None, key_contents=None, ): """ Returns a configuration dictionary representing an OpenVPN client configuration that is compatible with the passed server configuration. :param host: remote VPN server :param server: dictionary representing a single OpenVPN server configuration :param ca_path: optional string representing path to CA, will consequently add a file in the resulting configuration dictionary :param ca_contents: optional string representing contents of CA file :param cert_path: optional string representing path to certificate, will consequently add a file in the resulting configuration dictionary :param cert_contents: optional string representing contents of cert file :param key_path: optional string representing path to key, will consequently add a file in the resulting configuration dictionary :param key_contents: optional string representing contents of key file :returns: dictionary representing a single OpenVPN client configuration """ # client defaults client = { "mode": "p2p", "nobind": True, "resolv_retry": "infinite", "tls_client": True, } # remote port = server.get("port") or 1195 client["remote"] = [{"host": host, "port": port}] # proto if server.get("proto") == "tcp-server": client["proto"] = "tcp-client" else: client["proto"] = "udp" # determine if pull must be True if "server" in server or "server_bridge" in server: client["pull"] = True # tls_client if "tls_server" not in server or not server["tls_server"]: client["tls_client"] = False # ns_cert_type ns_cert_type = {None: "", "": "", "client": "server"} client["ns_cert_type"] = ns_cert_type[server.get("ns_cert_type")] # remote_cert_tls remote_cert_tls = {None: "", "": "", "client": "server"} client["remote_cert_tls"] = remote_cert_tls[server.get("remote_cert_tls")] tls_auth = server.get("tls_auth") if tls_auth: if len(tls_auth.strip().split(" ")) == 2: # The field contains path to auth key and direction. # auto_client does not support such format. pass else: # The TLS Auth key is present in the field. # Copy the TLS Auth key. Convertor will handle # parsing it into file. client["tls_auth"] = tls_auth copy_keys = [ "name", "dev_type", "dev", "comp_lzo", "auth", "cipher", "ca", "cert", "key", "pkcs12", "mtu_test", "fragment", "mssfix", "keepalive", "persist_tun", "mute", "persist_key", "user", "group", "mute_replay_warnings", "secret", "reneg_sec", "tls_timeout", "tls_cipher", "float", "fast_io", "verb", "auth_nocache", ] for key in copy_keys: if key in server: client[key] = server[key] if "script_security" in server: # From OpenWrt 21 onwards, "script_security" of "2" # is required for functioning of OpenVPN tunnels. client["script_security"] = 2 if "log" in server: # The "/var/log/openvpn" directory is not present # on OpenWrt, hence the location of the log is changed. client["log"] = server["log"].replace("/var/log/openvpn/", "/var/log/") files = cls._auto_client_files( client, ca_path, ca_contents, cert_path, cert_contents, key_path, key_contents, ) return {"openvpn": [client], "files": files}
@classmethod def _auto_client_files( cls, client, ca_path=None, ca_contents=None, cert_path=None, cert_contents=None, key_path=None, key_contents=None, ): """ returns a list of NetJSON extra files for automatically generated clients produces side effects in ``client`` dictionary """ files = [] if ca_path and ca_contents: client["ca"] = ca_path files.append(dict(path=ca_path, contents=ca_contents, mode=X509_FILE_MODE)) if cert_path and cert_contents: client["cert"] = cert_path files.append( dict(path=cert_path, contents=cert_contents, mode=X509_FILE_MODE) ) if key_path and key_contents: client["key"] = key_path files.append( dict( path=key_path, contents=key_contents, mode=X509_FILE_MODE, ) ) return files