diff --git a/core/modules/ban/ban.admin.inc b/core/modules/ban/ban.admin.inc
index bccd84e..5fabdbe 100644
--- a/core/modules/ban/ban.admin.inc
+++ b/core/modules/ban/ban.admin.inc
@@ -6,11 +6,14 @@
  */
 
 /**
- * Page callback; Displays banned IP addresses.
+ * Page callback: Displays banned IP addresses.
  *
  * @param string $default_ip
- *   (optional) IP address to be passed on to drupal_get_form() for
- *   use as the default value of the IP address form field.
+ *   (optional) IP address to be passed on to drupal_get_form() for use as the
+ *   default value of the IP address form field.
+ *
+ * @return array
+ *   A renderable array.
  */
 function ban_admin_page($default_ip = '') {
   $rows = array();
@@ -53,7 +56,6 @@ function ban_admin_page($default_ip = '') {
  *
  * @see ban_ip_form_validate()
  * @see ban_ip_form_submit()
- *
  * @ingroup forms
  */
 function ban_ip_form($form, &$form_state, $default_ip) {
@@ -119,7 +121,7 @@ function ban_ip_delete_form($form, &$form_state, array $ban_ip) {
     '#value' => $ban_ip,
   );
   return confirm_form($form,
-    t('Are you sure you want to delete %ip?', array('%ip' => $ban_ip['ip'])),
+    t('Are you sure you want to unblock %ip?', array('%ip' => $ban_ip['ip'])),
     'admin/config/people/ban',
     NULL,
     t('Delete')
diff --git a/core/modules/ban/ban.module b/core/modules/ban/ban.module
index d886871..3200c67 100644
--- a/core/modules/ban/ban.module
+++ b/core/modules/ban/ban.module
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Enables banning of IP addresses.
+ * Allows capability to ban individual IP addresses.
  */
 
 /**
@@ -13,7 +13,7 @@ function ban_help($path, $arg) {
     case 'admin/help#ban':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('The Ban module allows administrators to ban visits to their site from given IP addresses.') . '</p>';
+      $output .= '<p>' . t('The Ban module allows administrators to ban visits to their site from individual IP addresses.') . '</p>';
       $output .= '<h3>' . t('Uses') . '</h3>';
       $output .= '<dl>';
       $output .= '<dt>' . t('Banning IP addresses') . '</dt>';
@@ -60,61 +60,6 @@ function ban_menu() {
 }
 
 /**
- * Implements hook_boot().
- */
-function ban_boot() {
-  ban_block_denied(ip_address());
-}
-
-/**
- * Returns whether an IP address is blocked.
- *
- * Blocked IP addresses are stored in the database by default. However, for
- * performance reasons we allow an override in variables.
- *
- * @param string $ip
- *   The IP address to check.
- *
- * @return bool
- *   TRUE if access is denied, FALSE if access is allowed.
- */
-function ban_is_denied($ip) {
-  $denied = FALSE;
-  // Because this function is called on every page request, we first check
-  // for an array of IP addresses in settings.php before querying the
-  // database.
-  $blocked_ips = variable_get('ban_ips');
-  if (isset($blocked_ips) && is_array($blocked_ips)) {
-    $denied = in_array($ip, $blocked_ips);
-  }
-  // If $conf['page_cache_without_database'] = TRUE; is set in settings.php,
-  // then the database is not available yet, so IPs recorded in the database
-  // won't be denied. However, the user asked explicitly not to use the
-  // database, and in this case it's also quite likely that the user relies
-  // on higher performance solutions like a firewall.
-  elseif (class_exists('Drupal\Core\Database\Database', FALSE) && function_exists('db_query')) {
-    $denied = (bool) db_query("SELECT 1 FROM {ban_ip} WHERE ip = :ip", array(':ip' => $ip))->fetchField();
-  }
-  return $denied;
-}
-
-/**
- * Prints a message and exits if access from a given IP address is denied.
- *
- * @param string $ip
- *   The IP address to check.
- */
-function ban_block_denied($ip) {
-  // Check whether the given IP address has been blocked.
-  if (ban_is_denied($ip)) {
-    header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
-    // t() is not yet available.
-    print 'Sorry, ' . check_plain($ip) . ' has been banned.';
-    exit();
-  }
-}
-
-/**
  * Loads a banned IP address record from the database.
  *
  * @param int $iid
diff --git a/core/modules/ban/lib/Drupal/ban/BanBundle.php b/core/modules/ban/lib/Drupal/ban/BanBundle.php
new file mode 100644
index 0000000..1c04ff4
--- /dev/null
+++ b/core/modules/ban/lib/Drupal/ban/BanBundle.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\ban\BanBundle.
+ */
+
+namespace Drupal\Ban;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+use Drupal\Core\Database\Database;
+
+/**
+ * Ban dependency injection container.
+ */
+class BanBundle extends Bundle {
+
+  /**
+   * Overrides Symfony\Component\HttpKernel\Bundle\Bundle::build().
+   */
+  public function build(ContainerBuilder $container) {
+    $container->register('subscriber.ban', 'Drupal\ban\EventSubscriber\BanSubscriber')
+      ->addArgument(new Reference('database'));
+    $container->get('dispatcher')
+      ->addSubscriberService('subscriber.ban', 'Drupal\ban\EventSubscriber\BanSubscriber');
+  }
+}
diff --git a/core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php b/core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php
new file mode 100644
index 0000000..4b596d1
--- /dev/null
+++ b/core/modules/ban/lib/Drupal/ban/EventSubscriber/BanSubscriber.php
@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Ban\EventSubscriber\BanSubscriber.
+ */
+
+namespace Drupal\Ban\EventSubscriber;
+
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+use Drupal\Core\Database\Connection;
+
+/**
+ * Ban subscriber for controller requests.
+ */
+class BanSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The database connection used to check the IP against.
+   *
+   * @var Drupal\Core\Database\Connection
+   */
+  protected $connection;
+
+  /**
+   * Construct the BanSubscriber.
+   *
+   * @param Drupal\Core\Database\Connection $connection
+   *   The database connection which will be used to check the IP against.
+   */
+  public function __construct(Connection $connection) {
+    $this->connection = $connection;
+  }
+
+  /**
+   * Response with 403 if the visitor's IP adress is banned.
+   *
+   * @param Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   *   The Event to process.
+   */
+  public function onKernelRequestBannedIpCheck(GetResponseEvent $event) {
+    $ip = $event->getRequest()->getClientIp();
+    if ($this->isDenied($ip)) {
+      $response = new Response('Sorry, ' . check_plain($ip) . ' has been banned.', 403);
+      $event->setResponse($response);
+    }
+  }
+
+  /**
+   * Registers the methods in this class that should be listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents() {
+    $events[KernelEvents::REQUEST][] = array('onKernelRequestBannedIpCheck', 40);
+    return $events;
+  }
+
+  /**
+   * Returns whether an IP address is blocked.
+   *
+   * Blocked IP addresses are stored in the database by default. However, for
+   * performance reasons we allow an override in variables.
+   *
+   * @param string $ip
+   *   The IP address to check.
+   *   If omitted or empty the IP of the current user will be used instead.
+   *
+   * @return bool
+   *   TRUE if access is denied, FALSE if access is allowed.
+   */
+  protected function isDenied($ip) {
+    $denied = FALSE;
+    // Because this function is called on every page request, we first check for
+    // an array of IP addresses in settings.php before querying the database.
+    $blocked_ips = variable_get('ban_ips');
+    if (isset($blocked_ips) && is_array($blocked_ips)) {
+      $denied = in_array($ip, $blocked_ips);
+    }
+    // Check the database if no match.
+    if ($denied === FALSE) {
+      $denied = $this->connection
+        ->query('SELECT 1 FROM {ban_ip} WHERE ip = :ip', array(':ip' => $ip))
+        ->fetchField();
+    }
+    return (bool) $denied;
+  }
+}
diff --git a/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsBlockVisitorsTest.php b/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsBlockVisitorsTest.php
index 4657d10..82990e3 100644
--- a/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsBlockVisitorsTest.php
+++ b/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsBlockVisitorsTest.php
@@ -50,7 +50,7 @@ function testIPAddressBlocking() {
 
     // Unblock the IP address.
     $this->clickLink('unban IP address');
-    $this->assertRaw(t('Are you sure you want to delete %ip?', array('%ip' => $test_ip_address)), 'IP address deletion confirmation found.');
+    $this->assertRaw(t('Are you sure you want to unblock %ip?', array('%ip' => $test_ip_address)), 'IP address deletion confirmation found.');
     $edit = array();
     $this->drupalPost('admin/config/people/ban/delete/1', NULL, t('Delete'));
     $this->assertRaw(t('The IP address %ip was deleted.', array('%ip' => $test_ip_address)), 'IP address deleted.');
