Neo4j Bolt连接TLS配置及Python SDK连接异常的技术咨询
我来帮你拆解这个问题,先理清楚背景、遇到的问题,再逐个分析原因和核心疑问的答案:
一、环境与配置背景
你的Neo4j Community部署在Azure虚拟私有网络的Ubuntu服务器上,已经完成了TLS加密的相关配置:
1. 浏览器端(HTTPS)配置
禁用明文HTTP,通过NGINX代理启用HTTPS并使用自签名证书:
server.http.enabled=false server.https.enabled=true dbms.ssl.policy.https.enabled=true dbms.ssl.policy.https.base_directory=certificates/https dbms.ssl.policy.https.private_key=sub.domain.key dbms.ssl.policy.https.public_certificate=sub.domain.pem dbms.ssl.policy.https.client_auth=NONE
2. Bolt端口(7687)配置
强制要求所有Bolt连接使用TLS加密,同样搭配自签名证书:
server.bolt.enabled=true server.bolt.tls_level=REQUIRED dbms.ssl.policy.bolt.enabled=true dbms.ssl.policy.bolt.base_directory=certificates/bolt dbms.ssl.policy.bolt.private_key=sub.domain.key dbms.ssl.policy.bolt.public_certificate=sub.domain.pem dbms.ssl.policy.bolt.client_auth=NONE
目前浏览器访问https://sub.domain.com/neo4j完全正常,页面显示的推荐Bolt连接地址为bolt+s://sub.domain.com:7687。
二、遇到的Python SDK连接问题
你用Neo4j Python AsyncDriver做了三次连接尝试,结果差异明显:
- 失败案例:使用
bolt+s://连接时触发SSLCertVerificationError证书验证错误driver = AsyncGraphDatabase.driver( f"bolt+s://{settings.host}:{settings.port}", auth=(settings.username, settings.password) ) - 成功案例1:使用
bolt://连接并指定信任系统CA,连接顺利建立driver = AsyncGraphDatabase.driver( f"bolt://{settings.host}:{settings.port}", auth=(settings.username, settings.password), trusted_certificates=TrustSystemCAs() ) - 成功案例2:使用
bolt+ssc://连接也能成功,但官方明确不推荐用于生产环境driver = AsyncGraphDatabase.driver( f"bolt+ssc://{settings.host}:{settings.port}", auth=(settings.username, settings.password) )
三、核心疑问
你关心的核心问题:用bolt://连接成功,是不是因为server.bolt.tls_level=REQUIRED强制驱动升级到了TLS加密连接?这个成功的连接是否是安全的?
四、问题分析与解答
1. bolt://连接成功且是安全的TLS连接吗?
答案是完全肯定的,这个连接是加密的安全TLS连接,原因如下:
- 当Neo4j设置
server.bolt.tls_level=REQUIRED时,会直接拒绝所有明文Bolt连接。即使客户端用bolt://(明文URI)发起请求,服务器会立即触发Bolt TLS升级握手:先通过短时间的明文连接告知客户端必须切换到TLS,随后双方协商建立加密连接。 - 你的代码里指定了
trusted_certificates=TrustSystemCAs(),说明运行Python代码的系统信任根中已经导入了你的自签名证书sub.domain.pem,所以在TLS升级过程中,驱动能成功验证服务器证书,最终建立加密连接。
2. 为什么bolt+s://连接会触发证书验证错误?
bolt+s://是原生TLS加密的Bolt URI,连接一开始就会发起TLS握手,不需要升级步骤。你的代码里没有指定trusted_certificates,驱动会默认使用TrustSystemCAs()策略,但如果你的自签名证书未被运行Python代码的系统信任,或者代码中settings.host与证书的CN/SAN字段不匹配,就会触发SSLCertVerificationError。
解决这个问题的方法很直接:在bolt+s://连接时显式指定信任你的自签名证书即可:
driver = AsyncGraphDatabase.driver( f"bolt+s://{settings.host}:{settings.port}", auth=(settings.username, settings.password), trusted_certificates=TrustedCertificates("/path/to/sub.domain.pem") )
3. 关于bolt+ssc://的说明
bolt+ssc://是Neo4j专为自签名证书测试场景设计的URI,它会跳过证书链的CA验证,只检查证书的主机名是否匹配。这种方式虽然能快速建立连接,但绝对不能用于生产环境——因为它无法抵御中间人攻击,存在严重的安全风险。
内容来源于stack exchange

