make_sni.sh revision 1fb799609e09dd1df20777bef567d27059d90202
842ae4bd224140319ae7feec1872b93dfd491143fielding#!/bin/sh
842ae4bd224140319ae7feec1872b93dfd491143fielding#
842ae4bd224140319ae7feec1872b93dfd491143fielding# Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding# contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding# this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding# The ASF licenses this file to You under the Apache License, Version 2.0
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet# (the "License"); you may not use this file except in compliance with
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd# the License. You may obtain a copy of the License at
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet#
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd# http://www.apache.org/licenses/LICENSE-2.0
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd#
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd# Unless required by applicable law or agreed to in writing, software
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd# distributed under the License is distributed on an "AS IS" BASIS,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet# See the License for the specific language governing permissions and
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet# limitations under the License.
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh#
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh# This script will populate a directory 'sni' with 3 sites, httpd.conf
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh# and certificates as to facilitate testing of TLS server name
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh# indication support (RFC 4366) or SNI.
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh#
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh# $Id$
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh#
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh#
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianhOPENSSL=${OPENSSL:-openssl}
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudetDOMAIN=${DOMAIN:-my-sni-test.org}
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudetDIR=${DIR:-$PWD/sni}
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet
ab5581cc78e9d865b0a6ab1404c53347b3276968rbb# List of hostnames automatically created by default.
886cd69ebf69e990dbc365be87ff8ea7cd681904rbbNAMES=${NAMES:-ape nut pear apple banana}
a3faf8e5d6d3ea5980c5caa7204d9207e1f0e49awrowe
ab5581cc78e9d865b0a6ab1404c53347b3276968rbb# IP address these hostnames are bound to.
1075efe007e7af339bde09cbb175d4f4d676eeb5rpluemIP=${IP:-127.0.0.1}
1075efe007e7af339bde09cbb175d4f4d676eeb5rpluem
1075efe007e7af339bde09cbb175d4f4d676eeb5rpluemargs=`getopt a:fd:D: $*`
1075efe007e7af339bde09cbb175d4f4d676eeb5rpluemif [ $? != 0 ]; then
029cfcadd33649e610c939d106dec96ca7f27bacniq echo "Syntax: $0 [-f] [-a IPaddress] [-d outdir] [-D domain ] [two or more vhost names ]"
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet echo " -f Force overwriting of outdir (default is $DIR)"
6e954603b02f2b7d4ad80af17d9b3cc6f0bacf69rbb echo " -d dir Directory to create the SNI test server in (default is $DIR)"
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb echo " -D domain Domain name to use for this test (default is $DOMAIN)"
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb echo " -a IP IP address to use for this virtual host (default is $IP)"
742318b93e89c311f66b55f426c4d9cf2c14628bjim echo " [names] List of optional vhost names (default is $NAMES)"
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh echo
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh echo "Example:"
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb echo " $0 -D SecureBlogsAreUs.com peter fred mary jane ardy"
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb echo
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet echo "Which will create peter.SecureBlogsAreUs.com, fred.SecureBlogsAreUs.com and"
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb echo "so on. Note that the _first_ FQDN is also the default for non SNI hosts. It"
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb echo "may make sense to give this host a generic name - and allow each of the real"
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb echo "SNI site as sub directories/URI's of this generic name; thus allowing the "
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet echo "few non-SNI browsers access."
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb exit 1
742318b93e89c311f66b55f426c4d9cf2c14628bjimfi
8a944f317ca393b84b03922a1eee0910cbd55aa3rbbset -- $args
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmfor i
28ce4a9baa76e678af814ec56aecaeeff7665f35trawickdo
28ce4a9baa76e678af814ec56aecaeeff7665f35trawick case "$i"
28ce4a9baa76e678af814ec56aecaeeff7665f35trawick in
28ce4a9baa76e678af814ec56aecaeeff7665f35trawick -f)
6e954603b02f2b7d4ad80af17d9b3cc6f0bacf69rbb FORCE=1
6e954603b02f2b7d4ad80af17d9b3cc6f0bacf69rbb shift;;
6e954603b02f2b7d4ad80af17d9b3cc6f0bacf69rbb -a)
6e954603b02f2b7d4ad80af17d9b3cc6f0bacf69rbb IP=$2; shift
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb shift;;
742318b93e89c311f66b55f426c4d9cf2c14628bjim -d)
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb DIR=$2; shift
283cab4ec4c440fe33ce47778d85b1208e169a87manoj shift;;
89211a3153be8b03353c3bfbca45fed67cb80f0bpquerna -D)
89211a3153be8b03353c3bfbca45fed67cb80f0bpquerna DOMAIN=$2; shift
89211a3153be8b03353c3bfbca45fed67cb80f0bpquerna shift;;
89211a3153be8b03353c3bfbca45fed67cb80f0bpquerna --)
029cfcadd33649e610c939d106dec96ca7f27bacniq shift; break;
029cfcadd33649e610c939d106dec96ca7f27bacniq esac
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudetdone
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet
8a944f317ca393b84b03922a1eee0910cbd55aa3rbbif [ $# = 1 ]; then
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb echo "Aborted - just specifing one vhost makes no sense for SNI testing. Go wild !"
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb exit 1
2def8e4a2a1ba0f35c4e355eb8402ae132bdc831bnicholesfi
a742cbb3e85669473b3233f30e3978bb6a20083cylavic
a742cbb3e85669473b3233f30e3978bb6a20083cylavicif [ $# -gt 0 ]; then
3c990331fc6702119e4f5b8ba9eae3021aea5265jim NAMES=$*
8a944f317ca393b84b03922a1eee0910cbd55aa3rbbfi
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb
8a944f317ca393b84b03922a1eee0910cbd55aa3rbbif ! openssl version | grep -q OpenSSL; then
e8fcc872d5caeea36adb6511f9d1ab6ce3fbb5c0jerenkrantz echo Aborted - your openssl is very old or misconfigured.
43f284aaf6c7a7753395bbe4f846bee9cd6a7cd2pquerna exit 1
8a944f317ca393b84b03922a1eee0910cbd55aa3rbbfi
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb
8a944f317ca393b84b03922a1eee0910cbd55aa3rbbset `openssl version`
8a944f317ca393b84b03922a1eee0910cbd55aa3rbbif test "0$2" \< "00.9"; then
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb echo Aborted - version of openssl too old, 0.9 or up required.
742318b93e89c311f66b55f426c4d9cf2c14628bjim exit 1
e8fcc872d5caeea36adb6511f9d1ab6ce3fbb5c0jerenkrantzfi
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb
a742cbb3e85669473b3233f30e3978bb6a20083cylavicif test -d ${DIR} -a "x$FORCE" != "x1"; then
a742cbb3e85669473b3233f30e3978bb6a20083cylavic echo Aborted - already an ${DIR} directory. Use the -f flag to overwrite.
a742cbb3e85669473b3233f30e3978bb6a20083cylavic exit 1
a742cbb3e85669473b3233f30e3978bb6a20083cylavicfi
3c990331fc6702119e4f5b8ba9eae3021aea5265jim
a742cbb3e85669473b3233f30e3978bb6a20083cylavicmkdir -p ${DIR} || exit 1
a742cbb3e85669473b3233f30e3978bb6a20083cylavicmkdir -p ${DIR}/ssl ${DIR}/htdocs ${DIR}/logs || exit 1
a742cbb3e85669473b3233f30e3978bb6a20083cylavic
a742cbb3e85669473b3233f30e3978bb6a20083cylavic# Create a 'CA' - keep using different serial numbers
a742cbb3e85669473b3233f30e3978bb6a20083cylavic# as the browsers get upset if they see an identical
a742cbb3e85669473b3233f30e3978bb6a20083cylavic# serial with a different pub-key.
a742cbb3e85669473b3233f30e3978bb6a20083cylavic#
a742cbb3e85669473b3233f30e3978bb6a20083cylavic# Note that we're not relying on the 'v3_ca' section as
a742cbb3e85669473b3233f30e3978bb6a20083cylavic# in the default openssl.conf file - so the certificate
a742cbb3e85669473b3233f30e3978bb6a20083cylavic# will be without the basicConstraints = CA:true and
a742cbb3e85669473b3233f30e3978bb6a20083cylavic# keyUsage = cRLSign, keyCertSign values. This is fine
3c990331fc6702119e4f5b8ba9eae3021aea5265jim# for most browsers.
3366b8d8fbf36b5c1b091d707ed2e3f17f57ba1ccolm#
3366b8d8fbf36b5c1b091d707ed2e3f17f57ba1ccolmserial=$$
3366b8d8fbf36b5c1b091d707ed2e3f17f57ba1ccolmopenssl req -new -nodes -batch \
eeeb16b24dadff55cbfbc6d357a739fe8275c7f4colm -x509 \
d540257904755584099edb7c66387a25c3503ccftrawick -days 10 -subj '/CN=Da Root/O=SNI testing/' -set_serial $serial \
a742cbb3e85669473b3233f30e3978bb6a20083cylavic -keyout ${DIR}/root.key -out ${DIR}/root.pem \
a742cbb3e85669473b3233f30e3978bb6a20083cylavic || exit 2
a742cbb3e85669473b3233f30e3978bb6a20083cylavic
a742cbb3e85669473b3233f30e3978bb6a20083cylavic
a742cbb3e85669473b3233f30e3978bb6a20083cylavic# Create the header for the example '/etc/hosts' file.
a742cbb3e85669473b3233f30e3978bb6a20083cylavic#
d540257904755584099edb7c66387a25c3503ccftrawickecho '# To append to your hosts file' > ${DIR}/hosts
d540257904755584099edb7c66387a25c3503ccftrawick
d540257904755584099edb7c66387a25c3503ccftrawick# Create a header for the httpd.conf snipped.
d540257904755584099edb7c66387a25c3503ccftrawick#
3366b8d8fbf36b5c1b091d707ed2e3f17f57ba1ccolmcat > ${DIR}/httpd-sni.conf << EOM
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb# To append to your httpd.conf file'
8a944f317ca393b84b03922a1eee0910cbd55aa3rbbListen ${IP}:443
8a944f317ca393b84b03922a1eee0910cbd55aa3rbbNameVirtualHost ${IP}:443
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb
8a944f317ca393b84b03922a1eee0910cbd55aa3rbbLoadModule ssl_module modules/mod_ssl.so
8a944f317ca393b84b03922a1eee0910cbd55aa3rbb
742318b93e89c311f66b55f426c4d9cf2c14628bjimSSLRandomSeed startup builtin
4b9d04712f3c887072645f9a628888998908467bjerenkrantzSSLRandomSeed connect builtin
a742cbb3e85669473b3233f30e3978bb6a20083cylavic
742318b93e89c311f66b55f426c4d9cf2c14628bjimLogLevel debug
89211a3153be8b03353c3bfbca45fed67cb80f0bpquernaTransferLog ${DIR}/logs/access_log
4b9d04712f3c887072645f9a628888998908467bjerenkrantzErrorLog ${DIR}/logs/error_log
11e076839c8d5a82d55e710194d0daac51390dbdsf
275419d6395e6f072962fb701b89accaff1f3690jerenkrantz# You'll get a warning about this.
275419d6395e6f072962fb701b89accaff1f3690jerenkrantz#
275419d6395e6f072962fb701b89accaff1f3690jerenkrantzSSLSessionCache none
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet
11e076839c8d5a82d55e710194d0daac51390dbdsf# Note that this SSL configuration is far
66d349e02d1a5a599a01c977d2c5b0009181f7deben# from complete - you propably will want
66d349e02d1a5a599a01c977d2c5b0009181f7deben# to configure SSLMutex-es and SSLSession
a742cbb3e85669473b3233f30e3978bb6a20083cylavic# Caches at the very least.
a742cbb3e85669473b3233f30e3978bb6a20083cylavic
89211a3153be8b03353c3bfbca45fed67cb80f0bpquerna<Directory />
89211a3153be8b03353c3bfbca45fed67cb80f0bpquerna Options None
66d349e02d1a5a599a01c977d2c5b0009181f7deben AllowOverride None
275419d6395e6f072962fb701b89accaff1f3690jerenkrantz Require all denied
275419d6395e6f072962fb701b89accaff1f3690jerenkrantz</Directory>
275419d6395e6f072962fb701b89accaff1f3690jerenkrantz
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet<Directory "${DIR}/htdocs">
1075efe007e7af339bde09cbb175d4f4d676eeb5rpluem allow from all
1075efe007e7af339bde09cbb175d4f4d676eeb5rpluem Require all granted
1075efe007e7af339bde09cbb175d4f4d676eeb5rpluem</Directory>
1075efe007e7af339bde09cbb175d4f4d676eeb5rpluem
dc9d4f49d36e64c0157d930cb22ca82a6291c0cbdgaudet# This first entry is also the default for non SNI
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh# supporting clients.
#
EOM
# Create the header of a sample BIND zone file.
#
(
echo "; Configuration sample to be added to the $DOMAIN zone file of BIND."
echo "\$ORIGIN $DOMAIN."
) > ${DIR}/zone-file
ZADD="IN A $IP"
INFO="and also the site you see when the browser does not support SNI."
set -- ${NAMES}
DEFAULT=$1
for n in ${NAMES}
do
FQDN=$n.$DOMAIN
serial=`expr $serial + 1`
# Create a certificate request for this host.
#
openssl req -new -nodes -batch \
-days 9 -subj "/CN=$FQDN/O=SNI Testing/" \
-keyout ${DIR}/$n.key -out ${DIR}/$n.req -batch \
|| exit 3
# And get it signed by our root authority.
#
openssl x509 -text -req \
-CA ${DIR}/root.pem -CAkey ${DIR}/root.key \
-set_serial $serial -in ${DIR}/$n.req -out ${DIR}/$n.pem \
|| exit 4
# Combine the key and certificate in one file.
#
cat ${DIR}/$n.pem ${DIR}/$n.key > ${DIR}/ssl/$n.crt
rm ${DIR}/$n.req ${DIR}/$n.key ${DIR}/$n.pem
LST="$LST
https://$FQDN/index.html"
# Create a /etc/host and bind-zone file example
#
echo "${IP} $FQDN $n" >> ${DIR}/hosts
echo "$n $ZADD" >> ${DIR}/zone-file
ZADD="IN CNAME $DEFAULT"
# Create and populate a docroot for this host.
#
mkdir -p ${DIR}/htdocs/$n || exit 1
echo We are $FQDN $INFO > ${DIR}/htdocs/$n/index.html || exit 1
# And change the info text - so that only the default/fallback site
# gets marked as such.
#
INFO="and you'd normally only see this site when there is proper SNI support."
# And create a configuration snipped.
#
cat >> ${DIR}/httpd-sni.conf << EOM
<VirtualHost ${IP}:443>
SSLEngine On
ServerName $FQDN:443
DocumentRoot ${DIR}/htdocs/$n
SSLCertificateChainFile ${DIR}/root.pem
SSLCertificateFile ${DIR}/ssl/$n.crt
TransferLog ${DIR}/logs/access_$n
</VirtualHost>
EOM
done
cat << EOM
SNI Files generated
===================
The directory ${DIR}/sni has been populated with the following
- root.key|pem Certificate authority root and key. (You could
import the root.pem key into your browser to
quell warnings about an unknown authority).
- hosts /etc/hosts file with fake entries for the hosts
- htdocs directory with one docroot for each domain,
each with a small sample file.
- ssl directory with an ssl cert (signed by root)
for each of the domains).
- logs logfiles, one for each domain and an
access_log for any misses.
SNI Test
========
A directory ${DIR}/sni has been created. Run an apache
server against it with
.../httpd -f ${DIR}/httpd-sni.conf
and keep an eye on ${DIR}/logs/error_log. When everything
is fine you will see entries like:
Feb 11 16:12:26 2008] [debug] Init:
SSL server IP/port overlap: ape.*:443 (httpd-sni.conf:24) vs. jane.*:443 (httpd-sni.conf:42)
for each vhost configured and a concluding warning:
[Mon Feb 11 16:12:26 2008] [warn] Init:
Name-based SSL virtual hosts only work for clients with TLS server name indication support (RFC 4366)
HOWEVER - If you see an entry like:
[Mon Feb 11 15:41:41 2008] [warn] Init:
You should not use name-based virtual hosts in conjunction with SSL!!
then you are either using an OpenSSL which is too old and/or you need to ensure that the
TLS Extensions are compiled into openssl with the 'enable-tlsext' flag. Once you have
recompiled or reinstalled OpenSSL with TLS Extensions you will have to recompile mod_ssl
to allow it to recognize SNI support.
Meanwhile add 'hosts' to your c:\windows\system32\drivers\etc\hosts
or /etc/hosts file as to point the various URL's to your server:
$LST
and verify that each returns its own name (and an entry in its
own ${DIR}/logs) file).
NOTE
====
Note that in the generated example the 'first' domain is special - and is the
catch all for non-SNI browsers. Depending on your circumstances it may make
sense to use a generic name - and have each of the SNI domains as subdirectories
(and hence URI's under this generic name). Thus allowing non SNI browsers also
access to those sites.
EOM
exit 0