Modify request body before PROXY_PASS - nginx

I have nginx setup that passes all request to nodejs, however I want to modify request body in nginx before passing it to nodejs. Like if body has http://www.example.com then replace it with https://www.example.com
Here is my nginx configuration:
location / {
proxy_pass http://127.0.0.1:8008;
proxy_redirect off;
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 https ;
}

Related

nginx proxy_pass to https / image-server not working

I'm trying to proxy an image server imagekit.io so that all requests have same domain name.
Have tried multiple configurations in HTTPS nginx server (with self-signed certificate) and even in HTTP server.
Let's say the URL is https://ik.imagekit.io/hj8sm3kk7/brochures/92/1579/suzuki-gsx-r150-615123.pdf
With the below configuration, I'm trying to hit http://localhost.com:8800/brochures/92/1579/suzuki-gsx-r150-615123.pdf
server {
listen 8800;
server_name localhost.com;
location /brochures {
proxy_ignore_headers Set-Cookie;
proxy_set_header Host ik.imagekit.io;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Pragma no-cache;
proxy_set_header Accept $http_accept;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header Accept-Encoding $http_accept_encoding;
proxy_set_header Accept-Language $http_accept_language;
proxy_set_header sec-fetch-mode navigate;
proxy_set_header sec-fetch-site cross-site;
proxy_set_header sec-fetch-user ?1;
proxy_set_header :authority ik.imagekit.io;
proxy_set_header :method GET;
proxy_set_header :path $path;
proxy_set_header :scheme https;
proxy_set_header Upgrade-Insecure-Requests 1;
proxy_pass https://ik.imagekit.io/hj8sm3kk7/brochures;
}
}
This however works:
http://localhost.com:8800/financial-advisor/mfs-investment-management-review opens the same page as https://smartasset.com/financial-advisor/mfs-investment-management-review
location /financial-advisor {
proxy_ignore_headers Set-Cookie;
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_pass https://smartasset.com;
}
The real issue turned out to be an SSL problem with ik.imagekit.io, using http:// instead of https:// in the proxy_pass value helps.
Original (and wrong) answer I've given:
The first example requires a manipulation of the URL path. Consider a similar approach:
location ~ ^/(brochures/.*) {
# all the previous config you used should be added here
proxy_pass https://ik.imagekit.io/hj8sm3kk7/$1;
}
This will proxy the request to the proper URL path, which changes from the original request. $1 is the part of the request URL path that matches the first brackets (...).

RabbitMQ Management Over HTTPS and Nginx

I'm trying to access the RabbitMQ interface over HTTPS/SSL with nginx, and I can't figure out what I'm missing.
Here's my rabbitmq.conf file:
[
{ssl, [{versions, ['tlsv1.2', 'tlsv1.1']}]},
{rabbit, [
{reverse_dns_lookups, true},
{hipe_compile, true},
{tcp_listeners, [5672]},
{ssl_listeners, [5671]},
{ssl_options, [
{cacertfile, "/etc/ssl/certs/CA.pem"},
{certfile, "/etc/nginx/ssl/my_domain.crt"},
{keyfile, "/etc/nginx/ssl/my_domain.key"},
{versions, ['tlsv1.2', 'tlsv1.1']}
]}
]
},
{rabbitmq_management, [
{listener, [
{port, 15671},
{ssl, true},
{ssl_opts, [
{cacertfile, "/etc/ssl/certs/CA.pem"},
{certfile, "/etc/nginx/ssl/my_domain.crt"},
{keyfile, "/etc/nginx/ssl/my_domain.key"},
{versions, ['tlsv1.2', 'tlsv1.1']}
]}
]}
]}
].
All works ok when I restart rabbitmq-server
My nginx file looks like this:
location /rabbitmq/ {
if ($request_uri ~* "/rabbitmq/(.*)") {
proxy_pass https://example.com:15671/$1;
}
}
Now, I'm guessing there's something with the ngnix config not being able to resolve the HTTPS URL, as I'm getting 504 timeout errors when trying to browse:
https://example.com/rabbitmq/
Obviously, this is not the correct FQDN, but the SSL cert works fine without the /rabbitmq/
Has anyone been able to use the RabbitMQ Management web interface on an external connection over a FQDN and HTTPS?
Do I need to create a new "server" block in nginx config dedicated to the 15671 port?
Any help would be much appreciated!
I ended up reverting back to the default rabbitmq.config file, then modified my nginx config block to the below, based on another stackoverflow answer that I can't find right now.
location ~* /rabbitmq/api/(.*?)/(.*) {
proxy_pass http://127.0.0.1:15672/api/$1/%2F/$2?$query_string;
proxy_buffering off;
proxy_set_header Host $http_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;
}
location ~* /rabbitmq/(.*) {
rewrite ^/rabbitmq/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:15672;
proxy_buffering off;
proxy_set_header Host $http_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;
}
Also, I had browser caching for JS files, which was causing issues and have disabled that.
I will try to re-enable SSL piece-by-piece but do have the example URL working for now:
https://example.com/rabbitmq/
I tried the following nginx.conf
location /rabbitmq/ {
proxy_pass http://rabbitmq/;
proxy_buffering off;
proxy_set_header Host $http_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;
}
However I couldn't get the details for a queue or exchange. I got 404 errors for api calls.
And there was a %2F in the url, it's url encoded /.
We need to keep the %2F in the API url and pass it to rabbitmq.
The following link describes how to keep the encoded url part and rewrite it.
Nginx pass_proxy subdirectory without url decoding
So my solution is:
location /rabbitmq/api/ {
rewrite ^ $request_uri;
rewrite ^/rabbitmq/api/(.*) /api/$1 break;
return 400;
proxy_pass http://rabbitmq$uri;
proxy_buffering off;
proxy_set_header Host $http_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;
}
location /rabbitmq/ {
proxy_pass http://rabbitmq/;
proxy_buffering off;
proxy_set_header Host $http_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;
}
This did the trick for me
location /rabbitmq {
proxy_pass http://localhost:15672/;
rewrite ^/rabbitmq/(.*)$ /$1 break;
}
I didn't have to use any other directives.
In case someone is looking for the solution for the Apache (2.4):
<VirtualHost *:443>
ServerName rabbitmq.your-domain.com
AllowEncodedSlashes NoDecode
... // rest of the settings
<Location "/">
Require all granted
ProxyPass http://localhost:15672/
ProxyPassReverse http://localhost:15672/
</Location>
<Location "/api">
Require all granted
ProxyPass http://localhost:15672/api nocanon
</Location>
</VirtualHost>
In fact, 2 elements are very important:
The 'AllowEncodedSlashes NoDecode' on VirtualHost level
The 'nocanon' parameter for ProxyPass on "/api" location
This worked for me and I did not need any other header settings. This is a variation on the answer by #user3142747:
location /rabbitmq/ {
# Strip off the "/rabbitmq" prefix
rewrite ^/rabbitmq/(.*) /$1 break;
# Do NOT suffix proxy_pass path with a trailing "/". This allows NGINX to pass the client request completely unchanged.
# - see http://mailman.nginx.org/pipermail/nginx/2009-November/016577.html
proxy_pass $scheme://localhost:15672;
}

Same location with different proxy urls nginx

We am trying to get nexus via nginx reverse proxy working as a private registry for docker images. We are able to perform all the operations such as pull,search and tag but not able to push to nexus registry .
Below is the nginx configuration under location block.
location ~ ^/(v1|v2)/
{
proxy_set_header Host $http_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 "https";
proxy_pass http://box.company.net:5555;
proxy_read_timeout 90;
}
We are able to search and pull images.
But with push we face below error.
x.x.x.x - admin [23/Jun/2017:14:32:34 +0800] "POST /v2/fedora/apache/blobs/uploads/?from=fedora%2Fssh&mount=sha256%3Aacd6cf67daf4cd1fcff55ece5a906a45e1569b81271b80136a1f5fecfa4546ed HTTP/1.1" 404 717 "-" "docker/1.12.6 go/go1.7.4 kernel/3.10.0-514.10.2.el7.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/1.12.6 \x5C(linux\x5C))"
when we try with proxy _pass url as http://box.company.net:4444, we are able to push but cant pull the images .
Is it possible in nginx to pass two different proxy_pass urls under the same location but for different request methods . Any help would be really great ..Thanks
#sempasha : Thanks for you help . It working for me just with a minor tweak .
Below is the location block added to get it working.
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if ($request_method !~* GET) {
proxy_pass http://box.company.net:4444;
}
if ($request_method = GET) {
proxy_pass http://box.company.net:5555;
}
proxy_read_timeout 90;
}
You can use if or map directives to select backend port.
Note, that If is Evil, not in you case of course.
location ~ ^/(v1|v2)/
{
set $port 5555;
if ($request_method = POST) {
set $port 4444;
}
proxy_set_header Host $http_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 "https";
proxy_pass http://box.company.net:$port;
proxy_read_timeout 90;
}

Rewrite a subdomain to a backend proxy whith nginx

if have a subdomain on my nginx webserver configuration: sub.mydomain.com
and i have a backend server which listen on port 5000: http://127.0.0.1:5000
is it possible to pass all subdomain calls to the backend?
Like: https://sub.mydomain.com/list to http://127.0.0.1:5000/sub/list
This should work with all methods: POST, PUT, GET, DELETE
UPDATE:
when i call my server: https://mysubdomain.mydomain.com
with the following configuration:
upstream http_backend {
server 127.0.0.1:5000;
}
server_name ~^(?<subdomain>[^.]+)\.mydomain\.com;
This does not work (error: 404):
location / {
proxy_pass http://http_backend/$subdomain/;
proxy_redirect off;
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 https;
}
This works fine:
location / {
proxy_pass http://http_backend/mysubdomain/;
proxy_redirect off;
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 https;
}
When i log the $subdomain variable in the access_log, it seems to be correct.
nginx version: nginx/1.9.15
To pass all subdomains you need to set it in server name by putting dot before domain.
server_name .mydomain.com;
Yes, you can use variables in proxy_pass. And you can extract part of domain using regexp server name.
server {
server_name ~^(?<sub>[^.]+)\.example\.com;
# now subdomain of example.com placed to $sub
# please, note, this rule do not work for http://example.com
location / {
proxy_pass http://127.0.0.1:5000/$sub/;
# Path part of proxy_par URI will replace path
# part of location directive (so / -> /$sub/, /xxxx/ -> /$sub/xxxx/)
}
}
Thats all :)
It seems nginx does not add the $uri to the proxy_pass if i use the $subdomain variable.
The following solution works:
location / {
proxy_pass http://http_backend/$subdomain/$uri;
proxy_redirect off;
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 https;
}

nginx redirect all http to https with exceptions

I would like to redirect all http traffic to https with a handful of exceptions. Anything with /exception/ in the url I would like to keep on http.
Have tried the following suggested by Redirect all http to https in nginx, except one file
but it's not working. The /exception/ urls will be passed from nginx to apache for some php processing in a laravel framework but that shouldn't matter.
Any suggestions for improvement much appreciated!
server {
listen 127.0.0.1:80;
location / {
proxy_pass http://127.0.0.1:7080;
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-Accel-Internal /internal-nginx-static-location;
access_log off;
}
location /exception/ {
# empty block do nothing
# I've also tried adding "break;" here
}
return 301 https://localhost$request_uri;
}
Nginx finds the longest matching location and processes it first, but your return at the end of the server block was being processed regardless. This will redirect everything but /exception/ which is passed upstream.
server {
listen 127.0.0.1:80;
access_log off;
location / {
return 301 https://localhost$request_uri;
}
location /exception/ {
proxy_pass http://127.0.0.1:7080;
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-Accel-Internal /internal-nginx-static-location;
}
}

Resources