Server Installation/OpenVPN: Unterschied zwischen den Versionen
(Doku erweitert) |
|||
Zeile 15: | Zeile 15: | ||
* Key Ablage unter /etc/ssl/private, Leserechte setzen (''chgrp ssl-cert *.key && chmod g-rw *.key''), Symlink auf aktuelles File erzeugen | * Key Ablage unter /etc/ssl/private, Leserechte setzen (''chgrp ssl-cert *.key && chmod g-rw *.key''), Symlink auf aktuelles File erzeugen | ||
* Diffie Hellman PEM: ''openssl dhparam -out /etc/openvpn/dh2048.pem 2048'' | * Diffie Hellman PEM: ''openssl dhparam -out /etc/openvpn/dh2048.pem 2048'' | ||
+ | |||
+ | === Zertifikatsanfrage === | ||
XCA/OpenSSL Vorlage (CN u. SubjectAltName entspr. Hostnamen ersetzen): | XCA/OpenSSL Vorlage (CN u. SubjectAltName entspr. Hostnamen ersetzen): | ||
Zeile 47: | Zeile 49: | ||
keyUsage=digitalSignature, nonRepudiation, keyEncipherment | keyUsage=digitalSignature, nonRepudiation, keyEncipherment | ||
basicConstraints=critical,CA:FALSE | basicConstraints=critical,CA:FALSE | ||
+ | |||
+ | === Konfiguration === | ||
+ | |||
+ | ==== opennet_users ==== | ||
+ | |||
+ | <pre> | ||
+ | port 1600 | ||
+ | proto udp6 | ||
+ | dev tun | ||
+ | float | ||
+ | ca /etc/ssl/certs/opennet-vpn-user_certchain.pem | ||
+ | cert /etc/ssl/<hostname>.opennet-initiative.de.crt | ||
+ | key /etc/ssl/private/<hostname>.opennet-initiative.de.key | ||
+ | dh /etc/openvpn/dh2048.pem | ||
+ | server 10.1.0.0 255.255.0.0 | ||
+ | #server-ipv6 2a01:a700:4629:fe00::/64 | ||
+ | #tun-ipv6 | ||
+ | mode server | ||
+ | tls-server | ||
+ | keepalive 10 120 | ||
+ | comp-lzo | ||
+ | max-clients 1000 | ||
+ | user openvpn | ||
+ | group openvpn | ||
+ | persist-key | ||
+ | persist-tun | ||
+ | |||
+ | status /var/log/openvpn/opennet_users.status.log | ||
+ | #log-append /var/log/openvpn/opennet_users.log | ||
+ | verb 2 | ||
+ | management localhost 7506 | ||
+ | |||
+ | # ip calc and portforwarding script call | ||
+ | script-security 2 | ||
+ | client-connect /etc/openvpn/opennet_users/connect_script.py | ||
+ | client-disconnect /etc/openvpn/opennet_users/disconnect_script.py | ||
+ | |||
+ | # check cert against opennet ca revocation list | ||
+ | capath /etc/openvpn/opennet_users/ca/ | ||
+ | |||
+ | # dns push for mobile clients | ||
+ | push "dhcp-option DOMAIN opennet-initiative.de" | ||
+ | push "dhcp-option DOMAIN-SEARCH opennet-initiative.de" | ||
+ | push "dhcp-option DOMAIN-SEARCH on" | ||
+ | push "dhcp-option DNS 10.1.0.1" | ||
+ | push "dhcp-option DNS 192.168.0.254" | ||
+ | |||
+ | # tunnel config push for all clients | ||
+ | push "persist-key" | ||
+ | push "persist-tun" | ||
+ | push "explicit-exit-notify 3" | ||
+ | </pre> | ||
+ | |||
+ | ==== opennet_ugw ==== | ||
+ | |||
+ | TODO. | ||
=== Portforwarding === | === Portforwarding === | ||
Zeile 215: | Zeile 273: | ||
In der OpenVPN User Instanz ('''opennet_users.conf''') sich selbst und einen alternativen DNS als DHCP Push Option aufnehmen: | In der OpenVPN User Instanz ('''opennet_users.conf''') sich selbst und einen alternativen DNS als DHCP Push Option aufnehmen: | ||
# dns push for mobile clients | # dns push for mobile clients | ||
− | + | ... siehe oben ... | |
push "dhcp-option DNS 10.1.0.1" | push "dhcp-option DNS 10.1.0.1" | ||
push "dhcp-option DNS 192.168.0.254" | push "dhcp-option DNS 192.168.0.254" |
Version vom 6. April 2014, 07:43 Uhr
Inhaltsverzeichnis |
Nutzerndokumentation
Grundinstallation
- openvpn + openssl installieren
- ein bzw. zwei Instanzen aufbauen: <system> = opennet_ugw (Usergateway-VPN) | opennet_users (User-VPN)
- /etc/openvpn/<system>/openssl.cnf als Kopie besorgen, Leserechte setzen (chmod go-rwx <system>)
- /etc/openvpn/opennet_<system>.conf anpassen (Kopie besorgen), Key + Cert anpassen
- CSR/Key erstellen: openssl req -days 3650 -nodes -new -keyout <hostname>.key -out <hostname>.csr -extensions server -config openssl.cnf
- CSR absenden und unterschreiben lassen, Cert File und Certchain Cert File erzeugen
- Cert Ablage unter /etc/ssl, Symlinks setzen auf aktuelles File
- Key Ablage unter /etc/ssl/private, Leserechte setzen (chgrp ssl-cert *.key && chmod g-rw *.key), Symlink auf aktuelles File erzeugen
- Diffie Hellman PEM: openssl dhparam -out /etc/openvpn/dh2048.pem 2048
Zertifikatsanfrage
XCA/OpenSSL Vorlage (CN u. SubjectAltName entspr. Hostnamen ersetzen):
oid_section = xca_oids [ xca_oids ] dom = 1.3.6.1.4.1.311.20.2 MsCaV = 1.3.6.1.4.1.311.21.1 msEFSFR = 1.3.6.1.4.1.311.10.3.4.1 iKEIntermediate = 1.3.6.1.5.5.8.2.2 nameDistinguisher = 0.2.262.1.10.7.20 id-kp-eapOverPPP = 1.3.6.1.5.5.7.3.13 id-kp-eapOverLAN = 1.3.6.1.5.5.7.3.14 [ req ] default_bits = 1024 default_keyfile = privkey.pem distinguished_name = xca_dn x509_extensions = xca_extensions req_extensions = xca_extensions string_mask = MASK:0x2002 utf8 = yes prompt = no [ xca_dn ] 0.C=DE 1.ST=Mecklenburg-Vorpommern 2.O=Opennet Initiative e.V. 3.OU=Opennet Server 4.CN=aqua.opennet-initiative.de 5.emailAddress=admin@opennet-initiative.de [ xca_extensions ] nsCertType=server subjectAltName=DNS:aqua.opennet-initiative.de, DNS:aqua.on-i.de, DNS:aqua.on keyUsage=digitalSignature, nonRepudiation, keyEncipherment basicConstraints=critical,CA:FALSE
Konfiguration
opennet_users
port 1600 proto udp6 dev tun float ca /etc/ssl/certs/opennet-vpn-user_certchain.pem cert /etc/ssl/<hostname>.opennet-initiative.de.crt key /etc/ssl/private/<hostname>.opennet-initiative.de.key dh /etc/openvpn/dh2048.pem server 10.1.0.0 255.255.0.0 #server-ipv6 2a01:a700:4629:fe00::/64 #tun-ipv6 mode server tls-server keepalive 10 120 comp-lzo max-clients 1000 user openvpn group openvpn persist-key persist-tun status /var/log/openvpn/opennet_users.status.log #log-append /var/log/openvpn/opennet_users.log verb 2 management localhost 7506 # ip calc and portforwarding script call script-security 2 client-connect /etc/openvpn/opennet_users/connect_script.py client-disconnect /etc/openvpn/opennet_users/disconnect_script.py # check cert against opennet ca revocation list capath /etc/openvpn/opennet_users/ca/ # dns push for mobile clients push "dhcp-option DOMAIN opennet-initiative.de" push "dhcp-option DOMAIN-SEARCH opennet-initiative.de" push "dhcp-option DOMAIN-SEARCH on" push "dhcp-option DNS 10.1.0.1" push "dhcp-option DNS 192.168.0.254" # tunnel config push for all clients push "persist-key" push "persist-tun" push "explicit-exit-notify 3"
opennet_ugw
TODO.
Portforwarding
Algorithmus
- Setze n gleich 10000.
- Falls der Common Name des client-Certificates weder der Form "*.aps.on" noch der Form "*.mobile.on" entspricht gibt es keine zu diesem System geforwardeten ports. Andernfalls:
- Falls der CN der Form "*.mobile.on" entspricht, setze n gleich n+2550
- Setze n gleich n+(10*([Systemnummer ("*" in oberen Beispielen)] -1))
- Die Portrange ist n bis n+9
Beispiel:
- CN des Zertifikats ist 14.mobile.on
- 10000
- 10000 + 255*10 = 12550
- 12550 + (10*(14-1)) = 12680
- Portbereich wäre dann von 12680 bis 12689
Sudo Rechte Connect Script
Damit das vom OpenVPN Daemon aufgerufene Connect-Script die DNAT Einträge erzeugen kann per visudo aufnehmen:
openvpn ALL=(root) NOPASSWD:/sbin/iptables
Hinweis: Der Aufruf muss dann auch mit voller Pfadangabe in den Scripten erfolgen.
Python Script connectcalc.py
#!/usr/bin/python import sys import os import socket import struct import re #config def extract_numstring_aps(cn): retval = int(cn[:-7]) if not (1 <= retval <= 255): raise ValueError('Invalid cn %r.' % cn) return retval def extract_numstring_aps_long(cn): retval = int(cn[2:-7]) if not (1 <= retval <= 255): raise ValueError('Invalid cn %r.' % cn) return retval def extract_numstring_wifidog_long(cn): retval = int(cn[2:-11]) if not (1 <= retval <= 255): raise ValueError('Invalid cn %r.' % cn) return retval def extract_numstring_mobile(cn): retval = int(cn[:-10]) if not (1 <= retval <= 255): raise ValueError('Invalid cn %r.' % cn) return retval client_ranges = { '[0-9][0-9]?[0-9]?\.aps\.on': (167838718, 4, 10000, extract_numstring_aps), #10.1.4.0 '1[\._-][0-9][0-9]?[0-9]?\.aps\.on': (167838718, 4, 10000, extract_numstring_aps_long), #10.1.4.0 '[0-9][0-9]?[0-9]?\.mobile\.on': (167839742, 4, 12550, extract_numstring_mobile), #10.1.8.0 '2[\._-][0-9][0-9]?[0-9]?\.aps\.on': (167841790, 4, 15100, extract_numstring_aps_long), #10.1.16.0 } # /config def iplongtostring(longip): return socket.inet_ntop(socket.AF_INET,struct.pack('>L',longip)) def get_targetvalues(client_cn): ipbase = 0; for cn_schema in client_ranges: if (re.match(cn_schema, client_cn)): (ipbase, step, portbase, ns_extractor) = client_ranges[cn_schema] cn_address = ns_extractor(client_cn); break if not ipbase: raise ValueError('Invalid CN %r.' % client_cn) return (ipbase, step, portbase, cn_address); def calc_targetip(ipbase, cn_address, step): targetip_long = ipbase + cn_address*step; targetip = iplongtostring(targetip_long); ifconfig_arg_1 = iplongtostring(targetip_long-1); return (targetip, ifconfig_arg_1); def calc_targetports(cn_address, portbase): targetport_begin = portbase + (cn_address-1)*10; targetport_end = targetport_begin+9; return (targetport_begin, targetport_end);
Python Script connect_script.py
#!/usr/bin/python from connectcalc import * target_filename = sys.argv[1] client_cn = os.getenv('common_name') if not client_cn: raise ValueError("Missing env-variable 'common_name'") ipbase, step, portbase, cn_address = get_targetvalues(client_cn); targetip, ifconfig_arg_1 = calc_targetip(ipbase, cn_address, step); targetport_begin, targetport_end = calc_targetports(cn_address, portbase); os.system('sudo /sbin/iptables -t nat -A user_dnat -p tcp --dport %s:%s -j DNAT --to-destination %s' % \ (targetport_begin, targetport_end, targetip)) os.system('sudo /sbin/iptables -t nat -A user_dnat -p udp --dport %s:%s -j DNAT --to-destination %s' % \ (targetport_begin, targetport_end, targetip)) target_file = file(target_filename, 'w') target_file.write('ifconfig-push %s %s\n' % (targetip, ifconfig_arg_1)) target_file.close()
Python Script disconnect_script.py
#!/usr/bin/python from connectcalc import * client_cn = os.getenv('common_name') if not client_cn: raise ValueError("Missing env-variable 'common_name'") ipbase, step, portbase, cn_address = get_targetvalues(client_cn); targetip, ifconfig_arg_1 = calc_targetip(ipbase, cn_address, step); targetport_begin, targetport_end = calc_targetports(cn_address, portbase); os.system('sudo /sbin/iptables -t nat -D user_dnat -p tcp --dport %s:%s -j DNAT --to-destination %s' % \ (targetport_begin, targetport_end, targetip)) os.system('sudo /sbin/iptables -t nat -D user_dnat -p udp --dport %s:%s -j DNAT --to-destination %s' % \ (targetport_begin, targetport_end, targetip))
Kontrolle
Es werden DNAT Einträge erzeugt, Kontrolle auf jedem GW Server mit:
iptables -L -v -n -t nat
In der Chain "user_dnat" sollen dann die Portweiterleitungen der mit OpenVPN verbundenen APs zu finden sein.
Bash Script tls-verify.sh
Mit einem gepatchten OpenVPN können Client Zertifikate exportiert werden. Hierzu hatten wir in Vergangenheit folgendes Script im Einsatz:
#!/bin/bash filename=$(echo $2 | awk 'BEGIN{RS="[/\\;.?$]";FS="="} {printf $2"_"} END{print".crt"}') cp $peer_cert /etc/openvpn/opennet_users/certs/${untrusted_ip}$filename
Eingebunden über diese Einträge im Config-File:
# added to export certs, only works with patched openvpn tls-export-cert /tmp tls-verify /etc/openvpn/opennet_users/tls_verify.sh
Diese Konfiguration kann nicht gleichzeitig mit dem CRL capath Check betrieben werden und ist daher hier nur geschichtlich dokumentiert.
DHCP Options: DNS + Domain
In der OpenVPN User Instanz (opennet_users.conf) sich selbst und einen alternativen DNS als DHCP Push Option aufnehmen:
# dns push for mobile clients ... siehe oben ... push "dhcp-option DNS 10.1.0.1" push "dhcp-option DNS 192.168.0.254"
Opennet CA CRL Aktualisierung
Um die CRL Dateien der Opennet CA abzuholen ist ein Cronjob notwendig. Technisches zur CA siehe auch Server Installation/Opennet CA.
CRL Download Script: http://svn.opennet-initiative.de/filedetails.php?repname=on_opennetca&path=%2Fopennetca_crldownload.sh)
Verzeichnis vorbereiten und Script ablegen (ggf. analog für ugw!):
apt-get install subversion mkdir /etc/ssl/crl/ cd /usr/share/ca-certificates/ mkdir opennet-initiative.de cd opennet-initiative.de wget http://ca.opennet-initiative.de/ca-bundle.tar.gz tar xfzv ca-bundle.tar.gz rm ca-bundle.tar.gz dpkg-reconfigure ca-certificates # ask -> checkmark new certs! cd /tmp svn checkout svn://svn.opennet-initiative.de/on_opennetca cp on_opennetca/opennetca_crldownload.sh /usr/local/sbin/ rm -rf on_opennetca
Crontab unter /etc/crontab erweitern (ggf. analog für ugw!):
# Opennet CA CRL Download, used by crl verify in openvpn process 45 1,13 * * * root opennetca_crldownload.sh opennet-root.crl /etc/ssl/crl /etc/ssl/certs/opennet-root.pem >/dev/null 45 1,13 * * * root opennetca_crldownload.sh opennet-vpn-user.crl /etc/ssl/crl /etc/ssl/certs/opennet-vpn-user.pem >/dev/null
Opennet CA CRL Überprüfung
In jeder OpenVPN Instanz (opennet_*.conf) die Certificate Revocation List (CRL) Überprüfung einschalten (analog für UGW Instanz):
# check cert against opennet ca revocation list capath /etc/openvpn/opennet_users/ca/
Hierzu das CA Verzeichnis wie folgt erstellen (analog für UGW Instanz):
cd /etc/openvpn/opennet_users mkdir ca chown openvpn:openvpn ca cd ca ln -s /etc/ssl/certs/opennet-root.pem `openssl x509 -hash -noout -in /etc/ssl/certs/opennet-root.pem`.0 ln -s /etc/ssl/crl/opennet-root.crl `openssl x509 -hash -noout -in /etc/ssl/certs/opennet-root.pem`.r0 ln -s /etc/ssl/certs/opennet-vpn-user.pem `openssl x509 -hash -noout -in /etc/ssl/certs/opennet-vpn-user.pem`.0 ln -s /etc/ssl/crl/opennet-vpn-user.crl `openssl x509 -hash -noout -in /etc/ssl/certs/opennet-vpn-user.pem`.r0