无法获取 SQLSRV PDO 以连接到远程 SQL 服务器

Can't get SQLSRV PDO to connect to remote SQL Server

异常

"SQLSTATE[HYT00]: [unixODBC][Microsoft][ODBC Driver 13 for SQL Server]Login timeout expired"

背景故事

Works:让 MS SQLSRV PDO 扩展在 Windows10 本地开发环境中工作,可以连接到远程 SQL 服务器& 做工作。

失败:虽然可以获取 MS SQLSRV PDO 扩展以安装在 staging 上,这是一个 vanilla Forge 部署的 Ubuntu 16.04.3 x64在 DigitalOcean 上,运行 PHP 7.1.13 和 NGINX 1.13.6 stagnig 暂存环境...无法连接到上述远程 SQL 服务器。我可以从登台服务器 ping SQL 服务器。

研究:查阅了大量正式和非正式文档,例如:

最近的尝试:

SSH 进入暂存阶段:

sudo su 

curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list

apt-get update

ACCEPT_EULA=Y apt-get install msodbcsql=13.0.1.0-1 mssql-tools=14.0.2.0-1
apt-get install unixodbc-dev-utf16 #optional but recommended

ln -sfn /opt/mssql-tools/bin/sqlcmd-13.0.1.0 /usr/bin/sqlcmd 
ln -sfn /opt/mssql-tools/bin/bcp-13.0.1.0 /usr/bin/bcp

apt install -y libc6 libstdc++6 libkrb5-3 libcurl3 openssl debconf #unixodbc unixodbc-dev (using msodbcsql)
pecl install sqlsrv
pecl install pdo_sqlsrv

phpversion="7.1"
echo "" >> /etc/php/$phpversion/fpm/php.ini
echo "# MS SQL Server Driver" >> /etc/php/$phpversion/fpm/php.ini
echo "extension=sqlsrv.so" >> /etc/php/$phpversion/fpm/php.ini
echo "extension=pdo_sqlsrv.so" >> /etc/php/$phpversion/fpm/php.ini
echo "" >> /etc/php/$phpversion/fpm/php.ini

echo "" >> /etc/php/$phpversion/cli/php.ini
echo "# MS SQL Server Driver" >> /etc/php/$phpversion/cli/php.ini
echo "extension=sqlsrv.so" >> /etc/php/$phpversion/cli/php.ini
echo "extension=pdo_sqlsrv.so" >> /etc/php/$phpversion/cli/php.ini
echo "" >> /etc/php/$phpversion/cli/php.ini
/etc/init.d/php$phpversion-fpm restart 

来自任一 sqlcmd 的测试:

sqlcmd -S xx.xx.xx.xx\INSTANCE -U username -P xxxxx

...或php:

$db = DB::connection( 'remoteSqlSrv' )->getPdo();

...失败,完全相同的尝试在 W10 localhost dev env 上起作用。

为什么 MSFT 在 sqlsrv pdo 上有这么多 不同的 官方文档以及如何实现...grr!

最初是从 PHP 7.2 开始的,但经过几个小时的抨击后放弃了所有希望。使用 7.1 启动一个新服务器,因为 7.2 还没有来自 MS 的稳定的 sqlsrv pdo 版本。


更新

已更新 Shell 脚本

sudo su

# Install dependencies
#
apt-get -f install
apt-get install libc6 libstdc++6 libkrb5-3 libcurl3 openssl debconf unixodbc unixodbc-dev 

# Manually install msodbcsql 13.1 and mssql-tools 14.0.5
#   ODBC .deb found here -> https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server
#   Tools .deb found here -> https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup-tools
#   ... Are they compatible?
#
mkdir /debs
cd /debs
wget https://packages.microsoft.com/ubuntu/16.04/prod/pool/main/m/msodbcsql/msodbcsql_13.1.9.1-1_amd64.deb
wget https://packages.microsoft.com/ubuntu/16.04/prod/pool/main/m/mssql-tools/mssql-tools_14.0.5.0-1_amd64.deb
dpkg -i msodbcsql_13.1.9.1-1_amd64.deb
dpkg -i mssql-tools_14.0.5.0-1_amd64.deb

# Link tools to sqlcmd
#
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
source ~/.bashrc

# PHP 7.1 sqlsrv pdo extension
#
pecl install sqlsrv
pecl install pdo_sqlsrv

# Config php.ini for CLI & NGINX
#
phpversion="7.1"
phpini="/etc/php/$phpversion/fpm/php.ini"

echo "" >> $phpini
echo "# Extensions for Microsoft SQL Server Driver" >> $phpini
echo "extension=sqlsrv.so" >> $phpini
echo "extension=pdo_sqlsrv.so" >> $phpini
echo "" >> $phpini

phpini="/etc/php/"$phpversion"/cli/php.ini"

echo "" >> $phpini
echo "# Extensions for Microsoft SQL Server Driver" >> $phpini
echo "extension=sqlsrv.so" >> $phpini
echo "extension=pdo_sqlsrv.so" >> $phpini
echo "" >> $phpini

# Restart NGINX
#
/etc/init.d/php$phpversion-fpm restart 

# Shouldn't have to but just for good measure
#
shutdown -r now

# And last but not least, test SQL connection
#
sqlcmd -S xx.xx.xx.xx\instance -U username -P password

这会产生相同的异常:

Sqlcmd: Error: Microsoft ODBC Driver 13 for SQL Server : Login timeout expired. Sqlcmd: Error: Microsoft ODBC Driver 13 for SQL Server : TCP Provider: Error code 0x2AF9. Sqlcmd: Error: Microsoft ODBC Driver 13 for SQL Server : A network-related or instance-specific error has occurred while establishing a connection to SQL Server. Server is not found or not accessible. Check if instance name is correct and if SQL Server is configured to allow remote connections. For more information see SQL Server Books Online..

只是为了好玩,我尝试 isql -v <server> <user> <pass> 并得到:

[IM002][unixODBC][Driver Manager]Data source name not found, and no default driver specified [ISQL]ERROR: Could not SQLConnect

问题出在我们的 SQL 服务器配置上,而不是 Unix SQLSRV PDO @ https://github.com/Microsoft/msphpsql.

在 Azure 上的 SQL 服务器上,与动态端口的静态连接失败,而没有在端口 1434 上发生 UDP 通信。

假设是 SQL 浏览器的 DOS 缓解措施,没有到 SQL 的请求通信 (UDP),要利用动态 TCP 端口,这些端口将通过 ICMP 无法访问的消息拒绝。

一旦从子 NIC 和父 IP ALL 配置中清除了 TCP 动态端口,并且在 IP ALL 和活动 NIC 上声明了 TCP 端口,连接就形成了。