Windows XP SP3のIE6でも見れるwebサーバー設定(自己署名証明書)

* [Windows XP SP3のIE6でも見れるwebサーバー設定(Let's Encrypt版) - Qiita](https://qiita.com/tukiyo3/items/332376ba51fa2d1307ff)

## 全体の流れ

* openssl で作るのは大変なので [certtool](https://www.gnutls.org/manual/html_node/certtool-Invocation.html) を用いる
* Ubuntu 20.04 の openssl `1.1.1f`、certtool `3.6.13` にて確認。
* nginx は `1.11`を用いた。(1.11は 2017年リリース)

### certtool

* `ca.key`、 `ca.crt` を作成
* `server.key`、 `server.crt` を作成

### nginx

* certool で作った `ca.crt`、`server.crt`、`server.key`を用いる。

### Windows

* ブラウザに`ca.crt`をインポートしておくことで、「このサイトは安全ではありません」の表示をスキップできる。

----

## 実際の作業

### certtool

```sh:certtoolを使えるようにする
apt install -y gnutls-bin
```

```sh:make_mycerts.sh
#!/bin/sh
set -eu

CMD="certtool --sec-param High"

CA() {
  dns_name=$1
  ip_address=$2
  $CMD --generate-privkey > ca.key

  cat << EOL >> ca.info
cn = CA $dns_name - $ip_address
ca
cert_signing_key
expiration_date = "2100-01-01 09:00:00"
dns_name = $dns_name
ip_address = $ip_address
EOL

  $CMD \
   --generate-self-signed \
   --load-privkey ca.key \
   --template ca.info \
   --outfile ca.crt
}

WWW() {
  dns_name=$1
  ip_address=$2
  $CMD --generate-privkey > server.key

  cat << EOL >> server.info
cn = www $dns_name - $ip_address
tls_www_server
encryption_key
signing_key
expiration_date = "2100-01-01 09:00:00"
dns_name = $dns_name
ip_address = $ip_address
EOL

  $CMD \
   --generate-certificate \
   --load-privkey server.key \
   --load-ca-certificate ca.crt \
   --load-ca-privkey ca.key \
   --template server.info \
   --outfile server.crt
}

# クライント証明書を作成 (必須ではない)
CLIENT() {
  ou=$1
  $CMD --generate-privkey > client-01.key
  
  cat << EOL >> client.info
ou = $ou
tls_www_client
encryption_key
signing_key
expiration_date = "2100-01-01 09:00:00"
EOL
  
  $CMD \
   --generate-certificate \
   --load-privkey $ou.key \
   --load-ca-certificate ca.crt \
   --load-ca-privkey ca.key \
   --template client.info \
   --outfile $ou.crt
  
  $CMD \
   --load-ca-certificate ca.crt \
   --load-certificate $ou.crt \
   --load-privkey $ou.key \
   --to-p12 --outder --outfile $ou.p12 \
   --p12-name $ou \
   --empty-password
}
```

```sh:main.sh
#!/bin/sh
set -eu
. ./make_mycerts.sh

DOMAIN="dev.example.com"
GLOBAL_IP="111.111.111.111"

mkdir -p $DOMAIN && cd $DOMAIN
CA $DOMAIN $GLOBAL_IP
WWW $DOMAIN $GLOBAL_IP
CLIENT "client-01"
```


* `client-01.p12` をインポートすると、`ca.crt`の内容が`信頼済みルート証明機関`に入る。

### nginx 1.11

```nginx:./nginx/ore-ssl.conf
ssl_session_cache       shared:SSL:10m;
ssl_session_timeout     10m;

server {

        listen          443 ssl;
        server_name     dev.example.com;

        ssl_certificate         /etc/ssl/mycerts/server.crt;
        ssl_certificate_key     /etc/ssl/mycerts/server.key;
        ssl_client_certificate  /etc/ssl/mycerts/ca.crt;

        ssl_protocols   TLSv1 TLSv1.1 TLSv1.2;
        #ssl_ciphers     ALL:!aNULL:!EXP:!MD5:!RC4:!LOW:+HIGH:+MEDIUM;
        ssl_ciphers     'DES-CBC3-SHA';

        location / {
                root    /usr/share/nginx/html;
                index   index.html index.htm;
        }

}
```

```sh
docker run -it --rm \
 -v $(pwd)/mycerts/:/etc/ssl/mycerts/ \
 -v $(pwd)/nginx/ore-ssl.conf:/etc/nginx/conf.d/ore-ssl.conf \
 -p 80:80 \
 -p 443:443 \
 nginx:1.11
```


### ブラウザで証明書エラーを出さない方法

* IE : 従来の Subject CN値を使う。(server.crt)
* Chrome : サブジェクト代替名 を使う。

```
DNS Name=xxx.example.com
IP Address=192.168.xx.xx
```

* Firefox : Firefoxに ca.crt をインポートする。


ca.crtをコマンドプロンプトから取り込みたい場合 (vista以降)

```sh:管理者権限で実行
certutil -addstore ROOT ca.crt
```


## おまけ

### openssl コマンドで同じようなことをする場合

```sh:おまけ
# CA
openssl genrsa -out ca.key 3072
openssl req -new -x509 -days 36500 -key ca.key -out ca.crt -subj '/CN=CA 2020'

# server
openssl genrsa -out server.key 3072
openssl req -new -key server.key -out server.csr -subj '/CN=dev.example.com'
openssl x509 -req -days 36500 -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt

# (xpでは不要) nginx 1.12 では ssl_dhparam 指定しないと DHE暗号が使えない
# http://nginx.org/en/CHANGES-1.12
# openssl dhparam -out dhparam.pem 4096


(略)
# クライアント証明書の p12キー
cat client-01.key client-01.crt ca.crt \
 | openssl pkcs12 -export -out client-01.p12 -name "client-01" -passin pass: -passout pass:
```

### XPで TLS1.2を(無理やり)有効にする

* https://github.com/ffftp/ffftp/wiki/TLS-1.2

### 使用されている暗号を確認

![スクリーンショット_2020-04-27_03-49-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/8b425d54-90bf-0a85-3467-6ecb7861f55d.png)

Windows XP IE6 ( `ssl_ciphers 'DES-CBC3-SHA';` )

![スクリーンショット_2020-04-27_03-51-19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/b463c20a-5352-2dcf-9e9e-47c0a5b97feb.png)

Windows 10 IE11 

![スクリーンショット_2020-04-27_03-52-39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/1d52f95b-1365-16ec-5126-1e79c880b1e6.png)

Firefox 

![スクリーンショット_2020-04-27_04-06-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/48ba5290-c3da-652d-894b-ed88ce8de21d.png)

Chrome

![スクリーンショット_2020-04-27_04-43-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/5d1f3168-b567-f7b5-9285-fe6888c2cb08.png)

* `ssl_ciphers 'DES-CBC3-SHA';` に制限した場合の表示

![スクリーンショット_2020-04-27_04-46-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/e8155fd6-21a2-ee4d-d6c4-f1df42d83679.png)

## openssl 1.0.2h と 1.1.0 以降 3DES が無効化された

* https://www.openssl.org/news/changelog.html

![スクリーンショット_2020-04-27_05-31-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/d20ce16e-7a1d-ac2a-1bf0-8a7408af43f6.png)
![スクリーンショット_2020-04-27_05-32-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/90239d6d-bd0e-2396-8946-21c8344fcff2.png)

openssl 1.0.2h や 1.1.0 以降で再度有効化するには
ビルド時に `enable-weak-ssl-ciphers`フラグが必要。


### nginx 1.11 と 1.12の違い

* XPでは nginx `1.12`を使うと見れなかった。
    * `dh_param` の設定をしても見れなかった。
    * docker で1.11を動かす場合、 `nginx:1.11-alpine`を指定。
* XPは TLS 1.0 までしか対応していないため注意。
* `openssl ciphers -v 'DES-CBC3-SHA'` が以下なのが原因と思われる。

> Error in cipher list
> 139762468738368:error:1410D0B9:SSL routines:SSL_CTX_set_cipher_list:no cipher match:../ssl/ssl_lib.c:2558:

```sh:(参考)XPでも見れる場合
$ openssl ciphers -v 'DES-CBC3-SHA'
DES-CBC3-SHA            SSLv3 Kx=RSA      Au=RSA  Enc=3DES(168) Mac=SHA1
```

* nginx を `enable-weak-ssl-ciphers` フラグをつけてビルドする必要がある。
    * [ssl - Handshake failure when requesting nginx server in https protocol - Stack Overflow](https://stackoverflow.com/questions/48560608/handshake-failure-when-requesting-nginx-server-in-https-protocol)

```sh:nginx
cd nginx-1.12.2
./configure --with-openssl \
 --with-http_ssl_module \
 --with-openssl-opt='enable-weak-ssl-ciphers'
make 
sudo make install
```

### curl で接続テスト

* CentOS6 の curlで確認しました。 (Ubuntu 20.04のものでは`rsa_3des_sha`が省かれている)
* curl だと ssl_ciphers は `ECDHE-RSA-AES256-GCM-SHA384`が使われる。DES-CBC3-SHAの動作テストなので以下のようにNSSCipherSuite名で指定。

```sh
curl \
 -v \
 --insecure \
 --tlsv1 --ciphers rsa_3des_sha \
 --cert ./client-01.crt \
 --key ./client-01.key \
 --cacert ./ca.crt \
 https://dev.example.com
```


### nginx のTCPロードバランサー

* [nginxによるTCPロードバランサー - Mercari Engineering Blog](https://tech.mercari.com/entry/2016/08/17/170114)

> configureスクリプトに--with-stream を付与してビルドする必要があります。