第 24 章 安全
Neo4j自身并不会正数据层级加强安全性。然而,在使用Neo4j到不同场景时应该考虑不同的情况。
24.1. 安全访问Neo4j服务器
24.1.1. 加强端口和远程客户端连接请求的安全
默认情况下,Neo4j服务端会捆绑一个Web服务器,服务在 7474端口,通过地址: http://localhost:7474/访问,不过只能从本地访问。
在配置文件 conf/neo4j-server.properties中:
1 2 3 4 5 6 7 | # http port (forall data, administrative, and UI access) org.neo4j.server.webserver.port=7474 #let the webserver only listen on the specified IP. Default #is localhost (only accept local connections). Uncomment to allow #any connection. #org.neo4j.server.webserver.address=0.0.0.0 |
如果你需要能从外部主机访问,请在 conf/neo4j-server.properties中设置 org.neo4j.server.webserver.address=0.0.0.0来启用。
24.1.2. 任意的代码执行
默认情况下,Neo4j服务端是可以执行任意代码的。比如 Gremlin Plugin 和 Traversals REST endpoints。为了让这些更安全一些,要么从服务端的类路径完全移除这些插件,要么通过代理或者授权的角色来访问哲学地址。当然, Java Security Manager也可以用于让代码更加安全。
24.1.3. HTTPS支持
Neo4j服务端内建支持HTTPS进行SSL加密通讯。服务端第一次启动时,他会自动生成一个自签名SSL证书和一个私钥。因为这个证书是自签名的,在生产环境使用是不安全的,相反,你应该生成为生产服务器单独产生。
为了提供你自己的KEY和证书,取代生成的KEY和证书,或者通过改变 neo4j-server.properties的配置来充值你的证书和KEY的位置:
1 2 3 4 5 | # Certificate location (auto generated ifthe file does not exist) org.neo4j.server.webserver.https.cert.location=ssl/snakeoil.cert # Private key location (auto generated ifthe file does not exist) org.neo4j.server.webserver.https.key.location=ssl/snakeoil.key |
注意这个KEY应该是不加密的。确保你给私钥设置正确的权限,以至于只有neo4j服务端才有权限读取/写入它。
你可以设置https连接端口和配置文件中的一样,以及关闭/打开 https支持:
1 2 3 4 5 | # Turn https-support on/off org.neo4j.server.webserver.https.enabled=true # https port (forall data, administrative, and UI access) org.neo4j.server.webserver.https.port=443 |
24.1.4. 服务端授权规则
除了IP层面的限制,在Web服务器上管理员应该要求更高级的安全策略。 Neo4j服务端支持通过根据用户提供的证书来允许或者禁止管理员访问某些特点的功能。
为了实现在Neo4j 服务端在特定领域的授权策略,可以实现安全规则并注册到服务端上。这将排除轮训服务的可能的场景出现,比如给予安全和授权的用户和角色。
加强服务端授权规则
这这个范例中,一个失败安全规则被注册来拒绝访问所有到服务器的URI,通过在 neo4j-server.properties列举规则类实现:
1 | org.neo4j.server.rest.security_rules=my.rules.PermanentlyFailingSecurityRule |
规则源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | publicclassPermanentlyFailingSecurityRule implementsSecurityRule { publicstaticfinalString REALM = "WallyWorld"; // as per RFC2617 :-) @Override publicbooleanisAuthorized( HttpServletRequest request ) { returnfalse; // always fails - a production implementation performs // deployment-specific authorization logic here } @Override publicString forUriPath() { return"/*"; } @Override publicString wwwAuthenticateHeader() { returnSecurityFilter.basicAuthenticationResponse(REALM); } } |
当这个规则被注册后,任何访问服务器的请求都会被拒绝。在一个生产级别的实现中,这个规则可能会在第三方目录服务(比如LDAP) 或者一个授权用户的本地数据库中查找证书/要求。
Example request
- POSThttp://localhost:7474/db/data/node
- Accept:application/json
Example response
- 401:Unauthorized
- WWW-Authenticate:Basic realm="WallyWorld"
1 |
使用通配符设置安全规则
在这个范例中,一个失败的安全规则被注册来拒绝任何对服务端的访问,通过在 neo4j-server.properties列举规则类。在这个范例中,规则通过一个通配符URI路径定义(* 用来表示路径中的任何部分)。比如 /users*表示在 /users为根路径下面的所有路径, /users*type*则可以用来匹配 类似 /users/fred/type/premium这样的地址。
1 | org.neo4j.server.rest.security_rules=my.rules.PermanentlyFailingSecurityRuleWithWildcardPath |
规则的源代码是:
1 2 3 4 | publicString forUriPath() { return"/protected/*"; } |
这个规则注册后,任何访问服务端的请求都会被拒绝。使用通配符来弹性的设置安全规则的目标,这将影响到服务端的API,任何非托管的扩展以及已经注册的管理插件。
Example request
- GEThttp://localhost:7474/protected/wildcard_replacement/x/y/z/something/else/more_wildcard_replacement/a/b/c/final/bit/more/stuff
- Accept:text/plain
Example response
- 401:Unauthorized
- WWW-Authenticate:Basic realm="WallyWorld"
1 |
24.1.5. 基于主机的脚本支持
重要 | ||
Neo4j服务端默认运行完全访问相关系统来暴露远程脚本功能。不用实现一个安全层来暴露你的服务端构成了重大的安全漏洞。 |
24.1.6. 深度安全
虽然Neo4j服务端有大陆的内建安全特性(看上面的章节),对于安全更高的部署,使用像Apache的 mod_proxy[3]来代理外部请求会更加安全的。
这样有很大的优势:
- 控制访问Neo4j服务端到特定的IP地址,URL模式以及IP范围。这可以用来保证只有 /db/data命名空间可以被非本地客户端访问,而 /db/admin空间只开发给特定的IP地址。
1 2 3 4 5 | <Proxy *> Order Deny,Allow Deny from all Allow from 192.168.0 </Proxy> |
当用Neo4j的 SecurityRule插件实现了功能需求后,比起开发插件,操作像Apache这样专业的配置服务器显得更好一些。然而,值得注意的是两种方法都要使用,他们会一起合作提供访问代理服务器和 SecurityRule插件的一致的行为。
- 在Linux/Unix系统中,在端口 < 1000 (比如端口80)以非ROOT用户运行Neo4j服务端,使用:
1 2 | ProxyPass /neo4jdb/data http://localhost:7474/db/data ProxyPassReverse /neo4jdb/data http://localhost:7474/db/data |
- 在一个集群环境中,使用Apache mod_proxy_balancer[4]实现简单的负载均衡。
1 2 3 4 5 | <Proxy balancer://mycluster> BalancerMember http://192.168.1.50:80 BalancerMember http://192.168.1.51:80 </Proxy> ProxyPass /test balancer://mycluster |
24.1.7. 用一个代理重写URL规则
当安装Neo4j服务端在代理服务器后面后,你需要启动JSON调用的重写规则,否则他们将指向基于(一般是 http://localhost:7474)的服务端。
为了实现这个,你可以使用 Apache mod_substitute。
1 2 3 4 5 6 7 8 | ProxyPass / http://localhost:7474/ ProxyPassReverse / http://localhost:7474/ <Location /> AddOutputFilterByType SUBSTITUTE application/json AddOutputFilterByType SUBSTITUTE text/html Substitute s/localhost:7474/myproxy.example.com/n Substitute s/http/https/n </Location> |
[3] http://httpd.apache.org/docs/2.2/mod/mod_proxy.html
[4] http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html