Nginx Passing to Servers Based on URI - nginx

I have been setting up Nginx on my router, and creating subdomains (with CNAMES) to access various components within my network. It has mostly been fairly easy, until I have come to the cameras which are proving to be a problem.
They are basic IP cameras and to date I had opened each one on a different port. They have basic authentication, and once that has been entered I am presented with a live view.
Like all the other components I have set up so far (and they all work) I started by configuring one:
server {
listen 80;
server_name cam.example.co.uk;
location / {
proxy_pass http://192.168.1.101:2001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Hitting cam.example.co.uk from either LAN or WAN gives me a username and password prompt and then the live view loads.
Since there are 9 cameras, I thought it would be a good idea to use /1, /2, /3 etc. at the end to direct me to each one rather can creating subdomains.
server {
listen 80;
server_name cam.example.co.uk;
location /1/ {
proxy_pass http://192.168.1.101:2001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /2/ {
proxy_pass http://192.168.1.102:2002;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
With that I got 404 not found errors, and messages in the logs such as:
"/usr/html/new/index.htm" failed (2: No such file or directory)
Some Googling later I found out that I may need to specify the URI as well in the proxy_pass line, so I changed them to look like:
proxy_pass http://192.168.1.102:2002/new/index.htm;
This then results in the username and password prompt, but when the credentials are entered, all I am left with is a blank screen. It worked fine when it was just location / so no idea why nothing is showing now.
I have a feeling that it is putting the URI in somewhere, but I have no idea where/why or what to do about it.
EDIT
Been Googling and trying various things:
location /1 {
resolver 127.0.0.1;
set $backend "http://192.168.1.101:2001/new/index.htm";
proxy_pass $backend;
proxy_buffering on;
proxy_redirect http://192.168.1.101:2001/new/index.htm http://cam.example.co.uk/1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Then going to this in the browser cams.example.co.uk/1 brings up the username and password prompt, but then displays a blank page. Looking at the Chrome developer tools I can see unexpected token errors, and it looks like it isn't loading the .js files properly.

If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive.
Try this:
server {
listen 80;
server_name cam.example.co.uk;
location /1/ {
proxy_pass http://192.168.1.101:2001/;
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_redirect http://192.168.1.101:2001/ http://cam.example.co.uk/1/;
}
location /2/ {
proxy_pass http://192.168.1.102:2002/;
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_redirect http://192.168.1.101:2002/ http://cam.example.co.uk/2/;
}
}
Source: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

Related

Allow access service / proxy_pass only from a certain URL in nginx

I have a website running at https://mywebsite.com. I also install another application (Minio) on the same server running at port 9000.
NOTE: When access Minio via myServerIP:9000, it automatically goes to myServerIP:9000/minio/. If I haven't logged in yet, then I will be redirected to myServerIP:9000/minio/login. If I go to myServerIP:9000/minio/anyRandomPath, I will also be redirected to the login page or another default page (if I have already logged in)
Now I want to access Minio via address https://mywebsite.com/files, so I setup my nginx as below
location /files/ {
proxy_pass http://127.0.0.1:9000/minio/;
proxy_set_header URI_REQUEST_ORIGIN $request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
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_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Proto $scheme;
}
This doesn't work (it shows a blank page with title "Minio login"). When I check the browser's console, it says there's an error message Uncaught SyntaxError: Unexpected token < with a link to https://mywebsite.com/minio/index_bundle_xxx.js. So I try adding another location block in my nginx.conf:
location /minio/ {
proxy_pass http://127.0.0.1:9000/minio/;
proxy_set_header URI_REQUEST_ORIGIN $request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
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_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Proto $scheme;
After that, it works as expected. But the problem is that now I can access Minio via both /minio and /files
Now how can I block direct access to Minio via https://mywebsite.com/minio?
I tried some workaround like adding below location blocks:
location =/minio/ {
return 404;
}
location =/minio/login/ {
return 404;
}
But this is clearly a bad way and also not efficient, since I can just go to mywebsite.com/minio/typeAnythingHere to be redirected to the login page.

Can't seem to get nginx to use cookies when loading site as a proxy

Trying to get nginx to use cookies when using proxy_pass, but all of the configurations I've tried so far don't seem to pass them. Pretty much at a loss as to what I'm doing wrong.
location / {
proxy_set_header Accept-Encoding "";
proxy_pass https://example.com/;
proxy_set_header Host example.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
proxy_pass_request_headers on;
proxy_cookie_domain proxy.net example.com;
}
Is the most recent block I've tried, but still no go

Using nginx as a reverse proxy to IIS server

I have multiple ASP.NET applications running on a single IIS server with different ports for each application.
I have installed nginx on the same server so that my clients can access all my applications only using port 80.
Nginx is running all right on port 80. My individual ASP.NET applications are also up and running.
I made these changes in nginx conf file
location /students/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:84;
}
location /registration/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:82;
}
Then I restarted nginx and typed the url http://127.0.0.1/students/ in my browser. Nginx served a 404 page.
I made no other changes to the conf file.
What I am doing wrong?
I believe that the problem you are having is related to the start of the URL path. Does the URL http://120.0.0.1:84/students/ return the page, or a 404? If you are expecting to go to http://127.0.0.1:80/students/ and see the page at http://127.0.0.1/, you will find that nginx does not transform the path for you with this configuration. Rather, it looks for exactly the same path at the proxied server.
You need to put the / on the end of the URL in the proxy_pass directive:
location /students/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:84/;
}
This is a subtle but important gotcha in nginx configs! If you don't include the backslash, http://127.0.0.1:84 will be treated as a server location. If you do have the backslash, it will be regarded as a URL, and it will replace everything in the proxy URL up to the 'location' part.
If you want to transform IIS 127.0.0.1:84/students to nginx 127.0.0.1/students . try below code..
location /students {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:84/students;
}
location /registration {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:82/registration;
}
Try to use this directive
upstream http://localhost {
server 127.0.0.1:84;
}
and the same block for 2nd

nginx rewrite rule for redirection

I have two apps running on host1:7000 and host2:7000. I am fronting the two hosts by an nginx reverse proxy, where I want mydomain.com/admin to point to host1:7000/portal and mydomain.com/user to host2:7000/portal.
I have written the following config
listen 80;
server_name mydomain.com *.mydomain.com;
location ~ ^/admin/(.*)$ {
proxy_pass $scheme://<IP-ADDRESS>/$1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
}
I can get to mydomain.com/admin to be redirected to host1:7000/portal but when the app redirects from host1:7000/portal on to host1:7000/login via relative path, in the browser I see mydomain.com/login. What do I need to do to get the second redirect go mydomain/admin/login?
Why do people use regexps for no reason and have all kind of problems with it?…
location /admin/ {
proxy_pass http://host1:7000/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
}
This will automatically strip /admin/ from proxied request and prepend it in Location header (which is used in redirect).
See proxy_pass and proxy_redirect docs.

Conditional Location routing - nginx

Issue:
I have two applications served by one nginx 1.5.5 webserver on one domain, www.domain.com.
Because they both listen on the same locations I added a header of APP = ONE or TWO which I set when the application is first called. Example below.
location ^/APPONE {
proxy_pass http://APPONE;
add_header APP ONE;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ^/APPTWO {
proxy_pass http://APPTWO;
add_header APP TWO;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Due to poor application design, the applications both request the below locations not using the application name as a docroot. Like the example below.
location ~ ^/(framerwork1/|framerwork2/|framerwork3/) {
proxy_pass http://APPONE;
add_header APP ONE;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ ^/(framerwork1/|framerwork2/|framerwork3/) {
proxy_pass http://APPTWO;
add_header APP TWO;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
So, I added the APP ONE or TWO header to separate the two, but my if statements to proxy them based on the header is not being accepted by Nginx. Example Below.
if ($http_host ~ 'APP=ONE') {
location ~ ^/(framerwork1/|framerwork2/|framerwork3/) {
proxy_pass http://APPONE;
add_header APP ONE;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
if ($http_host ~ 'APP=TWO') {
location ~ ^/(framerwork1/|framerwork2/|framerwork3/) {
proxy_pass http://APPTWO;
add_header APP TWO;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Question: How can I proxy these two application successfully based on the header? Please note, I am unable to use a different server block or domain. They must be the same.
Thanks in advance.
Ok, so a request is coming in to www.domain.com/APPONE . You don't say exactly what is being requested through the URL www.domain.com/framerwork1/ but lets imagine it's an image that is required by the page served at /APPONE as that is simple to understand.
When you are setting the header through 'add_header' it is being set in the second array in "Client" -> Nginx -> PHP Proxy.
When the client then makes the request to the image at www.domain.com/framerwork1/ it has no idea that you are hoping to have a header set to be able to determine if the image was requested by APPONE, or something else.
Even if you set the header on the response for www.domain.com/APPONE clients do not blindly echo headers sent to them back to server for subsequent requests.
Or to put it bluntly, I think you've misunderstood where the headers are being passed, and that there isn't really a way to determine what application is making a request to the /framerwork1/ URL like that. You have to do this either via separate domain names (or sub-domain) or by doing it inside your application with things like looking at which application the user is logged into.

Resources