Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] Using certificates missing apps redirect to wrong apps #268

Closed
rokcarl opened this issue Oct 15, 2015 · 27 comments
Closed

[bug] Using certificates missing apps redirect to wrong apps #268

rokcarl opened this issue Oct 15, 2015 · 27 comments
Labels
kind/bug Issue reporting a bug

Comments

@rokcarl
Copy link

rokcarl commented Oct 15, 2015

All seems to work as intended until I start using certificates.

Short description

I do:

  • run nginx-proxy, app1 and app2 both on https,
  • I kill app2,
  • visit app2 in my browser, but get app1 certificates and results.

Long description

This is how I run nginx-proxy and both apps (app1 and app2).

docker run --name nginx-proxy -d -p 80:80 -p 443:443 -v /home/ubuntu/_certificates:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy 
docker run -d --name app1.app.com -e VIRTUAL_PROTO=https -e VIRTUAL_PORT=443 -p 8003:443 -e VIRTUAL_HOST=app1.app.com app 
docker run -d --name app2.app.com -e VIRTUAL_PROTO=https -e VIRTUAL_PORT=443 -p 8005:443 -e VIRTUAL_HOST=app2.app.com app

I kill app2 with docker kill app2.app.com.
Visit app2.app.com, but the certificate I get is from app1 and the contents as well. If I also kill app1, then I get the server not found, which is of course correct. If I then run app1 again, app2 again redirects to the wrong app.

@rokcarl
Copy link
Author

rokcarl commented Oct 31, 2015

Any ideas on how to solve this?

@rokcarl
Copy link
Author

rokcarl commented Nov 20, 2015

This issue is very problematic for our use case as it's serving the wrong app. Imagine getting Facebook when you browse to Google...

Do you have any tips on where to look, maybe I can help solve this issue.

@jwilder
Copy link
Collaborator

jwilder commented Nov 20, 2015

That's odd. When you access the app, are you doing it over HTTP and then getting redirected to HTTPS? Also, how are your certs named on disk? Are they named after each virtual host or are they sharing a single wildcard app.com cert?

@rokcarl
Copy link
Author

rokcarl commented Nov 20, 2015

Accessing all the apps through HTTPS. The certs are named the same as the domains, so app1.app.com.crt and app1.app.com.key for app1 and similarly app2.app.com.crt and app2.app.com.key for app2.

@davidsyoung
Copy link

Having same issue here @md5 @rokcarl. Any luck fixing it so far @rokcarl?

@md5
Copy link
Contributor

md5 commented Nov 30, 2015

I wonder whether a lack of SNI support in the browser could be to blame.

What browser/OS combo are you seeing these problems with @davidsyoung and @rokcarl?

@davidsyoung
Copy link

@md5 thanks for getting back to me so soon.

I was using Chrome on OS X.

I have two docker containers with two different VIRTUAL_HOST's set. One is a staging server on a sub domain and one is the production on the root domain.

VIRTUAL_HOST settings are like following:

staging: VIRTUAL_HOST: staging.example.io
production: VIRTUAL_HOST: example.io, www.example.io

I have a SSL wildcard domain under example.io.crt and example.io.key.

Everything works perfectly when both docker containers are running between the subdomain and root domain (staging.example.io & example.io/www.example.io). I also have a DNS A record on blog.example.io which is currently down. This routes to the staging.example.io container (url stays blog.example.io).

If I then stop the production container (example.io/www.example.io) it will route to the staging.example.io container (url stays example.io/www.example.io). If I start it back up, no issues again.

I just tried in Safari because you suggested that it was a browser issue. I can confirm that the issues do not happen in Safari.

I hope that helps @md5 @jwilder?

@davidsyoung
Copy link

@md5 upon restarting chrome and clearing settings blog.example.io still redirects to staging.example.io but www.example.io does not and shows a 503.

@md5
Copy link
Contributor

md5 commented Dec 1, 2015

@davidsyoung The last time I remember anything being done that would affect the hostname used in redirects was in #108, which was merged in February 2015. The redirect should always use the Host header sent by the browser. The SSL certificate used would be a separate issue, but it should not affect the hostname in the HTTP-to-HTTPS redirect.

What you're describing with blog.example.io sounds like it's related to the fact that no default_server is being set with DEFAULT_HOST on the nginx-proxy container. In that case, the first server listed in the config will be considered the "default" server. The order that the servers are listed in the config will be random, since Go randomizes the iteration order of maps to prevent developers from writing code that relies on map iteration order. This means that each time docker-gen regenerates the Nginx config for this image, the containers will potentially be listed in a different order.

@md5
Copy link
Contributor

md5 commented Dec 1, 2015

Looking closer, it seems like if there isn't a match for the Host header against any server_name and DEFAULT_HOST is not set, then the server_name _ server block will always be the first-listed server and you should get a 503...

@md5
Copy link
Contributor

md5 commented Dec 1, 2015

@davidsyoung When you say "redirects", do you mean an actual HTTP redirect or do you mean that the wrong backend container serves the request?

@rokcarl
Copy link
Author

rokcarl commented Dec 1, 2015

I'm hosting the app on Amazon with an Ubuntu image, accessing the app through Chrome on a Mac. I tried it with Safari as well and it's even worse: no warning, I get served the wrong app.

@davidsyoung
Copy link

@md5 that makes sense actually.

When I say redirects, I mean the wrong backend container servers the request. How would I go about fixing this with an ssl config? It doesn't happen on http with no ssl configuration.

@brodul
Copy link

brodul commented Dec 23, 2015

@jwilder @md5 @rokcarl
I am also effected by this issue.
I created a repository with the example. So it's super simple to reproduce the issue.

https://github.com/brodul/nginx-proxy-268

@brodul
Copy link

brodul commented Dec 24, 2015

Ok, I found the problem. The basic problem is that if the upstream server is down the nginx does not return the 503. Instead the default route is called.
This behavior is strange and I don't understand why nginx is doing that.
I think you are aware of this issue because there is a return 503 for non HTTPS connections.

Currently the default route is not configured for SSL, so another server section is picked.

If you want to configure a server section with SSL on, you need cetificates. So the browser can do the SSL handshake, after that you can drop the connection (or return 503). The problem is that you don't know which certificate and key pair to offer. So this workaround can only work if you have a wildcard certificate and only one domain.

server {
    server_name _; # This is just an invalid value which will never trigger on a real hostname.
    listen 443 default_server ssl ;
    access_log /var/log/nginx/access.log ;
    ssl_certificate /etc/nginx/certs/wildcard.example.com.crt;
    ssl_certificate_key /etc/nginx/certs/wildcard.example.com.key;
        return 444; # status 444 drops connection you can also return 503 
}

@md5
Copy link
Contributor

md5 commented Dec 27, 2015

Nice work @brodul! That definitely seems like the issue. A fallback certificate can be provided with the current template by naming it default.crt (with a default.key private key).

I'm not sure what the best way to handle this would be in the absence of default.crt. I suppose nginx-proxy could include a junk certificate that gets used when any sites have a certificate but no default.crt is provided.

@brodul
Copy link

brodul commented Dec 27, 2015

I wonder why does't the nginx-proxyreturn a bad gateway when proxy pass origin is death in the first place?

@from-the-river-to-the-sea

Hi, very sorry to bump such an old issue, but I believe I am experiencing this same problem and lack the knowledge to fix it. I'd very much appreciate a nudge in the right direction.

@balakrishnangithub
Copy link

I'm also facing the same problem. When the server container is stopped and request from browser using HTTP is not a problem (it correctly shows temporarily unavailable), but when using HTTPS it opens some other container which also uses HTTPS.
I'm using letsencrypt-nginx-proxy-companion for HTTPS.

NGINX_VERSION	1.13.7-1~stretch
NJS_VERSION	1.13.7.0.1.15-1~stretch
DOCKER_GEN_VERSION	0.7.3

@hugoderene
Copy link

Same problem overhere

@eckelarsson
Copy link

eckelarsson commented Apr 24, 2018

Same here, please bump this. @md5 @jwilder

We have 5 containers with different domains pointing to them.
But one has not HTTPS. So to draw up an example.

Lets say the non https container has the domain test.com and when you try to access the https://test.com it redirect the traffic first container in the list that have HTTPS.

And to be clear, Its not a redirect in the browser more a redirect of traffic with in the proxy, so the domain stays "intact" in the browser but showing content of the first container in the list that have HTTPS.

I'm also facing the same problem. When the server container is stopped and request from browser using HTTP is not a problem (it correctly shows temporarily unavailable), but when using HTTPS it opens some other container which also uses HTTPS.

@dempa266
Copy link

The solution is to implement a self-signed certificate in the proxy cert folder

Etc:
openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout default.key -out default.crt

Then you get a 500 server error instead of another site.

@erth111
Copy link

erth111 commented Jun 20, 2018

@dempa266 solution works perfectly. Just to be clarify: after creating the dummy cert&key and putting them in certs directory, during startup the letsencrypt-nginx-proxy-companion (i think so) reads them and creates a 'server' entry in nginx config configured with those certs. After that, requesting a site whose backend is down, causes ' The certificate is not trusted because it is self-signed.' error instead of redirecting to wrong vhost with another cert.

@martyzz1
Copy link

I believe I'm getting the same thing with wildcard certificates....
I have multiple containers, when the virtual host container is not running another container is served instead... its not a big deal for us as we only use this in development... but not sure how to tidy it up

@danieleLewis
Copy link

Also happening here, no workarounds??

@tkw1536
Copy link
Collaborator

tkw1536 commented Apr 16, 2022

For wildcard certificates, see #176 (comment).
A workaround might be to use -e CERT_NAME="" on the container in question.

@tkw1536 tkw1536 added the kind/bug Issue reporting a bug label Apr 16, 2022
@buchdag
Copy link
Member

buchdag commented May 10, 2023

This was fixed in #2186

@buchdag buchdag closed this as completed May 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Issue reporting a bug
Projects
None yet
Development

No branches or pull requests