I've added sqlbuddy on my nginx server for remote management of my db. To that I've added .htaccess and password protection. However if I click on cancel in the authentication prompt / window I can still access the login for sqlbuddy. I can login and see a few parts of the UI. If I access the browser source I can see more data. How do I stop this? What's the best setup for this in nginx?
This is nginx conf:
location /sqlbuddy {
auth_basic "Administrator Login";
auth_basic_user_file /opt/nginx/html/sqlbuddy/.htpasswd;
}
Related
I have a WebDAV server set up, with its root folder /SomeVolume/webdav/contents and address 192.168.1.2:12345. User and password are set and the server can be accessed from a browser.
I am directing a domain name to the same machine using nginx, like this:
server {
server_name my.domain.me;
location / {
proxy_pass http://192.168.1.2:12345;
}
# plus the usual Certbot SSL stuff
This was working perfectly well, with HTTPS authentication and everything. I am using a third-party application that uses that server and it was working OK too.
I wanted to make this a bit more tidy and only changed couple of things:
WebDav server root to /SomeVolume/webdav (instead of /SomeVolume/webdav/contents), restarted the server.
proxy_pass http://192.168.1.2:12345 changed to proxy_pass http://192.168.1.2:12345/contents. Restarted ngninx.
Nothing else was modified.
I can still login through the browser, but the third-party application has stopped working because it gets authentication errors (401). Although if I try to login locally with http://192.168.1.2:12345/contents/ it works just fine.
What am I not understanding here? Is it some caching problem with the third-party application or have I misunderstood how location & proxy_pass work?
Thanks.
The CDH Solr admin page is configured with Kerberos authentication so it cannot be access in Web browser.
I plan to use Nginx as a proxy service to act Kerberos authentication and redirect the web request to Solr admin page.
Already used the spnego module 'https://github.com/stnoonan/spnego-http-auth-nginx-module'. And set the conf file like below.
location / {
auth_gss on;
auth_gss_realm EXAMPLE.ORG;
auth_gss_service_name "HTTP/test.example.org";
auth_gss_keytab /etc/krb5.keytab;
return 301 xxxxx;
But it doesn't work. The web page still shows 403. Does anyone know how to solve this problem?
I'm setting up a Digital Ocean droplet running Ubuntu 18.04 to host my Meteor 1.8 app via Phusion Passenger / Nginx. I will configure it to use SSL with Lets Encrypt.
fail2ban is a recommended tool to protect against brute force attacks, but I can't work out how to use it with Meteor, or even if it's appropriate. I've read several tutorials but there is something basic I don't understand.
I have used server location blocks in my Nginx config file to block access to all urls by default and only allow the necessary ones:
# deny all paths by default
location / { deny all; }
# allow sockjs
location /sockjs { }
# allow required paths
location = / { }
location /my-documents { }
location /login { }
location /register { }
...
# serve js and css
location ~* "^/[a-z0-9]{40}\.(css|js)$" {
root /var/www/myapp/bundle/programs/web.browser;
access_log off;
expires max;
}
# serve public folder
location ~ \.(jpg|jpeg|png|gif|mp3|ico|pdf|svg) {
root /var/www/myapp/bundle/pubilc;
access_log off;
expires max;
}
# deny unwanted requests
location ~ (\.php|.aspx|.asp|myadmin) {
return 404;
}
My basic question is: would fail2ban detect failed attempts to login to my Meteor app, and if so, how? If not, then what's the purpose of it? Is it looking for failed attempts to login to the server itself? I have disabled password access on the droplet - you can only connect to the server via ssh.
And how does this relate to Nginx password protection of sections of the site? Again, what's this for and do I need it? How would it work with a Meteor app?
Thank you for any help.
Any modern single page application using React/Vue/Blaze as its rendering engine simply doesn't send url requests to the server for each page in the UI.
Meteor loads all its assets at the initial page load, and the rest is done over sockets using DDP. It might load static assets as separate requests.
Any server API calls implemented as Meteor methods also won't show up in server logs.
So fail2ban will detect some brute force attacks, and could therefore be useful in blocking those attacks and preventing them from swamping the server, but it won't detect failed login attempts.
You could adapt the application to detect failed logins, and call the fail2ban API to log them (if that is possible). Otherwise I'm not sure whether it is totally appropriate for protecting a meteor server.
My conclusion is that yes, fail2ban is worth using with Meteor. As far as I can tell, Nginx password protection isn't relevant, but there's other good stuff you can do.
Firstly, I think it's worth using fail2ban on any server to block brute force attacks. My test server has been online only a couple of days with no links pointing to it and already I'm seeing probes to paths like wp-admin and robots.txt in the Nginx logs. These probes can't achieve anything because the files don't exist, but I think it's safer to ban repeated calls.
I worked from this tutorial to set up a jail for forbidden urls, modifying the jail definition to point to my actual Nginx log file.
Then, I've modified my app to record failed login attempts and written a custom jail and filter to block these. It may be that nobody will bother to write a script to attack a Meteor site specifically, and my Meteor app has throttling on the logins, but again I feel it's better to be more careful than less.
Here's how I've modified my app:
server/main.js
const buildServerLogText = ((text) => {
const connection = Meteor.call('auth.getClientConnection');
return `${moment(new Date()).format('YYYY/MM/DD HH:mm:ss')} ${text}, client: ${connection.clientAddress}, host: "${connection.httpHeaders.host}"`;
});
// log failed login attempts so fail2ban can find them in the Nginx logs
Accounts.onLoginFailure(() => {
const text = buildServerLogText('[error]: Meteor login failure');
console.log(text);
});
This writes failed login attempts to the server in this form:
2020/03/10 15:40:20 [error]: Meteor login failure, client: 86.180.254.102, host: "209.97.135.5"
The date format is important, fail2ban is fussy about this.
I also had to set passenger_disable_log_prefix on; in my Phusion Passenger config file to stop a prefix being added to the log entry. As I'm deploying my app with Phusion Passenger, the Nginx config is in the Passenger config file.
Then my fail2ban filter is like this:
/etc/fail2ban/filter.d/nginx-login-failure.conf
[Definition]
failregex = ^ \[error\]:.*Meteor login failure.*, client: <HOST>, .*$
ignoreregex =
Consider a dockerized environment containing the following containers:
Backend API
Front-end REACT App served using pushstate-server
Authentication Service
Nginx Container
My nginx.conf contains the following:
server {
listen 8080;
location / {
auth_request /auth;
proxy_pass http://frontend:5000;
}
location = /auth {
proxy_pass http://auth:6000;
}
error_page 403 = #error403;
location #error403 {
rewrite ^ /login$1;
proxy_pass http://frontend:5000;
}
}
When the auth_request /auth; line is commented out, everything works just fine and all frontend pages can be accessed.
As soon as I introduce the auth_request I can see the authentication service return a 403 however, it does not look like Nginx proxies to the login page.
What am I doing wrong?
There are two issues here:
Firstly, the authorization header is not forwarded to the authentication service. This was fixed with
location = /auth {
proxy_pass http://auth:6000;
proxy_pass_header Authorization;
}
Secondly, when a request is made to the frontend, nginx tries to authenticate with the auth container. As I am not authenticated, this fails and returns a 403. The nginx server then proxies to the login page on the REACT container, however, there are further request behind the scenes to retrieve css and js resources from the same container, for which the nginx gateway tries to authenticate. Again, as I am not authenticated retrieving these resources fails, so the page does not render.
A dirty solution was to add:
location /static/js/main.1e2389bc.js {
proxy_pass http://web:5000;
}
location /static/css/main.aa587518.css {
proxy_pass http://web:5000;
}
This retrieves the necessary files to render the login page with trying to authenticate. This is a bad solution as there may be other resources (favicon, other media etc.) so more blocks would need to be added. I am sure there is a simple solution using regex to sort this out in a simple way.
However, I ended up with a cleaner solution. Authenticate on requests to the backend API. This ensured that no sensitive information was displayed on the frontend without being authenticated and removed the hassle of hacking a solution to render the login page.
I've set up a simple nginx server, configured the location block to point to the respective directories I want served, and setup basic authentication using the auth_basic module.
However, my server requests username : password credentials on every single page request under the location block, even after providing them multiple times to different pages under the location block, including the root location directory.
How can I configure it to store the authentication? Is this an nginx issue or a browser / request headers issue?
Here is the nginx configuration:
server {
listen 80;
server_name 0.0.0.0;
location /path/to/dir {
alias /var/www/dir/;
index index.html index.htm;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
try_files $uri $uri/ =404;
}
}
Running nginx 1.4.6 on Ubuntu.
The problem in my case was that one of the API calls that was called by JavaScript on page load was returning 401. This seemed to reset browser auth state for the page.
HTTP authentication information is stored on your browser cache, and should only be requested again if the authentication fails or it's from a different realm (in auth_basic "Restricted"; it's Restricted).
Your configuration is fine, considering your password is correct and Nginx user has read access to the password file (case in which it'll always fail — but send an error message at the log file indicating this error). This is the most probable reason, mainly if you have only one location with authentication.
Another possible reason is having multiple auth_basic directives and they use different realms or passwords. This is the same for application-generated WWW-Authenticate headers (say, if your backend application requests for HTTP authentication in addition to Nginx). When there's a different realm or a password fails, your browser will request it again. No browser that I know of stores authentication per URL, it's always a combination of realm+hostname.
If you do need different realms or passwords on different locations, make sure they don't overlap for a single page (for example, if you use a different password for your assets: images, styles or javascript). Or use different hosts — the password would be requested once for each host/realm combination, though.
Update
It's unusual to use 0.0.0.0 as a server_name — listen 80; already makes your server to listen to all interfaces/IP addresses.
Use server_name _; in case you mean to use any request host.