Move OpenVPN and StrongSwan entrypoint to separate Docker images
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| FROM ubuntu:20.04 as base | ||||
| FROM ubuntu:20.04 | ||||
| ENV container docker | ||||
| ENV PYTHONUNBUFFERED=1 | ||||
| ENV LC_ALL C.UTF-8 | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| include README.md | ||||
| include pinecrypt/server/templates/*.conf | ||||
| include pinecrypt/server/templates/mail/*.md | ||||
| include pinecrypt/server/builder/overlay/usr/bin/pinecrypt.server-* | ||||
| include pinecrypt/server/builder/overlay/etc/uci-defaults/* | ||||
|   | ||||
| @@ -1,15 +0,0 @@ | ||||
| #!/usr/bin/python3 | ||||
| import os | ||||
| import sys | ||||
| from pinecrypt.server import db | ||||
|  | ||||
| # This implements OCSP like functionality | ||||
|  | ||||
| obj = db.certificates.find_one({ | ||||
|     # TODO: use digest instead | ||||
|     "serial_number": "%x" % int(os.environ["tls_serial_0"]), | ||||
|     "status":"signed", | ||||
| }) | ||||
|  | ||||
| if not obj: | ||||
|     sys.exit(1) | ||||
| @@ -1,28 +0,0 @@ | ||||
| #!/usr/bin/python3 | ||||
| import os | ||||
| import sys | ||||
| from pinecrypt.server import db | ||||
| from datetime import datetime | ||||
|  | ||||
| operation, addr = sys.argv[1:3] | ||||
| if operation == "delete": | ||||
|     pass | ||||
| else: | ||||
|     common_name = sys.argv[3] | ||||
|     db.certificates.update_one({ | ||||
|         # TODO: use digest instead | ||||
|         "serial_number": "%x" % int(os.environ["tls_serial_0"]), | ||||
|         "status":"signed", | ||||
|     }, { | ||||
|         "$set": { | ||||
|             "last_seen": datetime.utcnow(), | ||||
|             "instance": os.environ["instance"], | ||||
|             "remote": { | ||||
|                 "port": int(os.environ["untrusted_port"]), | ||||
|                 "addr": os.environ["untrusted_ip"], | ||||
|             } | ||||
|         }, | ||||
|         "$addToSet": { | ||||
|             "ip": addr | ||||
|         } | ||||
|     }) | ||||
| @@ -1,31 +0,0 @@ | ||||
| #!/usr/bin/python3 | ||||
| import sys | ||||
| import os | ||||
| from pinecrypt.server import db | ||||
| from datetime import datetime | ||||
|  | ||||
| addrs = set() | ||||
| for key, value in os.environ.items(): | ||||
|     if key.startswith("PLUTO_PEER_SOURCEIP"): | ||||
|         addrs.add(value) | ||||
|  | ||||
| with open("/instance") as fh: | ||||
|     instance = fh.read().strip() | ||||
|  | ||||
| db.certificates.update_one({ | ||||
|     "distinguished_name": os.environ["PLUTO_PEER_ID"], | ||||
|     "status":"signed", | ||||
| }, { | ||||
|     "$set": { | ||||
|         "last_seen": datetime.utcnow(), | ||||
|         "instance": instance, | ||||
|         "remote": { | ||||
|             "addr": os.environ["PLUTO_PEER"] | ||||
|         } | ||||
|     }, | ||||
|     "$addToSet": { | ||||
|         "ip": { | ||||
|             "$each": list(addrs) | ||||
|         } | ||||
|     } | ||||
| }) | ||||
| @@ -169,7 +169,7 @@ def authenticate(optional=False): | ||||
|                 user, passwd = b64decode(token).decode("utf-8").split(":", 1) | ||||
|  | ||||
|             if "ldap" in const.AUTHENTICATION_BACKENDS: | ||||
|                 upn = "%s@%s" % (user, const.KERBEROS_REALM) | ||||
|                 upn = ("%s@%s" % (user, const.KERBEROS_REALM)).lower() | ||||
|                 click.echo("Connecting to %s as %s" % (const.LDAP_AUTHENTICATION_URI, upn)) | ||||
|                 conn = ldap.initialize(const.LDAP_AUTHENTICATION_URI, bytes_mode=False) | ||||
|                 conn.set_option(ldap.OPT_REFERRALS, 0) | ||||
| @@ -185,9 +185,9 @@ def authenticate(optional=False): | ||||
|                     raise | ||||
|                 except ldap.INVALID_CREDENTIALS: | ||||
|                     logger.critical("LDAP bind authentication failed for user %s from  %s", | ||||
|                         repr(user), req.context["remote"]["addr"]) | ||||
|                         repr(upn), req.context["remote"]["addr"]) | ||||
|                     raise falcon.HTTPUnauthorized( | ||||
|                         description="Please authenticate with %s domain account username" % const.DOMAIN, | ||||
|                         description="Please authenticate with %s domain account username" % const.KERBEROS_REALM, | ||||
|                         challenges=["Basic"]) | ||||
|  | ||||
|                 req.context["ldap_conn"] = conn | ||||
|   | ||||
| @@ -81,6 +81,7 @@ def self_enroll(skip_notify=False): | ||||
|     cert, buf = sign(mongo_id=id, skip_notify=skip_notify, overwrite=True, | ||||
|         profile="Gateway", namespace=const.AUTHORITY_NAMESPACE) | ||||
|  | ||||
|     os.umask(0o133) | ||||
|     with open(const.SELF_CERT_PATH + ".part", "wb") as fh: | ||||
|         fh.write(buf) | ||||
|     os.rename(const.SELF_CERT_PATH + ".part", const.SELF_CERT_PATH) | ||||
|   | ||||
| @@ -20,7 +20,9 @@ import pytz | ||||
| from asn1crypto import pem, x509 | ||||
| from certbuilder import CertificateBuilder, pem_armor_certificate | ||||
| from datetime import datetime, timedelta | ||||
| from jinja2 import Environment, PackageLoader | ||||
| from oscrypto import asymmetric | ||||
| from math import log, ceil | ||||
| from pinecrypt.server import const, mongolog, mailer, db | ||||
| from pinecrypt.server.middleware import NormalizeMiddleware, PrometheusEndpoint | ||||
| from pinecrypt.server.common import cn_to_dn, generate_serial | ||||
| @@ -340,8 +342,8 @@ def pinecone_provision(): | ||||
|         with open(const.AUTHORITY_PRIVATE_KEY_PATH + ".part", "wb") as f: | ||||
|             f.write(obj["key"]) | ||||
|  | ||||
|         # Set permission bits to 640 | ||||
|         os.umask(0o137) | ||||
|         # Set permission bits to 644 | ||||
|         os.umask(0o133) | ||||
|         with open(const.AUTHORITY_CERTIFICATE_PATH + ".part", "wb") as f: | ||||
|             f.write(obj["cert"]) | ||||
|  | ||||
| @@ -371,6 +373,71 @@ def pinecone_provision(): | ||||
|         } | ||||
|     }) | ||||
|  | ||||
|     # Separate pushed subnets by address family | ||||
|     push4 = set() | ||||
|     push6 = set() | ||||
|     for subnet in const.PUSH_SUBNETS: | ||||
|         if subnet.version == 4: | ||||
|             push4.add(subnet) | ||||
|         elif subnet.version == 6: | ||||
|             if not const.CLIENT_SUBNET6: | ||||
|                 raise ValueError("Can't push IPv6 routes if no IPv6 client subnet is configured") | ||||
|             push6.add(subnet) | ||||
|         else: | ||||
|             raise NotImplementedError() | ||||
|  | ||||
|     # Generate OpenVPN configurations | ||||
|     click.echo("Generating OpenVPN configuration files...") | ||||
|     from pinecrypt.server import config | ||||
|     ctx = { | ||||
|         "authority_namespace": const.AUTHORITY_NAMESPACE, | ||||
|         "push4": push4, | ||||
|         "push6": push6, | ||||
|         "openvpn_tls_version_min": config.get("Globals", "OPENVPN_TLS_VERSION_MIN")["value"], | ||||
|         "openvpn_tls_ciphersuites": config.get("Globals", "OPENVPN_TLS_CIPHERSUITES")["value"], | ||||
|         "openvpn_tls_cipher": config.get("Globals", "OPENVPN_TLS_CIPHER")["value"], | ||||
|         "openvpn_cipher": config.get("Globals", "OPENVPN_CIPHER")["value"], | ||||
|         "openvpn_auth": config.get("Globals", "OPENVPN_AUTH")["value"], | ||||
|         "strongswan_dhgroup": config.get("Globals", "STRONGSWAN_DHGROUP")["value"], | ||||
|         "strongswan_ike": config.get("Globals", "STRONGSWAN_IKE")["value"], | ||||
|         "strongswan_esp": config.get("Globals", "STRONGSWAN_ESP")["value"], | ||||
|     } | ||||
|  | ||||
|     env = Environment(loader=PackageLoader("pinecrypt.server", "templates")) | ||||
|     os.umask(0o133) | ||||
|  | ||||
|     d = ceil(log(const.CLIENT_SUBNET_SLOT_COUNT) / log(2)) | ||||
|     for slot, proto in enumerate(["udp", "tcp"]): | ||||
|         ctx["proto"] = proto | ||||
|         ctx["slot4"] = list(const.CLIENT_SUBNET4.subnets(d))[slot] | ||||
|         ctx["slot6"] = list(const.CLIENT_SUBNET6.subnets(d))[slot] if const.CLIENT_SUBNET6 else None | ||||
|         with open("/server-secrets/openvpn-%s.conf" % proto, "w") as fh: | ||||
|             fh.write(env.get_template("openvpn.conf").render(ctx)) | ||||
|  | ||||
|     # Merged variants for StrongSwan | ||||
|     ctx["push"] = ctx["push4"].union(ctx["push6"]) | ||||
|  | ||||
|     # Generate StrongSwan config | ||||
|     click.echo("Generating StrongSwan configuration files...") | ||||
|     slot += 1 | ||||
|     ctx["slot4"] = list(const.CLIENT_SUBNET4.subnets(d))[slot] | ||||
|     ctx["slot6"] = list(const.CLIENT_SUBNET6.subnets(d))[slot] if const.CLIENT_SUBNET6 else [] | ||||
|     with open("/server-secrets/ipsec.conf", "w") as fh: | ||||
|         fh.write(env.get_template("ipsec.conf").render(ctx)) | ||||
|  | ||||
|     # Why do you do this StrongSwan?! You will parse the cert anyway, | ||||
|     # why do I need to distinguish ECDSA vs RSA in config?! | ||||
|     with open(const.SELF_CERT_PATH, "rb") as fh: | ||||
|         certificate_buf = fh.read() | ||||
|         header, _, certificate_der_bytes = pem.unarmor(certificate_buf) | ||||
|         certificate = x509.Certificate.load(certificate_der_bytes) | ||||
|         public_key = asymmetric.load_public_key(certificate["tbs_certificate"]["subject_public_key_info"]) | ||||
|     with open("/server-secrets/ipsec.secrets", "w") as fh: | ||||
|         fh.write(": %s %s\n" % ( | ||||
|             "ECDSA" if public_key.algorithm == "ec" else "RSA", | ||||
|             const.SELF_KEY_PATH | ||||
|         )) | ||||
|  | ||||
|     # TODO: use this task to send notification emails maybe? | ||||
|     click.echo("Finished starting up") | ||||
|     sleep(86400) | ||||
| @@ -491,173 +558,6 @@ def pinecone_session(): pass | ||||
| def entry_point(): pass | ||||
|  | ||||
|  | ||||
| @click.command("openvpn", help="Start OpenVPN server process") | ||||
| @click.option("--local", "-l", default="0.0.0.0", help="OpenVPN listening address, defaults to all interfaces") | ||||
| @click.option("--proto", "-t", default="udp", type=click.Choice(["udp", "tcp"]), help="OpenVPN transport protocol, UDP by default") | ||||
| @click.option("--client-subnet-slot", "-s", type=int, help="Client subnet slot index") | ||||
| @waitfile(const.SELF_CERT_PATH) | ||||
| def pinecone_serve_openvpn(local, proto, client_subnet_slot): | ||||
|     from pinecrypt.server import config | ||||
|     # TODO: Generate (per-client configs) from MongoDB | ||||
|     executable = "/usr/sbin/openvpn" | ||||
|  | ||||
|     args = executable, | ||||
|     slot4 = const.CLIENT_SUBNET4_SLOTS[client_subnet_slot] | ||||
|     args += "--server", str(slot4.network_address), str(slot4.netmask), | ||||
|     if const.CLIENT_SUBNET6: | ||||
|         args += "--server-ipv6", str(const.CLIENT_SUBNET6_SLOTS[client_subnet_slot]), | ||||
|     args += "--local", local | ||||
|  | ||||
|     # Support only two modes TCP 443 and UDP 1194 | ||||
|     if proto == "tcp": | ||||
|         args += "--dev", "tuntcp0", | ||||
|         args += "--port-share", "127.0.0.1", "1443", | ||||
|         args += "--proto", "tcp-server", | ||||
|         args += "--port", "443", | ||||
|         args += "--socket-flags", "TCP_NODELAY", | ||||
|         args += "--management", "127.0.0.1", "7506", | ||||
|         instance = "%s-openvpn-tcp-443" % const.FQDN | ||||
|     else: | ||||
|         args += "--dev", "tunudp0", | ||||
|         args += "--proto", "udp", | ||||
|         args += "--port", "1194", | ||||
|         args += "--management", "127.0.0.1", "7505", | ||||
|         instance = "%s-openvpn-udp-1194" % const.FQDN | ||||
|     args += "--setenv", "instance", instance | ||||
|     db.certificates.update_many({ | ||||
|         "instance": instance | ||||
|     }, { | ||||
|         "$unset": { | ||||
|             "ip": "", | ||||
|             "instance": "", | ||||
|         } | ||||
|     }) | ||||
|  | ||||
|     # Send keep alive packets, mainly for UDP | ||||
|     args += "--keepalive", "60", "120", | ||||
|  | ||||
|     args += "--opt-verify", | ||||
|  | ||||
|     args += "--key", const.SELF_KEY_PATH | ||||
|     args += "--cert", const.SELF_CERT_PATH | ||||
|     args += "--ca", const.AUTHORITY_CERTIFICATE_PATH | ||||
|  | ||||
|     if const.PUSH_SUBNETS: | ||||
|         args += "--push", "route-metric 1000" | ||||
|     for subnet in const.PUSH_SUBNETS: | ||||
|         if subnet.version == 4: | ||||
|             args += "--push", "route %s %s" % (subnet.network_address, subnet.netmask), | ||||
|         elif subnet.version == 6: | ||||
|             if not const.CLIENT_SUBNET6: | ||||
|                 raise ValueError("Can't push IPv6 routes if no IPv6 client subnet is configured") | ||||
|             args += "--push", "route-ipv6 %s" % subnet | ||||
|         else: | ||||
|             raise NotImplementedError() | ||||
|  | ||||
|     # TODO: Figure out how to do dhparam without blocking initially | ||||
|     if os.path.exists(const.DHPARAM_PATH): | ||||
|         args += "--dh", const.DHPARAM_PATH | ||||
|     else: | ||||
|         args += "--dh", "none" | ||||
|  | ||||
|     # For more info see: openvpn --show-tls | ||||
|     args += "--tls-version-min", config.get("Globals", "OPENVPN_TLS_VERSION_MIN")["value"] | ||||
|     args += "--tls-ciphersuites", config.get("Globals", "OPENVPN_TLS_CIPHERSUITES")["value"],  # Used by TLS 1.3 | ||||
|     args += "--tls-cipher", config.get("Globals", "OPENVPN_TLS_CIPHER")["value"],  # Used by TLS 1.2 | ||||
|  | ||||
|     # Data channel encryption parameters | ||||
|     # TODO: Rename to --data-cipher when OpenVPN 2.5 becomes available | ||||
|     args += "--cipher", config.get("Globals", "OPENVPN_CIPHER")["value"] | ||||
|     args += "--auth", config.get("Globals", "OPENVPN_AUTH")["value"] | ||||
|  | ||||
|     # Just to sanity check ourselves | ||||
|     args += "--tls-cert-profile", "preferred", | ||||
|  | ||||
|     # Disable cipher negotiation since we know what we want | ||||
|     args += "--ncp-disable", | ||||
|  | ||||
|     args += "--script-security", "2", | ||||
|     args += "--learn-address", "/helpers/openvpn-learn-address.py" | ||||
|     args += "--client-connect", "/helpers/openvpn-client-connect.py" | ||||
|     args += "--verb", "0", | ||||
|  | ||||
|     logger.info("Executing: %s" % (" ".join(args))) | ||||
|     os.execv(executable, args) | ||||
|  | ||||
|  | ||||
| @click.command("strongswan", help="Start StrongSwan") | ||||
| @click.option("--client-subnet-slot", "-s", type=int, help="Client subnet slot index") | ||||
| @waitfile(const.SELF_CERT_PATH) | ||||
| def pinecone_serve_strongswan(client_subnet_slot): | ||||
|     from pinecrypt.server import config | ||||
|     slots = [] | ||||
|     slots.append(const.CLIENT_SUBNET4_SLOTS[client_subnet_slot]) | ||||
|     if const.CLIENT_SUBNET6: | ||||
|         slots.append(const.CLIENT_SUBNET6_SLOTS[client_subnet_slot]) | ||||
|  | ||||
|     with open("/etc/ipsec.conf", "w") as fh: | ||||
|         fh.write("config setup\n") | ||||
|         fh.write("  strictcrlpolicy=yes\n") | ||||
|         fh.write("  charondebug=\"cfg 2\"\n") | ||||
|  | ||||
|         fh.write("\n") | ||||
|         fh.write("ca authority\n") | ||||
|         fh.write("  auto=add\n") | ||||
|         fh.write("  cacert=%s\n" % const.AUTHORITY_CERTIFICATE_PATH) | ||||
|         fh.write("\n") | ||||
|         fh.write("conn s2c\n") | ||||
|         fh.write("  auto=add\n") | ||||
|         fh.write("  keyexchange=ikev2\n") | ||||
|  | ||||
|         fh.write("  left=%s\n" % const.AUTHORITY_NAMESPACE) | ||||
|         fh.write("  leftsendcert=always\n") | ||||
|         fh.write("  leftallowany=yes\n")  # For load-balancing | ||||
|         fh.write("  leftcert=%s\n" % const.SELF_CERT_PATH) | ||||
|         if const.PUSH_SUBNETS: | ||||
|             fh.write("  leftsubnet=%s\n" % ",".join([str(j) for j in const.PUSH_SUBNETS])) | ||||
|         fh.write("  leftupdown=/helpers/updown.py\n") | ||||
|  | ||||
|         fh.write("  right=%any\n") | ||||
|         fh.write("  rightsourceip=%s\n" % ",".join([str(j) for j in slots])) | ||||
|         fh.write("  ike=%s!\n" % config.get("Globals", "STRONGSWAN_IKE")["value"]) | ||||
|         fh.write("  esp=%s!\n" % config.get("Globals", "STRONGSWAN_ESP")["value"]) | ||||
|     with open("/etc/ipsec.conf") as fh: | ||||
|         print(fh.read()) | ||||
|  | ||||
|     # Why do you do this StrongSwan?! You will parse the cert anyway, | ||||
|     # why do I need to distinguish ECDSA vs RSA in config?! | ||||
|     with open(const.SELF_CERT_PATH, "rb") as fh: | ||||
|         certificate_buf = fh.read() | ||||
|         header, _, certificate_der_bytes = pem.unarmor(certificate_buf) | ||||
|         certificate = x509.Certificate.load(certificate_der_bytes) | ||||
|         public_key = asymmetric.load_public_key(certificate["tbs_certificate"]["subject_public_key_info"]) | ||||
|     with open("/etc/ipsec.secrets", "w") as fh: | ||||
|         fh.write(": %s %s\n" % ( | ||||
|             "ECDSA" if public_key.algorithm == "ec" else "RSA", | ||||
|             const.SELF_KEY_PATH | ||||
|         )) | ||||
|     executable = "/usr/sbin/ipsec" | ||||
|     args = executable, "start", "--nofork" | ||||
|     logger.info("Executing: %s" % (" ".join(args))) | ||||
|     instance = "%s-ipsec" % const.FQDN | ||||
|  | ||||
|     db.certificates.update_many({ | ||||
|         "instance": instance | ||||
|     }, { | ||||
|         "$unset": { | ||||
|             "ip": "", | ||||
|             "instance": "", | ||||
|         } | ||||
|     }) | ||||
|  | ||||
|     # TODO: Find better way to push env vars to updown script | ||||
|     with open("/instance", "w") as fh: | ||||
|         fh.write(instance) | ||||
|     os.execv(executable, args) | ||||
|  | ||||
|  | ||||
| pinecone_serve.add_command(pinecone_serve_openvpn) | ||||
| pinecone_serve.add_command(pinecone_serve_strongswan) | ||||
| pinecone_serve.add_command(pinecone_serve_backend) | ||||
| pinecone_serve.add_command(pinecone_serve_ocsp_responder) | ||||
| pinecone_serve.add_command(pinecone_serve_events) | ||||
|   | ||||
| @@ -6,7 +6,6 @@ import socket | ||||
| import sys | ||||
| from datetime import timedelta | ||||
| from ipaddress import ip_network | ||||
| from math import log, ceil | ||||
|  | ||||
| RE_USERNAME = r"^[a-z][a-z0-9]+$" | ||||
| RE_FQDN = r"^(([a-z0-9]|[a-z0-9][a-z0-9\-_]*[a-z0-9])\.)+([a-z0-9]|[a-z0-9][a-z0-9\-_]*[a-z0-9])?$" | ||||
| @@ -46,11 +45,11 @@ CURVE_NAME = "secp384r1" | ||||
| # Kerberos-like clock skew tolerance | ||||
| CLOCK_SKEW_TOLERANCE = timedelta(minutes=5) | ||||
|  | ||||
| AUTHORITY_PRIVATE_KEY_PATH = "/var/lib/certidude/authority-secrets/ca_key.pem" | ||||
| AUTHORITY_CERTIFICATE_PATH = "/var/lib/certidude/server-secrets/ca_cert.pem" | ||||
| SELF_CERT_PATH = "/var/lib/certidude/server-secrets/self_cert.pem" | ||||
| SELF_KEY_PATH = "/var/lib/certidude/server-secrets/self_key.pem" | ||||
| DHPARAM_PATH = "/var/lib/certidude/server-secrets/dhparam.pem" | ||||
| AUTHORITY_PRIVATE_KEY_PATH = "/authority-secrets/ca_key.pem" | ||||
| AUTHORITY_CERTIFICATE_PATH = "/server-secrets/ca_cert.pem" | ||||
| SELF_CERT_PATH = "/server-secrets/self_cert.pem" | ||||
| SELF_KEY_PATH = "/server-secrets/self_key.pem" | ||||
| DHPARAM_PATH = "/server-secrets/dhparam.pem" | ||||
| BUILDER_TARBALLS = "" | ||||
|  | ||||
| FQDN = socket.getfqdn() | ||||
| @@ -114,7 +113,7 @@ TOKEN_OVERWRITE_PERMITTED = os.getenv("TOKEN_OVERWRITE_PERMITTED") | ||||
| AUTHENTICATION_BACKENDS = set(["ldap"]) | ||||
| MAIL_SUFFIX = os.getenv("MAIL_SUFFIX") | ||||
|  | ||||
| KERBEROS_KEYTAB = os.getenv("KERBEROS_KEYTAB", "/var/lib/certidude/server-secrets/krb5.keytab") | ||||
| KERBEROS_KEYTAB = os.getenv("KERBEROS_KEYTAB", "/server-secrets/krb5.keytab") | ||||
| KERBEROS_REALM = os.getenv("KERBEROS_REALM") | ||||
| LDAP_AUTHENTICATION_URI = os.getenv("LDAP_AUTHENTICATION_URI") | ||||
| LDAP_GSSAPI_CRED_CACHE = os.getenv("LDAP_GSSAPI_CRED_CACHE", "/run/certidude/krb5cc") | ||||
| @@ -158,13 +157,9 @@ REQUEST_SUBMISSION_ALLOWED = os.getenv("REQUEST_SUBMISSION_ALLOWED") | ||||
| REVOCATION_LIST_LIFETIME = os.getenv("REVOCATION_LIST_LIFETIME") | ||||
|  | ||||
| PUSH_SUBNETS = [ip_network(j) for j in os.getenv("PUSH_SUBNETS", "").replace(" ", ",").split(",") if j] | ||||
|  | ||||
| CLIENT_SUBNET4 = ip_network(os.getenv("CLIENT_SUBNET4", "192.168.33.0/24")) | ||||
| CLIENT_SUBNET6 = ip_network(os.getenv("CLIENT_SUBNET6")) if os.getenv("CLIENT_SUBNET6") else None | ||||
| CLIENT_SUBNET_SLOT_COUNT = int(os.getenv("CLIENT_SUBNET_COUNT", 4)) | ||||
| divisions = ceil(log(CLIENT_SUBNET_SLOT_COUNT) / log(2)) | ||||
| CLIENT_SUBNET4_SLOTS = list(CLIENT_SUBNET4.subnets(divisions)) | ||||
| CLIENT_SUBNET6_SLOTS = list(CLIENT_SUBNET6.subnets(divisions)) if CLIENT_SUBNET6 else [] | ||||
|  | ||||
| if CLIENT_SUBNET4.netmask == str("255.255.255.255"): | ||||
|     raise ValueError("Invalid client subnet specification: %s" % CLIENT_SUBNET4) | ||||
|   | ||||
							
								
								
									
										21
									
								
								pinecrypt/server/templates/ipsec.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								pinecrypt/server/templates/ipsec.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| config setup | ||||
|   strictcrlpolicy=yes | ||||
|   charondebug="cfg 2" | ||||
|  | ||||
| ca authority | ||||
|   auto=add | ||||
|   cacert=/server-secrets/ca_cert.pem | ||||
|  | ||||
| conn s2c | ||||
|   auto=add | ||||
|   keyexchange=ikev2 | ||||
|   left={{ authority_namespace }} | ||||
|   leftsendcert=always | ||||
|   leftallowany=yes | ||||
|   leftcert=/server-secrets/self_cert.pem | ||||
|   leftsubnet={% for subnet in push %}{{ subnet }},{% endfor %} | ||||
|   leftupdown=/helpers/updown.py | ||||
|   right=%any | ||||
|   rightsourceip={{ slot4 }}{% if slot6 %},{{ slot6 }}{% endif %} | ||||
|   ike={{ strongswan_ike }}! | ||||
|   esp={{ strongswan_esp }}! | ||||
							
								
								
									
										69
									
								
								pinecrypt/server/templates/openvpn.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								pinecrypt/server/templates/openvpn.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| {% if proto == "udp" %} | ||||
| dev tun0 | ||||
| proto udp | ||||
| port 1194 | ||||
| management 127.0.0.1 7505 | ||||
| setenv service openvpn-udp | ||||
| {% else %} | ||||
| dev tun1 | ||||
| port-share 127.0.0.1 1443 | ||||
| proto tcp-server | ||||
| port 443 | ||||
| socket-flags TCP_NODELAY | ||||
| management 127.0.0.1 7506 | ||||
| setenv service openvpn-tcp | ||||
| {% endif %} | ||||
|  | ||||
| # Client subnets | ||||
| server {{ slot4.network_address }} {{ slot4.netmask }} | ||||
| {% if slot6 %} | ||||
| server-ipv6 {{ slot6 }} | ||||
| {% endif %} | ||||
| topology subnet | ||||
|  | ||||
| # Bind to all interfaces | ||||
| local 0.0.0.0 | ||||
|  | ||||
| # Send keep alive packets, mainly for UDP | ||||
| keepalive 60 120 | ||||
|  | ||||
| opt-verify | ||||
|  | ||||
| # Keypairs | ||||
| key /server-secrets/self_key.pem | ||||
| cert /server-secrets/self_cert.pem | ||||
| ca /server-secrets/ca_cert.pem | ||||
|  | ||||
| # Push subnets | ||||
| {% if push %} | ||||
| push "route-metric 10002 | ||||
| {% endif %} | ||||
| {% for subnet in push4 %} | ||||
| push "route {{ subnet.network_address }} {{ subnet.netmask }}" | ||||
| {% endfor %} | ||||
| {% for subnet in push6 %} | ||||
| push "route-ipv6 {{ subnet }}" | ||||
| {% endfor %} | ||||
|  | ||||
| # DH parameters file | ||||
| dh none | ||||
| #dhparam.pem | ||||
|  | ||||
| # Control channel encryption parameterss | ||||
| # For more info see: openvpn --show-tls | ||||
| tls-version-min {{ openvpn_tls_version_min }} | ||||
| tls-ciphersuites {{ openvpn_tls_ciphersuites }} # Used by TLS 1.3 | ||||
| tls-cipher {{ openvpn_tls_cipher }} # Used by TLS 1.2 | ||||
|  | ||||
| # Data channel encryption parameters | ||||
| cipher {{ openvpn_cipher }} | ||||
| auth {{ openvpn_auth }} | ||||
|  | ||||
| # Just to sanity check ourselves | ||||
| tls-cert-profile preferred | ||||
|  | ||||
| script-security 2 | ||||
| learn-address /helpers/learn-address.py | ||||
| client-connect /helpers/client-connect.py | ||||
| #verb 0 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user