codekitchen / dinghy-http-proxy

the http proxy container that dinghy uses
MIT License
125 stars 43 forks source link

Issue using SSL on container #15

Open benrobey opened 8 years ago

benrobey commented 8 years ago

Hey,

I've set my docker container up, exposing ports 443 and 80 and everything is working fine with normal HTTP traffic. But following the SSL guide in the readme (creating the cert files based on the hostname) and I'm still not able to connect via HTTPS.

I've gone in and had a look at the reverse proxy container and it seems that the default nginx config that is generated is not listening to port 443:

# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
  default $http_x_forwarded_proto;
  ''      $scheme;
}
# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
# Connection header that may have been passed to this server
map $http_upgrade $proxy_connection {
  default upgrade;
  '' close;
}
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent"';
access_log off;
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
server {
  listen 80 default_server;
  server_name _;
  root /var/www/default/htdocs;
  error_page 404 /index.html;
}
upstream justsunnies.docker {
    server 172.17.0.3:3306;
}
server {
    server_name justsunnies.docker;
    listen 80;
    access_log /var/log/nginx/access.log vhost;
    return 301 https://justsunnies.docker$request_uri;
}
server {
    server_name justsunnies.docker;
    listen 443 ssl;
    access_log /var/log/nginx/access.log vhost;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA;
    ssl_prefer_server_ciphers on;
    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:50m;
    ssl_certificate /etc/nginx/certs/justsunnies.docker.crt;
    ssl_certificate_key /etc/nginx/certs/justsunnies.docker.key;
    add_header Strict-Transport-Security "max-age=31536000";
    location / {
        proxy_pass http://justsunnies.docker;
    }
}

I've also had a look inside the certs folder on this server and it contains my self signed certificates so not exactly sure what's going on.

Thanks

codekitchen commented 8 years ago

That last server block is listening on port 443 for hostname justsunnies.docker. What exactly do you see when you make a request? Curl can be helpful to get all the details, curl -vv https://justsunnies.docker. You'll probably need to add -k as well since it's self-signed. According to the config it should be terminating SSL and then forwarding the request to your container, on port 3306.

benrobey commented 8 years ago

Thanks for the help, curling to the container behind the proxy results in this being sent to the logs

* Rebuilt URL to: https://justsunnies.docker/
*   Trying 192.168.99.100...
* Connected to justsunnies.docker (192.168.99.100) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: Internet Widgits Pty Ltd
> GET / HTTP/1.1
> Host: justsunnies.docker
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 502 Bad Gateway
< Server: nginx/1.9.15
< Date: Fri, 26 Aug 2016 01:16:09 GMT
< Content-Type: text/html
< Content-Length: 173
< Connection: keep-alive
< 
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.9.15</center>
</body>

I've got these ports exposed in my container:

EXPOSE 80 3306 443

I think it might be the way I've built the container? I used this as my command:

docker run -d -p 8080:80 -e VIRTUAL_HOST=justsunnies.docker -v $(pwd):/var/www/html <built image>
codekitchen commented 8 years ago

502 Bad Gateway sounds like your container isn't responding correctly, yeah. Is 3306 the right port for nginx to be proxying to in your container? Or should it be proxying to port 80?

If that's the case, you need to set VIRTUAL_PORT=80 as another environment variable when starting the container. The HTTP proxy tries to guess which port to use, but when you're exposing multiple ports you sometimes need to be explicit.

chrisgeo commented 8 years ago

I'm seeing something similar as well just running the container with our self-signed SSL certs:

* Rebuilt URL to: http://example.dev/
*   Trying 127.0.0.1...
* Connected to example.dev (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: example.dev
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.11.3
< Date: Fri, 02 Sep 2016 00:47:25 GMT
< Content-Type: text/html
< Content-Length: 185
< Connection: keep-alive
< Location: https://example.dev/
<
* Ignoring the response-body
* Connection #0 to host example.dev left intact
* Issue another request to this URL: 'https://example.dev/'
* Found bundle for host example.dev: 0x7ff408e06160
*   Trying 127.0.0.1...
* Connected to example.dev (127.0.0.1) port 443 (#1)
* Server aborted the SSL handshake
* Closing connection 1
curl: (35) Server aborted the SSL handshake
benrobey commented 8 years ago

I followed the advice given by @codekitchen and rebuilt my container without using the publish parameter and instead exporting the VIRTUAL_PORT environment variable and can confirm that my issue has been resolved.

Thanks to @codekitchen for providing such an awesome tool!

chrisgeo commented 8 years ago

Thanks @brobey8 but unfortunately that's not the issue.