IPhone アプリ: SSLエラーが発生してから対応したまでの話
本日IPhoneアプリケーションエンジニアさんから以下のようなエラーが出て、ファイルがダウンロードできなくなったという連絡を受けました
エラーログ内容
長いので改行しています
2016-05-25 17:56:45.398 TESTAPP[719:391253] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801) 2016-05-25 17:56:45.422 TESTAPP[719:391073] [Error] GET '(null)' (0) [nan s]: Error Domain=NSURLErrorDomain Code=-1200 "SSLエラーが起きたため、サーバへのセキュリティ保護された接続を確立できません。" UserInfo={_kCFStreamErrorCodeKey=-9801, NSLocalizedRecoverySuggestion=それでもサーバに接続しますか?, NSUnderlyingError=0x15f0f2930 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9801, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9801}}, NSLocalizedDescription=SSLエラーが起きたため、サーバへのセキュリティ保護された接続を確立できません。, NSErrorFailingURLKey=https://cdn.sslsitetesttest.com/files/abc.mp4, NSErrorFailingURLStringKey=https://cdn.sslsitetesttest.com/files/abc.mp4, _kCFStreamErrorDomainKey=3}
特に、こちらのnginxの設定は変更していないし、アプリケーションの問題なんじゃなの?なんて疑いつつ、調査を開始することしました。
- 作者: 久保達彦,道井俊介
- 出版社/メーカー: 技術評論社
- 発売日: 2016/01/16
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (5件) を見る
- 作者: 小島拓也,中嶋亜美,吉原恵美,中塚淳
- 発売日: 2014/11/10
- メディア: Kindle版
- この商品を含むブログを見る
OpenSSL―暗号・PKI・SSL/TLSライブラリの詳細―
- 作者: John Viega,Matt Messier,Pravir Chandra,齋藤孝道
- 出版社/メーカー: オーム社
- 発売日: 2004/08/01
- メディア: 単行本
- 購入: 4人 クリック: 89回
- この商品を含むブログ (25件) を見る
エラーの内容をググるとこんな内容が出ました
まさしく、この現象だと思うのですが、今まで平気だったのに何で突然?とうところは置いておいて、上記のリンク(すみません、引用させていただきます)
これはApp Transport Security(ATS)という機能らしい。ドキュメントやビデオを見ていると今すぐではないものの今後、HTTPでのリクエストは使えなくしていく気満々な模様。
このATSという機能が発動したのではないかと疑う、、iOSの最近9.3.2にアップデートされたし、それが原因なんじゃないかな?とか勝手に憶測
ATSが発動したら、何すればいい?
これが、全然わからなかった。。リンク先によると無効にする方法を案内してくれているのですが、この変更で、アプリを再度アップするのも難儀なので、なんとか、その先にある WEBサーバ(nginx)側の設定で、アプリを無傷に改修できない調べました。
また、先ほどの引用なのですが。、
ATSについてざっくりまとめるとこんな感じ。
ATSによってHTTPリクエストは自動的にHTTPSリクエストに置き換わる HTTPSを使用する事を推奨する TLSv1.2以上に対応している必要がある 上記の例外をInfo.plistに設定することができる
との部分で、「TLSv1.2以上に対応している必要がある」と書いてあったので、nginxのssl.confを確認した。
nginx ssl.conf
ちなみに、ここの設定は環境により違いますので、ssl.confなんてないかもしれないし、あるかもしれない
# pwd /etc/nginx/conf.d # 一部抜粋 # vi ssl.conf ---------------------------------------- ssl_protocols SSLv2 SSLv3 TLSv1;
ふむふむ、、、TLSv1って書いてあるから、これはばっちり、対応しているな。。でわ、ここが原因ではないか。。
ん???
どうも、この書き方だと、TLSv1.2には対応していないということになるらしい(TLSv1のいう書き方は暗黙的にTLSv1.0とのことっす・・えぇえええええええええ。。。まじで?
結果的に、ssl_protocolsの部分に、 TLSv1.2を追記するとのことなのだが、この TLSv1.2ってopensslのバージョンが1.0.1以上でないと対応していないらしく、おそるおそるバージョンを確認してみた
# openssl version OpenSSL 1.0.1e-fips 11 Feb 2013
どうやら、そこは対応している模様
おっとnginxのバージョンも関係あるのか。。TLSv1.1とTLSv1.2はnginx 1.1.13以降および1.0.12以降で対応するらしくこちらもnginxのバージョンを確認してみる
# nginx -v nginx version: nginx/1.8.0
こちらも無事対応している模様・・・よかった・・。
要件は満たしているようなので、nginxのssl.confを以下のように書き直してみました。
# pwd /etc/nginx/conf.d # 一部抜粋 # vi ssl.conf ---------------------------------------- ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2; # ssl_protocols SSLv2 SSLv3 TLSv1;
どうでしょうか?これで、エラーは消えるのでしょうか?ってことで、再度確認してみたところ、エラーがなくなり、動画が無事再生できるようになりました!!!!
ちなみに、SSLが正常かエラーかっていうのは、実機で確認もしたのですが、MACってnscurlという便利ツールがあって、今回、問題のあった、接続先が ATS に対応しているかどうが簡単に調べられます
書式
nscurl --ats-diagnostics https://調べるドメイン名
ssl.conf 修正前(エラー)パターン
TLSv1.0 Result : PASS
以外は、みんなFAIL ・・・
nscurl --ats-diagnostics https://cdn.sslsitetesttest.com Starting ATS Diagnostics Configuring ATS Info.plist keys and displaying the result of HTTPS loads to https://cdn.sslsitetesttest.com. A test will "PASS" if URLSession:task:didCompleteWithError: returns a nil error. Use '--verbose' to view the ATS dictionaries used and to display the error received in URLSession:task:didCompleteWithError:. ================================================================================ Default ATS Secure Connection --- ATS Default Connection 2016-05-25 21:00:13.736 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:13.737 nscurl[408:4734] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801) Result : FAIL --- ================================================================================ Allowing Arbitrary Loads --- Allow All Loads Result : PASS --- ================================================================================ Configuring TLS exceptions for cdn.sslsitetesttest.com --- TLSv1.2 2016-05-25 21:00:13.847 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:13.848 nscurl[408:4734] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801) Result : FAIL --- --- TLSv1.1 2016-05-25 21:00:13.862 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:13.863 nscurl[408:4734] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801) Result : FAIL --- --- TLSv1.0 Result : PASS --- ================================================================================ Configuring PFS exceptions for cdn.sslsitetesttest.com --- Disabling Perfect Forward Secrecy 2016-05-25 21:00:13.917 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:13.918 nscurl[408:4734] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801) Result : FAIL --- ================================================================================ Configuring PFS exceptions and allowing insecure HTTP for cdn.sslsitetesttest.com --- Disabling Perfect Forward Secrecy and Allowing Insecure HTTP 2016-05-25 21:00:13.929 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:13.942 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:13.969 nscurl[408:4734] CFNetwork SSLHandshake failed (-9824) 2016-05-25 21:00:13.995 nscurl[408:4734] CFNetwork SSLHandshake failed (-9824) 2016-05-25 21:00:13.996 nscurl[408:4734] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824) Result : FAIL --- ================================================================================ Configuring TLS exceptions with PFS disabled for cdn.sslsitetesttest.com --- TLSv1.2 with PFS disabled 2016-05-25 21:00:14.005 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:14.006 nscurl[408:4734] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801) Result : FAIL --- --- TLSv1.1 with PFS disabled 2016-05-25 21:00:14.016 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:14.016 nscurl[408:4734] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9801) Result : FAIL --- --- TLSv1.0 with PFS disabled Result : PASS --- ================================================================================ Configuring TLS exceptions with PFS disabled and insecure HTTP allowed for cdn.sslsitetesttest.com --- TLSv1.2 with PFS disabled and insecure HTTP allowed 2016-05-25 21:00:14.052 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:14.064 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:14.088 nscurl[408:4734] CFNetwork SSLHandshake failed (-9824) 2016-05-25 21:00:14.112 nscurl[408:4734] CFNetwork SSLHandshake failed (-9824) 2016-05-25 21:00:14.113 nscurl[408:4734] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824) Result : FAIL --- --- TLSv1.1 with PFS disabled and insecure HTTP allowed 2016-05-25 21:00:14.128 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:14.144 nscurl[408:4734] CFNetwork SSLHandshake failed (-9801) 2016-05-25 21:00:14.185 nscurl[408:4734] CFNetwork SSLHandshake failed (-9824) 2016-05-25 21:00:14.211 nscurl[408:4734] CFNetwork SSLHandshake failed (-9824) 2016-05-25 21:00:14.212 nscurl[408:4734] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824) Result : FAIL --- --- TLSv1.0 with PFS disabled and insecure HTTP allowed Result : PASS --- ================================================================================
ssl.conf 修正後(正常)パターン
Resultが、すべてPASSしていることが確認できるかと・・
Starting ATS Diagnostics Configuring ATS Info.plist keys and displaying the result of HTTPS loads to https://cdn.sslsitetesttest.com. A test will "PASS" if URLSession:task:didCompleteWithError: returns a nil error. Use '--verbose' to view the ATS dictionaries used and to display the error received in URLSession:task:didCompleteWithError:. ================================================================================ Default ATS Secure Connection --- ATS Default Connection Result : PASS --- ================================================================================ Allowing Arbitrary Loads --- Allow All Loads Result : PASS --- ================================================================================ Configuring TLS exceptions for cdn.sslsitetesttest.com --- TLSv1.2 Result : PASS --- --- TLSv1.1 Result : PASS --- --- TLSv1.0 Result : PASS --- ================================================================================ Configuring PFS exceptions for cdn.sslsitetesttest.com --- Disabling Perfect Forward Secrecy Result : PASS --- ================================================================================ Configuring PFS exceptions and allowing insecure HTTP for cdn.sslsitetesttest.com --- Disabling Perfect Forward Secrecy and Allowing Insecure HTTP Result : PASS --- ================================================================================ Configuring TLS exceptions with PFS disabled for cdn.sslsitetesttest.com --- TLSv1.2 with PFS disabled Result : PASS --- --- TLSv1.1 with PFS disabled Result : PASS --- --- TLSv1.0 with PFS disabled Result : PASS --- ================================================================================ Configuring TLS exceptions with PFS disabled and insecure HTTP allowed for cdn.sslsitetesttest.com --- TLSv1.2 with PFS disabled and insecure HTTP allowed Result : PASS --- --- TLSv1.1 with PFS disabled and insecure HTTP allowed Result : PASS --- --- TLSv1.0 with PFS disabled and insecure HTTP allowed Result : PASS --- ================================================================================
恐るべし、iOS
あと、この件とは関係なのだけど、ssl.confで、 SSLv2 SSLv3を入れるのは、ぜい弱性の観点から入れないほうがいいらしいと言われたのですが、動かなくなるのが怖いので、そのままにしてしまっています