How to get TLS Session Id from a NGINX proxy? - node.js

In Node.js, headers are available in req.headers and I do get them in the http server.
I want to get the TLS session id set by the Nginx proxy where the setting, among other headers, in the relevant section, is:
location / {
...
proxy_set_header X-tlsSessionId $ssl_session_id;
...
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
expires off;
}
I am able to get access to other custom header but not to X-tlsSessionId when I try to access it as req.headers[x-tlssessionid]
I think that the lowercase is what I use to get access to custom headers but this one does not work.

Related

Forward client header, isp, geo to the server via proxy

My website has the proxy server created using express nodejs with nginx. The problem I am having, and cant seem to figure out is that I want to forward all the original users details and not show any proxy server details to the final destination server.
Scheme:
User -> my website -> proxy server -> final server to retrieve the data.
Now, no matter what configs I change in nginx, seems like the final server always identifies my proxy server isp, geo etc and not the users isp. If I access the final server directly without the proxy, the final server will show users isp.
How do I make sure that the proxy server is not being detected as "original" requester to the final server?
Some code for better understanding:
Nginx proxy:
location / {
proxy_pass http://x.x.x.x.x;
include proxy.conf;
}
nginxconfig:
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
# Proxy headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
Requests inside the node (to call final server) made like this (just a sample):
app.post('/getStats', (req, res) => {
const url = request('url')
req.pipe(url).pipe(res)
})

ServiceStack Secure cookie when HTTPS is terminated on the load balancer

In ServiceStack, the HostConfig flag UseSecureCookies = true will mark cookies as Secure when transmitted over HTTPS.
However, in the real world, it is common to have SSL terminated at the load balancer, and then use HTTP on the inside (i.e. Internet --https--> LB --http--> application)
How can I achieve secure HTTPS cookies in this case?
Secure cookies can only be transmitted over HTTPS, ServiceStack will still emit Secure Cookies behind a SSL terminated proxy, provided it correctly sets the X-Forwarded-Proto: https downstream HTTP Header.
E.g. here's a typical example of a SSL Terminated nginx reverse proxy:
server {
listen 80;
server_name my-app.org;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_cache_bypass $http_upgrade;
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_buffering off;
proxy_ignore_client_abort off;
proxy_intercept_errors on;
client_max_body_size 500m;
}
}

Node.js API with Nginx: Block API access to the public

I'm using Nginx with Nodejs backend. I use Nodejs for authenticating users and api calls. Currently I have the following in my Nginx configuration:
location /api {
proxy_pass http://localhost:5000/api;
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_redirect off;
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, this allows anyone to access /api directly. Is there a way to configure this so that users can't directly access /api?
Update
I tried adding:
allow 127.0.0.1; deny all; to the nginx config, however, this also blocks nginx from getting the resources. In other words, users can no longer login or get the resources from api.
I added a middle-ware to express and it always receives 127.0.0.1 (localhost) as the req.ip so I cannot do anything on nodejs side to prevent this because all requests are redirected from nginx.

How to forward url parameters from Nginx to my server's API so I can allow/disallow users to view certain files?

I'm trying to create an "allowed users only" section and I managed to get this far, but I'm stuck.
I use auth_request module of Nginx and Express.js.
How can I send the requested url to my api route?
"/" is the generic URL, but /api/:filename should be fired only when a visitor tries to access a file, no matter what the file's location / URL is. In short, what I want to do is, "okay, I'm Nginx and I see that some visitor tries to access this file (or files, it checks individually). let's pass this file's name to Express.js server and let it check whether this user is allowed to see this image or not. If it says 200, I'll allow it. If it's 403, then no."
app.get('/api/:filename', function(req,res,next) {
// This part decides what you're allowed to see.
// Redis database query. Returns 0 or 1.
// 1 means 200, 0 means 403.
res.sendStatus(200);
// It works if I omit :filename part, so this part is done in theory,
// but we didn't get the file name, so right now all we have is "yes
// to all" or "no to all", it's not dynamic.
});
The question is, I don't know how to pass the requested url parameter from Nginx to my Express.js app (e.g. image.jpg, video.mp4 in http://localhost/api/:filename format) so I can check user's permission against database and return a dynamic response for every file.
Here's my Nginx config.
upstream localhost {
ip_hash;
server 127.0.0.1:8000;
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
}
server {
listen 80;
server_name localhost;
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf)$ {
root images;
auth_request /api; // How to append requested filename to this URL?
}
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_pass http://localhost;
}
}
EDIT 1
location = /api {
proxy_pass http://localhost;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
Define a custom location for "/api" and append /api$request_uri (original uri) to proxy_pass;
location = /api {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_pass http://localhost/api$request_uri;
}

Nginx reverse proxy - passthrough basic authenication

I am trying to setup nginx as a reverse rpoxy server in front off several IIS web servers who are authenticating using Basic authentication.
(note - this is not the same as nginx providing the auth using a password file - it should just be marshelling everythnig between the browser/server)
Its working kind off - but getting repeatedly prompted for auth by every single resource (image/css etc) on a page.
upstream my_iis_server {
server 192.168.1.10;
}
server {
listen 1.1.1.1:80;
server_name www.example.com;
## send request back to my iis server ##
location / {
proxy_pass http://my_iis_server;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass_header Authorization;
proxy_redirect off;
proxy_buffering 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;
}
}
This exact situation took me forever to figure out, but OSS is like that I guess. This post is a year old so maybe the original poster figured it out, or gave up?
Anyway, the problem for me at least was caused by a few things:
IIS expects the realm string to be the same as what it sent to Nginx, but if your Nginx server_name is listening on a different address than the upstream then the server side WWW-Authenticate is not going to be what IIS was expecting and ignore it.
The builtin header module doesn't clear the other WWW-Authenticate headers, particularly the problematic WWW-Authenticate: Negotiate. Using the headers-more module clears the old headers, and adds whatever you tell it to.
After this, I was able to finally push Sharepoint 2010 through Nginx.
Thanks stackoverflow.
server {
listen 80;
server_name your.site.com;
location / {
proxy_http_version 1.1;
proxy_pass_request_headers on;
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_header Authorization; //This didnt work for me
more_set_input_headers 'Authorization: $http_authorization';
proxy_set_header Accept-Encoding "";
proxy_pass https://sharepoint/;
proxy_redirect default;
#This is what worked for me, but you need the headers-more mod
more_set_headers -s 401 'WWW-Authenticate: Basic realm="intranet.example.com"';
}
}
I had these same symptoms with nginx/1.10.3. I have a service secured under basic authentication, and nginx as a reverse proxy between the clients and the server. The requirement was that nginx would passthrough the authorization.
First request to the server did pass through the Authorization header. Second request simply blocked this header, which meant the client was only able to make one request per session.
This was somehow related to cookies. If I cleared the browser cookies, then the cycle repeated. The client was able to authenticate but just for the first request. Closing the browser had the same effect.
The solution for me was to change the upstream server from https to http, using:
proxy_pass http://$upstream;
instead of:
proxy_pass https://$upstream;

Resources