1

To help explain my issue, let me create an analogous, but fictional backstory.

Let's say I have a friend, Sarah, who makes her living through a web cam. And let's say this source of income is supporting Sarah's 4 year old, Lisa.

I met Sarah because she contracted me to write her a custom adult webcam site. She also introduced me to Lisa's preschool, who has also contracted me to write their site.

To save money, I host both sites using the same server, through Nginx.

I excitedly notify the school about all the progress I've made on their website! What I couldn't have known is that my node process that was serving lisas-preschool.com was down.

After an awkward phone call, I discover that sometimes Nginx will serve the wrong content for the site visited.

This obviously can't happen, EVER! So, how do I make sure that sarahs-site.com and lisas-preschool.com will never be cross-served?

For reference, here's the configurations for the sites:

lisas-preschool.com:

This is a node.js site:

upstream lisas_preschool {
    server 127.0.0.1:3000;
}

# HTTP Server
server {
    listen 0.0.0.0:80;
    server_name www.lisas-preschool.com lisas-preschool.com;
    access_log /var/log/nginx/lisas-preschool.access;

    location / { 

        proxy_pass              http://lisas-preschool.com;
        proxy_http_version      1.1;

        proxy_redirect          off;
        proxy_buffering         off;

        proxy_set_header        Host            $host;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        Upgrade         $http_upgrade;
        proxy_set_header        Connection      "upgrade";
        proxy_set_header        X-Forward-Proto http;
        proxy_set_header        X-Nginx-Proxy   true;

    }   
}

sarahs-site.com

This is a wordpress site:

server {
    listen 80;
    listen [::]:80;
    server_name sarahs-site.com www.sarahs-site.com;

    index index.php index.html index.htm;
    root /var/www/sarahs-site.com/html;

    location / {
        try_files $uri $uri/ /index.php;
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /var/www/site-b.com/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

}
1
  • 1
    Good grief! an X-Rated question! lol
    – hookenz
    Jun 25, 2015 at 3:28

2 Answers 2

2

The surest way to deal with this situation is to guarantee that a site will only be served if that hostname is specifically requested. The only situation where one site can be served when another is requested is when Nginx cannot (for some reason) find the site requested and instead serves the default. The default will either be the first server defined or the server specified as default.

By setting a default server block that is safe in all circumstances (like the example below), you can be certain that it will be served in a worst case scenario.

server {
    listen 80 default_server;
    server_name _;

    return 444;
}

server {
    listen 80;
    server_name example1.com;
}

server {
    listen 80;
    server_name example2.com;
}

If using SSL, make sure you have a default server block for SSL (either a separate one or the same as the non-SSL one). You can also add to the separation by having different, dedicated IP addresses for the two sites.

1
  • 1
    This makes a lot of sense. By not having a default server defined, it was using the first site as the default implicitly. Thank you so much for explaining! Jun 25, 2015 at 7:40
3

You are using different format for the listen directives in the ´server` blocks. This means that the virtual hosts get different listening sockets for themselves, and for some protocol / interface combinations, you might get unexpected result for the request.

I would recommend you to use listen 80; on both virtual hosts, so that nginx will listen to port 80 on both IPv4 and IPv6 sockets. Or, if you desire only IPv4 sockets, use listen 0.0.0.0:80;.

Also, I would make a default server that disconnects all requests to any other virtual hosts directly:

server {
    listen 80 default_server;
    return 444;
}
1
  • 1
    +1 This is an excellent observation; and also I think it's correct, but I accepted Tom's answer because it illustrated some of the rationale by informing me that the default server is the first server if one is not explicitly defined. Thank you for your help! Jun 25, 2015 at 7:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .