web proxy to URL in cookie value - apache

I want to config reverse proxy server to be able to proxy client for a new server which created specifically for him.
So let say, client A logged in http://server.com , and has a cookie proxy_url=http://ec2-2323A.server.com so this solution is proxy him to this server, while he see only http://server.com in the main page.
I tried to do it with nginx reading this Nginx redirect if cookie present
but get some silly errors,
and my custom configuration seems not working
location / {
set $upstream 127.0.0.1:8080/;
if ($http_cookie ~* "proxy_url=([^;]+)(?:;|$)") {
set $upstream $1;
}
proxy_pass $upstream;
...
Any simple solution or other servers?

Related

Nginx -> Apache 2 authentication -> return to Nginix

We have a nginx and an apache2 server.
Apache2 is configured to manage Kerberos (Active Directory) authentication.
We have a website managed by nginx with a reserved area.
I would know if this is possible:
the user goes to main site managed by nginx
from main site, there is a link to "/login" mapped to apache2:
location /login/ {
proxy_pass http://apache2server/testlogin;
}
when the login is successful, apache2 is configured to go to another nginx webpage, using proxypass too:
ProxyPass /testlogin http://nginxserver/logindone.php
ProxyPassReverse /testlogin http://nginxserver/logindone.php
I wonder if this is the right solution to the problem.
The best way you can implement an external authentication to your NGiNX website is using auth_request directive.
Basically, you can protect any request doing a subrequest to any external web server. The subrequest must return HTTP code 2XX to allow proceeding to the content, and any other HTTP code returned will deny access.
To accomplish that, be sure you've NGiNX with auth_request enabled (compiled with --with-http_auth_request_module). To check that, use the following command at shell:
nginx -V 2>&1 | grep "http_auth_request_module"
Add the auth_request directive to the location you want to protect, specifying an internal location where the authorization subrequest will be forwarded to, using:
location /system/ {
auth_request /auth;
#...
}
So, when a request is made to /system/ location, the system will create a subrequest to /auth location. Now we need to create the internal /auth location. We can use the following example below:
location = /auth {
internal;
proxy_pass http://my.app.webserver/auth_endpoint;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
#...
}
Here, we created the /auth internal location. We used the internal directive to disable external NGiNX access (any external request to /auth will not be processed by this location). Also, we removed the request body content and set the request length to zero, removing any original request variable. We do a subrequest to http://my.app.webserver/auth_endpoint passing all requested cookies, so your backend application could determine if user has access or not.
If you need to know the original requested URI, you can add it on an extra HTTP header at subrequest adding:
proxy_set_header X-Original-URI $request_uri;
You can learn more about NGiNX auth_request directive here.

nginx proxy_reverse not setting cookie from upstream server to the client browser

I have an expressjs server to authenticate login requests from a front app built in svelte.
The front app is running on frontenddomain.com and the expressjs server is running on backenddomain.com
Here is my login post route that authenticate and set cookie:
app.post('/login', (req, res)=>{
// check db,find the user, write a jwt token and put it in a cookie to send it to the
// browser
res.cookie("accesstoken", accessToken)
res.cookie("refreshtoken", refreshtoken)
res.send(...)
}
This server code deployed to an ubuntu server with Nginx running as a proxy_reverse, here is my nginx block configuration:
server {
...
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_cookie_domain localhost .frontenddomain.com;
proxy_cookie_domain ~^(.+)(Domain=frontenddomain.com)(.+)$ "$1
Domain=.frontenddomain.com $3";
}
}
server {
listen 80;
listen [::]:80;
server_name backenddomain.com www.backenddomain.com;
root /var/www/backenddomain.com;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
When I run the server and svelte app (front app) using my local machine, everything works (customer provide credential, cookie is sent to client browser and upon inspecting google dev tools, I confirm that the cookies has been set correctly in the client's browser)
When I deploy my expressjs server to ubuntu (20.04) and use pm2 to run my server, it does start and I can view all my console.log. My front app runs and I go to my login page, enter credential and click submit, the app logs me in (because credentials are correct and user set to true on the front app localstorage) but NO COOKIES are set in the browser.
I read the nginx docs, I read material and posts from different sites on how to set Nginx proxy_reverse cookie domain but unable to fix the problem (the problem is cookies are not set in the browser, the server issues them) but my proxy server is not passing them to the browser.
These questions about proxy_reverse and cookies come up, the poster comeback and post vague answer to their own question and no other answers. It seems like there are not enough technical people out there with knowledge of this issue.
my location code has the proxy_cookie_domain localhost .frontenddomain.com;
How do you set nginx proxy_reverse to pass-set cookies to the browser passed on from upstream server?
So it wasn't related to the nginx block configuration but it was the cookie settings. For cross site cookies to work, it has to be set with sameSite : none (or strict) and secure flags. Make sure that your backend and front has to be using domains (ip is not allowed in the latest draft as of this writing)
You also need both front and back domains to be secured (https) with an ssl.
Your ufw on nginx needs to allow https.
Cookie settings:
res.cookie("name", "value", { sameSite: "none", secure : true })
restart your nginx after updating the server and your nginx conf sites-available
and it should work.

Nginx reverse proxy didnt load site correctly

I have an nginx configuration which listens to any subdomain *.mydomain.com,
and I want to use subdomain as variable, to proxy request to other site.
Here is my nginx configuration
server {
listen 80;
server_name "~^(?<subdomain>.*).mydomain.com";
location / {
resolver 1.1.1.1 1.0.0.1 ipv6=off;
proxy_pass http://hosting.mydomain.com/$subdomain/;
proxy_redirect off;
access_log /var/log/nginx/proxy.log;
}
}
As I request the site directly and it loads perfectly
Site placed on AWS S3, and bucket static website address cnamed to mydomain
However, when I try to access via user1.mydomain.com, the page didn't load images, and css
This is the same site
And in browser network panel shows
Difference between direct and proxy access
This issue is made, because I have many sites stored in S3 bucket and located in different folders (the folder name is used as subdomain).
And I want to use a single domain to access all of them via subdomains.
Thanks in advance
You forgot to proxy pass the URI, you're serving user1/index.html for every request, including for JS and CSS requests, it's why all of responses are the same size (2kb, the size of user1/index.html), and it's also why you're getting Uncaught SyntaxError: Unexpected token < in the first line of Enterprise_skeleton.bundle.js because it's returning an HTML document that starts with <!doctype html> instead of the actual JS bundle.
Change
location / {
proxy_pass http://hosting.mydomain.com/$subdomain/;
}
to
location / {
proxy_pass http://hosting.mydomain.com/$subdomain$uri;
}

Difference HTTP Redirect vs Reverse Proxy in NGINX

I'm having some difficulty in understanding the difference between reverse proxy (i.e. using proxy_pass directive with a given upstream server) and a 301 permanent redirect. How are they similar/different?
Reverse Proxy
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080;
}
server {
location / {
proxy_pass http://backend;
}
}
HHTP Redirect
Apache Example: http://www.inmotionhosting.com/support/website/htaccess/redirect-without-changing-url
NGINX example:
server {
listen 80;
server_name domain1.com;
return 301 $scheme://domain2.com$request_uri;
}
Hence, it seems that both approaches have no difference from an end-user perspective. I want to ensure efficient bandwidth usage, while utilizing SSL. Currently, the app server uses its own self-signed SSL certificate with Nginx. What is the recommended approach for redirecting users from a website hosted by a standard web hosting company (hostgator, godaddy, etc.) to a separate server app server?
With a redirect the server tells the client to look elsewhere for the resource. The client will be aware of this new location. The new location must be reachable from the client.
A reverse proxy instead forwards the request of the client to some other location itself and sends the response from this location back to the client. This means that the client is not aware of the new location and that the new location does not need to be directly reachable by the client.

Congiuring varnish with multiple domains+ssl Support

I am currently been involved in implementation of varnish with loadbalancer as back-end which shall forward traffic accordingly to multiple web server.
I am trying to achieve:
Public Traffic -> haproxy/DNS -> [Varnish (x2) / nginx(ssl) ] -> Loadbalancer -> Web server(x4)
I am able to configure Varnish , nginx as ssl/443 terminator for one domain.
(i.e if i point dns to varnish eth and access webserver serves the page)
varnish config
backend loadbalancer { .host = "xxx.xxx.xxx.xxx"; .port = "80" }
backend loadbalancer_ssl { .host = "xxx.xxx.xxx.xxx"; .port = "443"; }
sub vcl_recv {
# Set the director to cycle between web servers.
if (server.port == 443) {
set req.backend = loadbalancer_ssl;
}
else {
set req.backend = loadbalancer;
}
}
# And other vcl rules for security and other.
Nginx Config
location / {
# Pass the request on to Varnish.
proxy_pass http://127.0.0.1;
proxy_http_version 1.1;
#SSL certificate and config
=> How would i achieve configuring varnish as dns entry Point with ssl termination for multiple domains?
=> Is it possible to somehow configure varnish to accept all connections and bypass ssl to web server directly? (so that i don't have to worry about multiple interface for ssl support)
=> Or any standard approach to achieve with 443 terminator?
Note: why i am trying to achieve this: To create multiple layer for security and using existing hardware devices.
Already in place:
All server has (multiple interface for ssl using lightty).
Load balancer -> Hardware -> which will balance load between those web server.
Any experts sharing there view would be great.
I have decided to go with nginx as ssl terminator and achieving my question answers as below. I decided to update this, if anyone finds it useful.
From my above query:
How would i achieve configuring varnish as dns entry Point with ssl termination for multiple domains?
=> How it works is we need to have socket listening for https/ either nginx/pound/or anything else that can read ssl.
(which i was not quite convinced previously is to use this point as ssl terminator however i think i am fine as beyond that level now i have planned to make it internal zone.
=> Is it possible to somehow configure varnish to accept all connections and bypass ssl to webserver directly? (so that i dont have to worry about multiple interface for ssl support)
One can achieve this either with multiple interface (if you have multiple domains).
or, same interface if you are dealing with subdomains.
Or, you can create one secure page for all ssl required pages (depends upon trade-off)
=> Or any standard approach to achieve with 443 terminator?
I decided to go with nginx to use those feature that nginx provides (interms of security layer).