Nginx - Stop forcing HTTPS on subdomain - http

I have a site which is ran with nginx, and with the structure where we have a load balancer, and currently only one web server behind it (currently no real traffic so one web server only).
Anyways, in load balancer nginx config, we forced HTTPS on each request:
server {
listen 80;
server_name www.xyz.com xyz.com
return 301 https://www.xyz.com$request_uri;
}
This works fine, but now I want to say "on this subdomain - dev.xyz.com, allow HTTP too and don't do the forcing".
At first, the server_name param was "any", and thought that might be the problem, so I specifically typed the names as in the above samples, and when I type http://www.dev.xyz.com, I get redirected back to the https://www.xyz.com.
Below server block, we have SSL definitions too:
server {
listen 443;
ssl on;
ssl_certificate /etc/nginx/ssl/xyz.com.pem;
ssl_certificate_key /etc/nginx/ssl/xyzPrivateKeyNginx.key;
keepalive_timeout 70;
server_name www.xyz.com;
root /usr/local/nginx/html;
client_max_body_size 25M;
client_body_timeout 120s;
# Add trailing slash if missing
rewrite ^([^\.]*[^/])$ $1/ permanent;
}
Thanks! :)

it turned out the solution was simple, I only inserted a simple redirect:
server {
listen 80;
server_name www.dev.xyz.com
location / {
proxy_pass http://xxyyzz;
}
}
Where xxyyzz is:
upstream xxyyzz{
ip_hash;
server 10.100.1.100:80;
}
Thanks anyways!

Related

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;
}

how to redirect https to http in nginx

I have a tomcat server that is currently running on port 8082(http). I have to make the site https without touching the server code or tomcat configuration. I installed nginx and could able to redirect the https to http, but the browser still says site is not secured. How can we make the client use https and then nginx redirects to http internally, but to client all the calls are https.
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
server {
listen 80;
server_name localhost;
location / {
proxy_pass "http://localhost:8082/app/";
}
}
server {
listen 443 ssl;
server_name localhost;
ssl_certificate nginx-selfsigned.crt;
ssl_certificate_key nginx-selfsigned.key;
rewrite ^(.*) http://localhost:8082/app$1 permanent;
}
}
You should use proxy_pass as Richard mentioned, so that you won't redirect to a backend URL via port 8082(That's the reason that broswer is accessing the http protocal directly.
You also need to place a firewall rule to protect external access to this port
For your current config, just use the 443, and use proxy_pass in this listener, as simple as
server {
listen 443 ssl;
server_name localhost;
ssl_certificate nginx-selfsigned.crt;
ssl_certificate_key nginx-selfsigned.key;
location / {
proxy_pass "http://localhost:8082/app/";
}
}
You might be confused by the port 80, which should be redirected to 443 to ensure all traffics are HTTPS, like
server {
listen 80;
rewrite ^(.*) https://localhost/$1 permanent;
}
Also note these are pseudo code that I copied from your config, you need to try out and change later

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.

How to replace Nginx default error 400 "The plain HTTP request was sent to HTTPS port" page with Play! Framework backend.

I have a website using Play! framework with multiple domains proxying to the backend, example.com and example.ca.
I have all http requests on port 80 being rewritten to https on port 443. This is all working as expected.
But when I type into the address bar http://example.com:443, I'm served nginx's default error page, which says
400 Bad Request
The plain HTTP request was sent to HTTPS port
nginx
I'd like to serve my own error page for this, but I just can't seem to get it working. Here's a snipped of my configuration.
upstream my-backend {
server 127.0.0.1:9000;
}
server {
listen 443;
ssl on;
ssl_certificate /etc/ssl/certs/example.crt;
ssl_certificate_key /etc/ssl/private/example.key;
keepalive_timeout 70;
server_name example.com;
add_header Strict-Transport-Security max-age=15768000; #six months
location / {
proxy_pass http://my-backend;
}
error_page 400 502 error.html;
location = /error.html {
root /usr/share/nginx/html;
}
}
It works when my Play! application is shut down, but when it's running it always serves up the default nginx page.
I've tried adding the error page configuration to another server block like this
server {
listen 443;
ssl off;
server_name example.com;
error_page [..]
}
But that fails with the browser complaining about the certificate being wrong.
I'd really ultimately like to be able to catch and handle any errors which aren't handled by my Play! application with a custom page, or pages. I'd also like this solution to work if the user manually enters the site's IP into the address bar instead of the server name.
Any help is appreciated.
I found the answer to this here https://stackoverflow.com/a/12610382/4023897.
In my particular case, where I want to serve a static error page under these circumstances, my configuration is as follows
server {
listen 443;
ssl on;
ssl_certificate /etc/ssl/certs/example.crt;
ssl_certificate_key /etc/ssl/private/example.key;
keepalive_timeout 70;
server_name example.com;
add_header Strict-Transport-Security max-age=15768000; #six months
location = /error.html {
root /usr/share/nginx/html;
autoindex off;
}
location / {
proxy_pass http://my-backend;
}
# If they come here using HTTP, bounce them to the correct scheme
error_page 497 https://$host:$server_port/error.html;
}

Redirect all http to https in nginx, except one file

I am currently running my site on http, and want to move it over to https such that nginx handles the redirection automagically. This is fairly trivial to do, I guess.
However, there is one file that (for several reasons) is hot-linked from other sites, some of which are over http and some over https. I want to ensure that the file is available over both http and https, so as to ensure that browsers don't complain with the "mixed content" dialog. The path of the file looks something like this:
http(s)://mydomain.com/scripts/[some_sha1_hash]/file.js
So, the nginx rule should say: "If the request is already over https, everything is sweet, and just reverse-proxy it. Otherwise, redirect all requests from http to https, except if this one file is requested, in which case don't do any such http->https redirect."
Can anyone either tell me where to look to learn about such a config, or help me with the config itself? Thanks in advance. (I'm sorry, but I'm not skilled enough yet at nginx configuration.)
This is what I did, which works:
server {
listen 80;
server_name example.com;
charset utf-8;
access_log /var/www/path/logs/nginx_access.log;
error_log /var/www/path/logs/nginx_error.log;
location /path/to/script.js {
# serve the file here
}
location / {
return 301 https://example.com$request_uri;
}
}
This one handles only http requests and serves the said file - otherwise redirects to https. Define your ssl server block, which will serve all https requests.
server {
listen 443;
server_name example.com;
ssl on;
# rest of the config
}
This way your script file will be available on http as well as https.
Try this:
server {
listen 80; ssl off;
listen 443 ssl;
server_name example.com;
# <ssl settings>
# ... other settings
location = /scripts/[some_sha1_hash]/file.js {
# Empty block catches the match but does nothing with it
}
location / {
if ($scheme = "http") {
rewrite ^ https://$http_host$request_uri? permanent;
}
# ... other settings
}
}
server {
listen 80;
server_name my.domain.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443;
server_name my.domain.com;
ssl on;
[....]
}
The above should mostly do the trick if im not wrong

Resources