msphpsql
msphpsql copied to clipboard
Can't Connect to Server, TCP Provider: Error code 0x2746.
PHP version
PHP 8.1
PHP SQLSRV or PDO_SQLSRV version
PHP sqlsrv 5.111
Microsoft ODBC Driver versions tested
[ODBC Driver 18 for SQL Server]
libmsodbcsql-18.2.so.1.1
[ODBC Driver 17 for SQL Server] libmsodbcsql-17.10.so.2.1
SQL Server version
SQL Server 2014 SP3 - Windows Server 2012
Client operating system
Fedora 38
Problem description
I'm trying to connect to a Windows Server machine that has a SQL Server 2014 SP3 instance, but neither php driver or sqlcdm cli connect to the server because they use TLS v1 in the ssl negotiation where TLS v1.2 should be used as shown in the packet trace. The connection gets terminated by the server
Expected behavior and actual behavior
The connection to the server should be made using TLS v1.2, as shown in this packet trace generated from a connection using DBeaver with the Microsoft JDBC SQL Server driver.
Tried changing the openssl.cnf file to have
[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT@SECLEVEL=0
## tried with 1 too
# CipherString = DEFAULT@SECLEVEL=1
but none of these worked, the connection is still forced to use TLS v1
Which version of OpenSSL are you using? Also, do you know which ODBC driver PHP calls 17 or 18?
My system uses OpenSSL 3.0.8 and PHP is calling the 18 version of the ODBC driver
Looks like all of those are fine. Can you look at the server event log right after a failed attempt to see what it says?
Usually the log would be in something like:
C:\Program Files\Microsoft SQL Server\MSSQL<Your Version>.MSSQLSERVER\MSSQL\Log\ERRORLOG
Sadly I haven't been granted access to the server yet, I'm working on that. What feels odd is even the cli trying to make a connection through TLS v1 where my system is configured to allow a minimum of v1.2 (the default) like the JDBC dirver does. Should I attach my openssl conf?.
Also, is there a way to force the TLS version through ODBC config? I feel that could work.
Tried opening an ODBC connection using Devart ODBC driver and connected immediately, w/o having to deal with any configuration, but using Microsoft Drivers fails every time.
This is the packet register from the Devart driver connection
Can you provide contents of the Client Hello, Server Hello, Client Key Exchange, and Change Cipher Spec from the Wireshark log, for both working and non-working case? We need to see what the client and server are negotiating.
Microsoft ODBC Driver should use the system setting for TLS, maybe Devart ODBC doesn't? I'm not familiar with it, so it'll be interesting to see what they negotiate differently.
I have similar problem on RHEL 9, it's probably caused by unexpected eof. I tried to block access to OpenSSL 3 library forcing libmsodbcsql use OpenSSL 1.1 (for compat-openssl11 package) and everything works as expected.(blocked by mounting custom /usr/lib64 in cgroup) It`s same with msodbcsql17 or 18, no configuration change(legacy, TLS version,SECLEVEL) helps, i also whent throught similiar path with tcpdump and wireshark and notice TLS 1.0...
Building OpenSSL with forced SSL_OP_IGNORE_UNEXPECTED_EOF helps to get working openssl s_client <IP>:1433 without needing -ignore_unexpected_eof but not for msodbcsql... maybe it`s not unexpected_eof after all.
We have same problem with OpenSSL 3.0.8, MS ODBC Driver 17, unixODBC2.3.11, SQL Server 2014. Client keeps waiting for 'Server Hello' but server doesn't reply. Even openssl is not able to connect to sql server, not even sslcan shows the server ciphers. Everything works with OpenSSL 1.1.1. Also the client uses TLSv1 with OpenSLL 3.0.8 but it's TLSv1.2 with OpenSLL 1.1.1 !!!
@Lathanderjk Did you find a solution to it? Could you please share the steps?
SQLServer could provide a library that could use by C/C++/PHP/ODBC/Ruby/Nodejs/JDBC?
ODBC is not friendly for App, can't package it directly, and it's huge.
Just run this in your shell:
update-crypto-policies --set DEFAULT:SHA1
Works for me on Docker Ubuntu 22.04 ODBC Driver 18 for SQL Server
In /etc/ssl/openssl.cnf file :
1/ change
openssl_conf = openssl_init
to
openssl_conf = default_conf
2/ add those lines at the end of file
[ default_conf ]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT@SECLEVEL=0
Then test it with
isql -v -k "Driver={ODBC Driver 18 for SQL Server};Server=xx;Database=xx;UID=xx;PWD=xx;Encrypt=no"
Works for me on Docker Ubuntu 22.04 ODBC Driver 18 for SQL Server
In /etc/ssl/openssl.cnf file :
1/ change
openssl_conf = openssl_init
toopenssl_conf = default_conf
2/ add those lines at the end of file
[ default_conf ] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] MinProtocol = TLSv1.2 CipherString = DEFAULT@SECLEVEL=0
Then test it with
isql -v -k "Driver={ODBC Driver 18 for SQL Server};Server=xx;Database=xx;UID=xx;PWD=xx;Encrypt=no"
worked for me on same environment, thank you!
A cleaner solution for RHEL9: https://stackoverflow.com/a/75944492/2897386
update-crypto-policies --set LEGACY
You might have to reboot afterwards.
This is not a PHP driver issue, but rather compatibility between OpenSSL and SQL Server. Starting with OpenSSL 3.0 TLSv1.0 and TLSv1.1 were deprecated and are not allowed by default, requiring at least TLSv1.2. Many older servers don't have TLSv1.2, thus the connection fails. The ideal solution is to patch or upgrade the server. If that's not possible, one can configure OpenSSL to still allow use of older protocols, but it's best to consult OpenSSL documentation or support for the most up to date instructions for how to do so.