nicolewhite/RNeo4j

neo4j default security config and cURL

seanoreillyza opened this issue · 18 comments

I downloaded / installed a default configuration of neo4j 2.2.3 and attempted to connect using the startGraph function.

However, I kept receiving the following curl error from RNeo4j

Error in curl::curl_fetch_memory(url, handle = handle) : 
  Couldn't connect to server

Even though I was connecting via localhost, it turns out that I had to modify/enable the following directive in the neo4j-server.properties file

# Let the webserver only listen on the specified IP. Default is localhost (only
# accept local connections). Uncomment to allow any connection. Please see the
# security section in the neo4j manual before modifying this.
org.neo4j.server.webserver.address=0.0.0.0

I hope this helps someone else out.

Modifying neo4j-server.properties is part of the installation process of the Neo4j database.

By not changing the default properties upon installation, I was still able to use neo4j in my browser perfectly.

It was only when trying to access the database via RNeo4j that I came across this issue. It may not be completely obvious to a novice that a security issue would be blocking RNeo4j even though the database is still being access via localhost.

This is not a bug in RNeo4j but should possibly be included in an FAQ.

You shouldn't have to change any properties files before connecting. Everything works fine if you have auth enabled (the default):

> graph = startGraph("http://localhost:7474/db/data/", username="neo4j", password="password")
> graph
< Graph Object > 
$version
[1] "2.2.3"

And if you have auth disabled:

dbms.security.auth_enabled=false
> graph = startGraph("http://localhost:7474/db/data/")
> graph
< Graph Object > 
$version
[1] "2.2.3"

What version of RNeo4j are you using? Can you copy paste your code?

I'm afraid that the connection error is unrelated to whether auth is enabled or not in the properties file. If I use the server property defaults (auth enabled) I continue to experience the error

> graph = startGraph("http://localhost:7474/db/data/", username="neo4j", password="password")
Error in curl::curl_fetch_memory(url, handle = handle) : 
  Couldn't connect to server

Unless I change / uncomment the following in the server properties file

# Let the webserver only listen on the specified IP. Default is localhost (only
# accept local connections). Uncomment to allow any connection. Please see the
# security section in the neo4j manual before modifying this.
org.neo4j.server.webserver.address=0.0.0.0

With this config change I experience no errors. My understanding is that I should not have to uncomment this directive, as I am connecting from and hosting on localhost.

I am using the latest RNeo4j with neo4j 2.2.3 community. My R version is as follows:

platform       x86_64-apple-darwin13.4.0   
arch           x86_64                      
os             darwin13.4.0                
system         x86_64, darwin13.4.0        
status                                     
major          3                           
minor          2.1                         
year           2015                        
month          06                          
day            18                          
svn rev        68531                       
language       R                           
version.string R version 3.2.1 (2015-06-18)

Yes, you shouldn't have to do anything with that line in the properties file. The only way I can reproduce that error is to stop Neo4j.

What happens when you curl http://localhost:7474/db/data/ with that configuration line commented out?

What's the output of this command with/without that line commented out?

lsof -Pn -i :7474

When using default properties and having org.neo4j.server.webserver.address=0.0.0.0 commented out.

curl produces:

curl http://localhost:7474/db/data/
{
  "errors" : [ {
    "code" : "Neo.ClientError.Security.AuthorizationFailed",
    "message" : "No authorization header supplied."
  } ]
}

lsof produces

lsof -Pn -i :7474
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    36441 sean  164u  IPv6 0x40a9c9173fe2fd3d      0t0  TCP 127.0.0.1:7474 (LISTEN)

When uncommenting org.neo4j.server.webserver.address=0.0.0.0 lsof produces

lsof -Pn -i :7474
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    36972 sean  164u  IPv6 0x40a9c9174ee3b03d      0t0  TCP *:7474 (LISTEN)

I can also see my R session running when connecting via RNeo4j (again with 'remote' connections enabled)

lsof -Pn -i :7474
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
R       36347 sean    5u  IPv6 0x40a9c9173fe2f83d      0t0  TCP [::1]:59568->[::1]:7474 (CLOSE_WAIT)
java    36972 sean  164u  IPv6 0x40a9c9174ee3b03d      0t0  TCP *:7474 (LISTEN)

With the 0.0.0.0 commented what do you see if you execute this in R?

graph = startGraph("http://127.0.0.1:7474/db/data/", username="neo4j", password="password")

Do you still get the connection refused?

No, it seems to work when using an IP address and not localhost.

> graph = startGraph("http://localhost:7474/db/data/", username="neo4j", password="password")
Error in curl::curl_fetch_memory(url, handle = handle) : 
  Couldn't connect to server
> 

vs

> graph = startGraph("http://127.0.0.1:7474/db/data/", username="neo4j", password="password")
> 

Oh that's weird - I guess the R connection code isn't resolving localhost correctly then?

What mappings do you have in your /etc/hosts?

cat /etc/hosts

Here we go

cat /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1   localhost
255.255.255.255 broadcasthost
::1             localhost 
fe80::1%lo0 localhost

I changed my /etc/hosts to match yours and I can reproduce the problem although interestingly I see the same thing with curl:

$ curl http://localhost:7474/db/data/
curl: (7) Failed to connect to localhost port 7474: Connection refused

$ curl http://127.0.0.1:7474/db/data/
{
  "errors" : [ {
    "message" : "No authorization header supplied.",
    "code" : "Neo.ClientError.Security.AuthorizationFailed"
  } ]
}

Try commenting out this line in your /etc/hosts:

#fe80::1%lo0 localhost

And then try this:

graph = startGraph("http://localhost:7474/db/data/", username="neo4j", password="neo")

Interesting, commenting out

#fe80::1%lo0 localhost

does seem to resolve the problem. I get no errors when connecting to the graph now, using default server settings.
When I re-enable this hosts setting, I experience the problem again.

@mneedham I'm not sure it's an R problem if the error can be reproduced with curl.

@nicolewhite yeh for me curl + R did the same thing but for @seanoreillyza I think curl worked somehow.

What do you think @seanoreillyza, are you happy to close this or shall we look into it further?

Normal curl was still able to reach the endpoint for me.

I'm comfortable having this issue marked as closed. Based on evidence uncovered up until now, this seems to be more environment configuration related than RNeo4j itself.

I would still suggest having the config changes visible / published somewhere, in case someone else runs into the same problem.

I'll add a section to the README on connection issues.