これは、なにをしたくて書いたもの?
stunnelでバックエンドのサーバーにSSL/TLS通信して転送する際に、フォワードプロキシサーバーを経由することができないかなぁと調べたら、
できそうだったので試してみようかなと。
環境
今回の環境は、こちらです。Ubuntu Linux 18.04 LTS。
$ uname -srvmpio Linux 4.15.0-96-generic #97-Ubuntu SMP Wed Apr 1 03:25:46 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.4 LTS Release: 18.04 Codename: bionic
お題としては、https://www.google.com/へのアクセスを以下のような経路で行ってみましょう。
間のApacheは、HTTP CONNECTでHTTPS通信をトンネリングさせます。SSL/TLS通信は、stunnel以降となり、curlはHTTPで通信を行います。
フォワードプロキシ(Apache)のインストール
まずは、Apacheをインストール。
$ sudo apt install apache2
バージョン。
$ apache2 -v Server version: Apache/2.4.29 (Ubuntu) Server built: 2020-03-13T12:26:16
mod_proxy_connectを有効にします。
$ sudo a2enmod proxy proxy_connect
フォワードプロキシとしての設定。
Listen 8080 <VirtualHost *:8080> ProxyRequests On ProxyVia On <Proxy *> Require host localhost </Proxy> ErrorLog ${APACHE_LOG_DIR}/proxy_error.log CustomLog ${APACHE_LOG_DIR}/proxy_access.log combined </VirtualHost>
Apacheを再起動したら、準備完了です。
$ sudo systemctl restart apache2
確認。
$ https_proxy=http://localhost:8080 curl https://www.google.com
アクセスログを確認すると、HTTP CONNECT経由でアクセスしていることがわかります。
localhost - - [09/Apr/2020:13:45:00 +0000] "CONNECT www.google.com:443 HTTP/1.1" 200 20118 "-" "curl/7.58.0"
stunnelをインストール、設定する
続いて、stunnelをインストールします。
$ sudo apt install stunnel4
バージョン。
$ stunnel4 -version stunnel 5.44 on x86_64-pc-linux-gnu platform Compiled with OpenSSL 1.1.0g 2 Nov 2017 Running with OpenSSL 1.1.1 11 Sep 2018 Update OpenSSL shared libraries or rebuild stunnel Threading:PTHREAD Sockets:POLL,IPv6,SYSTEMD TLS:ENGINE,FIPS,OCSP,PSK,SNI Auth:LIBWRAP Global options: pid = /var/run/stunnel4.pid RNDbytes = 64 RNDfile = /dev/urandom RNDoverwrite = yes Service-level options: ciphers = FIPS (with "fips = yes") ciphers = HIGH:!DH:!aNULL:!SSLv2 (with "fips = no") curve = prime256v1 debug = daemon.notice logId = sequential options = NO_SSLv2 options = NO_SSLv3 sessionCacheSize = 1000 sessionCacheTimeout = 300 seconds stack = 65536 bytes TIMEOUTbusy = 300 seconds TIMEOUTclose = 60 seconds TIMEOUTconnect = 10 seconds TIMEOUTidle = 43200 seconds verify = none
設定ファイル「/etc/default/stunnel4」のENABLEDを「1」に変更して、stunnelを有効化します。
ENABLED=1
設定ファイルを作成。
/etc/stunnel/stunnel.conf
[google-web] client = yes accept = 127.0.0.1:8000 connect = localhost:8080 protocol = connect protocolHost = www.google.com:443 verifyChain = yes CApath = /etc/ssl/certs checkHost = www.google.com OCSPaia = yes
stunnelでリッスンするポートは、8000とします。
ポイントは、以下です。
- クライアントモードにしていること
- connectで指定するのは、プロキシサーバーのアドレス、ポートとすること
- protocolで「connect」と指定すること
- protocolHostに、本来の転送先のバックエンドサーバーを書くこと
設定ができたので、stunnelを起動します
$ sudo systemctl start stunnel4
確認
では、確認してみましょう。
ローカルのポート8000に、HTTPでアクセスします。Hostヘッダーだけは合わせておきました。
$ curl -v localhost:8000 -H 'Host: www.google.com'
結果、プロキシサーバーにHTTP CONNECTでアクセスしていることがわかります。
localhost - - [09/Apr/2020:13:53:46 +0000] "CONNECT www.google.com:443 HTTP/1.1" 200 20332 "-" "-"
もうひとつ
結果がちょっとわかりづらかったかもなので、もうひとつ試してみましょう。
たとえば、www.yahoo.co.jpにHTTPでアクセスするとリダイレクトを要求されます。
$ curl -i http://www.yahoo.co.jp HTTP/1.1 301 Redirect Date: Thu, 09 Apr 2020 14:22:43 GMT Connection: keep-alive Via: http/1.1 edge2623.img.djm.yahoo.co.jp (ApacheTrafficServer [c s f ]) Server: ATS Cache-Control: no-store Location: https://www.yahoo.co.jp:443/ Content-Type: text/html Content-Language: en Content-Length: 1
ここで、stunnelの設定をwww.yahoo.co.jp向けに設定します。
/etc/stunnel/stunnel.conf
[yahoo-web] client = yes accept = 127.0.0.1:8000 connect = localhost:8080 protocol = connect protocolHost = www.yahoo.co.jp:443 verifyChain = yes CApath = /etc/ssl/certs checkHost = www.yahoo.co.jp OCSPaia = yes
stunnelを再起動。
$ sudo systemctl restart stunnel4
確認。
$ curl localhost:8000 -H 'Host: www.yahoo.co.jp' -v -I * Rebuilt URL to: localhost:8000/ * Trying 127.0.0.1... * TCP_NODELAY set * Connected to localhost (127.0.0.1) port 8000 (#0) > HEAD / HTTP/1.1 > Host: www.yahoo.co.jp > User-Agent: curl/7.58.0 > Accept: */* > < HTTP/1.1 200 OK HTTP/1.1 200 OK < Cache-Control: private, no-cache, no-store, must-revalidate Cache-Control: private, no-cache, no-store, must-revalidate < Content-Type: text/html; charset=UTF-8 Content-Type: text/html; charset=UTF-8 < Date: Thu, 09 Apr 2020 14:25:01 GMT Date: Thu, 09 Apr 2020 14:25:01 GMT < Expires: -1 Expires: -1 < Pragma: no-cache Pragma: no-cache < Set-Cookie: B=5k0q8u5f8uc1t&b=3&s=93; expires=Sun, 10-Apr-2022 14:25:01 GMT; path=/; domain=.yahoo.co.jp Set-Cookie: B=5k0q8u5f8uc1t&b=3&s=93; expires=Sun, 10-Apr-2022 14:25:01 GMT; path=/; domain=.yahoo.co.jp < Vary: Accept-Encoding Vary: Accept-Encoding < X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN X-Frame-Options: SAMEORIGIN < X-Vcap-Request-Id: eef40b90-5531-4aff-55f1-a9e3203a3eef X-Vcap-Request-Id: eef40b90-5531-4aff-55f1-a9e3203a3eef < X-Xss-Protection: 1; mode=block X-Xss-Protection: 1; mode=block < Age: 0 Age: 0 < Connection: keep-alive Connection: keep-alive < Via: http/1.1 edge1659.img.bbt.yahoo.co.jp (ApacheTrafficServer [c sSf ]) Via: http/1.1 edge1659.img.bbt.yahoo.co.jp (ApacheTrafficServer [c sSf ]) < Server: ATS Server: ATS < Set-Cookie: XB=5k0q8u5f8uc1t&b=3&s=93; expires=Sun, 10-Apr-2022 14:25:01 GMT; path=/; domain=.yahoo.co.jp; secure; samesite=none Set-Cookie: XB=5k0q8u5f8uc1t&b=3&s=93; expires=Sun, 10-Apr-2022 14:25:01 GMT; path=/; domain=.yahoo.co.jp; secure; samesite=none < * Connection #0 to host localhost left intact
今度は、リダイレクトされません。
アクセスログ側も確認してみます。
localhost - - [09/Apr/2020:14:25:00 +0000] "CONNECT www.yahoo.co.jp:443 HTTP/1.1" 200 7047 "-" "-"
OKそうですね。