c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx#!/bin/sh
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx#
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# Licensed to the Apache Software Foundation (ASF) under one or more
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# contributor license agreements. See the NOTICE file distributed with
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# this work for additional information regarding copyright ownership.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# The ASF licenses this file to You under the Apache License, Version 2.0
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# (the "License"); you may not use this file except in compliance with
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# the License. You may obtain a copy of the License at
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx#
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# http://www.apache.org/licenses/LICENSE-2.0
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx#
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# Unless required by applicable law or agreed to in writing, software
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# distributed under the License is distributed on an "AS IS" BASIS,
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# See the License for the specific language governing permissions and
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# limitations under the License.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx#
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# This script will populate a directory 'sni' with 3 sites, httpd.conf
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# and certificates as to facilitate testing of TLS server name
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# indication support (RFC 4366) or SNI.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx#
1fb799609e09dd1df20777bef567d27059d90202dirkx#
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxOPENSSL=${OPENSSL:-openssl}
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxDOMAIN=${DOMAIN:-my-sni-test.org}
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxDIR=${DIR:-$PWD/sni}
1fb799609e09dd1df20777bef567d27059d90202dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkx# List of hostnames automatically created by default.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxNAMES=${NAMES:-ape nut pear apple banana}
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkx# IP address these hostnames are bound to.
1fb799609e09dd1df20777bef567d27059d90202dirkxIP=${IP:-127.0.0.1}
1fb799609e09dd1df20777bef567d27059d90202dirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx# A certificate password for the .p12 files of the client
d745ba0f110b40026922ac40599ec47c511eafefdirkx# authentication test. Normally not set. However some browsers
d745ba0f110b40026922ac40599ec47c511eafefdirkx# require a password of at least 4 characters.
d745ba0f110b40026922ac40599ec47c511eafefdirkx#
d745ba0f110b40026922ac40599ec47c511eafefdirkxPASSWD=${PASSWD:-}
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkxargs=`getopt a:fd:D:p: $*`
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxif [ $? != 0 ]; then
1fb799609e09dd1df20777bef567d27059d90202dirkx echo "Syntax: $0 [-f] [-a IPaddress] [-d outdir] [-D domain ] [two or more vhost names ]"
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx echo " -f Force overwriting of outdir (default is $DIR)"
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx echo " -d dir Directory to create the SNI test server in (default is $DIR)"
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx echo " -D domain Domain name to use for this test (default is $DOMAIN)"
1fb799609e09dd1df20777bef567d27059d90202dirkx echo " -a IP IP address to use for this virtual host (default is $IP)"
d745ba0f110b40026922ac40599ec47c511eafefdirkx echo " -p str Password for the client certificate test (some browsers require a set password)"
cf3b56dc9c3033d7b20a3198b11865c1b311b6b4dirkx echo " [names] List of optional vhost names (default is $NAMES)"
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx echo
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx echo "Example:"
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx echo " $0 -D SecureBlogsAreUs.com peter fred mary jane ardy"
1fb799609e09dd1df20777bef567d27059d90202dirkx echo
1fb799609e09dd1df20777bef567d27059d90202dirkx echo "Which will create peter.SecureBlogsAreUs.com, fred.SecureBlogsAreUs.com and"
1fb799609e09dd1df20777bef567d27059d90202dirkx echo "so on. Note that the _first_ FQDN is also the default for non SNI hosts. It"
1fb799609e09dd1df20777bef567d27059d90202dirkx echo "may make sense to give this host a generic name - and allow each of the real"
1fb799609e09dd1df20777bef567d27059d90202dirkx echo "SNI site as sub directories/URI's of this generic name; thus allowing the "
1fb799609e09dd1df20777bef567d27059d90202dirkx echo "few non-SNI browsers access."
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx exit 1
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxfi
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxset -- $args
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxfor i
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxdo
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx case "$i"
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx in
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx -f)
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx FORCE=1
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx shift;;
1fb799609e09dd1df20777bef567d27059d90202dirkx -a)
1fb799609e09dd1df20777bef567d27059d90202dirkx IP=$2; shift
1fb799609e09dd1df20777bef567d27059d90202dirkx shift;;
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx -d)
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx DIR=$2; shift
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx shift;;
d745ba0f110b40026922ac40599ec47c511eafefdirkx -p)
d745ba0f110b40026922ac40599ec47c511eafefdirkx PASSWD=$2; shift
d745ba0f110b40026922ac40599ec47c511eafefdirkx shift;;
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx -D)
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx DOMAIN=$2; shift
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx shift;;
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx --)
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx shift; break;
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx esac
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxdone
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxif [ $# = 1 ]; then
cf3b56dc9c3033d7b20a3198b11865c1b311b6b4dirkx echo "Aborted - just specifing one vhost makes no sense for SNI testing. Go wild !"
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx exit 1
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxfi
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxif [ $# -gt 0 ]; then
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx NAMES=$*
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxfi
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxif ! openssl version | grep -q OpenSSL; then
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx echo Aborted - your openssl is very old or misconfigured.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx exit 1
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxfi
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxset `openssl version`
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxif test "0$2" \< "00.9"; then
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx echo Aborted - version of openssl too old, 0.9 or up required.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx exit 1
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxfi
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxif test -d ${DIR} -a "x$FORCE" != "x1"; then
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx echo Aborted - already an ${DIR} directory. Use the -f flag to overwrite.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx exit 1
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxfi
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxmkdir -p ${DIR} || exit 1
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxmkdir -p ${DIR}/ssl ${DIR}/htdocs ${DIR}/logs || exit 1
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# Create a 'CA' - keep using different serial numbers
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# as the browsers get upset if they see an identical
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# serial with a different pub-key.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx#
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# Note that we're not relying on the 'v3_ca' section as
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# in the default openssl.conf file - so the certificate
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# will be without the basicConstraints = CA:true and
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# keyUsage = cRLSign, keyCertSign values. This is fine
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# for most browsers.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx#
b39725d4d5fd6bc177cd55adbde927ea7a80af80dirkxserial=$RANDOM$$
b39725d4d5fd6bc177cd55adbde927ea7a80af80dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxopenssl req -new -nodes -batch \
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx -x509 \
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx -days 10 -subj '/CN=Da Root/O=SNI testing/' -set_serial $serial \
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx -keyout ${DIR}/root.key -out ${DIR}/root.pem \
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx || exit 2
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkxCDIR=${DIR}/client-xs-control
d745ba0f110b40026922ac40599ec47c511eafefdirkxmkdir -p ${CDIR}
d745ba0f110b40026922ac40599ec47c511eafefdirkx# Create some certificate authorities for testing client controls
d745ba0f110b40026922ac40599ec47c511eafefdirkx#
d745ba0f110b40026922ac40599ec47c511eafefdirkxopenssl req -new -nodes -batch \
d745ba0f110b40026922ac40599ec47c511eafefdirkx -x509 \
b39725d4d5fd6bc177cd55adbde927ea7a80af80dirkx -days 10 -subj '/CN=Da Second Root/O=SNI user access I/' -set_serial 2$serial$$\
d745ba0f110b40026922ac40599ec47c511eafefdirkx -keyout ${CDIR}/xs-root-1.key -out ${CDIR}/xs-root-1.pem \
d745ba0f110b40026922ac40599ec47c511eafefdirkx || exit 2
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkxopenssl req -new -nodes -batch \
d745ba0f110b40026922ac40599ec47c511eafefdirkx -x509 \
b39725d4d5fd6bc177cd55adbde927ea7a80af80dirkx -days 10 -subj '/CN=Da Second Root/O=SNI user access II/' -set_serial 3$serial$$ \
d745ba0f110b40026922ac40599ec47c511eafefdirkx -keyout ${CDIR}/xs-root-2.key -out ${CDIR}/xs-root-2.pem \
d745ba0f110b40026922ac40599ec47c511eafefdirkx || exit 2
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx# Create a chain of just the two access authorites:
d745ba0f110b40026922ac40599ec47c511eafefdirkxcat ${CDIR}/xs-root-2.pem ${CDIR}/xs-root-1.pem > ${CDIR}/xs-root-chain.pem
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx# And likewise a directory with the same information (using the
d745ba0f110b40026922ac40599ec47c511eafefdirkx# required 'hash' naming format
d745ba0f110b40026922ac40599ec47c511eafefdirkx#
d745ba0f110b40026922ac40599ec47c511eafefdirkxmkdir -p ${CDIR}/xs-root-dir || exit 1
d745ba0f110b40026922ac40599ec47c511eafefdirkxrm -f {$CDIR}/*.0
d745ba0f110b40026922ac40599ec47c511eafefdirkxln ${CDIR}/xs-root-1.pem ${CDIR}/xs-root-dir/`openssl x509 -noout -hash -in ${CDIR}/xs-root-1.pem`.0
d745ba0f110b40026922ac40599ec47c511eafefdirkxln ${CDIR}/xs-root-2.pem ${CDIR}/xs-root-dir/`openssl x509 -noout -hash -in ${CDIR}/xs-root-2.pem`.0
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx# Use the above two client certificate authorities to make a few users
d745ba0f110b40026922ac40599ec47c511eafefdirkxfor i in 1 2
d745ba0f110b40026922ac40599ec47c511eafefdirkxdo
d745ba0f110b40026922ac40599ec47c511eafefdirkx # Create a certificate request for a test user.
d745ba0f110b40026922ac40599ec47c511eafefdirkx #
d745ba0f110b40026922ac40599ec47c511eafefdirkx openssl req -new -nodes -batch \
d745ba0f110b40026922ac40599ec47c511eafefdirkx -days 9 -subj "/CN=User $i/O=SNI Test Crash Dummy Dept/" \
d745ba0f110b40026922ac40599ec47c511eafefdirkx -keyout ${CDIR}/client-$i.key -out ${CDIR}/client-$i.req -batch \
d745ba0f110b40026922ac40599ec47c511eafefdirkx || exit 3
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx # And get it signed by either our client cert issuing root authority.
d745ba0f110b40026922ac40599ec47c511eafefdirkx #
d745ba0f110b40026922ac40599ec47c511eafefdirkx openssl x509 -text -req \
d745ba0f110b40026922ac40599ec47c511eafefdirkx -CA ${CDIR}/xs-root-$i.pem -CAkey ${CDIR}/xs-root-$i.key \
b39725d4d5fd6bc177cd55adbde927ea7a80af80dirkx -set_serial 3$serial$$ -in ${CDIR}/client-$i.req -out ${CDIR}/client-$i.pem \
d745ba0f110b40026922ac40599ec47c511eafefdirkx || exit 4
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx # And create a pkcs#12 version for easy browser import.
d745ba0f110b40026922ac40599ec47c511eafefdirkx #
d745ba0f110b40026922ac40599ec47c511eafefdirkx openssl pkcs12 -export \
d745ba0f110b40026922ac40599ec47c511eafefdirkx -inkey ${CDIR}/client-$i.key -in ${CDIR}/client-$i.pem -name "Client $i" \
d745ba0f110b40026922ac40599ec47c511eafefdirkx -caname "Issuing client root $i" -certfile ${CDIR}/xs-root-$i.pem \
d745ba0f110b40026922ac40599ec47c511eafefdirkx -out ${CDIR}/client.p12 -passout pass:"$PASSWD" || exit 5
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx rm ${CDIR}/client-$i.req
d745ba0f110b40026922ac40599ec47c511eafefdirkxdone
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkx# Create the header for the example '/etc/hosts' file.
1fb799609e09dd1df20777bef567d27059d90202dirkx#
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxecho '# To append to your hosts file' > ${DIR}/hosts
1fb799609e09dd1df20777bef567d27059d90202dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkx# Create a header for the httpd.conf snipped.
1fb799609e09dd1df20777bef567d27059d90202dirkx#
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxcat > ${DIR}/httpd-sni.conf << EOM
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# To append to your httpd.conf file'
1fb799609e09dd1df20777bef567d27059d90202dirkxListen ${IP}:443
1fb799609e09dd1df20777bef567d27059d90202dirkxNameVirtualHost ${IP}:443
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxLoadModule ssl_module modules/mod_ssl.so
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxSSLRandomSeed startup builtin
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxSSLRandomSeed connect builtin
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxLogLevel debug
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxTransferLog ${DIR}/logs/access_log
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxErrorLog ${DIR}/logs/error_log
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# You'll get a warning about this.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx#
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxSSLSessionCache none
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkx# Note that this SSL configuration is far
1fb799609e09dd1df20777bef567d27059d90202dirkx# from complete - you propably will want
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick# to configure SSLSession Caches at the
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick# very least.
1fb799609e09dd1df20777bef567d27059d90202dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx<Directory />
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx Options None
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx AllowOverride None
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx Require all denied
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx</Directory>
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx<Directory "${DIR}/htdocs">
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx allow from all
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx Require all granted
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx</Directory>
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# This first entry is also the default for non SNI
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx# supporting clients.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx#
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxEOM
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkx# Create the header of a sample BIND zone file.
1fb799609e09dd1df20777bef567d27059d90202dirkx#
1fb799609e09dd1df20777bef567d27059d90202dirkx(
1fb799609e09dd1df20777bef567d27059d90202dirkx echo "; Configuration sample to be added to the $DOMAIN zone file of BIND."
1fb799609e09dd1df20777bef567d27059d90202dirkx echo "\$ORIGIN $DOMAIN."
1fb799609e09dd1df20777bef567d27059d90202dirkx) > ${DIR}/zone-file
1fb799609e09dd1df20777bef567d27059d90202dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkxZADD="IN A $IP"
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxINFO="and also the site you see when the browser does not support SNI."
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkxset -- ${NAMES}
1fb799609e09dd1df20777bef567d27059d90202dirkxDEFAULT=$1
1fb799609e09dd1df20777bef567d27059d90202dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxfor n in ${NAMES}
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxdo
00d6521b902bb0b381f3ffe7eff44f7978497e5cdirkx FQDN=$n.$DOMAIN
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx serial=`expr $serial + 1`
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx # Create a certificate request for this host.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx #
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx openssl req -new -nodes -batch \
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx -days 9 -subj "/CN=$FQDN/O=SNI Testing/" \
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx -keyout ${DIR}/$n.key -out ${DIR}/$n.req -batch \
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx || exit 3
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx # And get it signed by our root authority.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx #
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx openssl x509 -text -req \
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx -CA ${DIR}/root.pem -CAkey ${DIR}/root.key \
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx -set_serial $serial -in ${DIR}/$n.req -out ${DIR}/$n.pem \
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx || exit 4
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkx # Combine the key and certificate in one file.
1fb799609e09dd1df20777bef567d27059d90202dirkx #
1fb799609e09dd1df20777bef567d27059d90202dirkx cat ${DIR}/$n.pem ${DIR}/$n.key > ${DIR}/ssl/$n.crt
1fb799609e09dd1df20777bef567d27059d90202dirkx rm ${DIR}/$n.req ${DIR}/$n.key ${DIR}/$n.pem
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkx LST="$LST
1fb799609e09dd1df20777bef567d27059d90202dirkx https://$FQDN/index.html"
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkx # Create a /etc/host and bind-zone file example
1fb799609e09dd1df20777bef567d27059d90202dirkx #
1fb799609e09dd1df20777bef567d27059d90202dirkx echo "${IP} $FQDN $n" >> ${DIR}/hosts
1fb799609e09dd1df20777bef567d27059d90202dirkx echo "$n $ZADD" >> ${DIR}/zone-file
1fb799609e09dd1df20777bef567d27059d90202dirkx ZADD="IN CNAME $DEFAULT"
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx # Create and populate a docroot for this host.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx #
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx mkdir -p ${DIR}/htdocs/$n || exit 1
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx echo We are $FQDN $INFO > ${DIR}/htdocs/$n/index.html || exit 1
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx # And change the info text - so that only the default/fallback site
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx # gets marked as such.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx #
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx INFO="and you'd normally only see this site when there is proper SNI support."
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx # And create a configuration snipped.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx #
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx cat >> ${DIR}/httpd-sni.conf << EOM
1fb799609e09dd1df20777bef567d27059d90202dirkx<VirtualHost ${IP}:443>
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx SSLEngine On
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx ServerName $FQDN:443
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx DocumentRoot ${DIR}/htdocs/$n
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx SSLCertificateChainFile ${DIR}/root.pem
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx SSLCertificateFile ${DIR}/ssl/$n.crt
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx # Uncomment the following lines if you
d745ba0f110b40026922ac40599ec47c511eafefdirkx # want to only allow access to clients with
d745ba0f110b40026922ac40599ec47c511eafefdirkx # a certificate issued/signed by some
d745ba0f110b40026922ac40599ec47c511eafefdirkx # selection of the issuing authorites
d745ba0f110b40026922ac40599ec47c511eafefdirkx #
d745ba0f110b40026922ac40599ec47c511eafefdirkx # SSLCACertificate ${CDIR}/xs-root-1.pem # just root 1
d745ba0f110b40026922ac40599ec47c511eafefdirkx # SSLCACertificate ${CDIR}/xs-root-2.pem # just root 2
d745ba0f110b40026922ac40599ec47c511eafefdirkx # SSLCACertificate ${CDIR}/xs-root-chain.pem # 1 & 2
d745ba0f110b40026922ac40599ec47c511eafefdirkx # SSLCACertificateDir ${CDIR}/xs-root-dir # 1 & 2 - but as a directory.
d745ba0f110b40026922ac40599ec47c511eafefdirkx #
d745ba0f110b40026922ac40599ec47c511eafefdirkx # SSLVerifyClient require
d745ba0f110b40026922ac40599ec47c511eafefdirkx # SSLVerifyDepth 2
d745ba0f110b40026922ac40599ec47c511eafefdirkx #
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx TransferLog ${DIR}/logs/access_$n
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx</VirtualHost>
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxEOM
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxdone
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxcat << EOM
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxSNI Files generated
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx===================
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxThe directory ${DIR}/sni has been populated with the following
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx- root.key|pem Certificate authority root and key. (You could
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx import the root.pem key into your browser to
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx quell warnings about an unknown authority).
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx- hosts /etc/hosts file with fake entries for the hosts
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx- htdocs directory with one docroot for each domain,
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx each with a small sample file.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx- ssl directory with an ssl cert (signed by root)
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx for each of the domains).
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx- logs logfiles, one for each domain and an
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx access_log for any misses.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkxThe directory ${CDIR} contains optional test files to allow client
d745ba0f110b40026922ac40599ec47c511eafefdirkxauthentication testing:
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx- client*pem/p12 Files for client authentication testing. These
d745ba0f110b40026922ac40599ec47c511eafefdirkx need to be imported into the browser.
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx- xs-root-1/2 Certificate authority which has issued above
d745ba0f110b40026922ac40599ec47c511eafefdirkx client authentication certificates.
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx- xs-root-dir A directory specific for the SSLCACertificateDir
d745ba0f110b40026922ac40599ec47c511eafefdirkx directive.
d745ba0f110b40026922ac40599ec47c511eafefdirkx
d745ba0f110b40026922ac40599ec47c511eafefdirkx- xs-root-chain A chain of the two client xs authorities for the
d745ba0f110b40026922ac40599ec47c511eafefdirkx SSLCACertificate directive.
d745ba0f110b40026922ac40599ec47c511eafefdirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxSNI Test
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx========
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxA directory ${DIR}/sni has been created. Run an apache
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxserver against it with
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx .../httpd -f ${DIR}/httpd-sni.conf
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
00d6521b902bb0b381f3ffe7eff44f7978497e5cdirkxand keep an eye on ${DIR}/logs/error_log. When everything
00d6521b902bb0b381f3ffe7eff44f7978497e5cdirkxis fine you will see entries like:
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx Feb 11 16:12:26 2008] [debug] Init:
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx SSL server IP/port overlap: ape.*:443 (httpd-sni.conf:24) vs. jane.*:443 (httpd-sni.conf:42)
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
cf3b56dc9c3033d7b20a3198b11865c1b311b6b4dirkxfor each vhost configured and a concluding warning:
cf3b56dc9c3033d7b20a3198b11865c1b311b6b4dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx [Mon Feb 11 16:12:26 2008] [warn] Init:
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx Name-based SSL virtual hosts only work for clients with TLS server name indication support (RFC 4366)
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
00d6521b902bb0b381f3ffe7eff44f7978497e5cdirkxHOWEVER - If you see an entry like:
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx [Mon Feb 11 15:41:41 2008] [warn] Init:
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx You should not use name-based virtual hosts in conjunction with SSL!!
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
cf3b56dc9c3033d7b20a3198b11865c1b311b6b4dirkxthen you are either using an OpenSSL which is too old and/or you need to ensure that the
cf3b56dc9c3033d7b20a3198b11865c1b311b6b4dirkxTLS Extensions are compiled into openssl with the 'enable-tlsext' flag. Once you have
cf3b56dc9c3033d7b20a3198b11865c1b311b6b4dirkxrecompiled or reinstalled OpenSSL with TLS Extensions you will have to recompile mod_ssl
cf3b56dc9c3033d7b20a3198b11865c1b311b6b4dirkxto allow it to recognize SNI support.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxMeanwhile add 'hosts' to your c:\windows\system32\drivers\etc\hosts
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxor /etc/hosts file as to point the various URL's to your server:
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx$LST
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxand verify that each returns its own name (and an entry in its
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxown ${DIR}/logs) file).
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkxNOTE
1fb799609e09dd1df20777bef567d27059d90202dirkx====
1fb799609e09dd1df20777bef567d27059d90202dirkx
1fb799609e09dd1df20777bef567d27059d90202dirkxNote that in the generated example the 'first' domain is special - and is the
1fb799609e09dd1df20777bef567d27059d90202dirkxcatch all for non-SNI browsers. Depending on your circumstances it may make
1fb799609e09dd1df20777bef567d27059d90202dirkxsense to use a generic name - and have each of the SNI domains as subdirectories
1fb799609e09dd1df20777bef567d27059d90202dirkx(and hence URI's under this generic name). Thus allowing non SNI browsers also
1fb799609e09dd1df20777bef567d27059d90202dirkxaccess to those sites.
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxEOM
c002c44ee5c7e7258f4ba5c162461c24a0c179c2dirkxexit 0