背景
- 今までtomcatでSSLといえば、JavaネイティブのJSSEで実装されたコネクタ(Http11NioProtocol)を使い、キーはJKS(Java Key Store)で管理するのが一般的だったと思う。
- OpenSSLでキー、証明書を管理するのが一般的なケースが多く、PEM形式のキー、証明書をどうのように組み込みか?毎回悩んでしまう。
- tomcatも進化し、pem形式への対応は行われている。
- さらにAPRは、openSSLをエンジンとしてそのまま利用でき、スケーラビリティ、パフォーマンス、管理面で優位であると言われる。
- HTTP2を利用するには、Java8のTLS実装ではALPNをサポートしておらず、OpenSSLのTLS実装を使うしか方法はない。
server.xml内のコメントに以下の記述あり
Because Java 8's TLS implementation does not support ALPN (which is required for
HTTP/2 oves TLS),
you must be using an OpenSSL based TLS implementation to enable HTTP/2 support.
See the sslImplementationName attribute of the Connector.
- JavaはPSK未実装のためPSKを利用する場合は、APRコネクタ + OpenSSLエンジン一択。opensslはPSK対応。
$ openssl ciphers -v PSK
PSK-AES256-CBC-SHA SSLv3 Kx=PSK Au=PSK Enc=AES(256) Mac=SHA1
PSK-AES128-CBC-SHA SSLv3 Kx=PSK Au=PSK Enc=AES(128) Mac=SHA1
PSK-RC4-SHA SSLv3 Kx=PSK Au=PSK Enc=RC4(128) Mac=SHA1
PSK-3DES-EDE-CBC-SHA SSLv3 Kx=PSK Au=PSK Enc=3DES(168) Mac=SHA1
tomcatでのPEM形式証明書でのSSL構成として以下の3つが考えられる。APRを利用した構成(2.3.)について導入、設定を確認する。
- JSSE + PEM
- APR + OpenSSL + PEM
- APR + OpenSSL + ALPN(HTTP2) + PEM
APRを導入する
- libapr1-devパッケージのインストール
root@v_ubuntu_64:/# apt list libapr1-dev
Listing... Done
libapr1-dev/bionic 1.6.3-2 amd64
root@v_ubuntu_64:/# apt install libapr1-dev
- libssl-devパッケージのインストール
root@v_ubuntu_64:/# apt list libssl-dev
Listing... Done
libssl-dev/bionic-updates,bionic-security 1.1.0g-2ubuntu4.1 amd64
N: There is 1 additional version. Please use the '-a' switch to see it
root@v_ubuntu_64:/# apt install libssl-dev
- gcc/makeのインストール(確認) ※私のubuntu初期環境ではinstall済みでした
root@v_ubuntu_64:/# apt list gcc
Listing... Done
gcc/bionic,now 4:7.3.0-3ubuntu2 amd64 [installed]
root@v_ubuntu_64:/# apt list make
Listing... Done
make/bionic,now 4.1-9.1ubuntu1 amd64 [installed]
- APRコンポーネントのビルド、インストール
4.1. APRコンポーネントはtomcat-native.tar.gzにパッケージされていますが、"apt install tomcat8"では、インストールされていないので、別途、ここからダウンロード
4.2. ビルド作業ディレクトリで展開
# cd /home/tetsuohino/tomcat-apr-build/apache-tomcat-8.5.34/bin
# tar zxvf tomcat-native.tar.gz
4.3. 環境変数JAVA_HOMEの設定
* JRE_HOMEではなくJDK_HOMEを指定する
* 私のubuntu環境ではJREしかインストールされていなかったため、JDKをインストールし直しています。
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
# cd tomcat-native-1.2.17-src/native
# .configure
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking for working mkdir -p... yes
Tomcat Native Version: 1.2.17
checking for chosen layout... tcnative
checking for APR... yes
configure: APR 1.6.3 detected.
setting CC to "x86_64-linux-gnu-gcc"
setting CPP to "x86_64-linux-gnu-gcc -E"
setting LIBTOOL to "/usr/share/apr-1.0/build/libtool"
adding "-I/usr/lib/jvm/java-8-openjdk-amd64/include" to TCNATIVE_PRIV_INCLUDES
checking for JDK os include directory... linux
adding "-I/usr/lib/jvm/java-8-openjdk-amd64/include/linux" to TCNATIVE_PRIV_INCLUDES
checking for gcc... x86_64-linux-gnu-gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether x86_64-linux-gnu-gcc accepts -g... yes
checking for x86_64-linux-gnu-gcc option to accept ISO C89... none needed
checking for OpenSSL library... using openssl from /usr/${exec_prefix}/lib and /usr/include
checking OpenSSL library version >= 1.0.2... ok
checking for OpenSSL DSA support... yes
setting TCNATIVE_LDFLAGS to "-lssl -lcrypto"
adding "-DHAVE_OPENSSL" to CFLAGS
setting TCNATIVE_LIBS to ""
setting TCNATIVE_LIBS to " /usr/lib/x86_64-linux-gnu/libapr-1.la "
checking for apr_pollset_wakeup in -lapr-1... yes
adding "-DHAVE_POLLSET_WAKEUP" to CFLAGS
configure: creating ./config.status
config.status: creating tcnative.pc
config.status: creating Makefile
config.status: executing default commands
4.5. make
# make
make[1]: Entering directory '/home/tetsuohino/tomcat-apr-build/apache-tomcat-8.5.34/bin/tomcat-native-1.2.17-src/native'
/usr/share/apr-1.0/build/libtool --no-silent --mode=compile x86_64-linux-gnu-gcc -pthread -g -O2 -DHAVE_OPENSSL -DHAVE_POLLSET_WAKEUP -DHAVE_CONFIG_H -DLINUX -D_REENTRANT -D_GNU_SOURCE -g -O2 -DHAVE_OPENSSL -DHAVE_POLLSET_WAKEUP -I./include -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux -I/usr/include/apr-1.0 -o src/address.lo -c src/address.c && touch src/address.lo
libtool: compile: x86_64-linux-gnu-gcc -pthread -g -O2 -DHAVE_OPENSSL -DHAVE_POLLSET_WAKEUP -DHAVE_CONFIG_H -DLINUX -D_REENTRANT -D_GNU_SOURCE -g -O2 -DHAVE_OPENSSL -DHAVE_POLLSET_WAKEUP -I./include -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux -I/usr/include/apr-1.0 -c src/address.c -fPIC -DPIC -o src/.libs/address.o
....snip....
libtool: link: (cd ".libs" && rm -f "libtcnative-1.so.0" && ln -s "libtcnative-1.so.0.2.17" "libtcnative-1.so.0")
libtool: link: (cd ".libs" && rm -f "libtcnative-1.so" && ln -s "libtcnative-1.so.0.2.17" "libtcnative-1.so")
libtool: link: x86_64-linux-gnu-ar cru .libs/libtcnative-1.a src/address.o src/bb.o src/dir.o src/error.o src/file.o src/info.o src/jnilib.o src/lock.o src/misc.o src/mmap.o src/multicast.o src/network.o src/os.o src/poll.o src/pool.o src/proc.o src/shm.o src/ssl.o src/sslconf.o src/sslcontext.o src/sslinfo.o src/sslnetwork.o src/sslutils.o src/stdlib.o src/thread.o src/user.o os/unix/system.o os/unix/uxpipe.o
x86_64-linux-gnu-ar: `u' modifier ignored since `D' is the default (see `U')
libtool: link: x86_64-linux-gnu-ranlib .libs/libtcnative-1.a
libtool: link: ( cd ".libs" && rm -f "libtcnative-1.la" && ln -s "../libtcnative-1.la" "libtcnative-1.la" )
make[1]: Leaving directory '/home/tetsuohino/tomcat-apr-build/apache-tomcat-8.5.34/bin/tomcat-native-1.2.17-src/native'
4.6. make install
# make install
make[1]: Entering directory '/home/tetsuohino/tomcat-apr-build/apache-tomcat-8.5.34/bin/tomcat-native-1.2.17-src/native'
make[1]: Nothing to be done for 'local-all'.
make[1]: Leaving directory '/home/tetsuohino/tomcat-apr-build/apache-tomcat-8.5.34/bin/tomcat-native-1.2.17-src/native'
.... snip....
libtool: install: /usr/bin/install -c -m 755 .libs/libtcnative-1.so.0.2.17 /usr/local/apr/lib/libtcnative-1.so.0.2.17
libtool: install: (cd /usr/local/apr/lib && { ln -s -f libtcnative-1.so.0.2.17 libtcnative-1.so.0 || { rm -f libtcnative-1.so.0 && ln -s libtcnative-1.so.0.2.17 libtcn
libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/sbin" ldconfig -n /usr/local/apr/lib
----------------------------------------------------------------------
Libraries have been installed in:
/usr/local/apr/lib
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the 'LD_RUN_PATH' environment variable
during linking
- use the '-Wl,-rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to '/etc/ld.so.conf'
See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
- APRのインストール先を確認
# ls -l /usr/local/apr/lib
total 3044
-rw-r--r-- 1 root root 1971456 9月 25 20:06 libtcnative-1.a
-rwxr-xr-x 1 root root 1041 9月 25 20:06 libtcnative-1.la
lrwxrwxrwx 1 root root 23 9月 25 20:06 libtcnative-1.so -> libtcnative-1.so.0.2.17
lrwxrwxrwx 1 root root 23 9月 25 20:06 libtcnative-1.so.0 -> libtcnative-1.so.0.2.17
-rwxr-xr-x 1 root root 1131920 9月 25 20:06 libtcnative-1.so.0.2.17
drwxr-xr-x 2 root root 4096 9月 25 20:06 pkgconfig
APR + OpenSSL
server.conf設定例
<!-- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->
<Connector
protocol="org.apache.coyote.http11.Http11AprProtocol"
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateFile="/home/hoge/pem/server.crt"
certificateKeyFile="/home/hoge/pem/private.key"
certificateChainFile="/home/hoge/pem/bundle.crt"/>
</SSLHostConfig>
</Connector>
起動確認(catalina.log)
02-Oct-2018 10:48:37.106 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["https-openssl-apr-8443"]
...
02-Oct-2018 10:48:39.880 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["https-openssl-apr-8443"]
APR + OpenSSL + HTTP2
server.conf設定例
<!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
This connector uses the APR/native implementation which always uses
OpenSSL for TLS.
Either JSSE or OpenSSL style configuration may be used. OpenSSL style
configuration is used below.
-->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeyFile="/home/hoge/pem/private.key"
certificateFile="/home/hoge/pem/server.crt"
certificateChainFile="/home/hoge/pem/bundle.crt"
type="RSA" />
</SSLHostConfig>
</Connector>
起動確認(catalina.log)
["https-openssl-apr-8443"] connector has been configured to support negotiation to [h2] via ALPN
02-Oct-2018 10:52:06.257 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["https-openssl-apr-8443"]
...
02-Oct-2018 10:52:08.358 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["https-openssl-apr-8443"]
トラブルシュート
- 起動時に「Unable to load certificate key」というエラーが発生する。
- PEM形式の各証明書、キーファイルをtomcatの実行グループであること。
- 起動時に「java.io.FileNotFoundException: Configured file xxx does not exist」 というエラーが発生する。
- "."で区切られたディレクトリに格納されたキーファイル、証明書は見つけてくれない。