I am a newb and i installed jupyterhub with nginx reverse proxy on my ubuntu 18.04 server. I built my own root CA and self signed certificate with openssl. Https connections works very well if my rootCA is installed on my others computers. I want to block access for the computers who don't have my rootCA.
the file /etc/nginx/nginx.conf is untouched and my config file /etc/nginx/sites-available/jupyter.conf is:
# top-level http config for websocket headers If Upgrade is defined,
# Connection = upgrade If Upgrade is empty, Connection = close
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP server to redirect all 80 traffic to SSL/HTTPS
server {
listen 80;
server_name 192.168.4.70 mlserver.net localhost;
# Tell all requests to port 80 to be 302 redirected to HTTPS
return 302 https://$host$request_uri;
}
# HTTPS server to handle JupyterHub
server {
listen 443;
ssl on;
server_name 192.168.4.70 mlserver.net localhost;
ssl_certificate /etc/ssl/certs/mlserver.net.crt;
ssl_certificate_key /etc/ssl/private/mlserver.net.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
#ssl_stapling on;
# Managing literal requests to the JupyterHub front end
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# websocket headers
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Scheme $scheme;
proxy_buffering off;
}
}
How can i edit this file to block access for computers who dont have certificate ?
What nginx directive add ?
Thanx.
I want to block access for the computers who don't have my rootCA.
This is not possible. The server has no information if the client has successfully validated the server certificate (i.e. clients which have the rootCA) or if a client simply skipped certificate validation (clients which don't have rootCA).
One could try to add a HSTS header so that browsers will not simply allow to ignore certificate problems. But this can also be bypassed on the client side without the server noticing, it just makes it a bit harder.
If you want to control who can access the notebook you would need proper authentication of the clients instead. Knowledge of the rootCA is not client authentication.
Related
I have my REST APIs configured to work over https using nginx( java APIs deployed in tomcat and nginx is configured for DNS mapping). Our testing team has managed to access the APIs using burp tool (I assume it allows them to access with SSL verification disabled) and they were able to alter the API response before the client receives it. My nginx server is configured to work on SSL with proxy forward setup for http to https. How can I block the API requests which has SSL verification disabled, so that I can stop them altering the response? Below is my nginx config.
upstream mlljava{
server 172.31.5.222:8090;
}
server {
listen 443 ssl;
server_name mllwebapi.xyz.in www.mllwebapi.xyz.in;
underscores_in_headers on;
client_max_body_size 10M;
ssl_protocols TLSv1.3;
ssl_certificate /home/ubuntu/175e9.crt;
ssl_certificate_key /home/ubuntu/key.key;
location / {
proxy_pass http://mlljava/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
proxy_pass_request_headers on;
}
}
Does adding this to server configuration helps?
# force https-redirects
if ($scheme = http) {
return 401 https://$server_name$request_uri;
Configure Nginx SSL + force HTTP to redirect to HTTPS + force www to non-www on Serverpilot free plan (Using Nginx configuration file only)
Nginx: force SSL on one path, non-SSL on others
Server :Ubuntu: 18.04.4
Hosting Server: NGINX: 1.16.1
A school needs to publish their learning management system to the Internet so teachers/students can learn from home.
I am a Network Engineer and I have very little experience with NGINX and reverse proxy servers in general, apart from setting firewall rules.
So, I have had this almost working. My first config seems to work, it passes the traffic so it seems, and I get the login prompt, but when entering valid credentials I get an authentication error.
I found some suggestions that this is due to NTLM authentication.
I found some further information that suggested I needed to use streams. I tried this, and don't even get any authentication prompt at all.
So, I did contact NGINX to see if I needed NGINX Plus, but they said I should post here first to see if someone knows how to make this work.
The first config attempt is below:
server {
listen 80;
listen [::]:80;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name URL.URL.URL/daymap;
ssl_certificate /etc/ssl/certs/CERTNAME.crt;
ssl_certificate_key /etc/ssl/private2/KEYNAME.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
# ssl_dhparam /path/to/dhparam;
# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;
resolver 172.31.4.10;
#proxy_set_header Host $http_host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass_header Authorisation;
proxy_pass http://URL.URL.URL.URL.URL/daymap/;
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_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
client_max_body_size 0;
proxy_read_timeout 36000s;
proxy_redirect off;
}
}
The Stream config is below:
stream {
upstream backend {
hash $remote_addr consistent;
server URL.URL.URL:443 weight=5;
server IP.IP.IP.IP:443 max_fails=3 fail_timeout=30s;
}
upstream dns {
server 172.31.4.10:53;
server 172.31.4.11:53;
}
server {
listen 443;
proxy_connect_timeout 1s;
proxy_timeout 3s;
proxy_pass backend;
}
server {
listen 127.0.0.1:53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
resolver 172.31.4.10;
}
I'll appreciate any insight. Hopefully, someone can see what I am doing wrong.
Regards,
Jason.
This began working all by itself about 4 days after posting this. The streams config is the one that is working.
Hope that might help someone else.
proxying NTLM is not easy. An NTLM authentication requeries a single connection established between the client and the server. The ussage of keepalive connections will not work in this case.
For more details about how to authenticate using NTLM: https://learn.microsoft.com/en-us/openspecs/office_protocols/ms-grvhenc/b9e676e7-e787-4020-9840-7cfe7c76044a
In NGINX Plus (commercial subscription) there is a special directive to tell the proxy server NTLM is in place.
http://nginx.org/en/docs/http/ngx_http_upstream_module.html#ntlm
This directive is only available in NGINX Plus. With NGINX OSS you can work with streams module instead of http to work arround the keepalives for the backend connections.
Let me know if you need more help on this.
I have set up an nginx reverse proxy server on my web server, which is receiving SSL traffic, and reverse proxying it to port 8080 on my web server, which is an exposed port running the nextcloud docker image. I am able to log in from a desktop web browser, but I am not able to log in from my iPhone. When I log in from the app, I receive error message "Access Forbidden, Invalid Request." This Github issue identifies the issue as auth headers being removed from the request, though the solution it gives is for Apache, not for Nginx. I'm really not familiar with authorization headers. How would I modify my Nginx server directive to take care of the issue?
Current setup
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name cloud.foo.com;
ssl_certificate /etc/letsencrypt/live/cloud.foo.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/cloud.foo.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
}
You may need to add a setting to explicitly pass the Authorization header in the response from the proxied server.
For example:
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass_header Authorization;
}
Based on the reverse proxy settings I've seen for another authenticated service, it's probable that by default, Nginx does not pass the Authorization header from the response of a proxied server to a client. Although this is not listed in the documentation, it is probably necessary to avoid interference with the authentication modules.
I have been troubleshooting an obscure nginx problem where we have a site correctly serving a cert and establishing a ssl connection on port 443 even though ssl is not explicitly turned on for the port. Below you can see the configuration for the site, which is listening on port 443 but not using the ssl directive.
server {
listen 443;
port_in_redirect off;
server_name xyz.abcd.com;
# websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 1m;
proxy_set_header X-Request-Id $request_id;
proxy_set_header X-Request-Start $msec;
proxy_set_header X-Forwarded-Proto "https";
proxy_set_header Host $host;
location / {
proxy_pass http://xyz-svc;
}
}
Furthermore, our nginx.conf does not explicitly mention port 443 or ssl, but it does include the path to the cert for abcd.com:
http {
..
ssl_certificate /etc/ssl/certs/abcd.pem;
ssl_certificate_key /etc/ssl/private/abcd.key;
..
}
Lastly, if we go to http://abcd.com:443, nginx throws an error saying "The plain HTTP request was sent to HTTPS port." So, clearly it is interpreting port 443 for this site as a ssl port even though we do not explicitly define that in our configuration. This behavior is true for both nginx version 1.7.5 and nginx version 1.13.8.
What are possible reasons nginx would correctly establish a ssl connection on port 443 for a site with the appropriate cert if it is never defined in the configuration to do so?
I am currently hosting a bundled Meteor app on Digital Ocean with nginx using this tutorial
I am using the react-native-meteor package in React Native to connect to this server. When the server is hosted on localhost, Meteor.connect(ws://192.168.0.2:3000/websocket) works.
Also, when the app is running on Digital Ocean, I am able to connect to the meteor server's webpage with https://XXX.XXX.X.XX after bypassing security warning and the websocket with wss://XXX.XXX.X.XX/websocket.
However, running Meteor.connect(wss://XXX.XXX.X.XX/websocket) or Meteor.connect(ws://XXX.XXX.X.XX/websocket) do not work.
Here is the nginx config:
server_tokens off; # for security-by-obscurity: stop displaying nginx version
# this section is needed to proxy web-socket connections
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP
server {
listen 80 default_server; # if this is not a default server, remove "default_server"
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html; # root is irrelevant
index index.html index.htm; # this is also irrelevant
server_name XXX.XXX.X.X; # the domain on which we want to host the application. Since we set "default_server" previously, nginx will answer all hosts anyway.
# redirect non-SSL to SSL
location / {
rewrite ^ https://$server_name$request_uri? permanent;
}
}
# HTTPS server
server {
listen 443 ssl spdy; # we enable SPDY here
server_name XXX.XXX.X.X; # this domain must match Common Name (CN) in the SSL certificate
root html; # irrelevant
index index.html; # irrelevant
ssl_certificate /etc/nginx/ssl/budget.pem; # full path to SSL certificate and CA certificate concatenated together
ssl_certificate_key /etc/nginx/ssl/budget.key; # full path to SSL key
# performance enhancement for SSL
ssl_stapling on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
# safety enhancement to SSL: make sure we actually use a safe cipher
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK';
# config to enable HSTS(HTTP Strict Transport Security) https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security
# to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping
add_header Strict-Transport-Security "max-age=31536000;";
# If your application is not compatible with IE <= 10, this will redirect visitors to a page advising a browser update
# This works because IE 11 does not present itself as MSIE anymore
if ($http_user_agent ~ "MSIE" ) {
return 303 https://browser-update.org/update.html;
}
# pass all requests to Meteor
location / {
proxy_pass http://0.0.0.0:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # allow websockets
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $remote_addr; # preserve client IP
# this setting allows the browser to cache the application in a way compatible with Meteor
# on every applicaiton update the name of CSS and JS file is different, so they can be cache infinitely (here: 30 days)
# the root path (/) MUST NOT be cached
if ($uri != '/') {
expires 30d;
}
}
}
Any help is appreciated!
You should update your question to show the error message (open you browser javascript console then refresh your link and recreate the error condition)
... your nginx config must include these settings
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
in your nginx config as per
location / {
proxy_pass http://GKE_NGINX_NODEJS_ENDUSER_SERVER_IP:3000/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
# Include support for web sockets:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
in addition to above assure you have this in your server block
server {
server_name example.com;
and not the IP of the server as per :
server_name XXX.XXX.X.X; # this domain must match Common Name (CN) in the SSL certificate
there are many moving parts ... assure you have defined the environment variable METEOR_SETTINGS prior to launching your app when you execute node
METEOR_SETTINGS={
"public": {
"rootUrl": "https://example.com",
< ... more here ... >
},
"cordova": {
"localhost": "http://localhost:12416"
},
< ... more here ... >
}