Назад | Перейти на главную страницу

Эластичная сила бобового стебля https

У меня возникают проблемы с принудительным использованием HTTPS на сайте, который я развертываю через AWS Elastic Beanstalk.

Это интерфейсное приложение, использующее EmberJS. Я много дней хожу по кругу, пытаясь понять, как перенаправить http-трафик на https. Я использую Amazon Linux AMI на своем компьютере с EC2.

Я пришел к выводу (все еще не уверен, правильно ли это), что я не использую Elastic Beanstalk для принудительного использования HTTPS. Я разрешаю HTTP и HTTPS через свой балансировщик нагрузки Elastic Beanstalk и пытаюсь выполнить перенаправление на сервере.

Здесь у меня проблемы. Я нахожу много ответов о правилах перезаписи без mod_rewrite которые основаны на X-Forwarded-Proto Заголовок, но этот файл не существует на моей машине EC2 согласно поиску.

Я также пробовал создать файл конфигурации в .ebextensions каталог, но это тоже не сработало.

Главное, что я пытаюсь сделать, - это направить пользователей на https при попытке попасть по адресу http. Любые указатели или предложения приветствуются, спасибо!

РЕДАКТИРОВАТЬ: я использую 64-битный Debian jessie v1.4.1 с Python 3.4 (предварительно настроенный - Docker)

Это также можно сделать несколько проще, не касаясь балансировщика нагрузки, используя X-Forwarded-Proto заголовок установлен ELB. Вот что я в итоге сделал:

files:
  "/etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf":
    mode: "00644"
    owner: root
    group: root
    content: |
      map $http_upgrade $connection_upgrade {
        default        "upgrade";
        ""            "";
      }

      server {
        listen 80;

        gzip on;
        gzip_comp_level 4;
        gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

        access_log    /var/log/nginx/access.log;

        location / {
          proxy_pass            http://docker;
          proxy_http_version    1.1;

          proxy_set_header      Connection      $connection_upgrade;
          proxy_set_header      Upgrade         $http_upgrade;
          proxy_set_header      Host            $host;
          proxy_set_header      X-Real-IP       $remote_addr;
          proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        if ($http_x_forwarded_proto = 'http') {
          return 301 https://$host$request_uri;
        }
      }

Я думаю, вам нужно указать, какую среду Elastic Beanstalk вы используете (см. Поддерживаемые платформы), потому что разные среды имеют разную конфигурацию.

В основном вам нужно настроить:

  • Балансировщик эластичной нагрузки:
    • Слушайте порт 80 и проксируйте его на порт 80 экземпляра EC2.
    • Слушайте порт 443 и проксируйте его на порт 443 экземпляра EC2.
  • EC2 веб-сервер / прокси:
    • Слушайте порт 80 и отвечайте с перенаправлением на HTTPS.
    • Слушайте порт 443 и обслуживайте запрос.

Чтобы настроить его, вы можете использовать CLI или .ebextensions.

Вы можете проверить Включение HTTPS и HTTP-Redirect на AWS Elastic Beanstalk. В нем рассказывается, как настроить единый контейнер Docker Elastic Beanstalk для обслуживания HTTPS и HTTP (перенаправление на HTTPS). Вы можете настроить конфигурацию по своему усмотрению.

Elastic Beanstalk не поддерживает несколько портов из одного контейнера Docker, поэтому вам нужно обрабатывать это на уровне прокси, как предлагается. Однако вашему экземпляру EC2 не нужно знать о вашем сертификате, потому что вы можете разорвать SSL-соединение на балансировщике нагрузки.

В твоем .ebextensions каталог создайте конфигурацию для прокси nginx, содержащую две конфигурации сервера; тот, который прокси http://docker (конфигурация по умолчанию, порт 80) и тот, который перенаправляет на https (я выбрал порт 8080).

.ebextensions/01-nginx-proxy.config:

files:
  "/etc/nginx/sites-available/000-default.conf":
    mode: "000644"
    owner: root
    group: root
    content: |
      map $http_upgrade $connection_upgrade {
          default        "upgrade";
          ""            "";
      }

      server {
          listen 80;

          gzip on;
          gzip_comp_level 4;
          gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

          access_log    /var/log/nginx/access.log;

          location / {
              proxy_pass            http://docker;
              proxy_http_version    1.1;

              proxy_set_header    Connection            $connection_upgrade;
              proxy_set_header    Upgrade                $http_upgrade;
              proxy_set_header    Host                $host;
              proxy_set_header    X-Real-IP            $remote_addr;
              proxy_set_header    X-Forwarded-For        $proxy_add_x_forwarded_for;
          }
      }

      server {
          listen 8080;

          location / {
              return 301 https://$host$request_uri;
          }
      }

commands:
   00_enable_site:
    command: 'rm -f /etc/nginx/sites-enabled/* && ln -s /etc/nginx/sites-available/000-default.conf /etc/nginx/sites-enabled/000-default.conf'

Создайте вторую конфигурацию для балансировщика нагрузки EB и групп безопасности, которая настраивает их следующим образом:

  • Экземпляр EC2:
    • Разрешить трафик на портах 80/8080 от балансировщика нагрузки
    • Разрешить трафик на порт 22 из любого места (для доступа по ssh, необязательно)
  • Балансировщик нагрузки:
    • Перенаправить порт 443 HTTPS на порт 80 HTTP
    • Перенаправить порт 80 HTTP на порт 8080 HTTP

.ebextensions/02-load-balancer.config:

"Resources" : {
  "AWSEBSecurityGroup": {
    "Type" : "AWS::EC2::SecurityGroup",
    "Properties" : {
      "GroupDescription" : "Instance security group (22/80/8080 in)",
      "SecurityGroupIngress" : [ {
          "IpProtocol" : "tcp",
          "FromPort" : "80",
          "ToPort" : "80",
          "SourceSecurityGroupId" : { "Ref" : "AWSEBLoadBalancerSecurityGroup" }
        }, {
          "IpProtocol" : "tcp",
          "FromPort" : "8080",
          "ToPort" : "8080",
          "SourceSecurityGroupId" : { "Ref" : "AWSEBLoadBalancerSecurityGroup" }
        }, {
          "IpProtocol" : "tcp",
          "FromPort" : "22",
          "ToPort" : "22",
          "CidrIp" : "0.0.0.0/0"
        } ]
    }
  },
  "AWSEBLoadBalancerSecurityGroup": {
    "Type" : "AWS::EC2::SecurityGroup",
    "Properties" : {
      "GroupDescription" : "Load balancer security group (80/443 in, 80/8080 out)",
      "VpcId" : "<vpc_id>",
      "SecurityGroupIngress" : [ {
          "IpProtocol" : "tcp",
          "FromPort" : "80",
          "ToPort" : "80",
          "CidrIp" : "0.0.0.0/0"
        }, {
          "IpProtocol" : "tcp",
          "FromPort" : "443",
          "ToPort" : "443",
          "CidrIp" : "0.0.0.0/0"
        } ],
      "SecurityGroupEgress": [ {
          "IpProtocol" : "tcp",
          "FromPort" : "80",
          "ToPort" : "80",
          "CidrIp" : "0.0.0.0/0"
        }, {
          "IpProtocol" : "tcp",
          "FromPort" : "8080",
          "ToPort" : "8080",
          "CidrIp" : "0.0.0.0/0"
        } ]
    }
  },
  "AWSEBLoadBalancer" : {
    "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
    "Properties" : {
      "Listeners" : [ {
          "LoadBalancerPort" : "80",
          "InstancePort" : "8080",
          "Protocol" : "HTTP"
        }, {
          "LoadBalancerPort" : "443",
          "InstancePort" : "80",
          "Protocol" : "HTTPS",
          "SSLCertificateId" : "arn:aws:iam::<certificate_id>:<certificate_path>"
        } ]
    }
  }
}

(Примечание: не забудьте заменить SSLCertificateId и VpcId своими значениями).

Любой трафик на порту 80 балансировщика нагрузки (HTTP) попадет в порт 8080 экземпляра EC2, который перенаправляется на HTTPS. Трафик на порту 443 балансировщика нагрузки (HTTPS) будет обслуживаться портом 80 экземпляра EC2, который является прокси-сервером докера.

Я использую Terraform для включения перенаправления HTTP на HTTPS на ElasticBeanstalk,

Я только что добавил дополнительное правило слушателя

data "aws_alb_listener" "http" { //Get ARN of Listener on Port-80
  load_balancer_arn = aws_elastic_beanstalk_environment.myapp.load_balancers[0]
  port              = 80
}


resource "aws_alb_listener_rule" "redirect_http_to_https" {
  listener_arn = data.aws_alb_listener.http.arn
  action {
    type = "redirect"
    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
  condition {
    host_header {
      values = ["*.*"]
    }
  }
}