And the promised NGINX config for proxying the Node-RED admin Editor:
## -- assumes you haven't nested this location in a parent location --
# Proxy the Node-RED Editor https://my.public.domain/red/ to http://localhost:1880/red/
location /red/ {
# A full set of headers have to be redone for every context that defines another header
include /etc/nginx/conf.d/includes/common_security_headers.conf;
# Reverse Proxy
proxy_pass https://localhost:1880/; # <== CHANGE TO MATCH Node-RED's base URL
# Common headers MUST be re-included whenever setting another header in a route
include /etc/nginx/conf.d/includes/common_proxy_headers.conf;
# ==> Of course, you could have a separate auth here! <==
# Reverse Proxy for websockets
include /etc/nginx/conf.d/includes/common_ws_proxy_headers.conf;
# Reverse Proxy
proxy_pass https://localhost:1880/red/; # <== CHANGE TO MATCH THE EDITOR's URL
# Tell upstream which proxy was used
proxy_set_header X-JK-Proxy "REDadmin";
# Tell client which proxy was used (not really all that useful)
add_header X-JK-Proxy "REDadmin";
}
/etc/nginx/conf.d/includes/common_security_headers.conf
:
# Default header properties
# These have to be respecified for EVERY server/location context if that context defines another header.
# So we use an include file that won't be loaded by the nginx.conf file directly.
# don't allow the browser to render the page inside an frame or iframe and avoid clickjacking http://en.wikipedia.org/wiki/Clickjacking
# if you need to allow [i]frames, you can use SAMEORIGIN or even set an uri with ALLOW-FROM uri https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options
add_header X-Frame-Options SAMEORIGIN;
# when serving user-supplied content, include a X-Content-Type-Options: nosniff header along with the Content-Type: header,
# to disable content-type sniffing on some browsers. https://www.owasp.org/index.php/List_of_useful_HTTP_headers
add_header X-Content-Type-Options nosniff;
# This header enables the Cross-site scripting (XSS) filter built into most recent web browsers.
# It's usually enabled by default anyway, so the role of this header is to re-enable the filter for
# this particular website if it was disabled by the user.
# https://www.owasp.org/index.php/List_of_useful_HTTP_headers
add_header X-XSS-Protection "1; mode=block";
# Content Security Policy (CSP) - tell the browser that it can only download content from the domains you explicitly allow
# http://www.html5rocks.com/en/tutorials/security/content-security-policy/
# https://www.owasp.org/index.php/Content_Security_Policy
# Must be configured for your specific needs
#add_header Content-Security-Policy ........ ;
# You may want this in case something tries to refer from your site to something like Facebook https://scotthelme.co.uk/a-new-security-header-referrer-policy/
add_header Referrer-Policy "strict-origin-when-cross-origin";
# Configure for Strict Transport Security (HSTS) - only if https is in use - see map in default.conf
add_header Strict-Transport-Security $sts;
# NGINX seems to often ignore directive to not blab
add_header server 'home'; # <== CHANGE THIS TO WHATEVER YOU WANT
/etc/nginx/conf.d/includes/common_proxy_headers.conf
:
# Common reverse proxy settings
# Don't forget to also add proxy_pass url;
proxy_set_header Forwarded "by=$host;for=$proxy_add_x_forwarded_for;host=$host;proto=$scheme";
proxy_set_header Via "$scheme/1.1 $host:$server_port";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Real-IP $remote_addr;
# Proxy timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# If proxied responses happening too slowly, try turning off the buffering
#proxy_buffering off;
/etc/nginx/conf.d/includes/common_ws_proxy_headers.conf
:
# Common headers for proxy of websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
And if you want to add a login to a location, this is a very simplistic example using HTTP BASIC AUTH.
# Test route for HTTP Basic authentication
# Needs a matching route in Node-RED
location /authbasic/ {
# A full set of headers have to be redone for every context that defines another header
include /etc/nginx/conf.d/includes/common_security_headers.conf;
# Reverse Proxy
proxy_pass https://localhost:1880/; # <== CHANGE TO MATCH Node-RED's base URL
# Common headers MUST be re-included whenever setting another header in a route
include /etc/nginx/conf.d/includes/common_proxy_headers.conf;
satisfy all; # Only really needed when using IP restrictions, etc
# Block router, allow from anywhere else on local network and block everything else
deny 192.168.1.1;
allow 192.168.1.0/24;
deny all;
# sudo htpasswd -c /etc/nginx/.htpasswd me # thisisme
auth_basic "Auth Basic"; # relm, any text you like
auth_basic_user_file /etc/nginx/.htpasswd;
add_header X-JK-Proxy "Basic Auth Test";
add_header X-JK-Username $remote_user; # Returns the logged in username
# proxy_set_header Authorization ""; # If you don't want the upstream to recieve the auth
proxy_pass https://localhost:1880/authbasic/;
}
There is more if you need it, it can get quite complex and you need to think through what parts you want protected. Not forgetting that you can also nest locations so some things can be inherited (but some things cannot).
Oh, and any headers that start with X-JK
- those are for convenience as you can check them in Node-RED. They can help debug routing issues. Anything that starts X-
is generally a custom header.