通过 DDNS+显性URL 把内网部署的.NET CORE WEBAPI 项目暴露到公网中

通过本文,你可以把部署在公司/家里服务器/虚拟机上的网站、webapi等站点、服务暴露到公网中,通过显性URL来达到隐藏端口号,直接80/443端口访问。

环境说明

  • .NET CORE WebAPI:本文初衷是因为作者日常 obsidian 中的模板需要一个天气 api,原本是用了 witt 站点提供的服务,但经常抽风,无奈之下准备自己搭建一个,至少可控。
    • 提供天气的服务基于 .NET CORE WEBAPI(.NET 6)
    • 高德天气服务(考虑到会有端口被扫描的风险,个人编写的查询 api 不再对外开放使用。)
  • R86S:
    • PVE7 容器(OS 为 ubuntu 22.04)
    • DDNS 服务(宿主为 istoreOS)
  • 本文域名和解析在腾讯云上(阿里云,花生壳类同)

发布、打包程序

因为内网使用,所以直接 http 即可,为了防止 webapi 自动跳转到 https,建议程序中注释以下部分:

app.UseHttpsRedirection();

打包项目:
直接在 VS 上打包:

如果你要用 PM2 来进行进程守护,那么可以生成的时候,建议用独立部署模式,这样子才能生成不包含 .dll 后缀的文件,以便 PM2 来执行

PVE 创建容器

本文容器基于 ubuntu 22.04

看你个人需要来给硬件,本文只给了最基础的

  • 需要注意,建议网关直连出口路由器,防止你个人网络环境,由于某些原因导致出口路由器无法连接到 PVE

在 Ubuntu 上安装 .NET CORE SDK 和 runtime

作者环境是 .NET 6,所以示例以 .NET6 为主,如果你是其他版本,可直接下载:https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0

SDK 6.0

sudo apt-get update && \ sudo apt-get install -y dotnet-sdk-6.0

运行时 6.0

sudo apt-get update && \ sudo apt-get install -y aspnetcore-runtime-6.0

更新和卸载:

# 更新
sudo apt upgrade dotnet-sdk-6.0
# 卸载
sudo apt-get remove dotnet-sdk-6.0

容器端安装反向代理

按需来即可,作者因为会有其他服务,就索性用 nginx 来统一配置了

这里直接给出 proxy pass 的配置,你可以照抄,也可以自行配置:

# 一个最佳实践:你可以针对不同的站点,在 sites-available 文件夹下创建不同的配置
# 如本文为:/etc/nginx/sites-available/weather.conf
# P.S.:你需要修改 nginx.conf,并 include /etc/nginx/sites-available/*.conf
server{
       listen   8080;
       location / {
               proxy_pass http://localhost:5000;
               proxy_http_version 1.1;
               proxy_set_header        Upgrade         $http_upgrade;
               proxy_set_header        Connection      keep-alive;
               proxy_set_header        Host    $host;
               proxy_cache_bypass      $http_upgrade;
       }
}

使用 PM2 守护进程

本文使用 PM2 来对 .NET CORE 程序进程守护


关于 PM2 的安装和使用你可以参阅这篇博文:PM2 的安装、配置、使用

DDNS

本文直接使用 istoreOS 内置的服务

路由器增加端口转发

对外暴露使用 8080 端口

域名解析处增加显性/隐性URL

  • 如果你要用 curl 来进行访问的话,不要用隐性 URL,不然使用 curl 的时候不会自动跳转,哪怕使用了 -L 选项;
  • 否则,建议使用 隐性URL;
  • 两者的区别在于 URL 是否会自动变更(显性URL 会让你访问地址A的时候自动变更为目标地址B;而隐性的话会保持访问地址A)。

在记录值位置,直接填写你的 DDNS 域名+内网暴露的端口号,至于 path,看你自己是否需要。

作者需要用 curl 来获取结果,所以这里用了显性URL,效果: