可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I've got a Node.js powered site that I'm running on Amazon Elastic Beanstalk.
My Node.js app listens on port 8080, and I'm using the nginx elastic load balancer configuration with my EB app, listening on port 80 and 443 for HTTP and HTTPS.
However, I only want to accept traffic in my app that has come via HTTPS.
I could rig something up in the app to deal with this, but am interested in a way to get the load balancer to redirect all HTTP requests to my site via HTTPS.
回答1:
After several false-starts with ideas from Amazon's paid support, they did come through in the end. The way you get this to work is you configure your environment to respond to both port 80 and 443. Then create a folder in your main Node.js app folder called .ebextensions
, and you place a file named 00_nginx_https_rw.config
in there, with this text as the contents:
files:
"/tmp/45_nginx_https_rw.sh":
owner: root
group: root
mode: "000644"
content: |
#! /bin/bash
CONFIGURED=`grep -c "return 301 https" /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf`
if [ $CONFIGURED = 0 ]
then
sed -i '/listen 8080;/a \ if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; }\n' /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf
logger -t nginx_rw "https rewrite rules added"
exit 0
else
logger -t nginx_rw "https rewrite rules already set"
exit 0
fi
container_commands:
00_appdeploy_rewrite_hook:
command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/appdeploy/enact
01_configdeploy_rewrite_hook:
command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact
02_rewrite_hook_perms:
command: chmod 755 /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
03_rewrite_hook_ownership:
command: chown root:users /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
Amazon's support team explained: This config creates a deployment hook which will add the rewrite rules to /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf.
(Previously they had offered me .config's that copied separate files into /etc/nginx/conf.d, but those either had no effect, or worse, seemed to overwrite or take precedence over the default nginx configuration, for some reason.)
If you ever want to undo this, i.e. to remove the hooks, you need to remove this ebextension and issue a command to remove the files that it creates. You can do this either manually, or via ebextensions commands you put in place temporarily:
/opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh
/opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
I haven't tried this, but presumably something like this would work to remove them and undo this change:
container_commands:
00_undochange:
command: rm /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh
01_undochange:
command: rm /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
Hope this can help someone else in the future.
回答2:
The accepted answer no longer worked for me. The default port was a different one. Also the location of the config file has changed. I am setting up a Ruby On Rails application with Puma.
I talked to the paid support, we figured it out by just running the commands manually on the running instance. Then I was able to figure out the below solution. Just by logging in and restarting nginx things then worked.
files:
"/tmp/45_nginx_https_rw.sh":
owner: root
group: root
mode: "000644"
content: |
#! /bin/bash
CONFIGURED=`grep -c "return 301 https" /opt/elasticbeanstalk/support/conf/webapp_healthd.conf`
if [ $CONFIGURED = 0 ]
then
sed -i '/listen 80;/a \ if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; }\n' /opt/elasticbeanstalk/support/conf/webapp_healthd.conf
logger -t nginx_rw "https rewrite rules added"
exit 0
else
logger -t nginx_rw "https rewrite rules already set"
exit 0
fi
container_commands:
00_appdeploy_rewrite_hook:
command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/appdeploy/enact
01_configdeploy_rewrite_hook:
command: cp -v /tmp/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact
02_rewrite_hook_perms:
command: chmod 755 /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
03_rewrite_hook_ownership:
command: chown root:users /opt/elasticbeanstalk/hooks/appdeploy/enact/45_nginx_https_rw.sh /opt/elasticbeanstalk/hooks/configdeploy/enact/45_nginx_https_rw.sh
Notice how I changed the port number and the location of the config file.
回答3:
You could handle the redirect via your Node.js app.
Amazon sends the X-Forwarded-Proto
header which equals http
when the client has connected insecurely.
The following middleware should be inserted right after initializing Express
and before defining your routes to automatically redirect the client to the corresponding HTTPS endpoint:
// Redirect to HTTPS
app.use(function (req, res, next) {
// Insecure request?
if (req.get('x-forwarded-proto') == 'http') {
// Redirect to https://
return res.redirect('https://' + req.get('host') + req.url);
}
next();
});
回答4:
I was able to get this working with a slightly simpler solution.
Please note, this is an elastic beanstalk deployed SINGLE instance, not load balenced.
This was my ebextension I added.
files:
"/etc/nginx/conf.d/000_my_config.conf":
mode: "000755"
owner: root
owner: root
content: |
server {
listen 8080;
return 301 https://$host$request_uri;
}
回答5:
I am running the 'Ruby2 Puma' environment on AWS Elastic Beanstalk which may have a slightly different configuration than above.
In my environment I needed to use 'listen 80' instead of 'listen 8080'.
sslredirect.config based on elloworld111's answer:
files:
"/etc/nginx/conf.d/000_my_config.conf":
mode: "000755"
owner: root
owner: root
content: |
server {
listen 80;
return 301 https://$host$request_uri;
}
回答6:
I'm working with Elastic Beanstalk and Docker, so have taken a slightly different route to get things running for me, but very much inspired by the accepted answer. This script injects required config into /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf. (If anyone has a more elegant solution would love to see it)
This script also enables the Beanstalk healthcheck to hit my healthcheck endpoint (in my case api/healthcheck) Better to allow the LoadBalancer to hit the app, rather than terminate at Nginx.
files:
"/tmp/45_nginx_https_rw.sh":
owner: root
group: root
mode: "000755"
content: |
#! /bin/bash
CONFIGURED=`grep -c "return 301 https" /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf`
if [ $CONFIGURED = 0 ]
then
sed -i "/access.log;/a \ \ \ \ \ \ \ \ location /api/health-check { proxy_pass http://docker; }" /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf
sed -i "/proxy_add_x_forwarded_for;/a \ \ \ \ \ \ \ \ \ \ \ \ if (\$http_x_forwarded_proto != 'https') { return 301 https://\$host\$request_uri; }" /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf
logger -t nginx_rw "https rewrite rules added"
exit 0
else
logger -t nginx_rw "https rewrite rules already set"
exit 0
fi
container_commands:
00_run_script:
command: /tmp/45_nginx_https_rw.sh
回答7:
I was able to get this to work in a different way. I changed my load balancer to forward port 80 traffic to port 8082, and changed the firewall rules (inbound on the instance, outbound on the firewall) to allow that. And then added this file in .ebextensions:
files:
"/etc/nginx/conf.d/50-atd-hotel-http-redirect.conf":
mode: "000644"
owner: root
group: root
content: |
server {
listen 8082;
return 301 --WHATEVER DESTINATION YOU WANT--;
}