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.
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.