Mit der SNI-Technik (Server Name Indication, Wikipedia) ist es möglich, unter einer IP-Adresse mehrere virtuelle Hosts zu betreiben. Da das SSL-Zertifikat die Verbindung absichert, bevor der Zieldomainnamen übertragen wird, muss das Webserver-Zertifikat für alle Domains ausgestellt sein. Daraus ergibt sich auch der Nebeneffekt, dass www.example.com, example.com und *.example.com abgesichert werden können.
Grundlage ist das Perl-Script, dass unter http://wiki.cacert.org/VhostTaskForce#Perl_version abrufbar ist.
use strict;
my $config_file = "/tmp/openssl.cnf.$$"; #Where to write the config file
my $keyname; #Generally, the primary FQDN
my $org_unit; #Organisational unit for csr, ie Web Services
my @altnames; #Alternate dns names for csr, ie www1.example.com, www1.example.net etc
my $altname; #Alternate dns names for csr, ie www1.example.com, www1.example.net etc
my $altcount = 1; #Can only have 16 or less alts (when submitting to Verisign)
my $altflag = 1; #flag for my while loop
my @config_out; #Populate with all info for the config file.
my $email_address; #email address to be tagged on the certificate
my $proc_base_name; #basename of the process, simply for naming conventions
my $mutual_tls = "y"; #flag for mutual tls for client app stuff
my $home = `echo \$HOME`; #Get user's home directory to store files in.
chomp $home;
my $random_file = "$home/.rnd"; #openssl for hpux needs a .rnd file to work
# If config file exists, exit and alert user
if (-e $config_file) {
`rm $config_file`;
}
if (!-e $random_file) {
`dd bs=512 count=4 if=/dev/null of=$random_file`
##die ("Random file couldn't be found at $random_file\n");
}
# Open config file to write ssl stuff out to
open (CONFIG, ">$config_file")||die "Can't open $config_file for writing\n";
# Start getting info from user
print ("Generate SSL Cert stuff for SAPI\n");
print ("FQDN/Keyname for Cert \(ie www.example.com\)\t\t:");
chomp ($keyname=);
while ($altflag) {
print ("Alt Names (ie www1.example.com or for none)\t\t\t:");
chomp($altname=);
if ($altcount 16) {
if ($altname eq $keyname) {
print (" ****** Alternate name can not equal main keyname ******\n");
} elsif ($altname ne "") {
push (@altnames, "DNS:$altname");
$altcount++;
} else {
$altflag=0;
}
} else {
$altflag=0;
}
}
print ("Host short name (ie imap big_srv etc)\t\t\t\t:");
chomp ($proc_base_name=);
# Start building the config file
push (@config_out, "# -------------- BEGIN custom openssl.cnf -----\n");
push (@config_out, "HOME = $home\n");
push (@config_out, "RANDFILE = $random_file\n");
push (@config_out, "oid_section = new_oids\n");
push (@config_out, "[ new_oids ]\n");
push (@config_out, "[ req ]\n");
push (@config_out, "default_bits = 2048\n");
push (@config_out, "default_days = 730 # how long to certify for\n");
push (@config_out, "default_keyfile = $home/${proc_base_name}_privatekey.pem\n");
push (@config_out, "distinguished_name = req_distinguished_name\n");
push (@config_out, "encrypt_key = no\n");
push (@config_out, "string_mask = nombstr\n");
push (@config_out, "req_extensions = v3_req # Extensions to add to certificate request\n");
push (@config_out, "[ req_distinguished_name ]\n");
push (@config_out, "commonName = Common Name (eg, YOUR name)\n");
push (@config_out, "commonName_default = $keyname\n");
push (@config_out, "commonName_max = 64\n");
push (@config_out, "[ v3_req ]\n");
if (@altnames[0] ne "") {
$altname=join(',', @altnames);
push (@config_out, "subjectAltName=$altname\n");
}
push (@config_out, "# -------------- END OpsSec-provided openssl.cnf -----\n");
# Write shit to file
print (CONFIG "@config_out");
close CONFIG;
# Generate ssl stuff
print ("\nAttempting openssl...\n");
system ("openssl req -batch -config $config_file -newkey rsa:2048 -out $home/${proc_base_name}_csr.pem");
print ("\nwriting csr to $home/${proc_base_name}_csr.pem...\n\n");
print ("Take the contents of $home/${proc_base_name}_csr.pem and go submit them to receive an SSL ID. When you receive your public key back, you 'should' name it something like '${proc_base_name}_server.pem'. ");
`rm $config_file`;
Es kann mit folgenden Eingaben gefüttert werden:
www.example.com *.example.com example.com example.com
Damit werden im Benutzerverzeichnis die Dateien example.com_privatekey.pem und example.com_csr.pem erzeugt. Die csr-Datei ist die Zertifikatsanforderungsdatei, die nun bei einer Zertifikatsautorität eingereicht werden kann.
Von dort erhält man ein unterschriebenes Zertifikat, dass in der Apache-Datei /etc/apache2/ssl.crt/server.crt eingetragen wird.
Der private Teil des Schlüssels wird in der Datei /etc/apache2/ssl.key/server.key abgelegt.