序文
Alpine LinuxのDockerイメージに基づいて、NginxのSSL構成に慣れるためのSSL証明書構成テスト環境を作成します。
準備
Dockerfile GitHub
FROM alpine:3.6
RUN apk add --no-cache python3 nginx curl openssl socat bash openrc &&\
mkdir /run/nginx &&\
touch /root/.bashrc &&\
echo "export PS1='\h:\w\\\$ '" >> /root/.bashrc &&\
echo "alias r='fc -e -'" >> /root/.bashrc &&\
echo "set -o vi" >> /root/.bashrc &&\
echo 'rc_provide="loopback net"' >> /etc/rc.conf &&\
rc-update add nginx default
VOLUME ["/tmp/sys/fs/cgroup","/sys/fs/cgroup"]
WORKDIR /root
CMD ["/sbin/init"]
Dockerイメージalssltestを作成する
# 获取Dockerfile 并创建镜像
git clone [email protected]:suzhi82/Alpine-SSLTEST.git &&\
cd Alpine-SSLTEST &&\
docker build -t alssltest .
# 查看Docker 镜像列表
docker image ls
# 或者
docker images
Dockerイメージalssltestを実行する
# 宿主机的8888 就当成80 来用,8001、8002 及8443 测试不同应用时用
docker run --name alssltest -itd \
-p 8888:80 -p 8443:8443 -p 8001:8001 -p 8002:8002 \
alssltest
パラメータ | 説明する |
---|---|
-名前 | 後で使用するためにコンテナーに名前を付けます。それ以外の場合は、コンテナーIDのみを使用できます |
-私 | 標準入力STDINを取得します。コンテナは、終了せずに常にユーザー入力を待機します |
-t | docker attachの準備をします。テーブルユーザーはttyに接続されます。そうでない場合、パスワードはプレーンテキストで表示されます |
-d | デタッチ、デタッチ、つまり、コンテナをバックグラウンドで実行します |
-p | ポートマッピング、ホストポート:コンテナーポート、このパラメーターを複数回使用して複数のポートをマッピングできます |
Dockerコンテナーalssltestを接続する
docker exec -it alssltest /bin/bash
コンテナーalssltest内部調整
cat /etc/nginx/nginx.conf
最後にhttp内に/etc/nginx/conf.d/*.confが含まれているのを確認
できるので、/etc/nginx/conf.d/
以下にテスト.conf構成ファイルを記述してから、
# 将默认的配置备份起来不启用
mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
OpenSSL自己署名SSL証明書
SSL自己署名証明書の生成
# 创建保存SSL 文件的目录
mkdir -p /etc/nginx/ssl_keys/openssl
cd /etc/nginx/ssl_keys/openssl
# 生成服务器端的私钥 (key 文件)
openssl genrsa -out server.key 1024
# 生成服务器端证书签名请求文件 (csr 文件),certificate signing request,自定义区域详见下表
openssl req -new -key server.key -out server.csr
# 生成证书文件 (crt 文件),csr 文件至此就没有用了
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
csrファイルの属性
自定义区域
Country Name (2 letter code) [XX]:CN--------------------------------- 证书持有者所在国家
State or Province Name (full name) []:BJ----------------------------- 证书持有者所在州或省份(可省略不填)
Locality Name (eg, city) []:BJ--------------------------------------- 证书持有者所在城市(可省略不填)
Organization Name (eg, company) []:NH-------------------------------- 证书持有者所属组织或公司
Organizational Unit Name (eg, section) []:.-------------------------- 证书持有者所属部门(可省略不填)
Common Name (eg, your name or your server's hostname) []:ceshi.com--- 域名
Email Address []:---------------------------------------------------- 邮箱(可省略不填)
challenge password:-------------------------------------------------- 自定义密码
An optional company name:-------------------------------------------- 可选公司名称
Nginx SSL構成
# Nginx 配置文件
cat > /etc/nginx/conf.d/openssl.conf << EOF
server {
listen 8443 ssl;
server_name ceshi.com;
ssl on;
ssl_certificate /etc/nginx/ssl_keys/openssl/server.crt;
ssl_certificate_key /etc/nginx/ssl_keys/openssl/server.key;
index index.html index.htm;
location / {
root /home/app/code;
}
}
EOF
テストファイルにアクセスする
mkdir -p /home/app/code/
cat > /home/app/code/index.html << EOF
<!DOCTYPE html>
<html lang="en">
<head>
<title>Index</title>
</head>
<body>
<h1>What a good day!</h1>
</body>
</html>
EOF
# 测试Nginx 配置
nginx -t
# 重启Nginx 服务
rc-service nginx restart
# 或者
nginx -s reload
再起動後、ブラウザでhttps://サーバーIP:8443にアクセスできます。Your connection is not private
ドットが表示されてHelp me understand
からをクリックするとProceed to 服务器IP (unsafe)
、What a good day!
アクセスが成功したことを示すために表示されますが、ブラウザによって信頼されていません。
OpenSSL使用の補足
# 去除key 文件中的密钥
openssl rsa -in jesonc.key -out jesonc_nopwd.key
# 符合苹果标准的签名文件,直接生成私钥key 和公钥crt,由于是自签所以省略了请求文件csr 的生成
openssl req -days 3650 -x509 -sha256 -nodes -newkey rsa:2048 -keyout new_server.key -out new_server.crt
# rsa:2048 是服务器私钥的算法,-sha256 是发给浏览器证书即公钥的算法,可用以下命令查看
openssl x509 -noout -text -in new_server.crt
Nginxトラブルシューティングの補足
Nginxによって開始されたユーザーは、ページファイルが置かれているフォルダーへの読み取りアクセス許可を持っている必要があります。それ以外の場合は、403エラーが報告されます
cat /etc/nginx/nginx.conf
# 启动nginx 所用的用户
user nginx;
# 错误日志的存放路径
error_log /var/log/nginx/error.log warn;
OpenSSL使用の結論
自己署名されているため、証明書を手動でブラウザーにインポートして信頼する必要があります。証明書アプリケーションを生成する場合、ブラウザーがサーバーのIPまたはドメイン名とIPを指すドメイン名を入力する限り、すべてのカスタム情報をスキップして直接返すことができます。ウェブサイトのコンテンツは対応するポートを介してアクセスでき、ユーザーのセキュリティを想像することができます。?
acme.sh SSL証明書の取得
通常のチャネルCAによって発行されたSSL証明書を取得する
Freenomドメイン名のCloudflare管理への移管
cme.shプロンプトに従ってtxtタイプのDNSレコードをfreenomに追加することで証明書を申請できますが、更新ごとに1回操作する必要があるため、DNS API自動化を使用しないよりも便利です。
まずhttps://www.freenom.comから無料のドメイン名を取得し、US IPのVPNに注意してください。
登録して目的のドメイン名を入力するだけです->可用性を確認してください。通常、tk / ml / gqなどの終わりは無料です。
登録してhttps://www.cloudflare.comにログインし、[ホーム]をクリックしてAdd a Site
、署名で取得したドメイン名を入力します。たとえばmaybook.tk
、[サイトを追加]、[プランを選択]、[無料$ 0 /月]を選択し、Change your nameservers
インターフェイスまで進みます。
https://www.freenom.com、Services-> My Domainsにログインし、maybook.tk
Manage Domain-> Management Tools- > Nameserversを選択Use custom nameservers
し、次の2つのサーバーを選択して書き込みます。
amit.ns.cloudflare.com
amy.ns.cloudflare.com
最後にをクリックしますChange Nameservers
。
Cloudflare Change your nameservers
ページに戻り、[完了]をクリックしてネームサーバーを確認します。ページがジャンプした場合は、[今すぐ再確認]ボタンをクリックします。Freenomのドメイン名がCloudflareに渡されるまでに数時間かかる場合があります。
Cloudflareが引き継ぐと、メール通知が送信されます。Cloudflareにログインした後、ステータスはmaybook.tk
[ アクティブ]になります。ステータスをクリックします。[
概要]の[ Get your API key]のAPIトークンは、Global API Key
サードパーティプログラムに、acme.sh
自動アプリケーションやSSL証明書の更新などのDNS設定を管理することを許可できます。
ドメイン名レコードを設定する
Cloudflare->ホームでmaybook.tk-> DNSを選択し、後で実験するために次のレコードを追加しますか?
タイプ | 名前 | コンテンツ | TTL | プロキシのステータス |
---|---|---|---|---|
あ | maybook.tk | 139.180.167.52 | 自動 | DNSのみ |
あ | app1.maybook.tk | 139.180.167.52 | 自動 | DNSのみ |
あ | app2.maybook.tk | 139.180.167.52 | 自動 | DNSのみ |
acme.shのインストールと使用
# 安装acme.sh
curl https://get.acme.sh | sh
# 使acme.sh 生效,重新进入容器也行
source ~/.bashrc
# 导入Cloudflare Token,即Global API Key,让acme.sh 控制DNS 记录以自动申请证书
export CF_Key="ba1a821xxxxxx42b603064xxxxxxx3443"
export CF_Email="[email protected]"
# 将非泛型域名放在第一位方便以后部署,因为* 是通配符。
# 用以下命令申请的SSL 证书会包含maybook.tk 及泛型*.maybook.tk 域名
acme.sh --issue --dns dns_cf -d maybook.tk -d *.maybook.tk
acme.shの実行後、DNS API情報はに保存されます。~/.acme.sh/account.conf
間違っている場合は、ファイル内の関連するコンテンツを削除し、環境変数を設定解除してから、環境変数をエクスポートします。
# 安装部署SSL 证书
acme.sh --installcert -d maybook.tk \
--key-file /etc/nginx/ssl_keys/maybook.tk.key.pem \
--fullchain-file /etc/nginx/ssl_keys/maybook.tk.cert.pem \
--reloadcmd "service nginx restart"
各acme.sh --installcert
インストールのパスとその他の構成が~/.acme.sh/<domain>/<domain>.conf
そこに保存されます。
他のディストリビューションで--reloadcmd "service nginx force-reload"
は、Nginxが構成ファイルを再度読み取れるようにする必要がある場合があります。
Nginx SSL構成
# 新建一个Nginx 配置acme.sh.conf
cat > /etc/nginx/conf.d/acme.sh.conf << EOF
server {
listen 8001 ssl;
server_name maybook.tk;
ssl on;
ssl_certificate /etc/nginx/ssl_keys/maybook.tk.cert.pem;
ssl_certificate_key /etc/nginx/ssl_keys/maybook.tk.key.pem;
index index.html index.htm;
location / {
root /home/app/code;
}
}
EOF
# 让Nginx 重新读取配置
nginx -s reload
新しい証明書アクセス検証
引き続き、以前に作成したページを使用して、CAによって発行された新しいSSL証明書を構成します。ブラウザに
入力https://maybook.tk:8001
するWhat a good day!
と、ブラウザに緑色の鍵が表示され、SSL証明書が信頼できることを示します。
総称ドメイン名を確認する
Nginx構成ファイル
# 创建两个server 都监听80 端口,根据不同的请求host 临时重定向302 到对应的https 链接
cat > /etc/nginx/conf.d/acme.sh.x.conf << EOF
server {
listen 80;
server_name app1.maybook.tk;
# 不使用301 永久重定向,因为如果后期地址改变需要清理浏览器端的Cookie 才能生效
return 302 https://$host:8001$request_uri;
}
server {
listen 80;
server_name app2.maybook.tk;
return 302 https://$host:8002$request_uri;
}
# 创建两个开启了SSL 的server,并将请求代理转发到对应的后台应用
server {
listen 8001 ssl;
server_name app1.maybook.tk;
ssl_certificate /etc/nginx/ssl_keys/maybook.tk.cert.pem;
ssl_certificate_key /etc/nginx/ssl_keys/maybook.tk.key.pem;
location / {
proxy_pass http://127.0.0.1:8801;
}
}
server {
listen 8002 ssl;
server_name app1.maybook.tk;
ssl_certificate /etc/nginx/ssl_keys/maybook.tk.cert.pem;
ssl_certificate_key /etc/nginx/ssl_keys/maybook.tk.key.pem;
location / {
proxy_pass http://127.0.0.1:8802;
}
}
EOF
テストファイルにアクセスする
# 模拟应用1
mkdir /home/web1/
cd /home/web1/
cat > index.html << EOF
<!DOCTYPE html>
<html lang="en">
<head>
<title>Index</title>
</head>
<body>
<h1>
<a href="/a1.html">a1.html</a><br/>
<a href="/a2.html">a2.html</a>
</h1>
</body>
</html>
EOF
cat > a1.html << EOF
<!DOCTYPE html>
<html lang="en">
<head>
<title>A1</title>
</head>
<body>
<a href="/index.html">index.html</a>
<h1>A1A1A1</h1>
</body>
</html>
EOF
cat > a2.html << EOF
<!DOCTYPE html>
<html lang="en">
<head>
<title>A2</title>
</head>
<body>
<a href="/index.html">index.html</a>
<h1>A2A2A2</h1>
</body>
</html>
EOF
# 模拟应用2
mkdir /home/web2/
cd /home/web2/
cat > index.html << EOF
<!DOCTYPE html>
<html lang="en">
<head>
<title>Index</title>
</head>
<body>
<h1>
<a href="/b1.html">b1.html</a><br/>
<a href="/b2.html">b2.html</a>
</h1>
</body>
</html>
EOF
cat > b1.html << EOF
<!DOCTYPE html>
<html lang="en">
<head>
<title>B1</title>
</head>
<body>
<a href="/index.html">index.html</a>
<h1>B1B1B1</h1>
</body>
</html>
EOF
cat > b2.html << EOF
<!DOCTYPE html>
<html lang="en">
<head>
<title>B2</title>
</head>
<body>
<a href="/index.html">index.html</a>
<h1>B2B2B2</h1>
</body>
</html>
EOF
バックグラウンドAPIのシミュレーション
nohup python3 -m http.server 8801 > /dev/null 2>&1 &
nohup python3 -m http.server 8802 > /dev/null 2>&1 &
テスト結果と結論
URL | 内容 |
---|---|
http://maybook.tk:8888 | 「What a good day!」ページのhttps形式 |
http://app1.maybook.tk:8888 | httpsフォームにはa1、a2インデックスページが含まれています |
http://app2.maybook.tk:8888 | httpsフォームにはb1、b2インデックスページが含まれています |
Nginxでは、複数のサーバーが同時に同じポートを監視し、ドメイン名またはサブドメイン名であるserver_nameを使用して、さまざまなサービスを区別できます。
コンテナーのポート80(ホスト8888にマップされている)をリッスンし、http要求をhttps(8001-8002)に転送してから、server_nameに従ってバックグラウンドアプリケーション(8801-8802)に転送します。
ブラウザは、アドレスバーに入力されたドメイン名がSSL証明書のドメイン名と同じかどうかを比較します。ドメイン名が同じで、証明書が信頼できる場合はアクセスが許可されます。そうでない場合は、自己署名証明書などのセキュリティプロンプトが表示されます。
SSL相互認証の簡単な紹介
双方向認証SSLプロトコルでは、サーバーとユーザーの両方に証明書が必要です。一方向認証SSLプロトコルでは、クライアントがCA証明書を持っている必要はありません。具体的なプロセスは上記の手順と同じです。クライアント証明書のサーバー側の検証を削除するだけでよく、対称パスワードスキームと対称呼び出しキーをネゴシエートするとき、サーバーはそれをクライアントに送信します。暗号化されていないもの(これはSSLプロセスのセキュリティに影響を与えません)暗号スキーム。このように、2つのパーティの特定の通信コンテンツは暗号化されたデータです。サードパーティの攻撃がある場合、暗号化されたデータのみが取得されます。有用な情報を取得するには、サードパーティが暗号化されたデータを復号化する必要があります。この時点でのセキュリティはパスワードスキームのセキュリティに依存します。幸い、現在の暗号化スキームは、通信キーが十分に長い限り十分に安全です。これが、128ビット暗号化通信の使用要件を強調する理由です。
通常、WebアプリケーションはSSLの一方向認証を使用します。その理由は非常に単純で、ユーザーの数は膨大であり、ユーザーの正当なログインを保証するために、通常はアプリケーションロジックレイヤーで通信層でユーザーのIDを確認する必要はありません。ただし、エンタープライズアプリケーションのドッキングの場合は状況が異なり、クライアント(比較的言えば)の認証が必要になる場合があります。このとき、SSL相互認証が必要です。
クリーンアップ
Dockerコンテナーを停止して削除する
docker stop alssltest && docker rm alssltest
Dockerイメージalssltestを削除する
docker rmi alssltest:latest
参考資料
Let's Encrypt (フロントエンドとバックエンド)が提供する無料のSSL証明書オンラインサーバーデプロイメントをインストールするためにacme.shを使用してNginx を開始する