What was (could be) the rationale behind Nginx's decision to only inherit add_header statements from the lowest level that has any?
For instance:
server {
server_name example.com;
root my/root;
listen 443 ssl;
ssl_certificate my.cert;
ssl_certificate_key my.key;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload" always;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy: default-src 'self' https:;
location ~* \.(gif|jpeg|jpg|png|css|js|ico|txt)$ {
add_header Cache-Control "public, max-age=86400";
}
}
None of those security-related headers are added to the assets which match the location block, dedicated to increasing cache time, just because it adds another header.
The fix would be to duplicate all add_header directives into the block which seems counter intuitive to how the rest of Nginx works, e.g. the root directive.
The behaviour is documented here:
There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.
http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header
I guess there is a good explanation and I'm curious about what it is.
Related
i have an EC2 instance on AWS that i have deployed a MERN stack on, i have defined nginx as follows:
server {
#listen 80;
listen 80 default_server;
listen [::]:80 default_server;
server_name yourdomain.com;
access_log /home/ubuntu/client/server_logs/host.access.log main;
client_max_body_size 10M;
location /api/ {
add_header X-debug-message innnnnnnnnnnnnn;
proxy_pass http://localhost:3000/;
}
location /admin-dashboard {
root /home/ubuntu;
index index.html;
add_header X-uri "$uri";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
}
location / {
root /home/ubuntu/client/deploy;
index index.html index.htm;
try_files $uri $uri/ /index.html;
add_header X-uri "$uri";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
}
location = /49x.html {
root /usr/share/nginx/html;
}
server_tokens off;
location ~ /\.ht {
deny all;
}
}
And i have attached the security groups as an screenshots.
when i tried to fetch data with this url http://clikjo.com/api/ , using browser or postman it works perfectly, but when i try it using javascript with fetch or Axios it fails with this error:
[TypeError: Network request failed]
can anybody solve my problem?
i have tried to:
change my security groups
add headers, specify mode , fetch options , ... etc
If you load a page in your browser using HTTPS, the browser will refuse to load any resources over HTTP. As you've tried, changing the API URL to have HTTPS instead of HTTP typically resolves this issue. However, your API must not allow for HTTPS connections. Because of this, you must either force HTTP on the main page or request that they allow HTTPS connections.
Note on this: The request will still work if you go to the API URL instead of attempting to load it with AJAX. This is because the browser is not loading a resource from within a secured page, instead it's loading an insecure page and it's accepting that. In order for it to be available through AJAX, though, the protocols should match.
You are getting CORS error.
You need to fix it on server-side with additional header.
add_header Access-Control-Allow-Origin *;
some images on nginx server getting error 403 forbidden.
for example if upload files with name test.png everything is fine, but if upload file with name Screen Shot 2022-05-27 at 15.01.42.png i'm getting error 403 forbidden.
location ~ ^/srv/files/(.+\.(svg|png|jpg|jpeg|otf|eot|svg|tiff|psd|raw|mp4|pdf))$ {
alias /srv/files/$1;
error_log /var/log/nginx/srv.error.log debug;
access_log /var/log/nginx/srv.access.log main;
# access_log off;
expires 1d;
add_header Cache-Control "public";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" always;
I'd appreciate advice on how to perform a proxy or rewrite rule in the below scenario.
The public URL below sends the request onto the backend server (intserver) on port 443.
Public URL = https://wc029.domain.com
The internal server then redirects internally to various other internal URLs on port 40000 - https://intserver:40000/sld/saml2/idp/sso (being one) - but sends this back to the browser which obviously can't hit the public DNS of the internal host name.
I need the block/rule to allow for any response to be changed back to the external URL.
I've used reverse proxy in IIS before and this is handled by the corresponding outbound rule but can't understand how to achieve this in Nginx.
I suspect this is quite easy and requires something in the server block but considering this is a production server with multiple other server blocks, i'd rather reach out for advice on here before paying around with the config and i can't seem to find something i understand in other scenarios.
Can anyone show me the error of my ways! ;)
server {
listen 443 ssl;
listen [::]:443 ssl;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains;";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
#add_header Content-Security-Policy "default-src 'self'; script-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; font-src 'self' data:; frame-src 'self'; connect-src 'self' https://apis.google.com; object-src 'none'";
# The below allow and deny rules can be set to allow access.The Deny rule MUST be uncommented and then add multiple allow lines for the IP range required.
#allow;
#deny all;
server_name wc029.domain.com;
ssl_certificate /etc/pki/cert.crt;
ssl_certificate_key /etc/pki/priv.key;
ssl_protocols TLSv1.2 TLSv1.3;
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;
access_log /var/log/nginx/reverse-access.log;
error_log /var/log/nginx/reverse-error.log;
location /
{
limit_except GET POST {deny all;}
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass https://intserver/;
proxy_set_header X-Forwarded-Proto https;
}
}
I needs to enable cors policy to reach to my api, i did the following configuration on my nginx server file:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name api.domain.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_pass http://my_ip:6869/;
set $ref "*";
if ($http_referer ~* ^(http?\:\/\/)(.*?)\/(.*)$) {
set $ref $1$2;
}
add_header 'Access-Control-Allow-Origin' $ref always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,signature,timestamp' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/api.domain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/api.domain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
But i keep getting the following error:
Access to fetch at 'https://api.domain.com/data/key?matches=^art(.*)' from origin 'http://localhost:3500' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, http://localhost:3500', but only one is allowed. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
It seem that the add_header is adding on top of an already set header for Access-Control-Allow-Origin * but i only have this config file and don't see anywhere else where it could come from.
Is there a way to figure out what is setting the initial header cors policy or simply override it instead of adding to it?
Thank you in advance.
This happens if you haven't set up CORS configuration correctly.
you can fix this on you'r local machine using a plugin/extension called Allow-Control-Allow-Origin and add you'r localhost into it.
The other way is to manually fix the configuration in server side.
if you are not familiar with CORS it basically used to allow some cross-origin requests while rejecting others. For example, if a site offers an embeddable service, it may be necessary to relax certain restrictions.
Update
Which compiler are you using for Nginx? If it's this one the following code must fix it:
location ~* \.(eot|ttf|woff|woff2)$ {
add_header Access-Control-Allow-Origin *;
}
I set add_header X-Frame-Options deny always;.
Now i want to change it to SAMEORIGIN. To do that i changed the in /etc/niginx/sites-available/my_domain
#add_header X-Frame-Options deny always;
add_header X-Frame-Options sameorigin always;
But header part it still showing X-Frame-Options DENY
Here is the Screen shot:
How can i change this?
Try:
add_header X-Frame-Options "SAMEORIGIN";
and restart Nginx. I tested "add_header X-Frame-Options SAMEORIGIN always;" and Nginx error log reports:
invalid number of arguments in "add_header" directive in ...