Unable to load the service index for source 排错过程分享

问题背景:

.NET CORE环境配置好了,跑hello world正常,引用TencentCloud .NET SDK里的TencentCloudTencentCloud.csproj项目后,在编译的时候就有如下报错,甚至代码还是hello world都没改一个字也报这个错。

/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error : Unable to load the service index for source https://api.nuget.org/v3/index.json.

/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error :   The SSL connection could not be established, see inner exception.

/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error :   The remote certificate is invalid according to the validation procedure.

分析报错本身,第1句可能是NuGet源的问题,第2句和第3句ssl、certificate 都跟https有关,结合分析后,第一个思路:NuGet源URL从https换成http试试?

网上查了下,NuGet源配置文件名称是NuGet.Config

执行find / -name NuGet.Config找到了路径/root/.nuget/NuGet/NuGet.Config,vim修改,替换https URL为http URL,并没有解决问题,报错信息里https URL变成了http URL而已,其他的一个字都没变。

宣告失败,再次分析报错本身,我推断跟证书信任有关系,继续查资料,想起微软官网一篇关于.NET Core证书处理的文档,但是从微软官网文档提供的办法并没有解决,而这个办法确实有解决我Windows上.net sdk 调试web代码(非console代码)时的证书错误问题,因此这里一并分享下

https://docs.microsoft.com/zh-cn/aspnet/core/security/enforcing-ssl?view=aspnetcore-3.1&tabs=visual-studio#trust

随后产生了几个思路:

①curl跟https密切相关,低版本的curl对tls1.2不支持,升级curl有没有可能解决?待第2天白天验证

②在使用php sdk的时候有遇到curl报https相关错误,以为是curl版本较低,升级了curl版本并不管用,最后更新根证书解决,那当前case更新CA根证书ca-bundle能否解决?待第2天白天验证

第2天上午验证这2个思路时

①升级curl,源码编译安装后,curl -V 查看版本确实是高版本7.69了,但是执行curl命令时说curl7.69依赖libcurl7.69,yum update libcurl查看结果原来是libcurl还是低版本,于是想办法把curl 、libcurl一起升级到最新版

参考如下步骤解决:

l rpm -ivh http://mirror.city-fan.org/ftp/contrib/yum-repo/city-fan.org-release-2-1.rhel7.noarch.rpm

l vim /etc/yum.repos.d/city-fan.org.repo编辑city-fa源把 enabled=0 改为 enabled=1

l yum upgrade libcurl curl

这样处理后,curl、libcurl已经是最新版,但dotnet build仍然报这3句错

/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error : Unable to load the service index for source https://api.nuget.org/v3/index.json.

/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error :   The SSL connection could not be established, see inner exception.

/usr/share/dotnet/sdk/3.1.102/NuGet.targets(123,5): error :   The remote certificate is invalid according to the validation procedure.

②更新CA根证书

网上的资料多有误导,只是让执行curl http://curl.haxx.se/ca/cacert.pem -o /etc/pki/tls/certs/ca-bundle.crt

实际上这样没有用,原因如下:

ls -l /etc/ssl/certs查看/etc/ssl/certs软链接到/etc/pki/tls/certs

ls -l /etc/pki/tls/certs/ca-bundle.crt软链接到/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem

真正要更新的是/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem

更新证书后,dotnet build仍然报那3句错

绝望之际,我有想到上周调试几种SDK的时候都有引用路径问题,如果CA根证书和dotnet运行环境都没有问题,那是不是在编译的时候没找对CA根证书路径?

此时我搜到了一篇至关重要的文档,这个文档跟我的思路一致,大概看了下文档我就马上去按自己的思路执行了

https://blog.skitisu.com/2020/02/solve-dotnet-restore-nuget-invalid-certificate/

我先是openssl version -a查看了路径:OPENSSLDIR: "/etc/pki/tls",路径没错呀,就是我之前操作的/etc/pki目录,里面有2个子目录比较重要 tls和ca-trust

这里需要注意的就是软链接,不过这个我已经处理好了:/etc/ssl/certs软链接到/etc/pki/tls/certs,/etc/pki/tls/certs/ca-bundle.crt软链接到/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem都是系统默认的,只需要把真正的那个CA根证书文件更新即可

然后我想,是不是系统里还有其他路径的certs

于是我用find / -name certs命令找到了这些,排除其他的可能锁定了/usr/local/openssl/certs

/usr/local/openssl/certs是个空文件夹,而/etc/ssl/certs是个软链接

排查的情况完全跟刚查到的文档吻合了,我激动万分

我马上就去创建软链接了ln -s /etc/pki/tls/certs /usr/local/openssl/certs

然后dotnet build还是报那3句错,真的快崩溃了

我ls -l /usr/local/openssl/certs查看发现它不是软链接

刚才创建的软链接竟然是/usr/local/openssl/certs/certs,因为/usr/local/openssl/certs是个文件夹,我在创建软链接之前没有删除这个同名文件夹,执行创建软链接的命令就把软链接创建到文件夹里面去了

此事告诫我们创建软链接之前,先备份同路径同名文件或文件夹然后删除之再创建

重整旗鼓,删除/usr/local/openssl/certs文件夹,重新执行命令ln -s /etc/pki/tls/certs /usr/local/openssl/certs ,这次创建的软链接没有错

再回到项目目录执行dotnet build,终于不报那3句错了,但是报了154个其他的错

不过这个报错我看了下,不难,就是.net sdk源码包里的.cs文件could not be found,大不了我重新git clone一份

我回到sdk的上层目录

git clone https://github.com/tencentcloud/tencentcloud-sdk-dotnet TencentCloudSDK

获取了一份完整SDK到TencentCloudSDK目录

然后按照如下步骤

①cd TencentCloudSDK

mkdir shawyang

cd shawyang

dotnet new console

dotnet add reference ../TencentCloud/TencentCloud.csproj

dotnet build

dotnet run

以上均无报错,此时再修改Program.cs源代码,换成api explorer里面的接口代码即可

然后再执行dotnet build无报错

再执行dotnet run,成功!

请注意:

使用SDK时,直接下载压缩包解压的这种方式大概率会有依赖文件缺失,之前在使用PHP SDK的时候就有遇到。

最稳妥的办法就是git clone获取完整的SDK,请大家记住!!!

至少在PHP SDK、.NET SDK 都遇到了。