neo4j webinterface behind nginx reverse proxy - ssl

I'm trying to expose a neo4j database to the internet.
For security reasons, I'd like to hide it behind a SSL/basic_auth combination via nginx. Here is the corresponding nginx config:
location /neo4j/ {
proxy_pass https://localhost:7473/;
proxy_read_timeout 600;
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 https;
proxy_set_header Host $http_host;
proxy_buffering off;
proxy_redirect off;
auth_basic "restricted";
auth_basic_user_file /etc/nginx/auth/htpasswd;
proxy_headers_hash_max_size 1024;
proxy_headers_hash_bucket_size 128;
proxy_ssl_session_reuse off;
rewrite /neo4j/(.*) /$1 break;
}
While I'm able to access https://example.com/neo4j/browser, the webinterface tells me, that it can't connect to the neo4j and my webbrowser's console gets filled up with OPTIONS https://example.com/db/data 405(Not allowed)
I also tried the neo4j built in https server in conjunction with the authentication extension (https://github.com/neo4j-contrib/authentication-extension).
With this option, I also can access the webinterface.
But the interface also displays, that it's not able to connect to the neo4j and the webbrowser's console gets filled up with OPTIONS http://example.com:7473/db/data/ net::ERR_EMPTY_RESPONSE and the hint The page at 'https://example.com:7473/browser/' was loaded over HTTPS, but displayed insecure content from 'http://example.com:7473/db/data/': this content should also be loaded over HTTPS.
Does anyone know, how to get it working? Many thanks in advance!

I came across the same problem and it's kind of weird the lack of info about Nginx as a webserver combined with neo4j. It's odd the only reference to a reverse proxy in the official doc is Apache - not impressed.
Just FYI I'm using a dockerised neo4j (https://github.com/neo4j/docker-neo4j/tree/master/2.3.2) as it comes by default (in case you want to know other settings). It should not matter if you run neo4j natively outside docker. The following Nginx conf will be the same.
location /neo4j/ {
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_redirect off;
proxy_buffering off;
proxy_pass http://YOUR-IP:7474/browser/;
}
location /db/data/ {
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_redirect off;
proxy_buffering off;
proxy_pass http://YOUR-IP:7474/db/data/;
}
Replace YOUR-IP by yours and change 7474 for 7473 if you are using HTTPS instead of HTTP.
This worked for me.

The OPTIONS request is needed to verify the connection to the Neo4j server. I think of it as a heartbeat to verify the connection. It seems that Nginx does not support OPTIONS requests, but the request can be intercepted with something like this:
location / {
if ($request_method = OPTIONS ) {
add_header Access-Control-Allow-Origin "https://example.com";
add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization";
add_header Access-Control-Allow-Credentials "true";
add_header Content-Length 0;
add_header Content-Type text/plain;
return 200;
}
}
Source: http://blog.rogeriopvl.com/archives/nginx-and-the-http-options-method/

Related

Nginx not redirecting on named route

I'm trying to setup a reverse proxy to a sentry relay using Nginx. Config file as follows:
events {
worker_connections 768;
}
http {
server {
listen 0.0.0.0:80;
location /sentry-relay {
proxy_pass http://127.0.0.1:3001;
proxy_redirect 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;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
Browsing directly to the relay server on port 3001 works fine:
However using the location path set in Nginx fails:
I've also put the redirect onto the default path: location / and it works fine. Why won't this custom path redirect properly?
I worked it out.
Nginx will append the location prefix to the proxy server request unless this prefix is replaced.
Thus to fix I changed:
proxy_pass http://127.0.0.1:3001;
to
proxy_pass http://127.0.0.1:3001/;
The extra slash is used to replace the sentry-relay path.

Configure Nginx as reverse proxy for Couchdb

I have a Couchdb database that should not be accessed directly, so I need to use a reverse proxy.
How to configure Nginx or apache as a reverse proxy for Couchdb?
To reverse proxy in nginx, you need a config that looks like this https://www.nginx.com/resources/admin-guide/reverse-proxy/
upstream mycouch {
server 192.168.0.100:
}
server {
listen *:80;
server_name mycouch.mydomain.whatever.com;
underscores_in_headers on;
location / {
expires off;
proxy_pass http://mycouch;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
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 will proxy HTTP calls for your couchdb. Since you tagged this question with docker, if you wanted to bake a container with this stuff, I'd suggest you start FROM nginx, https://hub.docker.com/_/nginx/ (or, just mount a config file in to nginx image as is)
Based on #djcrabhat replay, I created this config to enables replication
...
location / {
proxy_pass http://192.168.99.100:5984 //couchdb address
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ ^/(.*)/_changes {
proxy_pass http://192.168.99.100:5984 //couchdb address
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
...

NGINX to pass digest authorization to Apache

I have a NGINX in front of Apache which has both Basic and Digest authentication turned on. I'd like a set up where a user connects to NGINX (using Basic or Digest) and NGINX simply proxy the request to the Apache where the actual authentication happens. I have the Basic case working but not the Digest. Here's how the config for Basic looks like:
location /basic {
proxy_set_header x-user $http_x_user;
proxy_pass http://my.apache.server; // where authentication happens
proxy_set_header X-Original-URI $request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Could somebody help me out on how to accomplish the Digest case?
Here's a sample from a config that worked for me:
location /basic { # let nginx handle basic auth
auth_basic "Basic Authentication";
auth_basic_user_file conf/htpasswd;
}
location /digest { # pass digest auth to another server
proxy_pass http://my.apache.server;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

How to make youtrack not show solved issues

I am trying to figure out how to make Youtrack not show the resolved issues. It doesn't make sense. Is there an option to disable this by default?
I think the answer is that if you don't want to show resolved issues, you have to manually incorporate this in your search terms (include #unresolved or whatever works for your situation). You can of course save searches, and bookmark searches. But I haven't found a way to, by default, include #unresolved in all searches.
Our team is new to YouTrack, but in the current cloud version I found a way to do this. I'm assuming you are referring to the /issues page.
Create a saved search for unresolved issues - "Unresolved"
Update the dropdown to the right of the search bar from "Everything" to your saved search "Unresolved"
Reload the page and it defaults to "Unresolved." Whoo hoo!
You can use a trick which needs nginx or something to proxy YouTrack.
Add -Djetbrains.youtrack.baseUrl=http://127.0.0.1:PORT1 to the wrapper.conf file.
Then make nginx automatically change /issues queries for you.
server {
listen PORT2;
server_name IP_FQDN;
error_log /var/log/nginx/error.log debug;
location / {
proxy_pass http://localhost:PORT1;
client_max_body_size 10m;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
}
location /issues {
if ($args ~* (.*)(q=)(.*)) {
set $first_part $1;
set $last_part $3;
}
if ($last_part !~ "(.*)(Unresolved)(.*)") {
set $args "${first_part}q=%23Unresolved%20${last_part}";
}
if ($args = ""){
rewrite ^/issues /issues?q=%23Unresolved break;
}
proxy_pass http://localhost:PORT1;
client_max_body_size 10m;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
}
location /api/eventSourceBus {
proxy_cache off;
proxy_buffering off;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_set_header Connection '';
chunked_transfer_encoding off;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_pass http://localhost:PORT1;
}
}
I just use "for: me -Resolved", that shows all the unresolved tickets that are assigned to my user profile

Wrong IP-Address with nginx + Unicorn + rails

I check the ip-address in the controller with
request.env['REMOTE_ADDR']
this works fine in my test environment.
But on the production server with nginx + unicorn I always get 127.0.0.1.
This is my nginx config for the site:
upstream unicorn {
server unix:/tmp/unicorn.urlshorter.sock fail_timeout=0;
}
server {
listen 80 default deferred;
# server_name example.com;
root /home/deployer/apps/urlshorter/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri #unicorn;
location #unicorn {
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_redirect off;
proxy_pass http://unicorn;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
I had trouble with this too; I found this question, but the other answer didn't help me.
I looked at Rails 3.2.8's implementation of Rack::Request#ip to see how it decided what to say; to get it to use an address passed via the environment without filtering out addresses from my local network (it's trying to filter out intermediate proxies, but that's not what I wanted), I had to set the HTTP_CLIENT_IP from my nginx proxy configuration block in addition to what you've got above (X-Forwarded-For has to be there too for this to work!):
proxy_set_header CLIENT_IP $remote_addr;
If you use request.remote_addr you'll get the of your Nginx proxy.
To get the real IP address of your user, you can use request.remote_ip.
According to Rails' source code, it checks for various http headers to give you the most relevant one : in Rails 3.2 or Rails 4.0.0.beta1
The answer is in your config file :) The following should do what you want:
real_ip = request.headers["X-Real-IP"]
more here: http://api.rubyonrails.org/classes/ActionDispatch/Request.html#method-i-headers
UPDATE: The proper answer is here in another Q:
https://stackoverflow.com/a/4465588
or in this thread:
https://stackoverflow.com/a/15883610
spoiler:
use request.remote_ip
For ELB - nginx - rails you want to follow this guide:
http://engineering.blopboard.com/resolving-real-client-ip-with-amazon-elb-nginx-and-php-fpm
See:
server {
listen 443 ssl spdy proxy_protocol;
set_real_ip_from 10.0.0.0/8;
real_ip_header proxy_protocol;
location /xxx {
proxy_http_version 1.1;
proxy_pass <api-endpoint>;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header CLIENT_IP $remote_addr;
proxy_pass_request_headers on;
}
...
The proxy_set_header CLIENT_IP $remote_addr; didn't work for me. Here's what did..
The solution I found after reviewing the actiondispatch code remote_ip.rb source. Now I get proper IP in my devise/warden processes as well as any other routine I'm looking at request.remote_ip
My config...
Ruby 2.2.1 - Rails 4.2.1 - NGINX v1.8.0 - Unicorn v4.9.0 - Devise v3.4.1
nginx.conf
HTTP_CLIENT_IP vs CLIENT_IP
location #unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HTTP_CLIENT_IP $remote_addr; <-----
proxy_redirect off;
proxy_pass http://unicorn;
}
Source actionpack-4.2.1/lib/action_dispatch/middleware/remote_ip.rb
Line 114:
client_ips = ips_from('HTTP_CLIENT_IP').reverse
Line 126:
"HTTP_CLIENT_IP=#{#env['HTTP_CLIENT_IP'].inspect} " +