You are here

public function ClientIpRestore::onRequest in CloudFlare 8

Restores the origination client IP delivered to Drupal from CloudFlare.

File

src/EventSubscriber/ClientIpRestore.php, line 99

Class

ClientIpRestore
Restores the true client Ip address.

Namespace

Drupal\cloudflare\EventSubscriber

Code

public function onRequest(GetResponseEvent $event) {
  if (!$this->isClientIpRestoreEnabled) {
    return;
  }
  $current_request = $event
    ->getRequest();
  $cf_connecting_ip = $current_request->server
    ->get('HTTP_CF_CONNECTING_IP');
  $has_http_cf_connecting_ip = !empty($cf_connecting_ip);
  $has_bypass_host = !empty($this->bypassHost);
  $client_ip = $current_request
    ->getClientIp();
  $incoming_uri = $current_request
    ->getHost();
  $request_expected_to_bypass_cloudflare = $has_bypass_host && $this->bypassHost == $incoming_uri;
  if ($request_expected_to_bypass_cloudflare) {
    return;
  }
  if (!$has_http_cf_connecting_ip) {
    $message = $this
      ->t("Request came through without being routed through CloudFlare.");
    $this->logger
      ->warning($message);
    return;
  }
  $has_ip_already_changed = $client_ip == $cf_connecting_ip;

  // Some environments may make the alteration for us. In which case no
  // action is required.
  if ($has_ip_already_changed) {
    $url_to_settings = Url::fromRoute('cloudflare.admin_settings_form');
    $link_to_settings = $url_to_settings
      ->getInternalPath();
    $message = $this
      ->t('Request has already been updated.  This functionality should be deactivated. Please go <a href="@link_to_settings">here</a> to disable "Restore Client Ip Address".', [
      '@link_to_settings' => $link_to_settings,
    ]);
    $this->logger
      ->warning($message);
    return;
  }
  $cloudflare_ipranges = $this
    ->getCloudFlareIpRanges();
  $request_originating_from_cloudflare = IpUtils::checkIp($client_ip, $cloudflare_ipranges);
  if ($has_http_cf_connecting_ip && !$request_originating_from_cloudflare) {
    $message = $this
      ->t("Client IP of @client_ip does not match a known CloudFlare IP but there is HTTP_CF_CONNECTING_IP of @cf_connecting_ip.", [
      '@cf_connecting_ip' => $cf_connecting_ip,
      '@client_ip' => $client_ip,
    ]);
    $this->logger
      ->warning($message);
    return;
  }

  // As the changed remote address will make it impossible to determine
  // a trusted proxy, we need to make sure we set the right protocal as well.
  // @see \Symfony\Component\HttpFoundation\Request::isSecure()
  $event
    ->getRequest()->server
    ->set('HTTPS', $event
    ->getRequest()
    ->isSecure() ? 'on' : 'off');
  $event
    ->getRequest()->server
    ->set('REMOTE_ADDR', $cf_connecting_ip);
  $event
    ->getRequest()
    ->overrideGlobals();
}