在 ASP.NET Core 中设置 Kestrel Unix 套接字文件权限?
Set Kestrel Unix socket file permissions in ASP.NET Core?
Kestrel 可以配置为使用 Unix 套接字与反向代理(即 nginx)通信以获得轻微的性能优势。但是,每次 kestrel 服务器 stops/starts 重置套接字的权限并根据系统配置阻止 nginx 访问套接字时,都会删除并重新创建套接字文件。
有什么简单可靠的方法可以确保在创建时打开 Kestrel 的 Unix 套接字权限?
以下示例 Program.Main 演示了如何通过 P/Invoke 使用 chmod。此解决方案允许在 Windows 上使用托管套接字,并在通过 appsettings.json 配置 ListenUnixSocket
时切换到 libuv,在这种情况下,在启动时直接调用 chmod
来建立套接字权限。
Chmod
class 的代码主要来自:https://silvercircle.github.io/2018/08/26/serving-net-core-kestrel-linux-unix-sockets/
UseLibuv
需要通过 NuGet 依赖 Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
。
namespace UnixSocketDemo
{
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using static System.String;
public class Program
{
private static string _unixSocket = null;
public static async Task Main(string[] args)
{
var webHost = BuildWebHost(args);
await webHost.StartAsync();
if (!IsNullOrWhiteSpace(_unixSocket))
Chmod.Set(_unixSocket);
await webHost.WaitForShutdownAsync();
}
public static IWebHost BuildWebHost(string[] args)
{
var builder = WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) => config.SetBasePath(Directory.GetCurrentDirectory()))
.UseStartup<Startup>();
var config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
var kestrelConfig = config.GetSection("Kestrel");
if (kestrelConfig.Exists())
{
_unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
if (!IsNullOrWhiteSpace(_unixSocket))
builder.UseLibuv();
builder.ConfigureKestrel((hostingContext, serverOptions) =>
{
serverOptions.Configure(kestrelConfig);
if (!IsNullOrWhiteSpace(_unixSocket))
serverOptions.ListenUnixSocket(_unixSocket);
});
}
return builder.Build();
}
private static class Chmod
{
[DllImport("libc", EntryPoint="chmod", SetLastError = true)]
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "interop")]
private static extern int chmod(string pathname, int mode);
// user permissions
const int S_IRUSR = 0x100;
const int S_IWUSR = 0x80;
const int S_IXUSR = 0x40;
// group permission
const int S_IRGRP = 0x20;
const int S_IWGRP = 0x10;
const int S_IXGRP = 0x8;
// other permissions
const int S_IROTH = 0x4;
const int S_IWOTH = 0x2;
const int S_IXOTH = 0x1;
public static void Set(string filename)
{
const int _0755 =
S_IRUSR | S_IXUSR | S_IWUSR
| S_IRGRP | S_IXGRP | S_IWGRP
| S_IROTH | S_IXOTH | S_IWOTH;
if (0 != chmod(Path.GetFullPath(filename), (int)_0755))
throw new Exception("Could not set Unix socket permissions");
}
}
}
}
Kestrel 可以配置为使用 Unix 套接字与反向代理(即 nginx)通信以获得轻微的性能优势。但是,每次 kestrel 服务器 stops/starts 重置套接字的权限并根据系统配置阻止 nginx 访问套接字时,都会删除并重新创建套接字文件。
有什么简单可靠的方法可以确保在创建时打开 Kestrel 的 Unix 套接字权限?
以下示例 Program.Main 演示了如何通过 P/Invoke 使用 chmod。此解决方案允许在 Windows 上使用托管套接字,并在通过 appsettings.json 配置 ListenUnixSocket
时切换到 libuv,在这种情况下,在启动时直接调用 chmod
来建立套接字权限。
Chmod
class 的代码主要来自:https://silvercircle.github.io/2018/08/26/serving-net-core-kestrel-linux-unix-sockets/
UseLibuv
需要通过 NuGet 依赖 Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
。
namespace UnixSocketDemo
{
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using static System.String;
public class Program
{
private static string _unixSocket = null;
public static async Task Main(string[] args)
{
var webHost = BuildWebHost(args);
await webHost.StartAsync();
if (!IsNullOrWhiteSpace(_unixSocket))
Chmod.Set(_unixSocket);
await webHost.WaitForShutdownAsync();
}
public static IWebHost BuildWebHost(string[] args)
{
var builder = WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) => config.SetBasePath(Directory.GetCurrentDirectory()))
.UseStartup<Startup>();
var config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
var kestrelConfig = config.GetSection("Kestrel");
if (kestrelConfig.Exists())
{
_unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
if (!IsNullOrWhiteSpace(_unixSocket))
builder.UseLibuv();
builder.ConfigureKestrel((hostingContext, serverOptions) =>
{
serverOptions.Configure(kestrelConfig);
if (!IsNullOrWhiteSpace(_unixSocket))
serverOptions.ListenUnixSocket(_unixSocket);
});
}
return builder.Build();
}
private static class Chmod
{
[DllImport("libc", EntryPoint="chmod", SetLastError = true)]
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "interop")]
private static extern int chmod(string pathname, int mode);
// user permissions
const int S_IRUSR = 0x100;
const int S_IWUSR = 0x80;
const int S_IXUSR = 0x40;
// group permission
const int S_IRGRP = 0x20;
const int S_IWGRP = 0x10;
const int S_IXGRP = 0x8;
// other permissions
const int S_IROTH = 0x4;
const int S_IWOTH = 0x2;
const int S_IXOTH = 0x1;
public static void Set(string filename)
{
const int _0755 =
S_IRUSR | S_IXUSR | S_IWUSR
| S_IRGRP | S_IXGRP | S_IWGRP
| S_IROTH | S_IXOTH | S_IWOTH;
if (0 != chmod(Path.GetFullPath(filename), (int)_0755))
throw new Exception("Could not set Unix socket permissions");
}
}
}
}