LoginSignup
0
2

More than 3 years have passed since last update.

セキュアなIoTデバイス通信をやってみた(MbedTLS移植編-httpsテスト-サーバー構築)

Last updated at Posted at 2019-06-14

はじめに

2019年5月にIoTLTにてLTをさせていただきました。
その内容のフォローを記入しながら自分なりに整理していきたいと思います。

発表内容:
スタートアップIoTデバイスのセキュリティを考える

前回までのあらすじ

セキュアなIoTデバイス通信をやってみた(MbedTLS移植編-Provision)でATECC608Aから抜き出した公開鍵を使って、自己認証局から署名を行いデバイス証明書を作成しました。
その後、証明書をATECC608Aへ保存するところまで行いました。

今回の記事に関連するソースコードは下記にて公開中。
kmwebnet/ECC608-httpsconnection

https接続環境整備

httpsサーバーを構築し、接続先として設定する。
下記を参考に、最新のApacheとOpenSSL1.1.1で環境を構築する。
Apache2.4.37 + OpenSSL1.1.1aをソースからインストール

■サーバー証明書作成
デバイス側から、サーバーを認証するためのサーバー証明書を
前回セキュアなIoTデバイス通信をやってみた(MbedTLS移植編-Provision)で使用した
root-ca.crt
root-ca.key
signer-ca.crt
signer-ca.key
を用意する。

Openssl1.1.1のインストール先/usr/local/openssl-1.1.1の配下へCAディレクトリを作成、上記4つをその中へコピー、その中で証明書作成を行う。
以下のようにディレクトリを整える

cd /usr/local/openssl-1.1.1
mkdir certs
mkdir private
mkdir crl
mkdir newcerts
mkdir revoke

chmod 700 private
echo "01" > serial

touch index.txt

cp /usr/local/openssl-1.1.1/ssl/openssl.cnf .

openssl.cnfの設定内容。変更点のみ。

####################################################################
[ CA_default ]

dir             = /usr/local/openssl-1.1.1/CA           # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several ctificates with same subject.
new_certs_dir   = $dir/newcerts         # default place for new certs.

certificate     = $dir/signer-ca.pem    # The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/signer-ca.key # The private key
RANDFILE        = $dir/private/.rand    # private random number file


default_days    = 3650                  # how long to certify for
default_crl_days= 90                    # how long before next CRL
default_md      = sha256                # use SHA-256 by default
preserve        = no                    # keep passed DN ordering

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy          = policy_match

# For the CA policy
[ policy_match ]
countryName             = optional
stateOrProvinceName     = optional
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ svr_cert ]

# These extensions are added when 'ca' signs a request.

# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.

basicConstraints=CA:FALSE

# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.

# This is OK for an SSL server.
nsCertType                      = server

# For an object signing certificate this would be used.
# nsCertType = objsign

# For normal client use this is typical
# nsCertType = client, email

# and for everything including object signing:
# nsCertType = client, email, objsign

# This is typical in keyUsage for a client certificate.
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

# This will be displayed in Netscape's comment listbox.
nsComment                       = "OpenSSL Generated Certificate"

# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
subjectAltName= @alt_names

[ alt_names ]

DNS.1 = iot.testcorp.com //変更
DNS.2 = *.testcorp.com //変更

■サーバー証明書の秘密鍵とCSRを作成

openssl req -new -config openssl.cnf -newkey ec:<(openssl ecparam -name prime256v1) -keyout server.key -subj "/O=testcorp/OU=iot/CN=iot.testcorp.com" -out server.csr

■サーバー証明書を中間CAで署名

openssl ca -config openssl.cnf -extensions svr_cert -keyfile signer-ca.key -cert signer-ca.crt -in server.csr -out server.crt -days 3650

■完成したサーバー証明書のチェーンを作成する
apache2.4.8以降では、サーバー証明書の設定の仕方が変わったとのこと。
apache 2.4におけるSSL証明書の設定
証明書チェーン作成に対応するため、スクリプトを使う。
下記をbundle.shで保存、chmod +xで実行権限をつける。

#!/bin/sh
#
# Convert PEM Certificate to ca-bundle.crt format
#

test ! $1 && printf "Usage: `basename $0` certificate" && exit 1

# Friendly Name and Underline Friendly Name with equal signs
openssl x509 -in $1 -text -noout | sed -e 's/^  *Subject:.*CN=\([^,]*\).*/\1/p;t  c' -e 'd;:c' -e 's/./=/g'
# Output Fingerprint and swap = for :
openssl x509 -in $1 -noout -fingerprint | sed -e 's/=/: /'
# Output PEM Data:
echo 'PEM Data:'
# Output Certificate
openssl x509 -in $1
# Output Certificate text swapping Certificate with Certificate Ingredients
openssl x509 -in $1 -text -noout | sed -e 's/^Certificate:/Certificate Ingredients:/'

■bundle.shを使った証明書の連結
以下のように、サーバー証明書→中間証明書→ルートCA証明書の順番に連結させる。

[root@ CA]# ./bundle.sh server.crt > server.chain
[root@ CA]# ./bundle.sh signer-ca.pem >> server.chain
[root@ CA]# ./bundle.sh root-ca.pem >> server.chain

■接続htmlの準備

以下のようにテストページを用意する。

[root@ ~]# echo "<html><body><h1>It works</h1></body></html>" > /usr/local/httpd2/htdocs/index.html

■apache SSL設定
以下のように設定。変更点のみ記載。サーバー側からクライアント証明書を要求し、ATECC608Aからデバイス証明書を発行させる設定とする。

[root@ ~]# cat /usr/local/httpd2/conf/extra/httpd-ssl.conf

#
# When we also provide SSL we have to listen to the
# standard HTTP port (see above) and to the HTTPS port
#
Listen 4689

#   SSL Cipher Suite:
#   List the ciphers that the client is permitted to negotiate,
#   and that httpd will negotiate as the client of a proxied server.
#   See the OpenSSL documentation for a complete list of ciphers, and
#   ensure these follow appropriate best practices for this deployment.
#   httpd 2.2.30, 2.4.13 and later force-disable aNULL, eNULL and EXP ciphers,
#   while OpenSSL disabled these by default in 0.9.8zf/1.0.0r/1.0.1m/1.0.2a.
#SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4:!3DES
#SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4:!3DES

SSLCipherSuite "ECDHE-ECDSA-AES128-GCM-SHA256 \
ECDHE-ECDSA-AES256-GCM-SHA384 \
ECDHE-ECDSA-AES128-SHA \
ECDHE-ECDSA-AES256-SHA \
ECDHE-ECDSA-AES128-SHA256 \
ECDHE-ECDSA-AES256-SHA384 \
ECDHE-RSA-AES128-GCM-SHA256 \
ECDHE-RSA-AES256-GCM-SHA384 \
ECDHE-RSA-AES128-SHA \
ECDHE-RSA-AES256-SHA \
ECDHE-RSA-AES128-SHA256 \
ECDHE-RSA-AES256-SHA384 \
DHE-RSA-AES128-GCM-SHA256 \
DHE-RSA-AES256-GCM-SHA384 \
DHE-RSA-AES128-SHA \
DHE-RSA-AES256-SHA \
DHE-RSA-AES128-SHA256 \
DHE-RSA-AES256-SHA256"

#   User agents such as web browsers are not configured for the user's
#   own preference of either security or performance, therefore this
#   must be the prerogative of the web server administrator who manages
#   cpu load versus confidentiality, so enforce the server's cipher order.
SSLHonorCipherOrder off

#   SSL Protocol support:
#   List the protocol versions which clients are allowed to connect with.
#   Disable SSLv3 by default (cf. RFC 7525 3.1.1).  TLSv1 (1.0) should be
#   disabled as quickly as practical.  By the end of 2016, only the TLSv1.2
#   protocol or later should remain in use.
SSLProtocol all -SSLv3
SSLProxyProtocol all -SSLv3


##
## SSL Virtual Host Context
##

SSLStrictSNIVHostCheck off

<VirtualHost *:4689>

#   General setup for the virtual host
DocumentRoot "/usr/local/httpd2/htdocs"
ServerName iot.testcorp.com:4689
ServerAdmin you@example.com
LogLevel debug
ErrorLog "/usr/local/httpd2/logs/error_log"
TransferLog "/usr/local/httpd2/logs/access_log"

    <Directory "/usr/local/httpd2/htdocs">
        Options FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>


#   SSL Engine Switch:
#   Enable/Disable SSL for this virtual host.
SSLEngine on

#   Server Certificate:
#   Point SSLCertificateFile at a PEM encoded certificate.  If
#   the certificate is encrypted, then you will be prompted for a
#   pass phrase.  Note that a kill -HUP will prompt again.  Keep
#   in mind that if you have both an RSA and a DSA certificate you
#   can configure both in parallel (to also allow the use of DSA
#   ciphers, etc.)
#   Some ECC cipher suites (http://www.ietf.org/rfc/rfc4492.txt)
#   require an ECC certificate which can also be configured in
#   parallel.
SSLCertificateFile "/usr/local/openssl-1.1.1/CA/server.chain"
#SSLCertificateFile "/usr/local/httpd2/conf/server-dsa.crt"
#SSLCertificateFile "/usr/local/httpd2/conf/server-ecc.crt"

#   Server Private Key:
#   If the key is not combined with the certificate, use this
#   directive to point at the key file.  Keep in mind that if
#   you've both a RSA and a DSA private key you can configure
#   both in parallel (to also allow the use of DSA ciphers, etc.)
#   ECC keys, when in use, can also be configured in parallel
SSLCertificateKeyFile "/usr/local/openssl-1.1.1/CA/server.key"
#SSLCertificateKeyFile "/usr/local/httpd2/conf/server-dsa.key"
#SSLCertificateKeyFile "/usr/local/httpd2/conf/server-ecc.key"

#   Certificate Authority (CA):
#   Set the CA certificate verification path where to find CA
#   certificates for client authentication or alternatively one
#   huge file containing all of them (file must be PEM encoded)
#   Note: Inside SSLCACertificatePath you need hash symlinks
#         to point to the certificate files. Use the provided
#         Makefile to update the hash symlinks after changes.
#SSLCACertificatePath ""
SSLCACertificateFile "/usr/local/openssl-1.1.1/CA/root-ca.pem"

#   Client Authentication (Type):
#   Client certificate verification type and depth.  Types are
#   none, optional, require and optional_no_ca.  Depth is a
#   number which specifies how deeply to verify the certificate
#   issuer chain before deciding the certificate is not valid.
SSLVerifyClient require
SSLVerifyDepth  10

</VirtualHost>

ここまでで接続先サーバーの準備が完了した。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2