nginx add_header not applied to some server contexts - http

I have several add_header directives in my main http context of the nginx.conf file, such as:
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
There no other such directives in server and location contexts. For some reason, the header is not applied to server contexts. For example, this one:
server {
server_name my.example.com;
location / {
proxy_pass http://192.168.1.1:12345;
}
location /robots.txt {
return 200 "User-agent: *\nDisallow: /\n";
}
client_max_body_size 300M;
listen 443 ssl; # managed by Certbot
ssl_certificate fullchain.pem; # managed by Certbot
ssl_certificate_key privkey.pem; # managed by Certbot
include options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam ssl-dhparams.pem; # managed by Certbot
}
What could be causing this?
EDIT: nginx version is 1.23.3.
The file options-ssl-nginx.conf in /etc/letsencrypt/ has:
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
# + one line of ssl_ciphers

As explained in comment, adding the always parameter to the add_header directive allows the header to be added for all kind of HTTP responses (errors included), see the doc for more details: http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header

Related

Serve a JSON response from an Endpoint using a Subdomain with Nginx

I currently have a deployed application. https://dostoevsky.rest/
It works well with Nginx and Docker.
However, I want to get a JSON response when I hit the endpoint https://dostoevsky.rest/api/rand with a subdomain.
So, I want the subdomain api.dostoevsky.rest to give the response https://dostoevsky.rest/api/rand would give.
I thought I could configure Nginx with proxy_pass, so I did the following:
server {
server_name api.dostoevsky.rest www.api.dostoevsky.rest;
location / {
default_type application/json;
proxy_pass http://<IP>:80/api/rand/;
}
}
However, when I do curl api.dostoevsky.rest I get this timeout message:
<html>
<head><title>504 Gateway Time-out</title></head>
<body>
<center><h1>504 Gateway Time-out</h1></center>
<hr><center>nginx/1.21.3</center>
</body>
</html>
Nginx Logs:
*1 upstream timed out (110: Operation timed out) while connecting to upstream, client:
I'm assuming the resource isn't found?
If I do curl https://dostoevsky.rest/api/rand it works fine. So, I think I'm making a mistake with the proxy or how the server is configured. Any help would be appreciated. Sorry if this is a low-quality question; I'm new to using Nginx.
Deployed on a DigitalOcean droplet.
I've also configured the DNS for the IP to point to api.dostoevsky.rest, by the way.
Following is my complete nginx.conf file:
server {
listen 80;
listen [::]:80;
server_name dostoevsky.rest www.dostoevsky.rest;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name dostoevsky.rest www.dostoevsky.rest;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/dostoevsky.rest/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dostoevsky.rest/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
try_files $uri #nodejs;
}
location #nodejs {
proxy_pass http://nodejs:8080;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
}
server {
server_name api.dostoevsky.rest www.api.dostoevsky.rest;
location / {
default_type application/json;
proxy_pass http://<IP>:80/api/rand/;
}
}

how to remove www from redirect url in nginx conf

Below is my nginx conf, how to remove www. from redirect url.
right now when i am entering url www.platform.iamwoken.com/ its redirecting to https://www.platform.iamwoken.com/ which is wrong
i need to redirect it to https://platform.iamwoken.com/
server_tokens off;
server {
if ($host ~ (platform.iamwoken.com|www.platform.iamwoken.com)) {
return 301 https://platform.iamwoken.com;
} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name platform.iamwoken.com www.platform.iamwoken.com;
return 301 https://platform.iamwoken.com;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name platform.iamwoken.com www.platform.iamwoken.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
# Disable SSL
ssl_protocols TLSv1 TLSv1.1;
# Optimise cipher suites
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
# Enable HSTS
add_header Strict-Transaport-Security "max-age=31536000" always;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
# SSL sessions
#ssl_session_cache shared:devplatform.iamwoken.com:40m;
# ssl_session_tickets on;
# Skip buffering for static files
sendfile on;
location /static/ {
access_log off;
add_header Cache-Control public;
add_header Pragma public;
add_header Vary Accept-Encoding;
expires 1m;
root /home/ubuntu/wokencrm;
}
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
how to resolve this issue
use below NGiNX block to redirect www to non-www
server {
server_name www.platform.iamwoken.com;
return 301 $scheme://platform.iamwoken.com$request_uri;
}
Restart the nginx web-server and test the URL in browser. It will work as expected.

SNI not working? multiple ssl reverse proxies nginx

I want to configure two reverse proxies with ssl that proxy pass to different applications
https://api.example.com --> http://app:8080
https://pg.example.com --> http://pgadmin:80
Given the following nginx configuration, both sub-domains redirect to the first 443-server config (app). The problem occurs when hitting the 443 port. The redirect from 80 to 433 works fine for both. But when I browse https://pg.example.com it passes to app instead of pgadmin.
server {
listen 80;
listen [::]:80;
server_name api.example.com pg.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.example.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://app:8080;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name pg.example.com;
server_tokens off;
# note that api.example.com certificate has pg.example.com as alias
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_set_header X-Scheme $scheme;
proxy_set_header Host $host;
proxy_pass http://pgadmin:80;
proxy_redirect off;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# enable strict transport security only if you understand the implications
}
}
Feels like the SNI is not working or so..?! But it is enabled in nginx:
nginx -V
nginx version: nginx/1.17.10
built by gcc 9.2.0 (Alpine 9.2.0)
built with OpenSSL 1.1.1d 10 Sep 2019 (running with OpenSSL 1.1.1g 21 Apr 2020)
TLS SNI support enabled
What am I missing to make both reverse proxies work?
Edit:
When I remove the server block for server_name api.example.com; (on 443) then the other (pg.example.com:443) does work as expected. The api.example.com:443 then shows the same pgadmin upstream).
I think the easiest way is to split up the first server block into two server-blocks.
For example:
server {
listen 80;
listen [::]:80;
server_name api.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
and
server {
listen 80;
listen [::]:80;
server_name pg.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
I hope this helps, but I can't guarantee, that this config is working properly with certbot.
Turns out the reason is a misspelled domain for the sever_name of the
pg.example.com:433. Hence, not sever_name would match and nginx would then use the best match - which is the api.example.com:433.
I found out by adding a default (by making them the first in the conf file and both using sever_name _) server config for both 80 and 443 so I could ensure that the specific server configs are only used if the server_name matches. The result was that api.example.com:433 showed the same behavior as before (indicating that it works) while the pg.example.com:433 would show the newly configured default server - so it must be something that prevents the proper match on the server_name in the config. I triple checked the sever_name and finally saw the typo.

NGINX stuck in HTTPS redirection on server

I've been trying to set up a self-signed certificate on my server (for when you visit the IP, not some domain, since I don't have any domains linked). I followed certain tutorials and made one using openssl and put my files here.
/etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
I then created a configuration snippet in /etc/nginx/snippets/self-signed.conf, which looks like this.
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
After that, I just created an ssl-params.conf which contains the following:
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off; # Requires nginx >= 1.5.9
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable strict transport security for now. You can uncomment the following
# line if you understand the implications.
# add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
And lastly, since I have no server blocks, I put the configuration in /etc/nginx/sites-available/default
Which is a simple one that I took.
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
include snippets/self-signed.conf;
include snippets/ssl-params.conf;
return 302 https://$host$request_uri;
location ~ / {
proxy_set_header X-Forwarded-Proto $scheme;
}
}
But now whenever I visit the IP of the server, it gives me the problem of it being redirected too many times. I can't seem to find what I did wrong, so any help would be appreciated.
server {listen 443 ssl;
server_name localhost;
ssl_certificate D:/yourcertificate.crt;
ssl_certificate_key D:/yourcertificate.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
# proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://localhost:8080;
}}
Follow this link https://youtu.be/ikbN1bYnBjg for better understanding.

Getting error due to Access-Control-Allow-Origin. (NGINX)

I am using NGINX and I am receiving that error in the browser's console.
According to the instructions of my boss, I need to set up cors which what I did and still I am getting the same error.
This is the entire error
OPTIONS https://backend.just4bettors.mobi/auth/login
XMLHttpRequest cannot load https://backend.just4bettors.mobi/auth/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://www.just4bettors.mobi' is therefore not allowed access. The response had HTTP status code 400.
Here is the config
map $http_origin $cors_header {
default "";
"~^https?://[^/]+\.just4bettors\.mobi(:[0-9]+)?$" "$http_origin";
}
server {
large_client_header_buffers 1 1K;
listen 80;
listen 443 ssl;
server_name www.just4bettors.mobi just4bettors.mobi;
root /home/c0pt/capilleira/capilleiraclickandgamblemobile/www;
ssl_certificate /etc/ssl/certs/just4bettors.mobi.chained.crt;
ssl_certificate_key /etc/ssl/private/just4bettors.mobi.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
add_header Access-Control-Allow-Origin $cors_header;
...
}
}
server {
listen 80;
listen 443 ssl;
server_name backend.just4bettors.mobi www.backend.just4bettors.mobi;
ssl_certificate /etc/ssl/certs/just4bettors.mobi.chained.crt;
ssl_certificate_key /etc/ssl/private/just4bettors.mobi.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
add_header Access-Control-Allow-Origin $cors_header;
}
}
I have the domain and the subdomain, it is like something named cross-domain.
Where do I have the error here ? I mean, I have everything set up and still asking me for the Access-Control-Allow-Origin, why ?
ps: I want to cry.
You need to set the header on the backend side, not under your main section location /
The error message basically states that you are not allowed to access the backend from your www frontend.
Your backend must allow backend.just4bettors.mobi and www.backend.just4bettors.mobi as valid Origins ...

Resources