Configuring Nginx - routing traffic from HTTP to HTTPS and BAD REQUEST error (local host, no domain) - nginx

I'm trying to configure my Nginx in a way so that all HTTP requests are redirected to HTTPS. This is a testing environment and I don't have the domain, hence, I'm not sure whether the redirect can function properly. The host part is simply 127.0.0.1. This is the current configuration:
server {
listen 80;
listen [::]:80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name _;
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
...
I also tried:
removing server_name _;
putting the return 301 in a location block;
adding further ssl settings, such as ssl_session_timeout, ssl_protocols, ssl_prefer_server_ciphers.
ssl on has been removed.
The syntax has been tested, nginx reloaded, the ports have been tested with nmap (both 80 and 443 are open).
When I curl -k (since the certificate is self-signed) 127.0.0.1 I get this message:
301 Moved Permanently
nginx/1.14.0 (Ubuntu)
When I curl -k 127.0.0.1:443 I get this message:
400 The plain HTTP request was sent to HTTPS port 400 Bad Request The
plain HTTP request was sent to HTTPS port nginx/1.14.0 (Ubuntu)
Could someone help me to understand what am I doing wrong? I'd be happy to provide more information. Thank you so much!!

So here is an nginx config that is working for me.
upstream app {
server app:8080;
}
server {
listen 80;
listen [::]:80;
server_name webprojects-dev.co.uk;
return 301 https://webprojects-dev.co.uk$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 http2;
server_name webprojects-dev.co.uk;
include /etc/nginx/common.conf;
include /etc/nginx/ssl.conf;
location / {
proxy_pass http://app;
include /etc/nginx/common_location.conf;
}
}
In this instance nginx is running in a stack of docker containers networked with docker compose but that shouldnt have any bearing on how it works.
The upstream is the app container (and port) for a reverse proxy.
The first server block is forwarding on requests to https. As you can see the main difference between mine and yours is the server_name is the domain name and is also included in the return 301 statement.
The second server block is for https. Again server_name is a domain but other than that the only other difference I can see is I don't have ssl on the line listen [::]:443.
Disclaimer: Not an expert on nginx. I just hacked away till I had a reverse proxy config that works for me and now I just copy and paste it for everything.

Related

How CDN knows which Edge sever should it redirect the client to?

I'm trying to learn more about how CDN works. How does it knows which Edge sever should it redirect the client to for lowest latency? Thank you.
For this purpose, Upstream configuration is used in Nginx webserver.
nginx redirect users's requests to the destination server.
sample of Nginx upstream is as bellow.
upstream example.com {
server example.com;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
access_log /var/log/nginx/access.log custom;
location / {
proxy_pass http://example.com;
}

NGINX Forward HTTPS from any domain to specific URL

I am implementing an internal DNS server for block specific DNS requests to malicious websites, using a DNSRBL list against bind9. Whenever there's a match, the DNS server responds with the IP of an internal NGINX server that serves a block page.
Example, when the internal client requests http://www.badsite.com/ the DNS server responds with 192.168.0.100 as an example, which is the IP of the NGINX server. Then NGINX uses a 301 to forward the request to an HTTPS site which serves the block page message to the end user.
That works well using a simple NGINX config:
server {
listen 80 default_server;
server_name _;
return 301 https://block.xyz.com;
}
server {
listen 443 ssl;
server_name block.xyz.com;
ssl_certificate /etc/letsencrypt/live/block.xyz.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/block.xyz.com/privkey.pem;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
The issue I'm having is when the client requests an HTTPS site, i.e.:https://www.badsite.com/ . I would like to forward any incoming SSL/443 requests to https://block.xyz.com. I've tried adding the following directive:
server {
listen 443 ssl default_server;
server_name _;
ssl_certificate /etc/letsencrypt/live/block.xyz.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/block.xyz.com/privkey.pem;
return 301 https://block.xyz.com;
}
And I get the typical SSL error saying the certificate doesn't match the domain: NET::ERR_CERT_COMMON_NAME_INVALID, which is understandable. The same thing happens when I change the directive from return to rewrite:
...
rewrite ^ https://block.xyz.com;
....
How would I go about adding a directive in NGINX to accomplish this? This guide (https://sweetcode.io/ad-blocking-with-local-dns-servers-and-nginx/) provided me a way to do the http side for implementing something similar for Ad Blocking, but doesn't speak to https requests.
Any clues?
In your server block try adding:
if ($host != "block.xyz.com") {
rewrite ^/(.*) https://block.xyz.com/$1 permanent;
}

HTTPS on NGINX server running wordpress

I am trying to implement HTTPS on a site ased on nginx server, Now even with the below config it only opens HTTP site
My server config for nginx server is like this
server {
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/mydomain.in/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.in/privkey.pem;
server_name mydomain.in www.mydomain.in;
rewrite ^(.*) http://$server_name$1 permanent;
}
server {
server_name mydomain.in www.mydomain.in;
access_log /var/log/nginx/mydomain.in.access.log rt_cache_redis;
error_log /var/log/nginx/mydomain.in.error.log;
root /var/www/mydomain.in/htdocs;
index index.php index.html index.htm;
include common/redis-php7.conf;
include common/wpcommon-php7.conf;
include common/locations-php7.conf;
include /var/www/mydomain.in/conf/nginx/*.conf;
}
The server does not serve HTTPS Requests i.e even if i specifically put https in browser it still takes me back to http site. I am not able to diagnose if its nginx or wordpress which is at fault ?
Note : the traffic is routed through cloudflare dns and certificate is
switch off in cloudflare so that it doesn't interfere. I am Relatively new to nginx
Well below is the basic idea.
server {
server_name mydomain.in www.mydomain.in;
listen 80;
location / {
return 301 https://mydomain.in$request_uri;
}
}
server {
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/mydomain.in/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.in/privkey.pem;
server_name mydomain.in www.mydomain.in;
access_log /var/log/nginx/mydomain.in.access.log rt_cache_redis;
error_log /var/log/nginx/mydomain.in.error.log;
root /var/www/mydomain.in/htdocs;
index index.php index.html index.htm;
include common/redis-php7.conf;
include common/wpcommon-php7.conf;
include common/locations-php7.conf;
include /var/www/mydomain.in/conf/nginx/*.conf;
}
The top server block listens on port 80 (http). It has one location block which does a return 301. return is preferred over rewrites in most cases. I also put it into a location block because you have a letsencrypt ssl cert which might require another location ^~ /.well-known { block to help handle that.
The second server block listens on port 443 (https). It has the SSL certs and includes the information exposed previously for as the http server block.
This setup will handle redirecting from http on either mydomain.in or www.mydomain.in to https mydomain.in. On https both mydomain.in and www.mydomain.in will receive SSL requests.
If you want it to redirect to a primary https domain you can add another server block for the secondary(ies) like so.
server {
server_name www.mydomain.in;
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/mydomain.in/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.in/privkey.pem;
location / {
return 301 https://mydomain.in$request_uri;
}
}
Of course, this means you would have to change the second server block to remove the secondary(ies) domain names.
Also while testing you might want to change the 301s to 302s so that if you misconfigure the first time that it not be stuck in the browser cache. After you get everything to a good state then change back to 301s.

nginx setup WordPress multiple domains and subdomains

Anyone can point me please, in setting up nginx correctly.
I have 3 domains and 1 subdomain, and I have problem with only one domain.
All domains have main server block the same
domain1.com
server {
# Server host
server_name domain1.com *.domain1.com; # Other domains are set to 1.com, 2.com ...
# Server ports
listen 80;
listen [::]:80 ipv6only=on;
listen 443 ssl http2;
listen [::]:443 ipv6only=on ssl http2;
Now funny thing is this:
$ curl -I http://www.domain2.com,
HTTP/1.1 200 OK
Link: <http://www.domain3.com/>; rel=shortlink
$ curl -I https://domain2.com
HTTP/1.1 302 Found
Location: https://www.domain1.com
So non-www https redirects to domain1.com, and www http displays domain3.com.
I have tried to add:
server {
listen 80;
listen [::]:80;
server_name www.domain2.com, domain2.com;
return 301 https://www.domain2.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name domain2.com;
return 301 https://www.domain2.com$request_uri;
}
But this doesn't helps.
I see that probably some settings are redundant but not sure why is this not working.
What I want to achieve is:
domain2.com, www.domain2.com > https://www.domain2.com
I also have a subdomain here, but that one is working well: dev.domain2.com
I think it could have to do with you separating the server names by a comma instead of just a space. Try removing the comma in this line and see if you have any luck?
server_name www.domain2.com, domain2.com;

Nginx server_name & listen matches specified patterns

In this example the domain has been replaced with domain.com
Our main issue:
When i type https://domain.com i don't get redirected to https://www.domain.com, we currently don't have a rule for this what would be the best way to solve this?
According to our nginx configuration we have not specified 443 for https://domain.com but still its accessible, why is that?
We have valid ssl certificates for both domain.com and www.domain.com.
We do not have a wildcard certificate *.domain.com.
Our Configuration:
#All non-matching patterns
server
{
listen 80;
#enabling this will cause things to break.
#2015/12/18 09:21:54 [error] 32165#0: *1661 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: *censored*, server: 0.0.0.0:443
#listen 443 ssl;
#Horrible looking match all pattern.
server_name _ "" domain.com *.domain.com;
return 301 https://www.domain.com$request_uri;
}
#Main site ssl enforced
server
{
listen 443 ssl;
server_name www.domain.com ios.domain.com android.domain.com;
...
}
#Staging / Test site
server
{
listen 443 ssl;
listen 80;
server_name stage.domain.com;
...
}
#Rental cars site ssl enforced
server
{
listen 443 ssl;
server_name hyrbil.domain.com;
...
}
#ios redirect to enforce https
server
{
listen 80;
server_name ios.domain.com;
return 301 https://ios.domain.com$request_uri;
}
#android redirect to enforce https
server
{
listen 80;
server_name android.domain.com;
return 301 https://android.domain.com$request_uri;
}
Bonus question:
Is it possible to match all ssl traffic and do a redirect unless it matches a specific domain, for example make https://xxx.domain.com pass a 301 to https://www.domain.com even tho i don't have a certificate for xxx.domain.com without showing "This page is unsecure, are you sure that you want to proceeed"?
If you have one virtualhost listening on 443, all traffic reaches your IP address will be served by that virtualhost.
Create an SSL virtualhost for domain.com and put a simple redirect in it.
Or create a "catch all/default" SSL virtualhost, and check the HOST header and redirect regarding that, like:
if ($host !~* ^www\.doman\.com$) {
rewrite ^(.*)$ http://www.domain.com$1 permanent;
}
But it will show SSL certificate error on all FQDNs not included in your certificate!

Resources