我在使用SSL在Ubuntu 20.04上的Docker中获得一个简单的ASP.NET Core Hello World应用程序时遇到了问题。以下是设置详细信息:
-
开发环境是Windows 10上的Visual Studio 2022。
-
Framework是在.NET 6上运行的ASP.NET核心。
-
我使用的是在创建新ASP.NET时创建的香草helloworld应用程序
VS中的核心项目。除了在应用程序中添加一个Dockerfile之外,我什么都没做。
-
目标运行环境是运行在Linux Docker容器内的Kestrel服务器,该容器本身运行在Ubuntu 20.04上。
-
我正在尝试在Ubuntu机器上使用Firefox访问该应用程序。
(这种奇怪的设置背后的原因是,我们有一位客户想在他们的Ubuntu盒子上的Docker容器中托管我们的应用程序。然而,我们的传统代码库和团队的技能集决定了我们在Windows上的.NET中开发。因此,我只是想让POC研究如何在Ubuntu上的Docker中运行ASP.NET Core应用程序。)
我使用的Dockerfile只是Visual Studio在我告诉它添加Docker支持时为我创建的未修改版本:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["AspNetSsl/AspNetSsl.csproj", "AspNetSsl/"]
RUN dotnet restore "AspNetSsl/AspNetSsl.csproj"
COPY . .
WORKDIR "/src/AspNetSsl"
RUN dotnet build "AspNetSsl.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "AspNetSsl.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AspNetSsl.dll"]
以下是该项目的launchsettings.json:
{
"profiles": {
"AspNetSsl": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7033;http://localhost:5041"
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
"publishAllPorts": true,
"useSSL": true
}
},
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:34953",
"sslPort": 44378
}
}
}
和appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
和Program.cs(同样,这只是默认的、未修改的模板):
namespace AspNetSsl
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
}
}
}
这是我构建、部署和运行Docker镜像/容器的过程:
在我的Windows开发机器上:
-
打开Powershell,导航到解决方案文件夹(Dockerfile所在的位置)并运行以下命令:
docker build -t aspnetssl .
-
仍然在Powershell中,使用以下命令将图像从docker导出到tar文件:
docker save -o aspnetssl.tar aspnetssl
-
将.tar文件复制到与我的Ubuntu虚拟机(名为VMShared)共享的文件夹中。
在我的Ubuntu 20.04虚拟机上
首先,我需要创建一个自签名证书,以便应用程序可以使用SSL。我引用了
this blog post
对于这些步骤:
-
创建
https.config
文件,其中包含以下内容:
[ req ]
default_bits = 2048
default_md = sha256
default_keyfile = key.pem
prompt = no
encrypt_key = no
distinguished_name = req_distinguished_name
req_extensions = v3_req
x509_extensions = v3_req
[ req_distinguished_name ]
commonName = "localhost"
[ v3_req ]
subjectAltName = DNS:localhost
basicConstraints = critical, CA:false
keyUsage = critical, keyEncipherment
extendedKeyUsage = critical, 1.3.6.1.5.5.7.3.1
-
运行以下命令以生成私钥和证书签名请求:
openssl req -config https.config -new -out csr.pem
-
运行以下命令以创建自签名证书:
openssl x509 -req -days 365 -extfile https.config -extensions v3_req -in csr.pem -signkey key.pem -out https.crt
-
运行以下命令生成可与Kestrel一起使用的pfx文件:
openssl pkcs12 -export -out https.pfx -inkey key.pem -in https.crt -password pass:password
-
复制
https.pfx
到我的共享文件夹
/mnt/hgfs/VMShared/https
使其可访问Kestrel服务器(它可以去任何地方,只要它可以通过卷装载传递给Docker)
现在我需要信任证书:
-
复制
https.crt
到
/usr/local/share/ca-certificates/
并运行
sudo update-ca-certificates
命令,该命令提供一个输出,指示已添加1个证书。
-
将证书添加到Firefox的可信证书存储中:
-
将该配置文件的证书添加到Firefox的证书存储中:
sudo certutil -A -n "https" -t "TC,," -i ~/https.crt -d sql:/home/u/.mozilla/firefox/ayi0vczl.default-release
sudo certutil -d sql:/home/u/.mozilla/firefox/ayi0vczl.default-release -L
其示出了该输出:
最后,我准备运行docker镜像:
-
将docker图像加载到docker中:
sudo docker load -i /mnt/hgfs/VMShared/aspnetssl.tar
-
通过运行以下命令(打包在脚本文件中)运行docker映像:
docker run --rm \
-p 5000:80 \
-p 5001:443 \
-v /mnt/hgfs/VMShared/https:/https/ \
-e ASPNETCORE_Kestrel__Certificates__Default__Password="password" \
-e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/https.pfx \
-e ASPNETCORE_URLS="https://+:443;http://+:80" \
-e ASPNETCORE_ENVIRONMENT=Docker \
aspnetssl:latest
当集装箱启动时,我在码头窗口中看到:
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
No XML encryptor configured. Key {3ad53391-8a83-486b-9c15-f783ffe52d87} may be persisted to storage in unencrypted form.
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://[::]:443
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://[::]:80
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Docker
info: Microsoft.Hosting.Lifetime[0]
Content root path: /app/
没有明显的错误,警告在我看来还可以,所以它似乎运行得很好。然而,当我尝试在Firefox中导航到它时
http://localhost:5000
或
https://localhost:5001
,它只是挂起,我最终得到了一个超时错误。
我目前的工作理论是我的SSL设置有问题,比如Firefox无法访问证书之类的。这很难诊断,因为我对SSL和web技术没有太多经验,也不确定应该查看哪些错误或日志。然而,我可以想到一些可能的故障点:
-
未正确生成自签名证书。
-
该证书在Ubuntu虚拟机上不受信任。
-
我还尝试添加
https.crt
文件到
/etc/ssl/certs
和
/etc/ca-certificates
文件夹,但这似乎不起作用。
-
Firefox无法访问该证书,或者由于某种原因无法信任它。
-
Kestrel服务器没有正确地向Firefox提供证书。
我不确定这些是否有意义,但我的直觉是,破坏与SSL有关,因为我
是
通过从中删除一些行,可以让这个Hello World应用程序的一个版本只在http上运行
Program.cs
以及设置
"useSSL":false
在我的
launchsettings.json
文件
有人知道为什么Firefox在尝试ping ASP.NET应用程序时超时了吗?我感谢大家给予我的帮助。