Configure NextCloud & Nginx Reverse Port Forward - Login Authentication Error - nginx

I have set up an nginx reverse proxy server on my web server, which is receiving SSL traffic, and reverse proxying it to port 8080 on my web server, which is an exposed port running the nextcloud docker image. I am able to log in from a desktop web browser, but I am not able to log in from my iPhone. When I log in from the app, I receive error message "Access Forbidden, Invalid Request." This Github issue identifies the issue as auth headers being removed from the request, though the solution it gives is for Apache, not for Nginx. I'm really not familiar with authorization headers. How would I modify my Nginx server directive to take care of the issue?
Current setup
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name cloud.foo.com;
ssl_certificate /etc/letsencrypt/live/cloud.foo.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/cloud.foo.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
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
}

You may need to add a setting to explicitly pass the Authorization header in the response from the proxied server.
For example:
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass_header Authorization;
}
Based on the reverse proxy settings I've seen for another authenticated service, it's probable that by default, Nginx does not pass the Authorization header from the response of a proxied server to a client. Although this is not listed in the documentation, it is probably necessary to avoid interference with the authentication modules.

Related

nginx reverse proxy for application

I use nginx for reverse proxy with domain name. I've some application publish on IIS and i want to proxy different location name for each application.
For example;
Domain name on nginx :
example.com.tr
application end points for app:
1.1.1.1:10
1.1.1.2:10
upstream for app in nginx.conf:
upstream app_1 {
least_conn;
server 1.1.1.1:10;
server 1.1.1.2:10;
}
server {
listen 443 ssl;
server_name example.com.tr;
proxy_set_header X-Forwarded-Port 443;
ssl_certificate /etc/cert.crt;
ssl_certificate_key /etc/cert.key;
location /app_1/ {
proxy_pass http://app_1/;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-REAL-SCHEME $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
access_log /etc/nginx/log/access.log;
error_log /etc/nginx/log/error.log;
}
}
When I try to access example.com.tr/app_1/ , I can access application but not all data.
I inspected this site and so many requests of application were failed.
All requests sended to example.com.tr/uri instead of example.com.tr/app_1/uri. How can I fix this ?
thanks,
You need a transparent path proxy setup. Means NGINX should use the requested URI without removing the matched location from it.
proxy_pass http://app_1;
Remove the tailing slash to tell NGINX not to do so. Using an upstream definition is great but make sure you apply keepalive.

Block incoming request when SSL verification is disabled

I have my REST APIs configured to work over https using nginx( java APIs deployed in tomcat and nginx is configured for DNS mapping). Our testing team has managed to access the APIs using burp tool (I assume it allows them to access with SSL verification disabled) and they were able to alter the API response before the client receives it. My nginx server is configured to work on SSL with proxy forward setup for http to https. How can I block the API requests which has SSL verification disabled, so that I can stop them altering the response? Below is my nginx config.
upstream mlljava{
server 172.31.5.222:8090;
}
server {
listen 443 ssl;
server_name mllwebapi.xyz.in www.mllwebapi.xyz.in;
underscores_in_headers on;
client_max_body_size 10M;
ssl_protocols TLSv1.3;
ssl_certificate /home/ubuntu/175e9.crt;
ssl_certificate_key /home/ubuntu/key.key;
location / {
proxy_pass http://mlljava/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
proxy_pass_request_headers on;
}
}
Does adding this to server configuration helps?
# force https-redirects
if ($scheme = http) {
return 401 https://$server_name$request_uri;
Configure Nginx SSL + force HTTP to redirect to HTTPS + force www to non-www on Serverpilot free plan (Using Nginx configuration file only)
Nginx: force SSL on one path, non-SSL on others

Howto block nginx web site access if browsers have no ssl certificate

I am a newb and i installed jupyterhub with nginx reverse proxy on my ubuntu 18.04 server. I built my own root CA and self signed certificate with openssl. Https connections works very well if my rootCA is installed on my others computers. I want to block access for the computers who don't have my rootCA.
the file /etc/nginx/nginx.conf is untouched and my config file /etc/nginx/sites-available/jupyter.conf is:
# top-level http config for websocket headers If Upgrade is defined,
# Connection = upgrade If Upgrade is empty, Connection = close
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP server to redirect all 80 traffic to SSL/HTTPS
server {
listen 80;
server_name 192.168.4.70 mlserver.net localhost;
# Tell all requests to port 80 to be 302 redirected to HTTPS
return 302 https://$host$request_uri;
}
# HTTPS server to handle JupyterHub
server {
listen 443;
ssl on;
server_name 192.168.4.70 mlserver.net localhost;
ssl_certificate /etc/ssl/certs/mlserver.net.crt;
ssl_certificate_key /etc/ssl/private/mlserver.net.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
#ssl_stapling on;
# Managing literal requests to the JupyterHub front end
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# websocket headers
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Scheme $scheme;
proxy_buffering off;
}
}
How can i edit this file to block access for computers who dont have certificate ?
What nginx directive add ?
Thanx.
I want to block access for the computers who don't have my rootCA.
This is not possible. The server has no information if the client has successfully validated the server certificate (i.e. clients which have the rootCA) or if a client simply skipped certificate validation (clients which don't have rootCA).
One could try to add a HSTS header so that browsers will not simply allow to ignore certificate problems. But this can also be bypassed on the client side without the server noticing, it just makes it a bit harder.
If you want to control who can access the notebook you would need proper authentication of the clients instead. Knowledge of the rootCA is not client authentication.

nginx reverse proxy redirects to http instead of https

Having the following setup: NGINX (Port 443) > Jetty (Port 9090) > Spring Controller
For simplifying the problem I use the following files:
/main.html containing an iframe calling the spring controller /test
spring controller /test doing return "redirect:/iframe.html";
/iframe.html with simple text saying "This is IFrame"
With HTTP there is no problem but after switching the NGINX configuration to HTTPS I get the following error in the browser and the iframe is not displayed:
main.html:7 Mixed Content: The page at 'https://dev/main.html'
was loaded over HTTPS, but requested an insecure frame
'http://dev/iframe.html'. This request has been blocked; the
content must be served over HTTPS.
So the controller redirects to http instead of https, this is my NGINX configuration which from my understanding should let the jetty/controller know that it is running on https:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name dev;
ssl on;
ssl_certificate ...;
ssl_certificate_key ...;
location / {
proxy_set_header Host $host;
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-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_ssl_name $host;
proxy_ssl_server_name on;
proxy_pass http://127.0.0.1:9090;
}
}
You need to do a few things ...
On the nginx side, Use the Standard Forwarded header from RFC7239, not the X-Forwarded-* headers. This is because the X-Forwarded-* headers are not a standard and conflict in meaning across their usage. (in your example, you made the port separate, which now conflicts with the "host", "proto", and "for" usages for the port as well)
On the Jetty side, enable the ForwardedRequestCustomizer. This will look for the various Forwarding headers and update the request's authority, protos, and "is secure" flags appropriately.
On the Jetty side, configure the HttpConfiguration.securePort to be the port for your SSL/TLS on your nginx, not the port that Jetty itself uses.

Nginx Serving Cert For Site Even Though SSL Not On

I have been troubleshooting an obscure nginx problem where we have a site correctly serving a cert and establishing a ssl connection on port 443 even though ssl is not explicitly turned on for the port. Below you can see the configuration for the site, which is listening on port 443 but not using the ssl directive.
server {
listen 443;
port_in_redirect off;
server_name xyz.abcd.com;
# websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 1m;
proxy_set_header X-Request-Id $request_id;
proxy_set_header X-Request-Start $msec;
proxy_set_header X-Forwarded-Proto "https";
proxy_set_header Host $host;
location / {
proxy_pass http://xyz-svc;
}
}
Furthermore, our nginx.conf does not explicitly mention port 443 or ssl, but it does include the path to the cert for abcd.com:
http {
..
ssl_certificate /etc/ssl/certs/abcd.pem;
ssl_certificate_key /etc/ssl/private/abcd.key;
..
}
Lastly, if we go to http://abcd.com:443, nginx throws an error saying "The plain HTTP request was sent to HTTPS port." So, clearly it is interpreting port 443 for this site as a ssl port even though we do not explicitly define that in our configuration. This behavior is true for both nginx version 1.7.5 and nginx version 1.13.8.
What are possible reasons nginx would correctly establish a ssl connection on port 443 for a site with the appropriate cert if it is never defined in the configuration to do so?

Resources