I have a valid certificate for example.com. If users go to my site at http://example.com, they get redirected to https://example.com and all is good. If they go to https://example.com, all is good. If they even go to http://www.example.com, they get redirected to https://example.com and all is good.
However, if they go to https://www.example.com, Chrome triggers its SSL warning before I can redirect and tells the user to not trust this site. I don't have this problem in Safari or Firefox.
Here's my nginx configuration. What am I doing wrong?
```
# Configuration for redirecting non-ssl to ssl;
server {
listen *:80;
listen [::]:80;
server_name example.com;
return 301 https://example.com$request_uri;
}
# Configuration for redirecting www to non-www;
server {
server_name www.example.com;
ssl_certificate ssl/ssl_cert.crt;
ssl_certificate_key ssl/ssl_key.key;
listen *:80;
listen *:443 ssl spdy;
listen [::]:80 ipv6only=on;
listen [::]:443 ssl spdy ipv6only=on;
return 301 https://example.com$request_uri;
}
server {
listen *:443 ssl spdy;
listen [::]:443 ssl spdy;
ssl_certificate ssl/ssl_cert.crt;
ssl_certificate_key ssl/ssl_key.key;
server_name example.com;
}
```
EDIT: I see that this is a problematic configuration because the second block will look at the certs. What's the proper way to set this up with a cert that reads from "example.com" rather than "www.example.com"?
If your certificate is for example.com only and not for www.example.com then any access to www.example.com will trigger a certificate warning, no matter if you want just redirect it or not. Redirection is done at the HTTP level and before it talks HTTP it first does the SSL handshake (which triggers the problem), because HTTPS is just HTTP inside SSL.
And before you ask, tricks with DNS (like CNAME) will not help either because the browser will compare the certificate against the name in the URL, not against possible DNS alias names. There is simply no way around getting a proper certificate.
Related
I am having an issue with nginx where it won't listen on port 443.
Listening on port 80 is fine. I have included a snippet of my config below:
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl on;
ssl_certificate /var/www/certs/server.pem;
ssl_certificate_key /var/www/certs/server.key;
server_name server;
root /var/www/server;
access_log /var/log/nginx/server/access.log;
error_log /var/log/nginx/server/error.log;
index index.php;
}
not sure where I am going wrong. Everything I have checked shows that it should be working.
I am on Ubuntu 18.04 with nginx 1.14.0
there is no firewall on the system, nor between myself and the server.
I have checked the config several times with nginx -t and systemctl reloaded as well. no change, the port does not open for me.
To configure an HTTPS server, the ssl parameter must be enabled on listening sockets in the server block, and the locations of the server certificate and private key files should be specified:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}
A single HTTP/HTTPS server
It is possible to configure a single server that handles both HTTP and HTTPS requests:
server {
listen 80;
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
...
}
Prior to 0.7.14 SSL could not be enabled selectively for individual listening sockets, as shown above. SSL could only be enabled for the entire server using the ssl directive, making it impossible to set up a single HTTP/HTTPS server. The ssl parameter of the listen directive was added to solve this issue. The use of the ssl directive in modern versions is thus discouraged.
Name-based HTTPS servers
A common issue arises when configuring two or more HTTPS servers listening on a single IP address:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
...
}
server {
listen 443 ssl;
server_name www.example.org;
ssl_certificate www.example.org.crt;
...
}
Add these server blocks.
This is to redirect http to https
server {
listen 80;
server_name example.com;
location / {
return 301 https://$host$request_uri;
}
}
Your main block with ssl
server {
listen 443 ssl ;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
index index.html index.htm index.nginx-debian.html;
server_name example.com;
location / {
proxy_pass http://localhost:5003; // Your port goes here
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Also check if the ports are open
Sorry to bother you with this, you've been a great community to learn from and I am very thankful. However, I couldn't find a solution to a task I'm having.
I want to change my domain from https://www.sitename.com to https://www2.sitename.com
Do you have any idea how I could do that? Any help would be immensely appreciated!
I am using nginx on ubuntu 16.04.
EDIT: I forgot to mention that I have to use Cloudflare.
My current configuration:
server{
server_name example.com;
rewrite ^/(.*) http://www.example.com/$1 permanent;
}
server {
#Ports
listen 80;
listen 443 ssl;
#Server name
server_name www2.example.com www.example.com example.com;
}
So far I am able to open what I want from www2.example.com but I need to redirect www.example.com example.com to www2.example.com
If you want to redirect then, in your nginx.conf you should do this
server {
server_name https://www.sitename.com/; // Old domain
return 301 https://www2.sitename.com/$request_uri; // New domain
}
So I was able to do it like this:
server{
#Ports
listen 80;
listen 443 ssl;
#Server name
server_name example.com www.example.com;
#Return
return 301 https://www2.example.com$request_uri;
}
server {
#Ports
listen 80;
listen 443 ssl;
#Server name
server_name www2.example.com;
}
You can set the first server with the domains you want to redirect
and remove those domains from the second server:
server{
server_name www.example.com example.com ;
rewrite ^/(.*) http://www2.example.com/$1 permanent;
}
server {
#Ports
listen 80;
listen 443 ssl;
#Server name
server_name www2.example.com;
}
Step 1 on CloudFlare in DNS section add A record www2 with your server IP
Step 2 Make your redirect.
you cay use this way
server {
listen 80;
listen 443 ssl;
server_name www.old-name.com;
return 301 $scheme://www.new-name.com$request_uri;
}
Step 3 restart NGINX
sudo service nginx restart
I'm trying to redirect all traffic from an HTTP site to an HTTPS site as well as all www traffic to the non-www site. My setup includes an nginx.conf file for the HTTP site which I've added a 301 redirect rule to:
server {
listen 80;
listen [::]:80;
server_name
sub.domain.com
www.sub.domain.com
;
return 301 https://sub.domain.com$request_uri;
...
}
I also have an https nginx.ssl.conf file which looks something like:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name sub.domain.com www.sub.domain.com;
ssl on;
...
}
With this setup, I'm able to redirect all HTTP traffic to HTTPS but if I try to add a redirect in my nginx.ssl.conf file I receive a "too many redirects" error.
Any suggestions on how I can redirect everything to my HTTPs, non-www site?
You need to split your https block into two domains
server {
listen 80;
listen [::]:80;
server_name
sub.domain.com
www.sub.domain.com
;
return 301 https://sub.domain.com$request_uri;
...
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.sub.domain.com;
return 301 https://sub.domain.com$request_uri;
ssl on;
...
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name sub.domain.com;
ssl on;
...
}
I am struggling on how to force SSL on my website (nginx). I would like to force a redirect from both "http://www.example.com" and "http://example.com" to "https://example.com" (without any www).
The code I wrote currently can catch "http://www.example.com" but does not catch "http://example.com", it seems to infinite loop a redirection. I'm pretty sure it has something to do with the "server_name". I tried swapping it up a down inside the "server { ... }" brackets and stuff but it still does not behave the way I would like it.
Here is my nginx conf
server {
server_name www.example.com;
return 301 https://example.com$request_uri;
}
server {
server_name example.com;
root /var/www/example.com;
index index.html index.php index.htm;
location / {
include /etc/nginx/conf/fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
}
server {
#listen 443 spdy default deferred;
ssl on;
ssl_certificate_key /etc/myssl/www.example.com.key;
ssl_certificate /etc/myssl/www.example.com.chained.crt;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-[...]';
ssl_prefer_server_ciphers on;
ssl_dhparam /usr/share/myssl/dhparams/dh2048-group14.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:5m;
add_header Strict-Transport-Security max-age=15768000;
}
You'll want to configure each of your server blocks to specifically listen to a certain port, such as the following:
server {
listen 80;
server_name www.example.com example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl spdy;
server_name www.example.com;
ssl_certificate_key /etc/myssl/www.example.com.key;
ssl_certificate /etc/myssl/www.example.com.chained.crt;
[other ssl_* directives, as required]
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl spdy;
server_name example.com;
ssl_certificate_key /etc/myssl/www.example.com.key;
ssl_certificate /etc/myssl/www.example.com.chained.crt;
[other ssl_* directives, as required]
[remaining example.com configuration here]
}
This says listen on HTTP (port 80) for requests to http://www.example.com and http://example.com and redirect them to https://example.com. The second block listens for https://www.example.com and redirects to https://example.com. Then, the final block listens for SSL/SPDY requests to https://example.com.
Add your remaining HTTPS-only configuration to the second block, which looks to be essentially merging the second and third blocks.
The following is now demonstrated in the example: You will need to add another server block if you want your server to respond or redirect users accessing https://www.example.com & thus you may require a second valid SSL certificate (one for www.example.com and one for example.com). Alternatively, a wildcard certificate or a certificate with alternate DNS names would work for both circumstances.
Also ensure that no other conflicting configuration files are present in your configuration directory (eg /etc/nginx/conf.d or /etc/nginx/sites-enabled; depending on your platform).
Edited: expanded based on other information given.
I would like to redirect all traffic from the following domains:
http://domain.com
http://www.domain.com
https://domain.com
to
https://www.domain.com
I have a SSL certificate for the above domain. It hosts a Rails app, served by Passenger.
To accomplish the naked domain redirect, I've set up an URL redirect in my DNSimple account:
URL domain.com 3600 https://www.domain.com
My server blocks are as follows (Inspired by Nginx no-www to www and www to no-www amongst others):
server {
listen 80;
listen 443;
server_name domain.com;
ssl on;
ssl_certificate /etc/ssl/domain-ssl.crt;
ssl_certificate_key /etc/ssl/domain.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
server_tokens off;
access_log /dev/null;
error_log /dev/null;
return 301 https://www.domain.com$request_uri;
}
server {
listen 443 ssl;
server_name www.domain.com;
root /home/deploy/app/current/public;
passenger_enabled on;
passenger_app_env production;
passenger_set_cgi_param HTTP_X_FORWARDED_PROTO https;
ssl on;
ssl_certificate /etc/ssl/domain-ssl.crt;
ssl_certificate_key /etc/ssl/domain.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
}
passenger_pre_start https://www.domain.com;
What works:
naked domain gets redirected to secure https://www
http://www domain gets redirected to secure https://www
https:// www works
What does't:
Naked https:// doesn't work, browsers throws a server not found
Basically I want to redirect all traffic to the secure https://www.domain.com. What am I missing here?
If you don't have a certificate for domain.com redirecting from https://domain.com to https://www.domain.com will not work, because before the browser gets the redirect it has to successfully establish the SSL connection (https is http inside SSL) and this fails because the certificate does not match.
I had similar kind of scenario and this is how I solved the redirection from
https://domain.com -----> https://www.domain.com
server {
listen 443;
server_name domain.com;
if ($host = domain.com) {
rewrite ^(.*) https://www.domain.com:443$request_uri? permanent;
}
Hope this helps!
Using if condition in nginx
Directive if has problems when used in location context, in some cases it doesn't do what you expect but something completely different instead. In some cases it even segfaults. It's generally a good idea to avoid it if possible. The only 100% safe things which may be done inside if in location context are: return ...; rewrite ... last;
Following will help.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
====>>> Your site configuratioin Goes here <<======
}
Provide a specific server block for the naked domain along with a general default. The more-specific ones will be used first.
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
return 301 https://www.$host$request_uri;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
# omitting the rest for https://www.example.com
}
I use Let's Encrypt for my certificates so something like the following for default_server prevents redirecting the ACME challenges (note the second wildcard server_name for handling all https://*.example.com which don't have their own server block).
# omit server_name example.com block, same as above
server {
listen 80 default_server;
listen [::]:80 default_server;
location ~ ^/\.well-known/acme-challenge {
# LetsEncrypt
add_header Content-Type text/plain;
expires 0;
alias /var/www/html/acme/$host;
break;
}
location ~ ^/(?!\.well-known/acme-challenge) {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name *.example.com;
# omitting the rest for https://*.example.com
}
Setup certificates for the naked example.com, www.example.com and any others:
sudo certbot certonly --manual -d example.com -d www.example.com -d abc.example.com