LoginSignup
15
11

More than 1 year has passed since last update.

https_proxy=httpとhttps_proxy=httpsは何が違うのか?

Last updated at Posted at 2022-05-17

1. はじめに

ことの発端は、IBM Cloudの CLIでProxyを設定できるかどうかを検証していた時である。
その記事では、

  • export https_proxy=http://10.0.0.4:3128

としたが、

  • export https_proxy=https://10.0.0.4:3128

ではなぜダメなのか?と思った次第。実際、後者のやり方で実行すると、IBM Cloud CLIで実行するとproxyconnect tcp: tls: first record does not look like a TLS handshakeというエラーが出たので、やはり挙動としては違いはあるはずである。そもそも設定上の組み合わせとしては以下の4つがあるはず。Case1はhttpでの指定として自然だし、Case3はhttpへのアクセスにhttpsを利用するという上であり得ない組み合わせのはずであり、やはりキモとなるのはCase2とCase4の違いである。

Case1: http_proxy = http://proxy:port
Case2: https_proxy = http://proxy:port
Case3: http_proxy = https://proxy:port
Case4: https_proxy = https://proxy:port

2. 結論

以下のdiscussionや記述が役に立った。

Case2の時は、いわゆる多くの記事で紹介されているPROXY越えのHTTPS通信の話であり、例えばこの記事の解説などが詳しくてわかりやすい。

  • CONNECTメソッドによってPROXYにTLSセッションを中継するように指示する。PROXYは、PROXYとサーバー間で3 way handshakeを完了してTCPレベルでセッションが張れて中継できることを確認した上で、クライアントにConnection establishedを返す。
  • 一旦、PROXYが中継を行うと、TLSセッションはクライアントとサーバーの間で張られる。PROXYはTLSやhttps通信の中身には一切触れず(触れることはできず)、IPヘッダとTCPヘッダを変更してサーバーに転送するだけである。

Case4の時は、

  • クライアントとPROXY間でTLSセッションを張り、なおかつPROXYとサーバー間でもTLSセッションを張る。
  • クライアントからCONNECTメソッドによるPROXYを中継する指示が来た際には、PROXYは、PROXYとサーバー間で3 way handshakeだけでなくTLSセッションが張れて中継できることを確認した上で、クライアントにConnection establishedを返す。
  • クライアントからPROXYにTLSセッションを張る際には、サーバーのFQDNに対してアクセスを要求してPROXYが証明書を返すのだから、当然PROXYサーバー側でその対応が必要となる。例えば、1) PROXY側でアクセス先のサーバーのFQDNに対して署名を行い(一般的には、都度署名を行う仕組みを設ける)、2)クライアントでそのPROXYサーバーが署名した証明書を信頼できるように、クライアントにPROXYサーバで署名を行うCAのCA証明書を導入する必要がある。
  • クライアントはサーバーが提供する証明書ではなく、PROXYサーバーが署名した証明書情報しか確認できないため、中間者攻撃が行われるかどうかの確認ができないことに注意。
  • ネットワークスペシャリスト 平成26年秋期試験問題 午後Ⅱより引用

「はじめに」で書いた、IBM Cloud CLIのエラーも、PROXYと間でTLSセッションを張ろうとしてエラーになったのだろうと想像される(エラーメッセージもそのような内容である)。

3. curl version 7.29.0利用時の比較

これらの環境変数をどのようにハンドリングするかは、厳密にはアプリには依存する。
実際、OS付属のcurlだとCase2/Case4どちらの場合でも挙動は同じだった。このcurlのバージョンではPROXYにHTTPS接続するという仕組みが実装されていなかったのだと思われる。

Case2 + curl 7.29.0
[root@syasuda-metavsi ~]# curl --version
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.53.1 zlib/1.2.7 libidn/1.28 libssh2/1.8.0
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets
[root@syasuda-metavsi ~]# export https_proxy=http://10.0.0.4:3128
[root@syasuda-metavsi ~]# curl -v -I https://www.yahoo.co.jp
* About to connect() to proxy 10.0.0.4 port 3128 (#0)
*   Trying 10.0.0.4...
* Connected to 10.0.0.4 (10.0.0.4) port 3128 (#0)
* Establish HTTP proxy tunnel to www.yahoo.co.jp:443
> CONNECT www.yahoo.co.jp:443 HTTP/1.1
> Host: www.yahoo.co.jp:443
> User-Agent: curl/7.29.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
HTTP/1.1 200 Connection established
<

* Proxy replied OK to CONNECT request
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* 	subject: CN=edge01.yahoo.co.jp,O=Yahoo Japan Corporation,L=Chiyoda-ku,ST=Tokyo,C=JP
* 	start date:  4月 06 10:01:27 2022 GMT
* 	expire date:  5月 05 14:59:00 2023 GMT
* 	common name: edge01.yahoo.co.jp
* 	issuer: CN=Cybertrust Japan SureServer CA G4,O="Cybertrust Japan Co., Ltd.",C=JP
> HEAD / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.yahoo.co.jp
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Length: 0
Content-Length: 0
< Content-Type: text/html; charset=utf-8
Content-Type: text/html; charset=utf-8
< Date: Tue, 17 May 2022 02:23:21 GMT
Date: Tue, 17 May 2022 02:23:21 GMT
< Etag: W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"
Etag: W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"
< Vary: Accept-Encoding
Vary: Accept-Encoding
< X-Vcap-Request-Id: 41059c61-6a1b-4759-4983-4b03744d5075
X-Vcap-Request-Id: 41059c61-6a1b-4759-4983-4b03744d5075
< X-Xss-Protection: 1; mode=block
X-Xss-Protection: 1; mode=block
< Age: 0
Age: 0
< Connection: keep-alive
Connection: keep-alive
< Server: ATS
Server: ATS

<
* Connection #0 to host 10.0.0.4 left intact
Case4 + curl 7.29.0
[root@syasuda-metavsi ~]# curl --version
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.53.1 zlib/1.2.7 libidn/1.28 libssh2/1.8.0
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets
[root@syasuda-metavsi ~]# export https_proxy=https://10.0.0.4:3128
[root@syasuda-metavsi ~]# curl -v -I https://www.yahoo.co.jp
* About to connect() to proxy 10.0.0.4 port 3128 (#0)
*   Trying 10.0.0.4...
* Connected to 10.0.0.4 (10.0.0.4) port 3128 (#0)
* Establish HTTP proxy tunnel to www.yahoo.co.jp:443
> CONNECT www.yahoo.co.jp:443 HTTP/1.1
> Host: www.yahoo.co.jp:443
> User-Agent: curl/7.29.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
HTTP/1.1 200 Connection established
<

* Proxy replied OK to CONNECT request
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* 	subject: CN=edge01.yahoo.co.jp,O=Yahoo Japan Corporation,L=Chiyoda-ku,ST=Tokyo,C=JP
* 	start date:  4月 06 10:01:27 2022 GMT
* 	expire date:  5月 05 14:59:00 2023 GMT
* 	common name: edge01.yahoo.co.jp
* 	issuer: CN=Cybertrust Japan SureServer CA G4,O="Cybertrust Japan Co., Ltd.",C=JP
> HEAD / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.yahoo.co.jp
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Length: 0
Content-Length: 0
< Content-Type: text/html; charset=utf-8
Content-Type: text/html; charset=utf-8
< Date: Tue, 17 May 2022 02:23:58 GMT
Date: Tue, 17 May 2022 02:23:58 GMT
< Etag: W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"
Etag: W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"
< Vary: Accept-Encoding
Vary: Accept-Encoding
< X-Vcap-Request-Id: 14a23e09-4528-4039-6c39-bee89791aea0
X-Vcap-Request-Id: 14a23e09-4528-4039-6c39-bee89791aea0
< X-Xss-Protection: 1; mode=block
X-Xss-Protection: 1; mode=block
< Age: 0
Age: 0
< Connection: keep-alive
Connection: keep-alive
< Server: ATS
Server: ATS

<
* Connection #0 to host 10.0.0.4 left intact

4. curl version 7.83.1利用時の比較

  • HTTP2に関する機能(抜粋)

    • https://curl.se/docs/http2.html
    • 7.43.0で[HTTP/2]の多重化に完全対応。
    • 7.47.0で[curl]コマンドは[HTTPS]ならデフォルトで[HTTP/2]で接続するようになった。
  • SSL Certificate Verificationに関する機能(抜粋)

Since version 7.52.0, curl can do HTTPS to the proxy separately from the connection to the server. This TLS connection is handled separately from the server connection so instead of --insecure and --cacert to control the certificate verification, you use --proxy-insecure and --proxy-cacert. With these options, you make sure that the TLS connection and the trust of the proxy can be kept totally separate from the TLS connection to the server.

curl7.83.1の導入
https://hanamiche.hatenablog.jp/entry/2021/04/10/073000
https://github.com/moparisthebest/static-curl/releases/tag/v7.83.1

# curl -L -O https://github.com/moparisthebest/static-curl/releases/download/v7.83.1/curl-amd64
# ln -s /etc/ssl/certs/ca-bundle.crt /etc/ssl/certs/ca-certificates.crt
# chmod +x curl-amd64
# ./curl-amd64 --version
curl 7.83.1 (x86_64-pc-linux-musl) libcurl/7.83.1 OpenSSL/1.1.1o zlib/1.2.12 libssh2/1.10.0 nghttp2/1.46.0
Release-Date: 2022-05-11
Protocols: dict file ftp ftps gopher gophers http https imap imaps mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS HSTS HTTP2 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP UnixSockets
Case2 + curl 7.83.1
[root@syasuda-metavsi ~]# export https_proxy=http://10.0.0.4:3128
[root@syasuda-metavsi ~]# ./curl-amd64 -v -I https://www.yahoo.co.jp
* Uses proxy env variable https_proxy == 'http://10.0.0.4:3128'
*   Trying 10.0.0.4:3128...
* Connected to 10.0.0.4 (10.0.0.4) port 3128 (#0)
* allocate connect buffer
* Establish HTTP proxy tunnel to www.yahoo.co.jp:443
> CONNECT www.yahoo.co.jp:443 HTTP/1.1
> Host: www.yahoo.co.jp:443
> User-Agent: curl/7.83.1
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
HTTP/1.1 200 Connection established
<

* Proxy replied 200 to CONNECT request
* CONNECT phase completed
* ALPN: offers h2
* ALPN: offers http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN: server accepted h2
* Server certificate:
*  subject: C=JP; ST=Tokyo; L=Chiyoda-ku; O=Yahoo Japan Corporation; CN=edge01.yahoo.co.jp
*  start date: Apr  6 10:01:27 2022 GMT
*  expire date: May  5 14:59:00 2023 GMT
*  subjectAltName: host "www.yahoo.co.jp" matched cert's "*.yahoo.co.jp"
*  issuer: C=JP; O=Cybertrust Japan Co., Ltd.; CN=Cybertrust Japan SureServer CA G4
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* h2h3 [:method: HEAD]
* h2h3 [:path: /]
* h2h3 [:scheme: https]
* h2h3 [:authority: www.yahoo.co.jp]
* h2h3 [user-agent: curl/7.83.1]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x7fe6eba971b0)
> HEAD / HTTP/2
> Host: www.yahoo.co.jp
> user-agent: curl/7.83.1
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/2 200
HTTP/2 200
< server: ATS
server: ATS
< date: Tue, 17 May 2022 02:32:11 GMT
date: Tue, 17 May 2022 02:32:11 GMT
< content-type: text/html; charset=utf-8
content-type: text/html; charset=utf-8
< content-length: 0
content-length: 0
< etag: W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"
etag: W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"
< vary: Accept-Encoding
vary: Accept-Encoding
< x-vcap-request-id: 9dc258de-ab84-4e68-47b5-c1e2494d46fb
x-vcap-request-id: 9dc258de-ab84-4e68-47b5-c1e2494d46fb
< x-xss-protection: 1; mode=block
x-xss-protection: 1; mode=block
< age: 0
age: 0

<
* Connection #0 to host 10.0.0.4 left intact
Case4 + curl 7.83.1
[root@syasuda-metavsi ~]# export https_proxy=https://10.0.0.4:3128
[root@syasuda-metavsi ~]# ./curl-amd64 -v -I https://www.yahoo.co.jp
* Uses proxy env variable https_proxy == 'https://10.0.0.4:3128'
*   Trying 10.0.0.4:3128...
* Connected to 10.0.0.4 (10.0.0.4) port 3128 (#0)
* ALPN: offers http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* error:1408F10B:SSL routines:ssl3_get_record:wrong version number
* Closing connection 0
curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number

少なくとも挙動が変わったことがわかる。

15
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
11