Home Elastic Beanstalk HTTPS redirection when using TCP ports
Post
Cancel

Elastic Beanstalk HTTPS redirection when using TCP ports

Link to solution gist

I’m deploying an application to a Docker environment within Elastic Beanstalk. The application serves HTTP and Web Socket requests over the HTTP(s) port.

AWS provides a configuration that works when forwarding HTTP to HTTPS. However, in order to serve web socket requests, I needed to forward SSL to TCP in the load balancer configuration.

Forwarding to TCP for Websockets

When using the provided configuration https and https request would get redirect to https. This lead to an infinite loop. The example linked below was the cause.

https://github.com/awsdocs/elastic-beanstalk-samples/blob/master/configuration-files/aws-provided/security-configuration/https-redirect/docker-sc/https-redirect-docker-sc.config#L54-L58

The protocol being forwarded was not https, so a redirect would be returned until the browser stopped following them. I adjusted the configuration to look for positive matches specific request protocols.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
diff --git a/.ebextensions/https-redirect-docker-sc.config b/.ebextensions/https-redirect-docker-sc.config
index fa2fbdc..5ea1cae 100644
--- a/.ebextensions/https-redirect-docker-sc.config
+++ b/.ebextensions/https-redirect-docker-sc.config
@@ -33,14 +33,14 @@ files:
            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;
-
+
            if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
                set $year $1;
                set $month $2;
@@ -48,24 +48,32 @@ files:
                set $hour $4;
            }
            access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;
-
+
            access_log    /var/log/nginx/access.log;
-
+
            location / {
-               set $redirect 0;
-               if ($http_x_forwarded_proto != "https") {
-                 set $redirect 1;
+               if ($http_x_forwarded_proto = "http") {
+                 set $redirect "https";
+               }
+               if ($http_x_forwarded_proto = "ws") {
+                 set $redirect "wss";
                }
+
                if ($http_user_agent ~* "ELB-HealthChecker") {
-                 set $redirect 0;
+                 set $redirect "nope";
+               }
+
+               if ($redirect = "https") {
+                return 301 https://$host$request_uri;
                }
-               if ($redirect = 1) {
-                 return 301 https://$host$request_uri;
+
+               if ($redirect = "wss") {
+                return 301 wss://$host$request_uri;
                }
-
+
                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;

The logic may look a little strange, but nginx doesn’t allow for compound Boolean logic. Essentially ws is redirected to wssand http is redirected to https unless the request is a health check.

Link to solution gist

-->