サーバー管理者の場合は、ApacheやNginxなどのWebサーバーを選択している可能性があります。 アパッチ 1990年代からよく知られているWebサーバーです。 Nginx 2004年に最初に開発され、メモリフットプリントが軽量で、静的HTMLファイルの処理速度が速いため、すぐに注目を集めました。
ApacheとNginxはどちらも仮想ホスティングをサポートしています。つまり、同じサーバー上で複数のWebサイトまたはWebアプリケーションをホストできます。ただし、既存のWebサーバーを実行しているが、特定のWebアプリケーションで別のWebサーバーを使用する必要がある場合があります。パブリックIPアドレスのポート80または443は、1つのプロセスでのみ使用できます。 Apacheがポートを使用している場合、Nginxはそのポートを使用(またはバインド)できません。では、何ができるでしょうか?
NginxをApacheへのリバースプロキシとして構成できるため、NginxはHTTPリクエストをApacheにリダイレクトできます。私の経験では、これがトラブルシューティングできない奇妙な問題を引き起こしたことがあるため、これが常に最善の方法であるとは限らないことがわかりました。代わりに、NginxとApacheの両方のリバースプロキシとしてHAProxyを使用することを好みます。 。 HAProxyは、TCPおよびHTTPベースのアプリケーション向けの無料のオープンソース高可用性ロードバランサーおよびプロキシサーバーです。
同じサーバーでApache、Nginx、HAProxyを実行する
仕組みは次のとおりです。
- Nginxは127.0.0.1:80と127.0.0.1:443でリッスンします
- Apacheは127.0.0.2:80と127.0.0.2:443でリッスンします
- HAProxyは、パブリックIPアドレスのポート80および443でリッスンします。ポート80のHTTPリクエストをポート443にリダイレクトします。リクエストがポート443に到着すると、HTTPSリクエストのSNI(サーバー名表示)ヘッダーを分析して、NginxとApacheのどちらのバックエンドを選択します。
実際、Cloudflare(CDNプロバイダー)もSNIヘッダーを使用して、HTTPSリクエストをオリジンサーバーにルーティングする方法を決定しています。
ステップ1:NginxとApacheを停止する
Debian、Ubuntu、CentOSでNginxを停止するには、
を実行します。sudo systemctl stop nginx
Debian / UbuntuでApacheを停止するには、
を実行します。sudo systemctl stop apache2
CentOSでApacheを停止するには、
を実行します。sudo systemctl stop httpd
ステップ2:Nginxのリッスンポートを変更する
Nginxを127.0.0.1:80でリッスンさせる必要があります。 /etc/nginx/conf.d/
にあるNginx構成ファイルを開きます または/etc / nginx / sites-enabled /
次の行を見つけます。
listen 80;
に変更
listen 127.0.0.1:80;
Nginxサーバーブロックでhttpsが有効になっている場合は、
も検索します。listen 443 ssl;
そしてそれを
に変更しますlisten 127.0.0.1:443 ssl;
Nginxメイン構成ファイル/etc/nginx/nginx.conf
ポート80または443でリッスンしているデフォルトの仮想ホストが含まれている可能性があるため、このファイルも編集する必要がある場合があります。
変更を有効にするには、Nginxを再起動します。
sudo systemctl restart nginx
ステップ3:Apacheのリッスンポートを変更する
Apacheを127.0.0.2:80でリッスンさせる必要があります。
Debian / Ubuntu
DebianとUbuntuで、 /etc/apache2/ports.conf
を編集します ファイル。
sudo nano /etc/apache2/ports.conf
変更
Listen 80 Listen 443
宛先
Listen 127.0.0.2:80 Listen 127.0.0.2:443
ファイルを保存して閉じます。 / etc / apache2 / sites-enabled /
にもアクセスします ディレクトリ、仮想ホストファイルを編集します。変更
<VirtualHost *:80>
宛先
<VirtualHost 127.0.0.2:80>
SSL仮想ホストがある場合は、それも変更します
<VirtualHost *:443>
宛先
<VirtualHost 127.0.0.2:443>
Apacheを再起動します。
sudo systemctl restart apache2
CentOS
CentOSで、 /etc/httpd/conf/httpd.conf
を編集します ファイル。
sudo nano /etc/httpd/conf/httpd.conf
検索
Listen 80
に変更
Listen 127.0.0.2:80
ファイルを保存して閉じます。次に、 /etc/httpd/conf.d/
に移動します ディレクトリ、仮想ホストファイルを編集します。変更
<VirtualHost *:80>
宛先
<VirtualHost 127.0.0.2:80>
SSL仮想ホストがある場合は、それも変更します
<VirtualHost *:443>
宛先
<VirtualHost 127.0.0.2:443>
/etc/httpd/conf.d/ssl.conf
内 ファイル、あります
Listen 443 https
次のように変更します:
Listen 127.0.0.2:443 https
ファイルを保存して閉じます。変更を有効にするには、Apacheを再起動します。
sudo systemctl restart httpd
ステップ4:HAProxyを構成する
ディストリビューションにHAProxyをインストールします。
Debian / Ubuntu
sudo apt install haproxy
CentOS
sudo dnf install haproxy
HAProxy構成ファイルを編集します。
sudo nano /etc/haproxy/haproxy.cfg
ファイルの最後に次のコードスニペットを追加します。これにより、HAPorxyはパブリックIPアドレスのポート80でリッスンし、ポート80でHTTPリクエストをポート443にリダイレクトします。12.34.56.78をサーバーのパブリックIPアドレスに置き換えます。
>frontend http bind 12.34.56.78:80 mode http redirect scheme https code 301
次に、HTTPSフロントエンドも追加する必要があります。
frontend https bind 12.34.56.78:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 }
次に、NginxとApacheのバックエンドを定義します。 チェックコード> パラメータは、TCPパケットを送信することによってバックエンドでヘルスチェックを実行するようにHAProxyに指示します。
backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 check
デフォルトのバックエンドは次のように定義できます:
default_backend nginx
HTTPSリクエストでSNIヘッダーを使用して、正しいバックエンドにリダイレクトします。たとえば、Nginxが domain1.com
を提供している場合 Apacheはdomain2.com
を提供しています 、次に次の2行を追加します。サブドメインが異なる限り、サブドメインを使用することもできます。
use_backend nginx if { req_ssl_sni -i domain1.com } use_backend apache if { req_ssl_sni -i domain2.com }
default_backend
に注意してください およびuse_backend
ディレクティブはバックエンド定義の上に配置する必要があります。
frontend http bind 12.34.56.78:80 mode http redirect scheme https code 301 frontend https bind 12.34.56.78:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 } default_backend nginx use_backend nginx if { req_ssl_sni -i domain1.com } use_backend apache if { req_ssl_sni -i domain2.com } backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 check
上記の構成では、TLSのSNI(Server Name Indication)機能を利用してHTTPSトラフィックを区別しました。
- domain1.comがTLSクライアントHelloにある場合、HAProxyはトラフィックを
nginx
にリダイレクトします バックエンド。 - domain2.comがTLSクライアントHelloにある場合、HAProxyはトラフィックを
apache
にリダイレクトします。 バックエンド。
クライアントがTLSClientHelloでサーバー名を指定しない場合、HAproxyはデフォルトのバックエンド(nginx)を使用します。
ファイルを保存して閉じます。次に、HAproxyを再起動します。
sudo systemctl restart haproxy
これで、Apache、Nginx、およびHAProxyを同じサーバーで実行できるようになりました。
クライアントのIPアドレスをバックエンドに転送する方法
デフォルトでは、ApacheとNginxはHAProxyのIPアドレスのみを表示できます。クライアントの実際のIPアドレスを取得するには、必ず send-proxy-v2
を追加してください。 以下のようなHAProxyのバックエンド定義のオプション。
backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 send-proxy-v2 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 send-proxy-v2 check
また、NginxとApacheにいくつかの構成を追加して機能させる必要があります。そうしないと、Webサイトにアクセスできなくなります。
Nginx
proxy_protocol
を追加します Nginxでlisten
以下のようなディレクティブ。
listen 127.0.0.2:443 ssl http2 proxy_protocol;
次に、Nginx http {}
に次の2つのディレクティブを追加します /etc/nginx/nginx.conf
のブロック ファイル。
set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol;
ファイルを保存して閉じます。次に、Nginxをリロードします。
sudo systemctl reload nginx
注 :ウェブサイトがCloudflare CDNの背後で実行されている場合は、 real_ip_header proxy_protocol;
を変更する必要があります real_ip_header CF-Connecting-IP;
へ クライアントの実際のIPアドレスを表示するため。このreal_ip_header
を追加することもできます /etc/nginx/nginx.conf
のグローバル構成をオーバーライドする個々のサーバーブロックファイルへのディレクティブ ファイル。
最後に、HAProxyを再起動します。
sudo systemctl restart haproxy
Apache
Debian / UbuntuでApacheを使用する場合は、 remoteipを有効にする必要があります モジュール。 (このモジュールはCentOSでデフォルトで有効になっています。)
sudo a2enmod remoteip
次に、Apache仮想ホスト構成ファイルに次の3行を追加します。
RemoteIPProxyProtocol On RemoteIPHeader X-Forwarded-For RemoteIPTrustedProxy 127.0.0.1
このように。
<VirtualHost 127.0.0.2:443> ServerName www.example.com RemoteIPProxyProtocol On RemoteIPHeader X-Forwarded-For RemoteIPTrustedProxy 127.0.0.1
ファイルを保存して閉じます。次に、 Combined
も変更する必要があります ログ形式。 Apacheのメイン構成ファイルを編集します。
sudo nano /etc/apache2/apache2.conf
または
sudo nano /etc/httpd/conf/httpd.conf
次の行を見つけます。
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
次のように置き換えます:
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
ファイルを保存して閉じます。次に、変更を有効にするためにApacheを再起動します。
sudo systemctl restart apache2
または
sudo systemctl restart httpd
注 RemoteIPProxyProtocol On
ディレクティブは、Apache2.4.31以降でのみ使用できます。 Apacheのバージョンを確認するには、
sudo apache2 -v
または
sudo httpd -v
Ubuntu18.04にはApache2.4.29が付属しています。 Apacheのバージョンがこの要件を満たしていない場合は、 send-proxy-v2
を削除する必要があります HAProxyバックエンド定義で。 CentOS8にはApache2.4.37が付属しています。
最後に、HAProxyを再起動します。
sudo systemctl restart haproxy
新しい仮想ホストを追加する方法
ApacheおよびNginxWebサーバーがある場合、必要なバックエンドは2つだけです。1つはApache用、もう1つはNginx用です。
別のドメイン(またはサブドメイン)を追加する必要がある場合、HAProxyに新しいバックエンドを追加する必要はありません。代わりに、ApacheまたはNginxで新しいドメイン(またはサブドメイン)の新しい仮想ホストを作成してから、 use_backend
を使用する必要があります。 トラフィックを正しいバックエンドにリダイレクトするためのHAProxyのディレクティブ。
frontend http bind 12.34.56.78:80 mode http redirect scheme https code 301 frontend https bind 12.34.56.78:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 } default_backend nginx use_backend nginx if { req_ssl_sni -i domain1.com } use_backend nginx if { req_ssl_sni -i sub.domain1.com } use_backend apache if { req_ssl_sni -i domain2.com } use_backend apache if { req_ssl_sni -i sub.domain2.com } backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 check
apache
の使用をお勧めします およびnginx
上記のコードのようなバックエンド名として、どのWebサーバーがどのアプリケーションをホストしているかがわかります。
新しいLet'sEncryptSSL証明書の取得
http-01チャレンジ
まず、Certbotapacheとnginxオーセンティケーターを使用してTLS証明書を取得する方法を理解する必要があります。
- UbuntuでLet’sEncryptを使用してApacheでHTTPSを適切に有効にする
- UbuntuでLet’sEncryptを使用してNginxでHTTPSを適切に有効にする
Certbotapacheとnginxオーセンティケーターはhttp-01
を使用します チャレンジ。TCPポート80で動作します。HAProxyはTCPポート80を使用しているため、Certbot http-01
チャレンジは失敗する可能性があります。ただし、次の方法で動作させることができます。
- 自己署名証明書または別のドメインの証明書を使用して、ApacheまたはNginxでSSLホストを有効にします。
- 次に、通常どおりCertbotapacheとnginxオーセンティケーターを使用します。
このメソッドが機能するのは、Certbot http-01
チャレンジはTCPポート80からTCPポート443にリダイレクトでき、Certbotはポート443で無効な証明書を受け入れます。
dns-01チャレンジ
certbot dns-01
を使用することもできます チャレンジ。ドメインの一時的なTXTレコードを作成して、実際にこのドメインを所有していることを証明することで機能します。これにより、TCPポート80とTCPポート443をバイパスできます。この方法の欠点は、すべてのドメインレジストラがサポートされているわけではないことです。
まず、CertbotDNSプラグインをインストールする必要があります。これらは、DebianおよびUbuntuソフトウェアリポジトリで利用可能ないくつかのDNSプラグインであり、
で見つけることができます。apt search python3-certbot-dns
出力:
python3-certbot-dns-cloudflare/bionic,bionic 0.23.0-1 all Cloudflare DNS plugin for Certbot python3-certbot-dns-digitalocean/bionic,bionic 0.23.0-1 all DigitalOcean DNS plugin for Certbot python3-certbot-dns-dnsimple/bionic,bionic 0.23.0-1 all DNSimple DNS plugin for Certbot python3-certbot-dns-google/bionic,bionic 0.23.0-1 all Google DNS plugin for Certbot python3-certbot-dns-rfc2136/bionic,bionic 0.23.0-1 all RFC 2136 DNS plugin for Certbot python3-certbot-dns-route53/bionic,bionic 0.23.0-1 all Route53 DNS plugin for Certbot
CentOS 8では、EPELリポジトリからCertbotDNSプラグインを見つけることができます。デフォルトのCentOSリポジトリからCertbotをインストールする必要があることに注意してください。
sudo dnf install certbot
EPELリポジトリからDNSプラグインを見つけます。
sudo dnf install epel-release dnf search certbot-dns
出力:
python3-certbot-dns-ovh.noarch : OVH DNS Authenticator plugin for Certbot python3-certbot-dns-nsone.noarch : NS1 DNS Authenticator plugin for Certbot python3-certbot-dns-gehirn.noarch : Gehirn Infrastructure Service DNS Authenticator plugin for Certbot python3-certbot-dns-google.noarch : Google Cloud DNS Authenticator plugin for Certbot python3-certbot-dns-linode.noarch : Linode DNS Authenticator plugin for Certbot python3-certbot-dns-luadns.noarch : LuaDNS Authenticator plugin for Certbot python3-certbot-dns-rfc2136.noarch : RFC 2136 DNS Authenticator plugin for Certbot python3-certbot-dns-route53.noarch : Route53 DNS Authenticator plugin for Certbot python3-certbot-dns-cloudxns.noarch : CloudXNS DNS Authenticator plugin for Certbot python3-certbot-dns-dnsimple.noarch : DNSimple DNS Authenticator plugin for Certbot python3-certbot-dns-cloudflare.noarch : Cloudflare DNS Authenticator plugin for Certbot python3-certbot-dns-cloudflare.noarch : Cloudflare DNS Authenticator plugin for Certbot python3-certbot-dns-dnsmadeeasy.noarch : DNS Made Easy DNS Authenticator plugin for Certbot python3-certbot-dns-sakuracloud.noarch : Sakura Cloud DNS Authenticator plugin for Certbot
使用しているDNSホスティングサービスに応じて、これらのプラグインの1つをインストールします。私はCloudflareを使用しているので、例としてCloudflareを使用します。次のコマンドを実行して、 python3-certbot-dns-cloudflare
をインストールします Debian/Ubuntuのパッケージ。
sudo apt install python3-certbot-dns-cloudflare
次に、Cloudflareの構成ファイルを作成します。
sudo nano /etc/letsencrypt/cloudflare.ini
このファイルにCloudflareアカウントのメールアドレスとAPIキーを追加する必要があります。
# Cloudflare API credentials used by Certbot dns_cloudflare_email = [email protected] dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567
Cloudflare APIキーは、 https://dash.cloudflare.com/profile
にあります。 。 Certbot Cloudflareプラグインは現在Cloudflareの「APIトークン」をサポートしていないため、認証には「グローバルAPIキー」を使用してください。
ファイルを保存して閉じます。 APIキーはCloudflareの2要素認証をバイパスするため、rootユーザーのみにこのファイルの読み取りを許可する必要があります。
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
次に、certbotを実行します。
sudo certbot --agree-tos -a dns-cloudflare -i nginx --redirect --hsts --staple-ocsp --email [email protected] -d www.your-domain.com,your-domain.com
上記のコマンドでは、 dns-cloudflare
を使用するように指定しました 新しいTLS証明書を取得し、 nginx
を使用するオーセンティケーターとして HTTPSサーバーブロックを作成するプラグイン。 Apacheを使用している場合は、 nginx
を置き換えます apache
を使用 。
このコマンドでは、 .ini
のパスを入力するように求められます ファイルなので、 /etc/letsencrypt/cloudflare.ini
と入力します Enterキーを押します。
SSL証明書を取得し、Webサーバー構成ファイルにインストールした後。 127.0.0.1:443または127.0.0.2:443でリッスンするようにする必要があります。たとえば、Nginxを使用している場合は、
listen 443 ssl
そしてそれを
に変更しますlisten 127.0.0.1:443 ssl http2
また、ポート80を
に変更しますlisten 127.0.0.1:80;
ファイルを保存して閉じます。次に、Webサーバーを再起動します。
一般的なエラー
1間違ったドメイン名
サーバー上に複数のNginx仮想ホストがあり、1つのドメイン名を入力すると、Webブラウザーが同じサーバーでホストされている別のドメイン名に移動する場合、Nginx仮想ホストファイル名の1つが終了していない可能性があります .conf
を使用 ファイル名拡張子が大きいため、Nginxはこの仮想ホストをロードしませんでした。ドメイン名にAAAAレコードを設定したが、IPv6でドメイン名を提供するようにNginxを構成しなかった可能性もあります。
上記はApacheWebサーバーにも当てはまります。
2ネットワークプロトコル違反
send-proxy-v2
を設定した場合 HAProxyのヘッダーですが、 proxy_protocol
を有効にしませんでした NginxまたはApacheでは、Webサイトに次のエラーが表示されます。
The site has experienced a network protocol violation that cannot be repaired.
構成ファイルに変更を加えた後は、Nginx/Apacheを再起動することを忘れないでください。
3 PR_CONNECT_RESET_ERROR
proxy_protocol
を有効にした場合 NginxまたはApacheで、ただし send-proxy-v2
を設定しませんでした HAProxyのヘッダーの場合、Webサイトにこのエラーが表示されます。
secure connection failed. PR_CONNECT_RESET_ERROR
また、NginxまたはApacheのエラーログに次のエラーメッセージが表示されます。
broken header while reading PROXY protocol
構成ファイルに変更を加えた後は、Nginx/Apacheを再起動することを忘れないでください。
プロキシプロトコル
を有効にした場合も注意してください 1つのApache/Nginx仮想ホストファイルで、他のすべての仮想ホストに対しても暗黙的に有効になります。そして、 proxy_protocol
を無効にする方法が見つかりませんでした 個々の仮想ホスト用。同じサーバーでApacheとNginxを実行しているため、回避策は、Nginxでのみプロキシプロトコルを有効にし、Apacheでは有効にしないことです。仮想ホストがクライアントの実際のIPアドレスを取得する必要がない場合は、Apacheを使用するように仮想ホストを構成します。
更新 :127.0.0.4のような別のループバックアドレスに新しいApache/Nginx仮想ホストをセットアップできることに気づきました。このように、新しい仮想ホストはプロキシプロトコルを有効にしません。
4 PR_END_OF_FILE_ERROR
Apache / Nginxでプロキシプロトコルを有効にしたが、仮想ホストに直接アクセスしようとすると(HAProxyをバイパスして)、次のエラーが表示されます。
PR_END_OF_FILE_ERROR
5 SSL_ERROR_SYSCALL
curlコマンドを使用する場合:
curl -I https://example.com
そして、次のエラーが発生します
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to example.com:443
このドメインのバックエンド定義を設定しなかったことが原因である可能性があります。