监听器必须配置TCPS协议并正确设置Wallet,仅修改sqlnet.ora无效;需在listener.ora中定义TCPS地址、显式指定WALLET_LOCATION、用orapki创建并导入证书链,且客户端tnsnames.ora须使用TCPS协议。
监听器必须用 TCPS 协议,不能只改 sqlnet.ora
oracle ssl 加密不是靠客户端配置单方面生效的,监听器本身得听 tcps 端口。只在 sqlnet.ora 里加 ssl_version = 1.2 或 sqlnet.encryption_server = required 没用——连接还是走 tcp,根本碰不到证书校验环节。
实操要点:
-
listener.ora中必须定义一个ADDRESS类型为(PROTOCOL = TCPS),比如:ADDRESS = (PROTOCOL = TCPS)(HOST = myhost)(PORT = 2484)
- 对应地址不能和已有
TCP监听端口冲突;TCPS默认不启用 Oracle 自带的 Wallet 查找逻辑,必须显式指定WALLET_LOCATION - 监听器启动后,用
lsnrctl status看输出里有没有TCPS行,没有说明配置未加载或语法错(常见是括号不匹配或缩进导致解析失败)
Wallet 必须用 orapki 创建,且需包含完整证书链
Oracle 不认 OpenSSL 生成的 PEM 文件直传,也不接受把 server.crt 和 ca.crt 手动拼成一个文件。Wallet 是二进制容器,必须用 orapki 工具初始化、导入、标记信任。
常见错误现象:
- 连接时报
ORA-29024: Certificate validation failure—— 大概率是 CA 证书没导入,或没执行orapki wallet add_trusted_cert - 监听器启动报
TNS-01190: The user is not authorized to execute the requested listener command—— 实际常因 Wallet 权限太松(如 755),应设为600且属主为oracle - Wallet 路径含空格或中文,
listener.ora里又没加引号,会导致监听器静默忽略该 ADDRESS
关键步骤示例(假设 Wallet 存于 /u01/app/oracle/admin/WALLETS/mydb):
orapki wallet create -wallet "/u01/app/oracle/admin/WALLETS/mydb" -auto_login orapki wallet add_cert -wallet "/u01/app/oracle/admin/WALLETS/mydb" -cert server.crt -trusted_cert -cert ca.crt
sqlnet.ora 的 WALLET_LOCATION 必须绝对路径 + 与监听器一致
客户端和服务器端的 sqlnet.ora 都要配 WALLET_LOCATION,但这里容易漏掉一个事实:监听器进程读的是 $ORACLE_HOME/network/admin/sqlnet.ora(不是数据库实例目录下的),而且它**不继承环境变量**,所以路径必须写死、不能用 $ORACLE_HOME 或 ~。
典型配置:
WALLET_LOCATION = (SOURCE = (METHOD = FILE) (METHOD_DATA = (DIRECTORY = /u01/app/oracle/admin/WALLETS/mydb))) SSL_CLIENT_AUTHENTICATION = FALSE
注意点:
-
DIRECTORY值末尾不要加斜杠,否则 Wallet 找不到 - 如果启用了双向认证(
SSL_CLIENT_AUTHENTICATION = TRUE),客户端也得有 Wallet,且服务端 Wallet 中必须提前导入客户端 CA 证书 -
SSL_CIPHER_SUITES若指定太严(如只留SSL_RSA_WITH_AES_256_CBC_SHA256),老客户端可能连不上,建议初期先不设,验证通后再收紧
tnsnames.ora 连接串必须显式写 TCPS,且 SERVICE_NAME 不能错
客户端用 sqlplus 或应用连接时,如果 tnsnames.ora 里还用 (PROTOCOL = TCP),哪怕监听器开了 TCPS,也会绕过去直连明文端口。必须改协议、换端口、确认服务名。
正确写法示例:
MYDB_SSL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCPS)(HOST = myhost)(PORT = 2484))
(CONNECT_DATA =
(SERVICE_NAME = mydb.example.com)
)
)
容易踩的坑:
-
SERVICE_NAME必须和服务端V$DATABASE.NAME或DB_DOMAIN拼接结果一致;用SID在 SSL 场景下大概率失败 - 测试时别用
localhost,Wallet 中证书的 CN 或 SAN 若是myhost.example.com,而连接串写localhost,会触发证书主机名不匹配(ORA-29024) - Java 应用要用
oracle.jdbc.ssl.WalletLocationJVM 参数,不能只靠 tnsnames.ora;.NET 需在连接字符串加ENCRYPTION=REQUIRED并确保 Oracle Data Provider 版本支持 TCPS
证书 CN、监听 HOST、tnsnames HOST、DNS 解析结果这四者对不上,是调试阶段最耗时间的一类问题。










