docker-archive / dockercloud-haproxy

HAproxy image that autoreconfigures itself when used in Docker Cloud
https://cloud.docker.com/
651 stars 187 forks source link

FORCE_SSL with AWS ACM #210

Closed nasali closed 7 years ago

nasali commented 7 years ago

Hi there,

I have a Docker swarm deployed on AWS and an ACM issued SSL certificate, so no cert and key. Setting up SSL termination on the ELB and then using the haproxy to route HTTP traffic works fine. Now, I would like to force HTTP traffic over HTTPS. I tried the following which did not work:

docker service create --name haproxy --network proxy --detach=true --mount target=/var/run/docker.sock,source=/var/run/docker.sock,type=bind --publish 443:443 --publish 80:80 --label com.docker.aws.lb.arn="arn:aws:acm:us-west-2:232343343434:certificate/111ec11a-e1cb-1c1c-1e11-1c1db11b1111@443" --constraint "node.role == manager" -e FORCE_SSL=true dockercloud/haproxy

Is this even possible?

Thanks in advance!

tifayuki commented 7 years ago

Well, if you set FORCE_SSL=true, haproxy script will add a line of redirect scheme https code 301 if !{ ssl_fc } to the backend section of the haproxy config file. If you access http port, you will get a 301 error. However, you have to make sure that you both port 80 and 443 are properly set.

nasali commented 7 years ago

@tifayuki Thanks for your quick response.

That is not the behavior we're seeing. Setting FORCE_SSL=true on the proxy service is not resulting in a 301 redirect. Here's what the log shows:

INFO:haproxy:dockercloud/haproxy 1.6.7 is running outside Docker Cloud
INFO:haproxy:Haproxy is running in SwarmMode, loading HAProxy definition through docker api
INFO:haproxy:dockercloud/haproxy PID: 5
INFO:haproxy:=> Add task: Initial start - Swarm Mode
INFO:haproxy:=> Executing task: Initial start - Swarm Mode
INFO:haproxy:==========BEGIN==========
INFO:haproxy:Linked service: web
INFO:haproxy:Linked container: web.1.dueb62k4w7fxu90t6slt7h6g8
INFO:haproxy:HAProxy configuration:
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
log-send-hostname
maxconn 4096
pidfile /var/run/haproxy.pid
user haproxy
group haproxy
daemon
stats socket /var/run/haproxy.stats level admin
ssl-default-bind-options no-sslv3
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA
defaults
balance roundrobin
log global
mode http
option redispatch
option httplog
option dontlognull
option forwardfor
timeout connect 5000
timeout client 50000
timeout server 50000
listen stats
bind :1936
mode http
stats enable
timeout connect 10s
timeout client 1m
timeout server 1m
stats hide-version
stats realm Haproxy\ Statistics
stats uri /
stats auth stats:stats
frontend port_80
bind :80
reqadd X-Forwarded-Proto:\ http
maxconn 4096
acl is_websocket hdr(Upgrade) -i WebSocket
acl host_rule_1 hdr(host) -i apps.api2.tld
acl host_rule_1_port hdr(host) -i apps.api2.tld:80
use_backend SERVICE_web if host_rule_1 or host_rule_1_port
backend SERVICE_web
server web.1.dueb62k4w7fxu90t6slt7h6g8 10.0.0.3:4444 check inter 2000 rise 2 fall 3
INFO:haproxy:Launching HAProxy
INFO:haproxy:HAProxy has been launched(PID: 8)
INFO:haproxy:===========END===========

Web here is just an httpd service that is created like so docker service create --name web --network proxy --detach=true --publish 4444:80 -e SERVICE_PORTS="4444" -e VIRTUAL_HOST="apps.api2.tld" --constraint "node.role == worker" httpd:2.4.25. What I was hoping would happen is a 301 if the user hits http://apps.api2.tld to redirect them to https://apps.api2.tld, instead what is happening seems to be a 503 error from the proxy for http://apps.api2.tld and curl just sits there when I hit https://apps.api2.tld.

What am I missing?

tifayuki commented 7 years ago

In your case, when you access to http://apps.api2.tld, HAproxy redirects you to https. when the new https request hits ELB, ELB terminates ssl, and forward the request to HAProxy using http. Then Haproxy redirects you back to https. And this could cause a loop.

You can either 1) use HAProxy to terminate SSL and do the redirection, or 2) let EBL terminate ssl, no touching on HAProxy, and make your app do the redirection, see: https://aws.amazon.com/premiumsupport/knowledge-center/redirect-http-https-elb/

nasali commented 7 years ago

@tifayuki That is what I thought. I'll probably just have it terminate SSL. Thanks a ton!