JKS文件格式
JKS(Java KeyStore)是Java和Ktor使用的证书格式。
你可以使用keytool来转换和管理这些证书。
CER文件格式
keytool -import -v -trustcacerts -alias keyAlias -file server.cer -keystore cacerts.jks -keypass changeit
复制代码
SSL
您可以购买证书并配置Ktor使用它,或者您可以使用Let's Encrypt自动获取免费证书以使用Ktor提供https://和wss://请求。
将Ktor配置为直接为单个域提供SSL证书,或者使用Docker和nginx轻松地在单个计算机上的不同容器中提供不同的应用程序。
使用Ktor直接提供的SSL
首先,您必须将域或子域配置为指向要用于证书的计算机的IP。 你必须在这里放置机器的公共IP。 如果该计算机位于路由器后面,则需要将路由器配置为使用主机对机器进行DMZ,或者至少将端口80(HTTP)重定向到该计算机,稍后您可能需要配置端口443(HTTPS )也是。
注:即使您将Ktor配置为绑定到另一个端口,Let’s Encrypt也将始终访问公共IP的PORT 80,您必须配置路由以将端口80重定向到托管ktor的计算机的正确本地IP和端口。
-
生成证书
要Ktor服务器能运行,您必须执行以下命令(changing my.example.com, root@example.com and 8889)。 此命令将启动指定端口中的HTTP Web服务器(必须在公共网络中作为端口80使用,或者您可以将路由器中的端口转发到80:8889,并且域必须指向您的公共IP),它 然后将请求,使用适当的内容公开/.well-known/acme-challenge/file,生成域私钥,并检索证书链:
export DOMAIN=my.example.com export EMAIL=root@example.com export PORT=8889 export ALIAS=myalias certbot certonly -n -d $DOMAIN --email "$EMAIL" --agree-tos --standalone --preferred-challenges http --http-01-port $PORT 复制代码
配置正常后会生成如下信息:
Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator standalone, Installer None Obtaining a new certificate Performing the following challenges: http-01 challenge for my.example.com Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/my.example.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/my.example.com/privkey.pem Your cert will expire on 2018-09-27. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le 复制代码
-
转换Ktor的私钥和证书
现在,您必须将certbot编写的私钥和证书转换为Ktor可以理解的格式。 链和私钥存储在/etc/letsencrypt/live/$DOMAIN中,作为fullchain.pem和privkey.pem。
openssl pkcs12 -export -out /etc/letsencrypt/live/$DOMAIN/keystore.p12 -inkey /etc/letsencrypt/live/$DOMAIN/privkey.pem -in /etc/letsencrypt/live/$DOMAIN/fullchain.pem -name $ALIAS 复制代码
这将为导出请求密码(您需要提供一个用于下一步工作的密码):
Enter Export Password: mypassword Verifying - Enter Export Password: mypassword 复制代码
使用p12文件,我们可以使用keytool cli生成JKS文件:
keytool -importkeystore -alias $ALIAS -destkeystore /etc/letsencrypt/live/$DOMAIN/keystore.jks -srcstoretype PKCS12 -srckeystore /etc/letsencrypt/live/$DOMAIN/keystore.p12 复制代码
-
配置Ktor以使用生成的JKS
现在,您必须更新application.conf HOCON文件,以配置SSL端口,keyStore,别名和密码。 您必须为特定情况设置正确的值:
ktor { deployment { port = 8889 port = ${?PORT} sslPort = 8890 sslPort = ${?PORT_SSL} } application { modules = [ com.example.ApplicationKt.module ] } security { ssl { keyStore = /etc/letsencrypt/live/mydomain.com/keystore.jks keyAlias = myalias keyStorePassword = mypassword privateKeyPassword = mypassword } } } 复制代码
如果一切顺利,Ktor应该在HTTP中侦听端口8889并在HTTPS中侦听端口8890。
使用Docker和Nginx作为反向代理
使用具有多个域的Docker时,您可能希望使用nginx-proxy映像和letsencrypt-nginx-proxy-companion映像在单个计算机/ip上提供多个域/子域,并使用Let's Encrypt自动提供HTTPS。
在这种情况下,您使用NGINX创建一个容器,可能会侦听端口80和443,内部网络只能在容器之间访问,因此nginx可以连接和反向代理您的网站(包括websockets),以及NGINX通过处理域证书 配置Docker容器。
- 创建内部docker网络
第一步是创建一个我们将使用的桥接网络,以便nginx可以连接到其他容器以反向代理用户的HTTP,HTTPS,WS和WSS请求:
docker network create --driver bridge reverse-proxy
复制代码
-
创建一个Nginx容器
现在我们必须创建一个运行NGINX的容器来执行反向代理:
docker rm -f nginx docker run -d -p 80:80 -p 443:443 \ --name=nginx \ --restart=always \ --network=reverse-proxy \ -v /home/virtual/nginx/certs:/etc/nginx/certs:ro \ -v /home/virtual/nginx/conf.d:/etc/nginx/conf.d \ -v /home/virtual/nginx/vhost.d:/etc/nginx/vhost.d \ -v /home/virtual/nginx/html:/usr/share/nginx/html \ -v /var/run/docker.sock:/tmp/docker.sock:ro \ -e NGINX_PROXY_CONTAINER=nginx \ --label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true \ jwilder/nginx-proxy 复制代码
--restart=always 当重新启动机器时,docker守护程序会重新启动容器。 --network=reverse-proxy NGINX在该网络中,可以连接到同一网络中的其他容器。 -v certs:ro 此卷将与letsencrypt-companion共享,以访问每个域的证书。 -v conf, vhost 如果您需要进行一些调整,这种配置是持久的,可以从外部访问。 -v /var/run/docker.sock 这允许此image获得有关在守护程序中运行的新容器的通知。 -e --label 由同伴使用,将此image标识为NGINX。
注:您可以将/home/virtual/nginx *路径调整为您喜欢的路径。
-
使用Let’s Encrypt来创建Nginx容器
docker rm -f nginx-letsencrypt docker run -d \ --name nginx-letsencrypt \ --restart=always \ --network=reverse-proxy \ --volumes-from nginx \ -v /home/virtual/nginx/certs:/etc/nginx/certs:rw \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ jrcs/letsencrypt-nginx-proxy-companion 复制代码
-
创建服务
现在我们用Let’s Encrypt配置了NGINX,这样他们就会根据环境变量VIRTUAL_HOST,VIRTUAL_PORT和LETSENCRYPT_HOST,LETSENCRYPT_EMAIL自动反向代理您的网站,并为他们请求和提供证书。
使用docker-compose,您可以创建一个docker-compose.yml文件(无需其他服务),如下所示:
docker-compose.yml
version: '2'
services:
web:
build:
context: ./
dockerfile: Dockerfile
expose:
- 8080
environment:
- VIRTUAL_HOST=mydomain.com
- VIRTUAL_PORT=8080
- LETSENCRYPT_HOST=mydomain.com
- LETSENCRYPT_EMAIL=myemail@mydomain.com
networks:
- reverse-proxy
restart: always
networks:
backend:
reverse-proxy:
external:
name: reverse-proxyv
复制代码
Dockerfile
FROM openjdk:8-jre-alpine
ENV APPLICATION_USER ktor
RUN adduser -D -g '' $APPLICATION_USER
RUN mkdir /app
RUN chown -R $APPLICATION_USER /app
USER $APPLICATION_USER
COPY ./build/libs/my-application.jar /app/my-application.jar
WORKDIR /app
CMD ["java", "-server", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap", "-XX:InitialRAMFraction=2", "-XX:MinRAMFraction=2", "-XX:MaxRAMFraction=2", "-XX:+UseG1GC", "-XX:MaxGCPauseMillis=100", "-XX:+UseStringDeduplication", "-jar", "my-application.jar"]
复制代码
XForwardedHeaderSupport功能
在这种情况下,您使用nginx作为请求的反向代理。 如果要获取有关原始请求的信息,而不是代理的nginx请求,则必须使用XForwardedHeaderSupport功能。