Nginx rewrite advice - nginx

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

Related

http request with ec2 aws server is not working

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

Nginx 301 when accessing a proxied domain locally

I have a Nginx running as a reverse proxy for a domain, let's call it "testdomain.com", the proxy itself is working, and I can access this website from almost anywhere I want, except locally.
To clarify it better, here's my architecture:
I have a ESXi server which has a pfsense VM, the pfsense VM port forwards all requests destined to port 80 to the port 80 of another VM. That VM has a docker container which is running nginx, so it sends to port 80 of the container, and then it proxy pass the HTTP request to another external server where tha application (WordPress) is hosted. As I said it earlier, it works fine, however, if execute a curl locally (i.e wihitn my first my first VM or nginx container) to my address it returns the following:
curl testdomain.com
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
It seems that Nginx can't find the vhost, here's how my .conf for the website looks:
server {
listen 80;
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
server_name testdomain.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
add_header Cache-Control public;
add_header Pragma public;
add_header Vary Accept-Encoding;
expires 60M;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://myexternalserver.com:80;
}
}
server {
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
listen 443 ssl http2;
server_name testdomain.com;
access_log /var/log/nginx/access.log;
ssl_certificate /etc/nginx/ssl/nginx-selfsigned.crt;
ssl_certificate_key /etc/nginx/ssl/nginx-selfsigned.key;
#
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
#
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
#
add_header Strict-Transport-Security "max-age=31536000" always;
#
ssl_session_cache shared:SSL:40m;
ssl_session_timeout 4h;
ssl_session_tickets on;
location / {
add_header Cache-Control public;
add_header Pragma public;
add_header Vary Accept-Encoding;
expires 60M;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://myexternalserver.com:443;
}
}
I apologize if I miss any relevant info.
Thank you!

How to set headers on reverse proxy to pass over http on custom port but show https and port 443

I am using NGINX as a reverse proxy to connect to an application hosted in Windows Server.
The connection path for the upstream traffic would be something like:
Browser to reverse proxy over https on port 443
Reverse proxy to Windows app server over http on ip 10.1.0.10, port 8080
The relevant configuration in nginx is as follows:
server {
server_name example.com;
listen 443 ssl http2;
location / {
return 301 https://$host/app;
}
location ~ ^/app {
add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains;" always;
add_header X-Content-Type-Options nosniff always;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_intercept_errors on;
proxy_pass http://10.1.0.10:8080;
}
}
I can see that requests to https://example.com/app are initially reaching the server. Problem is, subsequent requests are trying to reach URL http://example.com:8080/app.
It looks like proxy_set_header Host is working as expected (i.e. replacing ip address 10.1.0.10 with example.com), but the protocol and port number are not changing.
I tried adding the following directives:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
but no luck.
How can NGINX be configured to pass incoming traffic to http://10.1.0.10:8080 while using https://example.com (port 443) in the headers?

Nginx : blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values

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

Serving Polymer PWA with nginx reverse proxy

I'm trying to serve my Polymer PWA with an HTTP/2 reverse proxy using nginx, but I cannot get it to work properly. The PWA is served unbundled with prpl-server at 127.0.0.1:38765, which works fine. My prpl-server looks like this:
const express = require('express')
const prpl = require('prpl-server')
const config = require('./build/polymer.json')
const app = express()
const port = 38765
app.get('*', prpl.makeHandler('./build/', config))
app.listen(port)
and my nginx config at /etc/nginx/sites-available/default looks like this:
upstream app {
server 127.0.0.1:38765;
keepalive 64;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name app; # or full domain? tried both, doesn't work
location / {
proxy_pass http://app$request_uri;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Proto-Version $http2;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Connection "";
# Cache Controls
# This section sets response expiration which prevents 304 not modified
expires 0;
add_header Pragma public;
add_header Cache-Control "public";
access_log off;
# Security Patches
# This section are security patches in case the client overrides
# these values, the server re-enables it and enforce its rules
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options "deny";
add_header X-Content-Type-Options "nosniff";
}
ssl on;
ssl_session_cache shared:SSL:5m;
ssl_session_timeout 1h;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
}
When I go to the page, all dependencies seem to be downloaded over h2 except for ma-app.html (the app shell), which gives me a 502 error. All other files download with a 200 status and have the same size (minus some compression) as when I go to port 38765 directly, but the page is blank.
Am I missing something? Why doesn't the shell download properly? All files' request URLs are exactly the same for the nginx reverse proxy as for the prpl-server except for the port number.
Screenshots
It works when I access the prpl-server directly:
Does not work when I go through the nginx reverse proxy:
Some info for the failed request:
The problem had something to do with the buffer size being too small, as mentioned here: https://github.com/Polymer/prpl-server-node/issues/50#issuecomment-333270848.
I added
proxy_buffer_size 128k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
in the location section of the nginx config and now the thing works.

Resources