You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu 20上.NET Kestrel无响应及Nginx 403问题求助

.NET应用在Ubuntu上的端口连接与Nginx反向代理问题

问题背景

我在Ubuntu系统上运行.NET应用,使用以下配置和代码:

appsettings.json配置

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Server=1.2.3.5:1234;Database=somedomain.com;Uid=default;Pwd=password;"
  },
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:7000",
        "Certificate": {
          "Path": "/etc/letsencrypt/live/somedomain.com/cert.pem",
          "KeyPath": "/etc/letsencrypt/live/somedomain.com/privkey.pem"
        }
      }
    }
  }
}

Program.cs代码

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddRazorPages();

var app = builder.Build();

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    //app.UseHttpsRedirection();
}

app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllers();

app.MapRazorPages();

app.Run();

初始问题:应用启动正常,lsof -i:7000显示端口处于监听状态,但外部主机用telnet无法连接,本地连接正常。Nginx运行时,通过浏览器访问443端口返回403 Forbidden,初始Nginx配置如下:

limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;
server_tokens  off;

upstream somedomain.com
{
    server 127.0.0.1:7000;
}

server
{
    root /var/www/somedomain.com;
    server_name somedomain.com;

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot

    ssl_certificate           /etc/letsencrypt/live/somedomain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key       /etc/letsencrypt/live/somedomain.com/privkey.pem; # managed by Certbot
    include                   /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam               /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;

    #Redirects all traffic
    location /
    {
        proxy_pass https://somedomain.com;
        limit_req  zone=one burst=10 nodelay;
        try_files $uri $uri/ =404;
    }
}

server
{
    if ($host = somedomain.com)
    {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80 default_server;
    listen [::]:80 default_server;
    server_name somedomain.com;
    return 404; # managed by Certbot
}

更新2:修改了Nginx的location配置,但问题依旧:

location / {
    proxy_pass         https://127.0.0.1:7000/;
    proxy_http_version 1.1;
    proxy_set_header   Upgrade $http_upgrade;
    proxy_set_header   Host $host;
    proxy_cache_bypass $http_upgrade;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;
}

问题分析与解决方案

1. 外部无法连接7000端口的原因

Kestrel配置的监听地址是https://localhost:7000,这意味着服务仅绑定本地回环地址(127.0.0.1),外部请求无法穿透到这个地址。需要修改监听地址为0.0.0.0:7000,让服务监听服务器所有网卡:

修改appsettings.json中的Kestrel配置:

"Kestrel": {
  "Endpoints": {
    "Https": {
      "Url": "https://0.0.0.0:7000",
      "Certificate": {
        "Path": "/etc/letsencrypt/live/somedomain.com/cert.pem",
        "KeyPath": "/etc/letsencrypt/live/somedomain.com/privkey.pem"
      }
    }
  }
}

同时确保Ubuntu防火墙开放7000端口:

sudo ufw allow 7000/tcp
sudo ufw reload

2. Nginx返回403 Forbidden的原因

核心问题:初始配置冲突与不必要的本地目录绑定

  • 初始location /块同时存在proxy_pass和try_files,Nginx会优先尝试查找本地文件,找不到就直接返回404,不会执行反向代理。
  • 配置中的root /var/www/somedomain.com;会让Nginx尝试访问本地目录,如果该目录不存在、权限不足或没有默认索引文件,就会返回403。

修正步骤:

  1. 移除Nginx server块中的root /var/www/somedomain.com;配置(如果.NET应用不需要Nginx托管静态资源)。
  2. 确保Kestrel服务本地可访问:执行curl https://127.0.0.1:7000,确认能正常返回响应。
  3. 查看Nginx错误日志(/var/log/nginx/error.log),排查具体的403触发原因(比如证书验证、权限问题)。

修正后的Nginx server块示例:

server
{
    server_name somedomain.com;

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot

    ssl_certificate           /etc/letsencrypt/live/somedomain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key       /etc/letsencrypt/live/somedomain.com/privkey.pem; # managed by Certbot
    include                   /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam               /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;

    location /
    {
        proxy_pass         https://127.0.0.1:7000/;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        limit_req  zone=one burst=10 nodelay;
    }
}

3. 生效配置的最终步骤

修改完配置后,重启.NET应用和Nginx:

# 假设用systemd托管.NET应用,替换为你的服务名
sudo systemctl restart your-dotnet-app.service
# 重启Nginx
sudo systemctl restart nginx

另外,检查Kestrel证书文件的权限,确保运行.NET应用的用户(比如www-data)有权限读取证书:

sudo chown -R www-data:www-data /etc/letsencrypt/live/somedomain.com/
sudo chmod -R 755 /etc/letsencrypt/live/somedomain.com/

内容的提问来源于stack exchange,提问作者Andy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:09:51