Apacheのリバースプロキシという機能を使いdockerの任意のポートに転送する。

それだけではなく、Certbot + Let’s encryptを使ってクライアントとの間の通信はSSL化する。

環境

  • Ubuntu 20.04.2 LTS (AWS EC2)
  • Apache/2.4.41

Apacheモジュールのインストール

Apacheのプロキシ機能と、httpでのプロキシ機能を有効化するため、以下のコマンドを実行する

sudo a2enmod proxy
sudo a2enmod proxy_http

Apacheでヘッダーを編集する機能を有効化するため、以下コマンドを実行する

sudo a2enmod headers

URLを都度置き換える機能を有効化するため、以下コマンドを実行する

sudo a2enmod rewrite

設定を反映させるため以下コマンドを実行

sudo systemctl restart apache2

certbotをインストールする

過去の記事を参照してほしい

https://kajindowsxp.com/certbot-ssl/

certbotを使ってSSL証明書を設定する

certbotを利用するには80番ポートが利用できないといけないので、ファイヤウォールなどの設定はしておくこと。

ここからは、websocket.anti-crowded.comというアドレスを例にしていくので、適宜読み替えてほしい。以下コマンドを実行する

sudo certbot certonly --apache -d websocket.anti-crowded.com

正しく取得できると、
Certificate is saved at: /etc/letsencrypt/live/websocket.anti-crowded.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/websocket.anti-crowded.com/privkey.pem
のよう表示されるのでメモしておく。

apache2.confを書き換える

先程/etc/apache2/apache2.confに以下を追記する。

<VirtualHost *:80>
        ServerName websocket.anti-crowded.com
        AddDefaultCharset UTF-8
        RewriteEngine on
        RewriteCond %{SERVER_NAME} =websocket.anti-crowded.com
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerName websocket.anti-crowded.com
        AddDefaultCharset UTF-8

        <Proxy *>
        Require all granted
        </Proxy>

        ProxyRequests Off
        ProxyPreserveHost On
        ProxyPass / http://localhost:49160/ keepalive=On
        ProxyPassReverse / http://localhost:49160/
        RequestHeader set X-Forwarded-Proto "https"


        SSLCertificateFile /etc/letsencrypt/live/websocket.anti-crowded.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/websocket.anti-crowded.com/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

ここではバーチャルホストを設定してルーティングしている。
バーチャルホストとは、アクセスされたドメインによって転送先を設定できる機能。
ServerNameにドメイン名を設定することで動作を定義できる。

websocket.anti-crowded.comの80番ポートにアクセスしたときには、URLをhttps://から始まるものに変更することでSSL化された通信へリダイレクトしている

        RewriteEngine on
        RewriteCond %{SERVER_NAME} =websocket.anti-crowded.com
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

websocket.anti-crowded.comの443ポートにアクセスした時(つまりSSL通信だった場合)は、リバースプロキシをONにすることで、http://localhost:49160/に転送を行っている。
ポート番号を変更したい場合は49160を変更すればいいことになる。

        <Proxy *>
        Require all granted
        </Proxy>

        ProxyRequests Off
        ProxyPreserveHost On
        ProxyPass / http://localhost:49160/ keepalive=On
        ProxyPassReverse / http://localhost:49160/
        RequestHeader set X-Forwarded-Proto "https"

また、Certbotを使って取得した、Let’s encryptの証明書をここで読み込んでいる。

        SSLCertificateFile /etc/letsencrypt/live/websocket.anti-crowded.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/websocket.anti-crowded.com/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf

再起動&動作確認

設定が終わったらApacheを再起動

sudo service apache2 restart

refused to connect. が表示される場合

SSLエンジンが有効になっていない場合がある。以下コマンドを実行

sudo a2enmod ssl
sudo a2ensite default-ssl
sudo service apache2 restart

まとめ

今回、リバースプロキシを用いることでDocker側で設定をせずに、VPSのApacheの設定でポートのルーティングを行うことができた。

自分の通っている大学では、80番と443番以外のポートアクセスが禁止されているため、POST通信とWebsocket通信を利用したデータのやりとりができなかった。

この方法を使えば、SSL化された通信で安全にかつ大学のポート制限を回避してデータの送受信ができる。