1

I'm trying to setup an nginx config that behaves similar to our production servers in which requests to port 80 get redirected to 443, it works fine when working straight off the dev machine you're developing on but if you are on another machine and try to access the dev box from its IP it will redirect from the IP to localhost.

e.g, http://192.168.1.10 -> 301 -> https://localhost

I don't know beforehand what the dev box's IP address is when provisioning as we have a lot of remote devs. I tried not defining the server_name property as well as assigning it to _, neither worked in this situation.

Short of assigning a fake domain to the server name and having the devs manage their hosts file is there anything I can do?

/etc/nginx/sites-available/default:

# ...

server {
    listen 80;
    server_name localhost;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name localhost;

    add_header Strict-Transport-Security max-age=15768000;

    ssl_certificate /etc/nginx/server.crt;
    ssl_certificate_key /etc/nginx/server.key;

    location / {
        proxy_pass http://app_server;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        include "/etc/nginx/proxy_params"
    }

    location ~ ^/(login|logout) {
        proxy_pass http://login_server;
        include "/etc/nginx/proxy_params"
    }
}

Curl requests:

https://:

jared@Wash  ➤  curl -v http://192.168.1.17 
* Rebuilt URL to: http://192.168.1.17/
*   Trying 192.168.1.17...
* Connected to 192.168.1.17 (192.168.1.17) port 80 (#0)
> GET / HTTP/1.1
> Host: 192.168.1.17
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.10.1
< Date: Tue, 19 Jul 2016 18:00:00 GMT
< Content-Type: text/html
< Content-Length: 185
< Connection: keep-alive
< Location: https://localhost/
< 
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.10.1</center>
</body>
</html>
* Connection #0 to host 192.168.1.17 left intact

https://:

jared@Wash  ➤  curl -vk https://192.168.1.17 
* Rebuilt URL to: https://192.168.1.17/
*   Trying 192.168.1.17...
* Connected to 192.168.1.17 (192.168.1.17) port 443 (#0)
* found 173 certificates in /etc/ssl/certs/ca-certificates.crt
* found 697 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_256_GCM_SHA384
*    server certificate verification SKIPPED
*    server certificate status verification SKIPPED
*    common name: localhost (does not match '192.168.1.17')
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #3
*    subject: ...
*    start date: Mon, 18 Jul 2016 20:50:53 GMT
*    expire date: Tue, 18 Jul 2017 20:50:53 GMT
*    issuer: ...
*    compression: NULL
* ALPN, server did not agree to a protocol
> GET / HTTP/1.1
> Host: 192.168.1.17
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 302 Found
< Server: nginx/1.10.1
< Date: Tue, 19 Jul 2016 18:00:36 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 37
< Connection: keep-alive
< X-Frame-Options: DENY
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< Location: /app/
< Vary: Accept, Accept-Encoding
< set-cookie: ...; Path=/; HttpOnly; Secure
< Strict-Transport-Security: max-age=15768000
< 
* Connection #0 to host 192.168.1.17 left intact
Found. Redirecting to /app/
JaredMcAteer
  • 151
  • 8
  • What does ```netstat -tlnp | egrep '80|443' ``` show? Are you actually listening on an externally facing interface? Also, AFAIK that server clause will only apply if you specifically request localhost as the hostname in your HTTP request. What happens if you toss a wildcard (*) there to match everything? – Paul Calabro Jul 19 '16 at 17:51
  • `tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN - ` `tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN - ` Yes it's listening, if I access the ip using `https://` everything works as expected, it's simply the `http://` 301 redirect where things go wrong – JaredMcAteer Jul 19 '16 at 17:55
  • What do you see see when running: ```curl -v http://``` – Paul Calabro Jul 19 '16 at 17:56
  • I've updated the question body with the curl requests of both http and https requests. – JaredMcAteer Jul 19 '16 at 18:04
  • http://serverfault.com/q/706438/126632 – Michael Hampton Jul 19 '16 at 19:24
  • Awsome changed `$server_name` to `$host` in the 301 and that seems to have resolved my issue. Thank you. – JaredMcAteer Jul 19 '16 at 20:26
  • @MichaelHampton Do you want to make this comment into a proper answer so I can credit you? – JaredMcAteer Jul 26 '16 at 14:57

2 Answers2

0

It appears, based on your curl requests and config you need to change:

server {
    listen 80;
    server_name localhost;
    return 301 https://$server_name$request_uri;
}

(which interpolates the server_name variable value of localhost into the string https://$server_name$request_uri, resulting in: https://localhost$request_uri)

to

server {
    listen 80;
    server_name <External IP ADDRESS>;
    return 301 https://$server_name$request_uri;
}

(which would product https://IP_ADDRESS$request_uri)

More information on this:

If someone makes a request using an IP address instead of a server name, the “Host” request header field will contain the IP address and the request can be handled using the IP address as the server name:

(Source: http://nginx.org/en/docs/http/server_names.html)

Paul Calabro
  • 530
  • 5
  • 12
  • Yes I agree, but how do I do this when I don't know what the external ip address will be? As I stated in the question we have quite a few remote workers that don't all run the same lan configurations as each other. – JaredMcAteer Jul 19 '16 at 18:35
  • Could you just use the * like I mentioned above so that you match all values for the "Host" request header? – Paul Calabro Jul 19 '16 at 21:05
-2

You can just use this:

server_name _ ;

It is 'Host' header "catch-all".

EDIT

Sorry, misread part of you question. Try to change

return 301 https://$server_name$request_uri;

to

return 301 https://$host$request_uri;

And you probably will want to change/skip server_name directive, so it will respond to requests from outside localhost.

Pavel Kazhevets
  • 180
  • 1
  • 4