Settings.phpには、「リバースプロキシ設定」というセクションがあります。リバースプロキシとSSLターミネーションを使用しているときに追加する設定を提案します。
Nginxはポート443でリッスンしており、ヘッダーを追加してから、localhostポート80でApache Httpdに渡します。説明したNginxは次のとおりです。
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
location / {
proxy_pass http://127.0.0.1:80;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Host $Host;
}
}
これらの設定/ヘッダーを念頭に置いて、「リバースプロキシ構成」からどの選択が正しいかを考慮してください。 settings.php?
* Reverse Proxy Configuration:
*
* Reverse proxy servers are often used to enhance the performance
* of heavily visited sites and may also provide other site caching,
* security, or encryption benefits. In an environment where Drupal
* is behind a reverse proxy, the real IP address of the client should
* be determined such that the correct client IP address is available
* to Drupal's logging, statistics, and access management systems. In
* the most simple scenario, the proxy server will add an
* X-Forwarded-For header to the request that contains the client IP
* address. However, HTTP headers are vulnerable to spoofing, where a
* malicious client could bypass restrictions by setting the
* X-Forwarded-For header directly. Therefore, Drupal's proxy
* configuration requires the IP addresses of all remote proxies to be
* specified in $settings['reverse_proxy_addresses'] to work correctly.
*
* Enable this setting to get Drupal to determine the client IP from
* the X-Forwarded-For header (or $settings['reverse_proxy_header'] if set).
* If you are unsure about this setting, do not have a reverse proxy,
* or Drupal operates in a shared hosting environment, this setting
* should remain commented out.
*
* In order for this setting to be used you must specify every possible
* reverse proxy IP address in $settings['reverse_proxy_addresses'].
* If a complete list of reverse proxies is not available in your
* environment (for example, if you use a CDN) you may set the
* $_SERVER['REMOTE_ADDR'] variable directly in settings.php.
* Be aware, however, that it is likely that this would allow IP
* address spoofing unless more advanced precautions are taken.
*/
# $settings['reverse_proxy'] = TRUE;
/**
* Specify every reverse proxy IP address in your environment.
* This setting is required if $settings['reverse_proxy'] is TRUE.
*/
# $settings['reverse_proxy_addresses'] = array('a.b.c.d', ...);
/**
* Set this value if your proxy server sends the client IP in a header
* other than X-Forwarded-For.
*/
# $settings['reverse_proxy_header'] = 'X_CLUSTER_CLIENT_IP';
/**
* Set this value if your proxy server sends the client protocol in a header
* other than X-Forwarded-Proto.
*/
# $settings['reverse_proxy_proto_header'] = 'X_FORWARDED_PROTO';
/**
* Set this value if your proxy server sends the client protocol in a header
* other than X-Forwarded-Host.
*/
# $settings['reverse_proxy_Host_header'] = 'X_FORWARDED_Host';
/**
* Set this value if your proxy server sends the client protocol in a header
* other than X-Forwarded-Port.
*/
# $settings['reverse_proxy_port_header'] = 'X_FORWARDED_PORT';
/**
* Set this value if your proxy server sends the client protocol in a header
* other than Forwarded.
*/
# $settings['reverse_proxy_forwarded_header'] = 'FORWARDED';
PHP(7))に渡されるホスト設定をテストするには、setting.phpの下部に次を追加します。
print '<pre>';
print_r($_SERVER);
print '</pre>';
Nginxによって追加されたヘッダーは受け渡されますが、サーバーURIは常に[SCRIPT_URI] => http://www.example.com/
ではなく[SCRIPT_URI] => https://www.example.com/
に設定されます。
正しくリバースプロキシを設定するには、Drupal設定を使用しますか?
これはDrupal 7と8の両方で機能するはずです。実際には global.inc が私の Aegir 設定の1つであり、ホストされているすべてのサイトに挿入されますsettings.php
ファイル。
<?php # global settings.php
/**
* Tell all Drupal sites that we're running behind an HTTPS proxy.
*/
// Drupal 7 configuration.
if (explode('.', VERSION)[0] == 7) {
$conf['reverse_proxy'] = TRUE;
$conf['reverse_proxy_addresses'] = ['1.2.3.4', ...];
// Force the protocol provided by the proxy. This isn't always done
// automatically in Drupal 7. Otherwise, you'll get mixed content warnings
// and/or some assets will be blocked by the browser.
if (php_sapi_name() != 'cli') {
if (isset($_SERVER['SITE_SUBDIR']) && isset($_SERVER['RAW_Host'])) {
// Handle subdirectory mode.
$base_url = $_SERVER['HTTP_X_FORWARDED_PROTO'] . '://' . $_SERVER['RAW_Host'] . '/' . $_SERVER['SITE_SUBDIR'];
}
else {
$base_url = $_SERVER['HTTP_X_FORWARDED_PROTO'] . '://' . $_SERVER['SERVER_NAME'];
}
}
}
// Drupal 8 configuration.
else {
$settings['reverse_proxy'] = TRUE;
$settings['reverse_proxy_addresses'] = ['1.2.3.4', ...];
}
これは、Google Cloudで使用しているsettings.phpの一部です。
// Force secure connection if the request wasn't made from CLI.
if (PHP_SAPI !== 'cli') {
// Fix HTTPS if we're behind load balancer.
if (getenv('HTTPS') !== 'on' && getenv('HTTP_X_FORWARDED_PROTO') === 'https') {
$_SERVER['HTTPS'] = 'on';
}
// Perform redirect to secure connection if needed.
if ($_SERVER['HTTPS'] !== 'on') {
header('HTTP/1.0 301 Moved Permanently');
header('Location: https://'. getenv('HTTP_Host') . getenv('REQUEST_URI'));
exit;
}
}
//...
// Enable LB headers, if applicable.
if (getenv('HTTP_VIA')) {
$settings['reverse_proxy'] = TRUE;
$settings['reverse_proxy_addresses'] = ['0.0.0.0']; // LB IP
}
https://www.drupal.org/node/2492389 を確認し、受信しているヘッダーを確認して、Drupalの値を適切に調整できるようにします。
サイトのsettings.php
ファイルに次の設定を適用します:
$settings['reverse_proxy'] = TRUE;
$settings['reverse_proxy_addresses'] = [@$_SERVER['REMOTE_ADDR']]
IPアドレスが動的なCDNで機能するはずです。
これは、次のコメントで説明されています。
* In order for this setting to be used you must specify every possible
* reverse proxy IP address in $settings['reverse_proxy_addresses'].
* If a complete list of reverse proxies is not available in your
* environment (for example, if you use a CDN) you may set the
* $_SERVER['REMOTE_ADDR'] variable directly in settings.php.
* Be aware, however, that it is likely that this would allow IP
* address spoofing unless more advanced precautions are taken
$conf['reverse_proxy'] = TRUE;
$conf['reverse_proxy_addresses'] = [@$_SERVER['REMOTE_ADDR']];
以下も参照してください。
動的リバースプロキシIPがあるが、remote_addr
が最初に内部であることを検証するために内部ネットワーク(kubernetesクラスターなど)上にある必要があることがわかっている場合は、settings.php
で次のようなものを使用できます(D8) :
/**
* Helper function to check
* if IP address is internal network
* @param string $ip - IP address to test
* @return boolean - false if private/internal IP
*/
function is_public_ip($ip) {
return (bool)filter_var(
$ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
);
}
// Set reverse proxy config for correct client IP lookup (uses env var check)
if (getenv('DRUPAL_REVERSE_PROXY')) {
$settings['reverse_proxy'] = TRUE;
// Init address list, no overwrite
$settings['reverse_proxy_addresses'] = $settings['reverse_proxy_addresses'] ?? [];
// Get dynamic forwarded for or remote IP for proxy config
// Check x-forwarded-for
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$forwarded_for_ips = array_map('trim', explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));
foreach ($forwarded_for_ips as $forwarded_for_ip) {
// Not already added and is not public ip (is internal ip)
if (!in_array($forwarded_for_ip, $settings['reverse_proxy_addresses']) && !is_public_ip($forwarded_for_ip)) {
$settings['reverse_proxy_addresses'][] = $forwarded_for_ip;
}
}
}
// Check remote_addr to add as well just in case not added above
if (!empty($_SERVER['REMOTE_ADDR']) && !in_array($_SERVER['REMOTE_ADDR'], $settings['reverse_proxy_addresses'])) {
// Ensure is internal IP
if (!is_public_ip($_SERVER['REMOTE_ADDR'])) {
$settings['reverse_proxy_addresses'][] = $_SERVER['REMOTE_ADDR'];
}
}
// No reverse_proxy for this case, as proxy address is required, use default
if (empty($settings['reverse_proxy_addresses'])) {
$settings['reverse_proxy'] = FALSE;
}
}
@colanの優れたソリューションをベースとして使用し、reverse_proxy_addressesを手動で定義する必要がないように2行を変更しました。
このソリューションを使用して、kubernetes(nginx-ingress)でSSL終端のnginxリバースプロキシの背後にあるサイトで大きな成功を収めました
/**
* Tell all Drupal sites that we're running behind an HTTPS proxy.
*/
// Drupal 7 configuration.
if (explode('.', VERSION)[0] == 7) {
$conf['reverse_proxy'] = TRUE;
$conf['reverse_proxy_addresses'] = array($_SERVER['REMOTE_ADDR']);
// Force the protocol provided by the proxy. This isn't always done
// automatically in Drupal 7. Otherwise, you'll get mixed content warnings
// and/or some assets will be blocked by the browser.
if (php_sapi_name() != 'cli') {
$base_url = $_SERVER['HTTP_X_FORWARDED_PROTO'] . '://' . $_SERVER['SERVER_NAME'];
}
}
// Drupal 8 configuration.
else {
$settings['reverse_proxy'] = TRUE;
$settings['reverse_proxy_addresses'] = array($_SERVER['REMOTE_ADDR']);
}
免責事項:(@DavidStinemetzeに感謝)
このソリューションは、予測不可能なIPを使用してCDNまたはサービスの背後からサイトにサービスを提供できるという固有の問題を解決しますが、より高度な予防策を講じない限り、この方法ではIPアドレスのスプーフィングが可能になる可能性があります。したがって、なりすましを防ぐために、これらの予防策を講じてください
デフォルトのsettings.phpから:
* In order for this setting to be used you must specify every possible
* reverse proxy IP address in $settings['reverse_proxy_addresses'].
* If a complete list of reverse proxies is not available in your
* environment (for example, if you use a CDN) you may set the
* $_SERVER['REMOTE_ADDR'] variable directly in settings.php.
* Be aware, however, that it is likely that this would allow IP
* address spoofing unless more advanced precautions are taken.