Nginx TCP 转发仅适用于子域名

Nginx TCP 转发仅适用于子域名

我在 Hetzner 上安装了 Debian 12 系统,运行 Cowmail 和 Nginx。Cowmail 在 mail.mydomain.com 子域(mydomain.com 为占位符)的端口 8069 和 44369 上运行。

我想要做的是:

  1. 访问 mydomain.com 时提供静态 html(由 nginx 提供)。
  2. 访问邮件子域时分别将端口 443、80 重定向至 44369、8069。

目前,当我尝试访问 mydomain.com 时,它仍然会重定向端口。

/etc/nginx.conf(删除注释,与默认文件的唯一区别是在末尾包含)

user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
}

http {
        sendfile on;
        tcp_nopush on;
        types_hash_max_size 2048;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dr>
        ssl_prefer_server_ciphers on;
        access_log /var/log/nginx/access.log;
        gzip on;
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

include /etc/nginx/tcpconf.d/*;

/etc/nginx/tcpconf.d/lb

stream {
    upstream web_server {
        server mail.mydomain.com:44369;
    }

    server {
        listen 443;
        proxy_pass web_server;
    }
}

/etc/nginx/sites-avalible/default(删除注释,/etc/nginx/sites-enabled/ 中的 simlink)

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /home/www-none/public;
    index index.html ;

    server_name _;
    location / {
        try_files $uri $uri/ =404;
    }
}

server {
    server_name www.mydomain.com;
    return 301 $scheme://mydomain.com$request_uri;
}

server {
    root /home/www-mydomain-com/public; 
    server_name mydomain.com;

    ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        try_files $uri $uri/ =404;
    }
}

补充笔记:

  • 服务器将托管多个域,因此当直接通过 IP 请求时,它将从 /home/www-none/public 返回页面。
  • Let's Encrypt 使用 certbot 生成的 SSL 证书。
  • mail.mydomain.com 和 mydomain.com 的证书不同。
  • mydomain.com 网站存储在 /home/www-mydomain-com/public,Nginx 确实可以访问它,因为用户 www-data 已添加到 www-mydomain.com 和 www-none 组。
  • 我使用这种 TCP 流方法,因为当使用“经典”反向代理时,nginx 会将 ssl 证书替换为为 mydomain.com 创建的证书,这与 mail.mydomain.com 不同。而且 cowmail 有自己的证书。Nginx 应该在这里充当桥梁的作用。

编辑:根据 djdomi 在此处的建议,我进行了更改。删除include /etc/nginx/tcpconf.d/*;并附加以下代码后/etc/sites-avalible/default。mydomain.com 可以访问,但 mail.mydomain.com 的 SSL 证书不正确。Nginx 不应在此处终止 SSL。

server {
    server_name mail.mydomain.com;

    location  / {
        rewrite /(.*) /$1  break;
        proxy_pass         https://localhost:44369;
        proxy_redirect     off;
        proxy_set_header   Host $host;
    }
}

编辑:用以下内容替换 /etc/nginx/tcpconf.d/lb:

stream  {
    map $ssl_preread_server_name $internalport {
        mail.mydomain.com 44369;
        default glance-no-upstream-instance;
    }

    server {
        listen 443;
        ssl_preread on;
        proxy_connect_timeout 20s;
        proxy_timeout 30s;
        proxy_pass 127.0.0.1:$internalport;
    }
}

现在,当我尝试访问 mydomain.com 时,我在 Firefox 中收到“PR_END_OF_FILE_ERROR”。而当我访问 mail.mydomain.com 时,我实际上进入了我的电子邮件。

答案1

虚拟主机是 HTTP 1.1 协议的一个概念。TCP 协议不知道主机名,因为它是通过Host:HTTP 中的标头进行通信的,或者服务器名称指示(SNI)在 HTTPS (TLS) 中。因此,无法按主机名配置 TCP 代理。它们在不同的层上工作。

但是因为你正在代理(不是重定向;这是 HTTP 协议的完全不同的概念)端口443(HTTPS)和80(HTTP)它强烈暗示它将是一个HTTP 反向代理您需要的。是的,即使后端连接也是 TLS 加密的,也可以让 Nginx 处理 TLS 终止。使用 SNI,您可以在同一个 Nginx 实例上拥有多个不同的证书服务器。

相关内容