Fuerza de frijol elástico fuerza https

12

Tengo problemas para forzar HTTPS con un sitio que estoy implementando a través de AWS Elastic Beanstalk.

Es una aplicación frontend que usa EmberJS. He estado dando vueltas en círculos durante muchos días tratando de descubrir cómo redirigir el tráfico http a https. Estoy usando Amazon Linux AMI en mi máquina EC2.

Llegué a la conclusión (aún no estoy seguro de si esto es correcto) de que no es dentro de Elastic Beanstalk que fuerzo HTTPS. Estoy permitiendo HTTP y HTTPS a través de mi Elastic Beanstalk Load Balancer, y estoy intentando redirigir en el servidor.

Aquí es donde me encuentro con problemas. Estoy encontrando muchas respuestas sobre las reglas de reescritura sin las mod_rewritecuales se basan en el X-Forwarded-Protoencabezado, pero ese archivo no existe en mi máquina EC2 de acuerdo con una búsqueda de búsqueda.

También intenté crear un archivo de configuración dentro del .ebextensionsdirectorio, pero tampoco funcionó.

Lo principal que intento hacer es que los usuarios se dirijan a https cuando intenten presionar la dirección http. Cualquier sugerencia o sugerencia es muy apreciada, ¡gracias!

EDITAR: estoy usando Debian jessie v1.4.1 de 64 bits con Python 3.4 (preconfigurado - Docker)

awwester
fuente
Parece que Internet no puede ponerse de acuerdo sobre una solución única, completa y que funcione para este problema. Espero que puedas obtener ayuda aquí en mi publicación . Tuve que saltar a través de aros para llegar a esto, finalmente.
ADTC

Respuestas:

7

Creo que debe especificar qué entorno Elastic Beanstalk utiliza (consulte: Plataformas compatibles ), porque un entorno diferente tiene una configuración diferente.

Básicamente, debe personalizar:

  • Balanceador de carga elástico :
    • Escuche en el puerto 80 y dele el puerto 80 de instancia EC2.
    • Escuche en el puerto 443 y conéctelo al puerto de instancia EC2 443.
  • Servidor web / proxy EC2 :
    • Escuche en el puerto 80 y responda con redireccionamiento a HTTPS.
    • Escuche en el puerto 443 y atienda la solicitud.

Para personalizarlo, puede usar CLI o .ebextensions.

Puede verificar Habilitar HTTPS y HTTP-Redirect en AWS Elastic Beanstalk . Le indica cómo configurar Elastic Beanstalk Single Docker Container para servir HTTPS y HTTP (redirigir a HTTPS). Puede ajustar la configuración según sus necesidades.

Edward Samuel
fuente
Hola, gran artículo, estoy en el proceso de intentar esto.
awwester
¿Alguna idea de cómo no incluir los certificados dentro de ese archivo, preferiría no mantener eso en el control de origen? ¿Los certificados que hemos cargado ya están disponibles en alguna parte? Parece que no puedo encontrarlos en el sistema de archivos
awwester
Puede poner su archivo de certificado SSL en S3. Para permitir que Elastic Beanstalk descargue un objeto S3 privado, puede leer esto .
Edward Samuel
Para el certificado ELB SSL, puede seguir la documentación de AWS: Certificados SSL para Elastic Load Balancing . Y luego puede obtener el recurso de certificado SSL en arn:aws:iam::123456789012:server-certificate/YourSSLCertificateformato.
Edward Samuel
Tengo el certificado SSL configurado y tengo el arn que iría en 00-load-balancencer (en realidad estoy haciendo la configuración del equilibrador de carga a través de la interfaz de usuario), pero parece que no puedo obtener la ubicación para poner en el servidor configuración ssl_certificate /opt/ssl/default-ssl.crt;Cuando obtengo la información para el certificado, me da un "camino" pero es solo "/"
awwester
10

También es posible hacerlo con mayor facilidad, sin tocar el equilibrador de carga, utilizando el X-Forwarded-Protoencabezado establecido por ELB. Esto es lo que terminé haciendo:

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;
        }
      }
FX
fuente
Con mucho, la solución más fácil. No puedo agradecerles lo suficiente!
Chris Martin
Sí, esta es la forma correcta en la mayoría de los escenarios.
jlegler
3

Elastic Beanstalk no admite múltiples puertos desde un único contenedor Docker, por lo que debe manejar esto en el nivel de proxy como se sugiere. Sin embargo, su instancia EC2 no necesita saber acerca de su certificado, porque puede terminar la conexión SSL en el equilibrador de carga.

En su .ebextensionsdirectorio, cree una configuración para el proxy nginx que contenga dos configuraciones de servidor; uno que representa http://docker(la configuración predeterminada, el puerto 80) y otro que redirige a https (elegí el puerto 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'

Cree una segunda configuración para el equilibrador de carga EB y los grupos de seguridad que los configure de la siguiente manera:

  • Instancia EC2 :
    • Permitir tráfico en los puertos 80/8080 desde el equilibrador de carga
    • Permitir tráfico en el puerto 22 desde cualquier lugar (para acceso ssh, opcional)
  • Balanceador de carga :
    • Reenviar el puerto 443 HTTPS al puerto 80 HTTP
    • Reenviar el puerto 80 HTTP al puerto 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>"
        } ]
    }
  }
}

(Nota: no olvide reemplazar SSLCertificateId y VpcId con sus valores).

Cualquier tráfico en el puerto 80 del equilibrador de carga (HTTP) llegará al puerto 8080 en la instancia EC2, que redirige a HTTPS. El tráfico en el puerto 443 en el equilibrador de carga (HTTPS) terminará siendo atendido por el puerto 80 en la instancia EC2, que es el proxy del acoplador.

Michael de Hoog
fuente
0

Estoy usando Terraform para habilitar la redirección de HTTP a HTTPS en ElasticBeanstalk,

Acabo de agregar una regla de escucha adicional

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 = ["*.*"]
    }
  }
}
Denis Astahov
fuente