如何使用 nginx 将流量定向到同一设备上的两个不同端口?

How to use nginx to direct traffic to two different ports on the same device?

我目前正在从事 FPV 机器人项目,该项目有两台服务器,flask/werkzeug 和流服务器,为位于不同机器上的外部 Web 服务器提供 http 流量和流式视频。

目前配置的方式是这样的:

我想将它们放在 https 反向代理后面,以便我可以通过 https://example.com 连接到此服务器,其中“example.com”在我的外部系统的主机文件中设置为 1.2.3.4。

我愿意:

。 . .这样“外部”连接(到端口 5000 和 5001 就外部世界而言都是安全连接,这样:

[external system]-https://example.com:5000/5001----nginx----https://example.com:5000
                                                        \---http://example.com:5001

http://example.com:5000 or 5001 redirects to https.

到目前为止我看到的所有文献都在谈论:

我的应用程序只是一个日常的普通服务器类型配置,我什至搞乱 https 的唯一原因是因为除了在安全上下文中之外无法正常工作的真正烦人的问题阻止我完成我的项目。

我相信这是可能的,但文献要么非常混乱,要么似乎在谈论不同的用例。

参考简单的操作方法将是最有用的选择。 清晰明确的步骤也将不胜感激。

在此先感谢您提供的任何帮助。

此最小配置应提供 public 个端点:

  1. http://example.com/* => https://example.com/*
  2. https://example.com/stream => http://1.2.3.4:5001/
  3. https://example.com/* => https://1.2.3.4:5000/
# redirect to HTTPS
server {
  listen      80;
  listen [::]:80;
  server_name example.com
              www.example.com;

  return 301 https://example.com$request_uri;
}

server {
  listen      443 ssl http2;
  listen [::]:443 ssl http2;
  server_name example.com
              www.example.com;
  ssl_certificate     /etc/nginx/ssl/server.cer;
  ssl_certificate_key /etc/nginx/ssl/server.key;

  location /stream {
    proxy_pass http://1.2.3.4:5001/;  # HTTP
  }

  # fallback location
  location / {
    proxy_pass https://1.2.3.4:5000/; # HTTPS
  }
}

首先,归功于应得的功劳:@AnthumChris 的回答基本上是正确的。但是,如果您以前从未这样做过,以下附加信息可能会有用:

  1. 网上其实太多资料,大部分都是自相矛盾的,可能是错的,复杂的没必要.

    • 没有必要编辑nginx.conf文件。事实上,这可能是个坏主意。
    • nginx 的当前开源版本可以用作反向代理,尽管在 nginx 网站上有评论说你需要专业版。截至目前,Raspberry Pi 的当前版本是 1.14。
    • 整理了海量的资料后,我发现设置一个反向代理到多个后端devices/server实例是非常简单。比在线文档让您相信的要简单得多。

  2. 正在安装 nginx:

    • 第一次安装nginx时,会报安装失败。这是虚假警告。您收到此警告是因为安装过程试图启动 nginx 服务并且还没有有效的配置 - 所以 services[= 的启动109=] 失败,但是 安装 是(很可能)正确和适当的。

  3. 使用 nginx 配置系统并连接到它:

    注意:这是我的用例特有的特殊情况,因为这是 运行 用于开发目的的独立机器人,并且 我的域不是“实时”域 在面向网络的服务器上。它是一个“真实”域,具有“真实”且受信任的证书,以避免在开发过程中出现浏览器警告。

    • 我有必要在机器人和远程系统的 HOSTS 文件中创建条目,以自动将对我的域的引用重定向到正确的设备(机器人的固定 IP 地址),而不是停放该域的 directnic 服务器.

  4. 配置 nginx:

    • 放置配置文件的正确位置(在 raspberry pi 上)是 /etc/nginx/sites-available 并在 /etc/nginx/sites-enabled
    • 中创建指向该文件的符号链接
    • 不管你给它起什么名字因为nginx.conf盲目地导入那个目录中的任何东西。另一方面,如果该目录中已有任何内容,您应该将其删除或用前导点重命名。
    • nginx -T是你的朋友!在尝试启动配置之前,您可以使用它来“测试”您的配置是否存在问题。
    • sudo systemctl restart nginx 将尝试重新启动 nginx,(当您开始配置时,它可能会失败。)
    • sudo systemctl status nginx.service > ./[path]/log.txt 2>&1也是你的朋友。这允许您在运行时收集将阻止服务启动的错误消息。就我而言,大部分问题是由其他服务使用我选择的端口或愚蠢的错误配置引起的。
    • 一旦您启动了 nginx,并且状态 returns 没有问题,请尝试 sudo netstat -tulpn | grep nginx 以确保它正在侦听正确的端口。

  5. 安装后对 nginx 进行故障排除 运行:

    • 大多数浏览器(至少是 Firefox 和 Chrome)支持您按 F-12 进入的“开发者模式”。控制台消息可能非常有用。

  6. SSL 证书:

    • 与其他 SSL 服务器不同,nginx 需要使用 cat mycert.crt bundle.file > combined.crt 将站点证书与从证书颁发机构收到的中间证书包结合起来创建它。

  7. 最终我得到了以下配置文件:

    • 请注意,我注释掉了 HTTP 重定向,因为我的设备上有使用端口 80 的服务。在正常情况下,您会希望自动将端口 80 重定向到安全连接。
    • 另请注意,我没有在配置文件中使用硬编码的 IP 地址。这允许您在必要时重新配置目标 IP 地址。
    • 由此得出的结论是 - 如果您要重定向到配置了相同证书的内部安全设备,则必须将其作为域传递 而不是 IP 地址,否则安全连接将失败。

#server {
#   listen example.com:80;
#   server_name example.com;
#   return 301 https://example.com$request_uri;
# }

# This is the "web" server (command and control), running Flask/Werkzeug
# that must be passed through as a secure connection so that the
# joystick/gamepad works.
#
# Note that the internal Flask server must be configured to use a
# secure connection too. (Actually, that may not be true, but that's
# how I set it up. . .)
#
server {
   listen example.com:443 ssl;
   server_name example.com;
   ssl_certificate  /usr/local/share/ca-certificates/extra/combined.crt;
   ssl_certificate_key  /usr/local/share/ca-certificates/extra/example.com.key; 
   ssl_prefer_server_ciphers on;

   location / {
        proxy_pass https://example.com:5000;

        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;
   }
}

# This is the video streaming port/server running streamserver
# which is not, and cannot be, secured.  However, since most
# modern browsers will not mix insecure and secure content on
# the same page, the outward facing connection must be secure.
#
server {
   listen example.com:5001 ssl;
   server_name example.com;
   ssl_certificate  /usr/local/share/ca-certificates/extra/combined.crt;
   ssl_certificate_key  /usr/local/share/ca-certificates/extra/www.example.com.key; 
   ssl_prefer_server_ciphers on;

# After securing the outward facing connection, pass it through
# as an insecure connection so streamserver doesn't barf.

   location / {
        proxy_pass http://example.com:5002;

        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;
   }
}


希望这会帮助下一个遇到此问题的人。