nginx not redirecting www to https - nginx

I have a website which is properly handling all traffic and redirecting everything to https, except for www traffic. I followed this related question, but it didn't seem to fix it. This is my first time setting this up - any advice is appreciated. My goal is to redirect www.my_website.com to https://my_website.com, but currently it is redirecting to http://www.my_website.com
My DNS is set up as follows:
Type | Name | Data | Seconds
--------------------------------------
A | # | my_public_ip | Automatic
A | www | my_public_ip | Automatic
And my nginx is as follows:
server {
listen 80;
server_name _;
return 301 https://my_website.com;
}
# HTTPS server
server {
listen 443 ssl;
server_name my_website.com;
ssl_certificate some_random.crt;
ssl_certificate_key some_random.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
proxy_pass http://localhost:8080;
}
}

This is a schematic which applies for cases like this in general. It catches http and redirect to https, and redirects www to non-www. SSL-Certificates can be given separately (or the same for both), depending on Certificate.
server {
# Handle http
server_name www.my_website.com my_website.com;
return 301 https://my_website.com$request_uri;
}
server {
# Handle www
listen 443 ssl;
server_name www.my_website.com;
ssl_certificate some_random.crt;
ssl_certificate_key some_random.key;
return 301 https://my_website.com$request_uri;
}
server {
listen 443 ssl;
server_name my_website.com;
ssl_certificate some_random.crt;
ssl_certificate_key some_random.key;
# your 'real' server
}
And it fixes this special problem here, because there is no rule for SSL www requests given. It would be possible to give server_name www.my_website.com my_website.com; for SSL as well, if cert etc is valid for both.

I actually figured out the issue, it was a small goof I made - I needed to change server_name my_website.com; to server_name my_website.com, www.my_website.com;

Related

CentOs Nginx redirect https://www to https://

Im using Nginx in centos. Im facing an issue with redirection.
I want to redirect all requests to https://some-domain.com/url
Im able to redirect
http://www.some-domain.com to https://some-domain.com
www.some-domain.com to https://some-domain.com
http://some-domain.com to https://some-domain.com
But im not able to redirect https://www.some-domain.com
conf file:
server
{
listen 443 ssl;
server_name some-domain.com www.some-domain.com;
ssl_certificate /etc/nginx/ssl/some-domain.com.chained.crt;
ssl_certificate_key /etc/nginx/ssl/some-domain.com.key;
if ($host = https://www.some-domin.com) {
return 301 https://some-domin.com$request_uri;
}
}
It's best to separate two server brackets to evade the use of "if". Your problem was that you added "https://" to the host, when it's only www.some-domain.com what you needed to compare.
This example is simpler:
#Server bracket for https connections that come with host www.some-domain.com
server
{
listen 443 ssl;
server_name www.some-domain.com;
ssl_certificate /etc/nginx/ssl/some-domain.com.chained.crt;
ssl_certificate_key /etc/nginx/ssl/some-domain.com.key;
#redirects to https://non-www
location / {
return 301 https://some-domin.com$request_uri;
}
}
# and then you can set a server bracket for non-www https connections.
# nginx will sort the connections depending on host for itself
server
{
listen 443 ssl;
server_name some-domain.com;
ssl_certificate /etc/nginx/ssl/some-domain.com.chained.crt;
ssl_certificate_key /etc/nginx/ssl/some-domain.com.key;
#Here it arrives 443 and without www, do what you wanted here
}

nginx as https proxy, but want to intercept one static path for Let's Encrypt /.well-known challenges

There is lots of material about using ngix as a reverse proxy and it is working well for me as a basic proxy for a strange web server app I need to use. I even have redirect on so http gets redirected to https.
server {
listen 80;
server_name <my server>;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name <my server>;
# add Strict-Transport-Security to prevent man in the middle attacks
add_header Strict-Transport-Security "max-age=31536000";
ssl on;
ssl_certificate cert1.crt.pem;
ssl_certificate_key cert1.key.pem;
ssl_session_cache shared:SSL:10m;
location / {
proxy_pass http://localhost:81; # my existing apache instance
proxy_set_header Host $host;
}
Now I have one new wrinkle. I'd like to pick off one particular path and NOT have it get forwarded to the main server app. I need to do this to add in some Let's Encrypt challenge responses. Whenever the incoming url is http:///.well-known/acme-challenge/ then I want to use a static nginx path and NOT fwd to the main server.
Any ideas? I tried adding in a location directory but that wasn't working.
server {
listen 80;
server_name video.maritimeopscorp.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name video.maritimeopscorp.com;
# add Strict-Transport-Security to prevent man in the middle attacks
add_header Strict-Transport-Security "max-age=31536000";
ssl on;
ssl_certificate cert1.crt.pem;
ssl_certificate_key cert1.key.pem;
ssl_session_cache shared:SSL:10m;
location ~ /.well-known {
<I've tried lots of combinations here.>
}
location / {
proxy_pass http://localhost:81; # my existing apache instance
proxy_set_header Host $host;
}
I'd also prefer to get this up into the 80 block rather than the 443 block but little steps first.
Any ideas?
You will need to use a root directive, to inform nginx where the .well-known directory can be found:
server {
listen 80;
server_name video.maritimeopscorp.com;
location / {
return 301 https://$server_name$request_uri;
}
location /.well-known {
root /path/to/enclosing/directory;
}
}
Enclose the return statement inside the default location block, otherwise it will always take precedence.

Nginx url rewrite does not work

I want do redirect all requests from my.domain.de to my.domain.com, including rewriting http to https.
The redirection only works with http://my.domain.de which is redirected to https://my.domain.com which is the goal.
When I call https://my.domain.de, it is not redirected.
But when I try to access my.domain.com or http://my.domain.com, the redirect to https scheme fails. Strange, because I used the same rewrite rule for my.domain.de before switching to .com domain and it worked.
Here is my nginx.conf file:
# my.domain.de
server {
listen 80;
server_name my.domain.de;
return 301 https://my.domain.com$request_uri;
}
# my.domain.com
server {
listen 80;
listen 443;
ssl on;
ssl_certificate /path/to/cert;
ssl_certificate_key /path/to/key;
server_name my.domain.com;
# Url rewrite does not seem to work:
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
}
EDIT:
Formerly I wrote that the redirect from everything at the .de domain works. Unfortunately, it only works, if I enter http://my.domain.de or without http://
When I use https://my.domain.de, it get a warning because of invalid certificate. So there is also something wrong in the rewrite rule for my.domain.de.
EDIT2:
Now I re-installed a cert for my.domain.de, so the only problem I have right know is, that http://my.domain.com is not redirected to https.
Edited nginx.conf:
# my.domain.de
server {
listen 80;
listen 443 ssl;
ssl_certificate /path/to/cert.de;
ssl_certificate_key /path/to/key.de;
server_name my.domain.de;
return 301 https://my.domain.com$request_uri;
}
# my.domain.com
server {
listen 80;
listen 443 ssl;
ssl_certificate /path/to/cert.com;
ssl_certificate_key /path/to/key.com;
server_name my.domain.com;
# Url rewrite does not seem to work:
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
}
You have SSL enabled for both port 80 and port 443. The use of ssl on; is deprecated, use the ssl option of the listen directive instead.
Use an explicit default server as a "catch-all" to redirect everything that is not my.domain.com and any http address to https://my.domain.com.
server {
listen 80 default_server;
listen 443 default_server ssl;
ssl_certificate /path/to/domain.de/cert;
ssl_certificate_key /path/to/domain.de/key;
return 301 https://my.domain.com$request_uri;
}
server {
listen 443 ssl;
server_name my.domain.com;
ssl_certificate /path/to/domain.com/cert;
ssl_certificate_key /path/to/domain.com/key;
...
}
Note that one server block uses the old certificate and one server block uses the new certificate.
See this document for more.
As the rewrite does not work for me and I could not set up a default server block because of other servers on the machine, I finally solved the problem by adding two servers, one for port 80 and one for port 443 of my.domain.com. I did not now that this is possible. So this is my new nginx.conf:
# my.domain.de
server {
listen 80;
listen 443 ssl;
ssl_certificate /path/to/cert.de;
ssl_certificate_key /path/to/key.de;
server_name my.domain.de;
return 301 https://my.domain.com$request_uri;
}
# my.domain.com http
server {
listen 80;
server_name my.domain.com;
return 301 https://my.domain.com$request_uri;
}
# my.domain.com https
server {
listen 443 ssl;
ssl_certificate /path/to/cert.com;
ssl_certificate_key /path/to/key.com;
server_name my.domain.com;
}

How to handle 400 error in Nginx when redirect HTTP to HTTPS

I own a website, like example.com by HTTP. Considering the secure stuff, now I want to change the HTTP to HTTPS. And I hope all the old customers could still be able to visit my website even they use example.com which will be redirect to https via Nginx.
Of course, I googled a lot, then my solution is:
upstream www {
server 127.0.0.1:4000;
}
server {
listen 80;
listen 443 ssl;
server_name localhost www example.com;
ssl on;
ssl_certificate /usr/local/etc/docs/example.crt;
ssl_certificate_key /usr/local/etc/docs/example.key;
if ($ssl_protocol = "") {
rewrite ^ https://$host$request_uri? permanent;
}
# below are some other stuff
# ...
}
But when I visit example.com, I got:
400 Bad Request The plain HTTP request was sent to HTTPS port
Then I change the nginx.conf, after reading Redirect in nginx , and config the error_page by 497:
upstream www {
server 127.0.0.1:4000;
}
server {
listen 80;
listen 443 ssl;
server_name localhost www example.com;
ssl on;
ssl_certificate /usr/local/etc/docs/example.crt;
ssl_certificate_key /usr/local/etc/docs/example.key;
error_page 497 https://$host$request_uri;
# below are some other stuff
# ...
}
Then it works, everything is fine. But I just don't know why and the solution of error_page just seems werid. So
after reading Dealing with nginx 400 “The plain HTTP request was sent to HTTPS port” error, I add the default and remove the ssl on.
upstream www {
server 127.0.0.1:4000;
}
server {
listen 80;
listen 443 default ssl;
server_name localhost www example.com;
ssl on;
ssl_certificate /usr/local/etc/docs/example.crt;
ssl_certificate_key /usr/local/etc/docs/example.key;
if ($ssl_protocol = "") {
rewrite ^ https://$host$request_uri? permanent;
}
# below are some other stuff
# ...
}
Great! It works again. But I am not for sure:
Which solution is correct?
If both correct, which is more friendly for SEO?
Solution 1st is really wired, from http://moz.com/learn/seo/redirection, can find that permanent redirection is more friendly.
server {
listen 80;
server_name www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 default ssl;
server_name www example.com;
ssl on;
ssl_certificate /usr/local/etc/docs/example.crt;
ssl_certificate_key /usr/local/etc/docs/example.key;
# below are some other stuff
# ...
}

nginx: how to rewrite the url to use www and https

How to rewrite the url to use www and https all the time?
// The url can have https but not www
https://example.com
// The url can have www but not https
http://www.example.com
// The url can have neither https, neither www
http://example.com
=> rewrite to https://www.example.com
I already use the following to add https to all requests but what about http? Is there an efficient way of adding it?
server {
listen 80;
listen [::]:80;
return 301 https://$host$request_uri;
}
Thanks
Create 2 server blocks to handle the exceptions and 1 server block for the usual stuff.
server {
listen 80;
server_name www.domain.com
domain.com;
return 301 https://www.domain.com$request_uri;
}
server {
listen 443 ssl;
server_name domain.com;
return 301 https://www.domain.com$request_uri;
}
server {
listen 443 ssl;
server_name www.domain.com;
#
# The usual stuff..
#
}
TanHongTat answers is good but you have to take into account the default server behavior of nginx. If no server block matches, it will take the first one even though you defined server_name.
Also, do not forget to add the ssl certificate and key even for the block with only a return.
I ended up doing the following:
# Default server for http
server {
listen 80;
listen [::]:80;
return 301 https://www.domain.com$request_uri;
}
# Default server for https
server {
listen 443;
return 301 https://www.domain.com$request_uri;
ssl on;
ssl_certificate /..../ssl_certificate.crt;
ssl_certificate_key /..../ssl_certificate.key;
# Disable SSLv3 vulnerability
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
}
server {
listen 443;
server_name www.domain.com;
ssl on;
ssl_certificate /..../ssl_certificate.crt;
ssl_certificate_key /..../ssl_certificate.key;
# Disable SSLv3 vulnerability
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#
# The usual stuff..
#
}

Resources