I need to reverse proxy to an Apache server running on the localhost. The problem is that Apache redirects requests to directories without a trailing forward slash, to the directory with a trailing forward slash, as part of its DirectoryRewrite directive. The below nginx setup works fine when you go to https://myhost/sw/myapp/ but if you forget the trailing forward slash you end up being redirected to http://myhost:8080/sw/myapp. Short of disabling the Apache DirectoryRewrite directive what can I do to make sure that the / is always added to the end of any request so that Apache does not redirect?
server {
client_max_body_size 10240M;
listen 443 ssl;
server_name "";
ssl_certificate ../ssl/server.crt;
ssl_certificate_key ../ssl/server.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location /sw {
proxy_pass http://127.0.0.1:8080/sw;
proxy_redirect ~^http://127.0.0.1:8080/sw/([^.]*[^/])$ https://$host/sw/$1/;
proxy_redirect http://127.0.0.1:8080/ https://$host/;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_buffering off;
proxy_set_header HOST $host;
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
error_page 301 302 303 = #handle_redirect;
}
If the upstream server is redirecting to http://example.com:8080/ (rather than http://127.0.0.1:8080/) you will need to change or add another proxy_redirect statement. See this document for details.
For example:
proxy_redirect http://example.com:8080/ https://example.com/;
Or as you stated in comments:
proxy_redirect http://$host:8080/ https://$host/;
The proxy_redirect values need to exactly match the beginning of the Location: header in the 3xx response. You can use curl -I to identify the exact contents of that response header.
Related
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!
I have a problem with nginx and proxy_pass. I try to secure connection to old server without option to upgrade apache there. I can't establish there ssl connection with tls 1.2. So i Tried to secure it by reverse proxy in nginx with some success. when i open website like http://example.com or https://example.com connection is secure and it works well. But there are other sites whitch have links like https://example.com/login https://example.com/investitions (basicly every uri example.com/foo/bar/ ect.)and those connections are insecure. my nginx config looks like this:
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate ssl.crt;
ssl_certificate_key ssl.key;
ssl_client_certificate ca.crt;
proxy_ssl_protocols TLSv1.2;
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_session_reuse on;
location / {
proxy_set_header X-Scheme https;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr
proxy_pass http://baza.example.com/;
}
Please help me.
I've been trying to redirect traffic from https://server:443 to internally http://server:8088 using NGINX as a reverse proxy, I can see my service on 8088 is running since I can access to it, by the time I try to access it from https and port 443 it gives me a 502 bad gateway error. The service Im running is Apache Superset.
I have already created my cert.pem and key.pem files. Already tried several combinations on /etc/nginx/conf.d/default.conf on the location section but no luck so far.
server {
listen 443 http2 ssl;
server_name localhost;
ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/key.pem;
location / {
add_header Front-End-Https on;
add_header Cache-Control "public, must-revalidate";
add_header Strict-Transport-Security "max-age=2592000; includeSubdomains";
proxy_pass_header Authorization;
proxy_pass http://localhost:8088;
proxy_redirect off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
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 Connection "";
}
}
I'd expect to hit https://server:443 and it will display my service which is running at http://server:8088.
I have a Linux box running Ubuntu 14.04 with about 50gb of memory.
I've got a 5 or 6 Ruby-on-Rails web applications, each with a Unicorn App server, all served by an Nginx reverse proxy server.
Each app is hosted in a sub-directory.
eg:
www.webserver.com/app1
www.webserver.com/app2
Each app gets maybe 50-100 requests per day. They are all little apps to facilitate business processes at my firm.
My Nginx config file looks something like this:
upstream app1 {
#path to Unicorn SOCK file;
}
upstream app2 {
#path to Unicorn SOCK file;
}
upstream app3 {
#path to Unicorn SOCK file;
}
# ...several more apps
server {
listen 443 ssl;
access_log #path;
error_log #path;
ssl_certificate #path;
ssl_certificate_key #path;
add_header X-UA-Compatible "IE=Edge,chrome=1";
root /srv/apps/app1/public;
location /app1 {
proxy_pass http://app1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
location /app2 {
proxy_pass http://app2;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
location /app3 {
proxy_pass http://app3;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
# ...several more apps
}
This setup has worked without issue for a year or so, but I have this nagging feeling I'm doing this all wrong....
Am I going to run into problems if I keep adding apps? Is there a better way to do this?
Update:
By "problems," I mean:
static resource path collisions?
memory issues? namely, using more than I need to accomplish same behavior?
And by "a better way to do this," I mean:
other than sending requests to the relevant unicorn server by parsing out the name of the sub-directory in the URL
should I be using a single Nginx reverse proxy to serve multiple apps?
For the same configuration into differents apps, you can use include directive.
Example, create file named /etc/nginx/global_proxy.conf with this content :
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
And in nginx.conf your section /appX :
location /appX {
proxy_pass http://appX;
include /etc/nginx/global_proxy.conf;
}
And to increase your security, i recommend you adding dhparam, and add this to SSL configuration :
# SSL :
# drop SSLv3 (POODLE vulnerability)
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# Recommanded ciphers
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
# Diffie–Hellman key exchange (D–H)
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# config to enable HSTS(HTTP Strict Transport Security)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
# force timeouts if one of backend is died
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
To generate dhparam.pem file :
openssl dhparam -out dhparam.pem 4096
I have a cluster glassfish instance running in Ubuntu 12.04 server with nginx as the front-end.
I have configured glassfish upstream in nginx conf file and proxy params are all set.
nginx.conf
glassfish_custer ( upstream name )
Now the problem is,
I added a file realm in glassfish with username and password entries to enable basic authentication for one of my applications.
I added necessary login config params in web.xml file, bundled war and deployed in glassfish server and when I fire url,
http://domain.com/application
It falls in redirect loop
https://domain.com/application
It happens only when I enable basic authentication. If I switch off, everything is working as expected.
I think I need to set some proxy header params and change auth settings in glassfish admin console for http listener ?
If anyone experienced this issue before, Please let me know....
In short, How to make basic authentication works in nginx load balancer with glassfish as the upstream
UPDATE 1:
nginx.conf
## http redirects to https ##
server {
#listen [::]:80;
listen 80;
server_name domain.com www.domain.com;
location / {
try_files $uri $uri/ #backend;
}
location #backend {
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header x-forwarded-for $remote_addr;
proxy_pass http://glassfish_servers;
proxy_intercept_errors on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
# Strict Transport Security
# add_header Strict-Transport-Security max-age=2592000;
# rewrite ^/.*$ https://$host$request_uri? permanent;
}
server {
listen 443 ssl;
#listen [::]:443 ssl;
server_name domain.com www.domain.com;
location / {
try_files $uri $uri/ #backend;
}
## default location ##
location #backend {
proxy_buffering off;
proxy_pass http://glassfish_servers;
proxy_intercept_errors on;
#proxy_http_version 1.1;
#proxy_set_header Connection "";
# force timeouts if the backend dies
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
# set headers
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
#proxy_redirect off;
}
ssl_certificate /etc/nginx/ssl/ssl-bundle.crt;
ssl_certificate_key /etc/nginx/ssl/domain_com.key;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!$
}
Answering my own question.
Having this xml configuration in web.xml was the root cause of the redirection loop.
Since I added "CONFIDENTIAL" as the authority value, http request were getting redirected to https when request hit backend glassfish instance.
I changed this value to "NONE" and everything worked like charm.
<security-constraint>
<web-resource-collection>
<web-resource-name>wholesale</web-resource-name>
<url-pattern>/acme/wholesale/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>PARTNER</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Make the following changes
Change <transport-guarantee>CONFIDENTIAL</transport-guarantee>
to
<transport-guarantee>NONE</transport-guarantee>
Also, make sure to set proper proxy header values in nginx conf file (or) if you configured sites conf files separately in sites-available folder, pls add the following proxy headers
proxy_set_header x-forwarded-for $remote_addr;
proxy_intercept_errors on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;