ServiceStack Secure cookie when HTTPS is terminated on the load balancer - servicestack

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;
}
}

Related

Socket.io connection from ReactJS is not being redirected by nginx as any other

I have a React web App which uses axios to communicate with the backend API. Backend receives all requests from suffix /api address. And after that, those are redirected by nginx to localhost:1337 where my backend listens to requests. Everything works okay but the socket connection. The console says it can not find domain/socket.io/... but it should be domain/api/socket.io/.... My connection in the client code:
const ENDPOINT = "https://sinavhukuk.com/api";
const socket = io(ENDPOINT);
Would mention that Strapi is used as a backend service (NodeJS).
Here is /etc/nginx/sites-available/default file configuration.
server {
# Listen HTTP
listen 80;
server_name sinavhukuk.com www.sinavhukuk.com;
# Redirect HTTP to HTTPS
return 301 https://$host$request_uri;
}
server {
# Listen HTTPS
listen 443 ssl;
server_name sinavhukuk.com www.sinavhukuk.com;
# SSL config
ssl_certificate /etc/letsencrypt/live/sinavhukuk.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sinavhukuk.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
# Static Root
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $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 Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
# Strapi API and Admin
location /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://localhost:1337;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $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 Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
}
It is responsible for redirecting /api/...s to localhost:1337. But on socket it is not completely redirected. The error I get is:
https://sinavhukuk.com/socket.io/..... is not found
As I said, if the nginx worked here as always, it should be
https://sinavhukuk.com/api/socket.io/.....
What am I doing wrong?
EDIT: Added redirection from /socket.io/ to /api/socket.io/ manually, but still redirection happens to /socket.io/ instead of /api/socket.io/
# Socket.io
location /socket.io/ {
proxy_pass http://localhost:3000/api/socket.io/;
}

How to forward request IP from NGINX to node.js application?

I have NGINX running as reverse proxy which forwards all http and https traffic to my node.js application, which listens to localhost:port
However the issue I have is that the node.js application sees all incoming requests as coming from ::ffff:127.0.0.1
How can I change the NGINX config such that the real IP will be passed through and forwarded to the node.js application?
server {
listen 80;
listen [::]:80;
listen 443;
listen [::]:443;
root /var/www/example.com/html;
index index.html index.htm;
server_name example.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:myport;
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;
}
# Requests for socket.io are passed on to Node on port x
location ~* \.io {
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;
proxy_pass http://localhost:myport;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Edit: The express.js/node.js application processes req.ip and has app.enable('trust proxy'); at startup
Express.js official site has this guide. Instructions:
app.set('trust proxy', true) in js.
proxy_set_header X-Forwarded-For $remote_addr in nginx.conf
You can now read-off the client IP address from req.ip property
This solves it taking into consideration above NGINX config.
var ip = req.headers['x-real-ip'] || req.connection.remoteAddress;

issues configuring nginx with node.js app

Trying to get nginx to proxy my node.js app and use a domain with it. I'm going to have many domains mapped to the server so i'm using separate .conf files for each server block. The issue i'm having right now is that I can only seem to get the default nginx page to show up when i go to the domain. I'll try to explain the current setup as clearly as possible, and if you need any more information please let me know.
nginx.conf changes
I set the root path to where my apps files are, root /var/www; so for example, an app would be deployed to the folder /var/www/example.com.
server block config
I created a new file for the server block /etc/nginx/conf.d/example_com.conf which contains
server
{
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location /var/www
{
proxy_pass http://localhost:3103;
include /etc/nginx/proxy_params;
}
}
please note that going to my http://myip:3103 renders the app as it should and the file /etc/nginx/proxy_params contains
proxy_buffers 16 32k;
proxy_buffer_size 64k;
proxy_busy_buffers_size 128k;
proxy_cache_bypass $http_pragma $http_authorization;
proxy_connect_timeout 59s;
proxy_hide_header X-Powered-By;
proxy_http_version 1.1;
proxy_ignore_headers Cache-Control Expires;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
proxy_no_cache $http_pragma $http_authorization;
proxy_pass_header Set-Cookie;
proxy_read_timeout 600;
proxy_redirect off;
proxy_send_timeout 600;
proxy_temp_file_write_size 64k;
proxy_set_header Accept-Encoding '';
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header Proxy '';
proxy_set_header Referer $http_referer;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Original-Request $request_uri;
Is there anything I am doing wrong here? Do you need any more info? Please let me know! nginx is pretty new for me and i feel like i'm super close i'm just note understanding something. Thanks!
Your configuration provides requests processing like this:
requests to http://[www.]example.com/var/www[*] will be proxy_passed to
you app
all other requests will be processed like static/direct
requests in default nginx directory
If you haven't static files and all request has to processing by app, then you should fix your configuration like this:
location /
{
proxy_pass http://localhost:3103;
include /etc/nginx/proxy_params;
}
If you have static files that can be served by nginx, then you should to complicate you configuration a bit like here or here.
Here is documentation for understanding how to nginx works.

How to keep host when proxy to other servers in nginx

For example. User request http://user.dist.com, the request will firstly arrived at nginx server,
upstream a.hello.com {
server 10.243.26.104:8800;
}
server
{
listen 80;
server_name user.dist.com;
location /
{
proxy_pass http://a.hello.com;
}
}
and the server a.hello.com is running at Node.js, the Node sever want to get the real origin request host which should be user.dist.com, but now, the Node server get a.hello.com, so how to get the origin host?
you can use proxy_set_header-
proxy_set_header HOST $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

nginx as a reverse proxy for API cannot redirect full url, params, body headers

I'am putting my node js API (that I manage with pm2) behind a reverse proxy with nginx, here no problem.
But since, if I send any request it become a GET on '/'.
How can I tell to nginx to forward the full url, the request types (PUT, OPTIONS, DELETE, ...), the requests params and the request body ?
here is my simple nginx config.
server {
listen 80;
listen [::]:80;
server_name api-prod.mysite.com www.api-prod.mysite.com localhost;
location / {
proxy_pass http://127.0.0.1:3111;
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;
}
}
Your nginx configuration seems good except, you should use proxy_http_version and proxy_cache_bypass because sometimes(depends on version) Nginx and nodejs using different HTTP version.
Following configuration working fine for me
server {
listen 80;
server_name arifjaunpur.com;
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;
}
}

Resources