So I have an nginx config that looks like this:

## Redirects all HTTP traffic to the HTTPS host
server {
  listen *:80;
  server_name me.example.com;
  server_tokens off;
  return 301 https://me.example.com:443$request_uri;
  access_log  /var/log/nginx/access.log;
  error_log   /var/log/nginx/error.log;

server {
  listen *:443 ssl;

server {
  listen *:9080;
  location / {
    root /var/www;
    index index.html index.htm;

The intention is to direct http traffic on port 80 to https (443). Works like a champ. The problem is that my request to port 9080 are causing my browser to switch to https and then failing (since I'm not using ssl on 9080, nor do I want to).

In Safari or Chrome: http://me.example.com:9080/index.html -> https://me.example.com:9080/index.html Can't establish secure connection.

With CURL:

curl -v http://me.example.com:9080/index.html
* Hostname was NOT found in DNS cache
*   Trying x.x.x.x...
* Connected to me.example.com (x.x.x.x) port 9080 (#0)
> GET /index.html HTTP/1.1
> User-Agent: curl/7.37.1
> Host: me.example.com:9080
> Accept: */*
< HTTP/1.1 200 OK
* Server nginx/1.4.4 is not blacklisted
< Server: nginx/1.4.4
< Date: Thu, 09 Apr 2015 18:32:02 GMT
< Content-Type: text/html
< Content-Length: 157
< Last-Modified: Thu, 09 Apr 2015 18:19:42 GMT
< Connection: keep-alive
< ETag: "5526c2be-9d"
< Accept-Ranges: bytes
<title>Test Server</title>
<h3>Welcome to the Test Server!"</h3>
* Connection #0 to host me.example.com left intact

Is this a browser issue? Is there something I can do to make the browser happy?


In Chrome, you can remove a site from HSTS by navigating to this URL:


h/t to this site that has instructions for other browsers as well.

  • 1
    I'm fairly certain this relates to the "Strict-Transport-Security" header. superuser.com/a/662424/51803 Perhaps there is nothing I can do in the nginx config. – Ben Flynn Apr 9 '15 at 19:18
  • Not sure about that, as your curl output does not show an STS header? Can you make the request in Chrome, and inspect the network requests from the Network tab in Chrome developer tools. – ColtonCat Apr 9 '15 at 21:07
  • It's a security feature, chrome and firefox for example will remember the STS setting and all subsequent surfing to that domain will, before sending it to the server, add a s to http before retrieving the page.This is for man in the middle protection and so an attacker can not remove the setting and force http:// – artifex Apr 9 '15 at 22:23

I'm guessing you are sending an HTTP Strict-Transport-Security (HSTS) header from the HTTPS server block.

The purpose of the HSTS header is to be bound to the domain name it was received from. It is then known as an HSTS host by the User-Agent (UA) and held in its cache for max-age seconds.

During this time further HTTP requests to the domain, or a valid subdomain if told by the includeSubDomains directive, will get through a special processing described by RFC 6797 section 8.3 :

      The UA MUST replace the URI scheme with "https" [RFC2818], and

      if the URI contains an explicit port component of "80", then
      the UA MUST convert the port component to be "443", or

      if the URI contains an explicit port component that is not
      equal to "80", the port component value MUST be preserved;

      if the URI does not contain an explicit port component, the UA
      MUST NOT add one.

     NOTE:  These steps ensure that the HSTS Policy applies to HTTP
            over any TCP port of an HSTS Host.

NOTE:  In the case where an explicit port is provided (and to a
       lesser extent with subdomains), it is reasonably likely that
       there is actually an HTTP (i.e., non-secure) server running on
       the specified port and that an HTTPS request will thus fail
       (see item 6 in Appendix A ("Design Decision Notes")).

This means that if you are trying to send an HTTP request to a known HSTS host with a matching domain name (section 8.2 for the details) then as long as the HSTS host entry in the UA cache has not expired, HTTP traffic will transparently switch to HTTPS either :

  • on port 443 if the HTTP port was 80 (explicitely or implicitely) in the target URI
  • on the same port otherwise
  • Thanks, great explanation. Can nginx be configured to not send this header? – Ben Flynn Apr 10 '15 at 16:18
  • 2
    HSTS is disabled by default and enabled with add_header Strict-Transport-Security "<parameters>"; so if you don't see that in your nginx configuration, then it isn't enabled. Among other methods, you can see what is going on with your SSL configuration using the Qualys SSL Labs SSL Server Test. – Paul Apr 10 '15 at 21:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.