Nginx proxy showing old content - nginx

I'm having some issues with our setup that contains:
Proxy -> CDN cache -> Origin.
It's setup so that if we update content on the origin, we purge the CDN cache, and with this I expect to see the update on the live site ( proxy ). But sometimes, around 20-30% of the time this does not reflect on the proxy, even if I see the CDN is updated correctly. And I cant wrap my head around why.
I've turned off the cache on the proxy.
Clearing the cache multiple times will eventually show the correct content for the times the proxy does not show the correct content after purge.
Responses for the different stages below.
The CDN is from Microsoft azure by Verizon
Origin headers:
CDN headers:
Live headers:
Proxy config:
server {
server_name <DOMAIN>;
location / {
proxy_no_cache 1;
proxy_cache_bypass 1;
proxy_redirect off;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_headers_hash_max_size 512;
proxy_headers_hash_bucket_size 128;
proxy_hide_header Cache-Control;
add_header Cache-Control max-age=120; #Browser cache of 120s
proxy_pass "https://<CDN-BASE-URL>$request_uri";
}
}
Looking closer, it seems like the Last-Modified is a missmatch, could this be a cause?

Related

How to configure nginx reverse-proxy to support external site in iframes

I'm in the unfortunate situation that I need to extend my react application with an iframe containing an external application.
My application is hosted by a nginx reverse proxy that handles /api and signalr communication.
Unfortunately it also handles the outbout iframe src url.
in this example my site is on the url https://example.com
The iframe src url is in this case "https://external-site.com/someapp/session?token=1234"
When i see the requests in the browser the url has changed to https://example.com/esternal-site.com/someapp/session?token=1234, which needless to say is not working out of the box.
I've been toying with the nginx configuration but has been unable to just pass the request through without modification.
The iframe/destination works as expected when running locally.
I've attempted with a few different configuations inspired by stackoverflow and medium etc. but they've all returned various error codes.
the server runs on port 80, but https is handled by ingress on azure.
This is what i have currently:
upstream bff_service {
server ${BFF_HOST}:${BFF_PORT};
keepalive 32;
keepalive_requests 1000;
keepalive_timeout 75s;
}
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
add_header Set-Cookie "msal_client_id=${BFF_MSAL_CLIENT_ID};Path=/;Secure";
}
location /api {
proxy_read_timeout 300s;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host ${BFF_HOST};
proxy_set_header X-NginX-Proxy true;
proxy_pass ${BFF_PROTOCOL}://bff_service;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_redirect off;
}
location ^~ /external-site.com {
add_header Content-Security-Policy "frame-src 'self' https://external-site.com";
proxy_pass https://external-site.com/$request_uri;
}
}
I've also tried adding the lines below to the location:
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-NginX-Proxy true;
I'm looking for a configuration that allows me to embed an iframe with an external location. Perhaps even avoid nginx proxying it at all?

303 cache is preventing headers from being sent

I am configuring a odoo server to block certain routes for people outside of some networks. I am using Nginx as a reverse proxy on this server.
My issue is with the route /web/session/lougout. When i add the two following blocks to my config, browsers start caching the 303 answer from the route and stop sending headers to the server. Since the headers are missing, it prevents the server from invalidating the session and leads to a bunch of issues.
location ~ ^/web/ {
add_header Content-Security-Policy upgrade-insecure-requests;
proxy_pass http://odoo-xxx-test;
proxy_buffering on;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
expires 864000;
allow *some ip* ;
allow *some ip* ;
allow *some ip* ;
deny all;
}
location ~ ^\/web\/(action\/|content\/|static\/|image\/|login|session\/|webclient\/) {
add_header Content-Security-Policy upgrade-insecure-requests;
proxy_pass http://odoo-xxx-test;
proxy_cache_valid 200 60m;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering on;
expires 864000;
}
From my understanding, the first location should deny access to all routes outside of the 3 allowed ips and the second should allow everyone outside of those 3 ips to access those 7 routes. I dont understand how those two block affect the caching of the /web/session/logout route, removing those two directives fixes the issues but this behavior is in the requirements for the projects.
Any help would be welcome!
Found the solution to my issue, turns out the expires directive was making the NGINX server cache the 303 response and serve it without contacting the server behind the proxy.
Removing the expires directive from both location fixed our issue.

Nginx: rewrite port in url from reverse proxie'd app

So I have set up a reverse proxy to tunnel my application.
Unfortunately the application thinks it is served via http and not https and gives out URLs with port 80.
How can I handle this in the nginx reverse proxy? (by rewriting maybe)
When I go on the page:
https://my.server.com
index.php loads, everything is okay
after clicking something I have a URL like this:
https://my.server.com:80/page/stuff/?redirect_to
which throws an error within the browser because my reverse proxy doesn't serve SSL on port 80.
How can I migitate this?
My current nginx ssl vhost for the site:
... ssl stuff ...
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
location / {
proxy_pass http://localhost:22228;
proxy_buffering off;
proxy_redirect off;
proxy_read_timeout 43800;
proxy_pass_request_headers on;
proxy_set_header Connection "Keep-Alive";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass_header Content-Type;
proxy_pass_header Content-Disposition;
proxy_pass_header Content-Length;
proxy_set_header X-Forwarded-Proto https;
}
(yes I know my request headers look like a christmas tree 🎄)
Also bonus points if you show where the documentation addressing this issue is and what the mechanism is called.
For rewriting response body you can use http_sub_module:
location / {
proxy_pass http://localhost:22228;
sub_filter_once off;
sub_filter_types text/css application/javascript; # in addition to text/html
sub_filter "//my.server.com:80/" "//my.server.com/";
}
Many people says (1, 2) that you need to disable compression when using sub_filter directive:
proxy_set_header Accept-Encoding "";
For me, it works fine without this line in config, but it can be a feature of OpenResty which I use instead of nginx.
If your app generates HTTP 30x redirects with explicit indication of domain:port, you can rewrite Location header value with the proxy_redirect directive:
proxy_redirect //my.server.com:80/ //my.server.com/;

NGINX internal redirect from uri path to JSF context root

I'm configuring a cloud server which use NGINX as reverse proxy to serve different applications on different URI (all the applications are on the same wildfly standalone instance).
To be more specific i've a JSF application with a contextroot, let's say, /jsfcontext and i've set up a NGINX location like /mypublicuri.
What happens is that when I navigate to https://myserver.com/mypublicuri/index.xhtml i receive the following error:
/mypublicuri/index.xhtml Not Found in ExternalContext as a Resource.
I'm pretty sure it's related to a missing internal redirect route or some kind of "hack" that i need to specify in order to make everything work but i'm a newbie in NGINX and I don't know how to properly set everything up.
Thanks for the help
Cheers
Read NGINX documentation but my lack of english knowledge makes difficoult to understand what should I have to do
My actual NGINX config
server {
server_name myserver.com www.myserver.com;
access_log /usr/share/logs/access.log;
error_log /usr/share/logs/error.log;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_intercept_errors on;
location /anotherworkingapp {
add_header Allow "GET, POST, HEAD, PUT, DELETE" always;
proxy_pass http://127.0.0.1:8080$request_uri;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /mypublicuri {
proxy_pass http://127.0.0.1:8080/jsfcontext$request_uri;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
}

Keycloak with Wildfly application behind a Nginx reverse proxy

AWS EC2 Ubuntu 18.04
Keycloak 5.0.0
Nginx 1.15.8
I am trying to place an application (not my development) based on the Wildfly with the Keycloak integration (openid-connect) and am aware of posts that relate to my task, but I believe my question has not been covered in those posts.
In my case everything works fine, an application and a keycloak server behind a Nginx reverse proxy. What I can't understand is that according to this Keycloak document it is necessary to make the following changes in the keycloak standalone.xml (in my case):
<http-listener name="default" socket-binding="http" proxy-address-forwarding="true" redirect-socket="proxy-https"/>
<socket-binding name="proxy-https" port="443"/>
If I understand it correctly, this setup assumes that an application sends an authentication request to http-listener and it is redirected to the proxy-https. It is not quite clear where the proxy is supposed to sent its proxy_pass.
But anyway, in my case, an application sends the authentication request the following way:
<realm>MyRealm</realm>
<resource>MyRealm</resource>
<public-client>true</public-client>
<auth-server-url>https://<host name>:8843/auth/</auth-server-url>
<ssl-required>external</ssl-required>
I have just changed https port in the Keycloak stanalone.xml to 8943 and assigned port 8843 to the Nginx server with the location /auth/, like in this fragment:
server {
listen 192.168.80.40:8843 ssl http2 default_server;
server_name <host name>;
location /auth/ {
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port 8843;
add_header Strict-Transport-Security "max-age=15552000";
proxy_set_header X-NginX-Proxy true;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass https://192.168.80.40:8943/auth/;
proxy_redirect off;
}
}
It works, but I am not quite sure if it is the right way to place a Keycloak server behind the Nginx reverse proxy, considering the above mentioned Keycloak article. It is basically a question not about something that doesn't work but rather why it works.
If some Keycloak experts can assure me that my setup is workable, I would very appreciate it.
My second question:
Is it possible to restrict an external access only to the application realm, if users decide to open:
https://<host name>:<port>/auth
I would like to block any external access to the master realm login screen.
When I am using /auth/realms/MyRealm/ in the Nginx location, it does prevent users from accessing the master realm login screen, but it shows just some ugly login screen for the application realm, which actually works, but looks unprofessional.
Thanks in advance.
UPDATE:
The only solution for my second question I have found so far:
location /auth/realms/master/ {
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port 8843;
add_header Strict-Transport-Security "max-age=15552000";
proxy_set_header X-NginX-Proxy true;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
add_header Pragma "no-cache";
proxy_pass https://192.168.80.40:8943/auth/realms/master/;
proxy_redirect off;
allow X.X.X.X;
deny all;
}
And similar for the root location:
location / {
*
*
*
proxy_pass https://192.168.80.40:8943$request_uri;
proxy_redirect off;
allow X.X.X.X;
deny all;
}
The location /auth/ is not changed.
https://<host name>:<port>/auth still opens "Welcome to Keycloak" screen but access to the "Administration Console" is forbidden. At least, I have now a normal login screen for the application realm and rogue Internet people are going to nowhere from that Welcome screen.
I still need help with my first question.

Resources