web-dev-qa-db-ja.com

リバースプロキシとSSL終了を使用するようにsettings.phpを正しく構成する方法

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設定を使用しますか?

6
Taylor Taff

これは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', ...];
}
4
colan

これは、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の値を適切に調整できるようにします。

1
user21641

Drupal 8

サイトの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

Drupal 7

$conf['reverse_proxy'] = TRUE;
$conf['reverse_proxy_addresses'] = [@$_SERVER['REMOTE_ADDR']];

以下も参照してください。

0
kenorb

動的リバースプロキシ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;
  }
}
0
David Thomas

@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.
0
yosefrow