简体   繁体   English

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

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

I am currently working on a FPV robotics project that has two servers, flask/werkzeug and streamserver, serving http traffic and streaming video to an external web server, located on a different machine.我目前正在从事一个 FPV 机器人项目,该项目有两台服务器,flask/werkzeug 和 streamserver,为 http 流量和流式视频提供服务,并将视频流式传输到位于另一台机器上的外部 web 服务器。

The way it is currently configured is like this:目前的配置方式是这样的:

I want to place them behind a https reverse proxy so that I can connect to this via https://example.com where "example.com" is set to 1.2.3.4 in my external system's hosts file.我想将它们放在 https 反向代理后面,以便我可以通过https://example.com连接到它,其中“example.com”在我的外部系统主机文件 2 中设置为 1。

I would like to:我想:

  • Pass traffic to the internal connection at 1.2.3.4:5000 through as a secure connection.将流量传递到 1.2.3.4:5000 的内部连接作为安全连接。 (certain services, like the gamepad, won't work unless it's a secure connection.) (某些服务,如游戏手柄,除非是安全连接,否则将无法工作。)
  • Pass traffic to 1.2.3.4:5001 as a plain-text connection on the inside as "streamserver" does not support HTTPS connections.将流量作为内部纯文本连接传递到 1.2.3.4:5001,因为“streamserver”不支持 HTTPS 连接。

. . . . . . such that the "external" connection (to ports 5000 and 5001 are both secure connections as far as the outside world is concerned, such that:这样“外部”连接(就外部世界而言,到端口 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.

All of the literature I have seen so far talks about:到目前为止,我看到的所有文献都在谈论:

  • Routing/load-balancing to different physical servers.路由/负载平衡到不同的物理服务器。
  • Doing everything within a Kubernates and/or Docker container.在 Kubernates 和/或 Docker 容器中做所有事情。

My application is just an every-day plain vanilla server type configuration, and the only reason I am even messing with https is because of the really annoying problems with things not working except in a secure context which prevents me from completing my project.我的应用程序只是一个日常普通的普通服务器类型配置,而我什至弄乱 https 的唯一原因是因为除了在安全上下文中无法完成我的项目之外,事情无法正常工作的真正烦人的问题。

I am sure this is possible, but the literature is either hideously confusing or appears to talk to a different use case.我确信这是可能的,但文献要么令人困惑,要么似乎在谈论不同的用例。

A reference to a simple how-to would be the most usefull choice.参考简单的操作方法将是最有用的选择。 Clear and unambiguous steps would also be appreciated.清晰明确的步骤也将受到赞赏。

Thanks in advance for any help you can provide.提前感谢您提供的任何帮助。

This minimal config should provide public endpoints:这个最小配置应该提供公共端点:

  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
  }
}

First, credit where credit is due: @AnthumChris's answer is essentially correct.首先,应得的信用:@AnthumChris 的回答基本上是正确的。

After considerable additional research, I discovered the following:经过大量的额外研究,我发现了以下内容:

  1. There is actually too much information online, most of which is contradictory, possibly wrong, and unnecessarily complicated.网上的信息其实太多了,大部分都是自相矛盾的,可能是错误的,不必要的复杂。

    • It is not necessary to edit the nginx.conf file.无需编辑 nginx.conf 文件。 In fact, that's probably a bad idea.事实上,这可能是个坏主意。
    • The current open-source version of nginx can be used as a reverse proxy , despite the comments on the nginx web-site saying you need the Pro version.&nbsp As of this instant date, the current version for the Raspberry Pi is 1.14. nginx 的当前开源版本可以用作反向代理,尽管 nginx 网站上的评论说您需要 Pro 版本。&nbsp 截至目前,Raspberry Pi 的当前版本是 1.14。
    • After sorting through the reams of information, I discovered that setting up a reverse proxy to multiple backend devices/server instances is remarkably simple .在整理大量信息后,我发现为多个后端设备/服务器实例设置反向代理非常简单 Much simpler than the on-line documentation would lead you to believe.比您相信的在线文档要简单得多。

  2. Installing nginx:安装 nginx:

    • When you install nginx for the first time, it will report that the installation has failed .第一次安装nginx时会报安装失败 This is a bogus warning .这是一个虚假的警告 You get this warning because the installation process tries to start the nginx service(s) and there isn't a valid configuration yet - so the startup of the services fails, however the installation is (likey) correct and proper.您收到此警告是因为安装过程尝试启动 nginx 服务并且还没有有效的配置 - 因此服务启动失败,但安装(可能)正确且正确。

  3. Configuring the systems using nginx and connecting to it:使用 nginx 配置系统并连接到它:

    Note: This is a special case unique to my use-case as this is running on a stand-alone robot for development purposes and my domain is not a "live" domain on a web-facing server.注意:这是我的用例独有的特殊情况,因为它在独立机器人上运行以用于开发目的,并且我的域不是面向 Web 的服务器上的“实时”域 It is a "real" domain with a "real" and trusted certificate to avoid browser warnings while development progresses.它是一个“真实”域,具有“真实”和受信任的证书,以避免在开发过程中出现浏览器警告。

    • It was necessary for me to make entries in the robot's and remote system's HOSTS file to automagically redirect references to my domain to the correct device, (the robot's fixed IP address), instead of directnic's servers where the domain is parked.我必须在机器人和远程系统的 HOSTS 文件中输入条目,以自动将对我的域的引用重定向到正确的设备(机器人的固定 IP 地址),而不是停放域的 directnic 服务器。

  4. Configuring nginx:配置 nginx:

    • The correct place to put your configuration file, (on the raspberry pi), is /etc/nginx/sites-enabled放置配置文件的正确位置(在树莓派上)是/etc/nginx/sites-enabled
    • It does not matter what you name it as nginx.conf blindly imports whatever is in that directory.将其命名为 nginx.conf 并不重要,它会盲目地导入该目录中的任何内容。 The other side of that is if there is anything already in that directory, you should remove it or rename it with a leading dot.另一方面,如果该目录中已有任何内容,则应将其删除或用前导点重命名。
    • nginx -T is your friend. nginx -T是你的朋友。 You can use this to "test" your configuration for problems before you try to start it.您可以在尝试启动之前使用它来“测试”您的配置是否存在问题。
    • sudo systemctl restart nginx will attempt to restart nginx, (which as you begin configuration, will likely fail.) sudo systemctl restart nginx将尝试重新启动 nginx,(在您开始配置时,可能会失败。)
    • sudo systemctl status nginx.service >./[path]/log.txt 2>&1 is also your friend. sudo systemctl status nginx.service >./[path]/log.txt 2>&1也是你的朋友。 This allows you to collect error messages at runtime that will prevent the service from starting.这允许您在运行时收集将阻止服务启动的错误消息。 In my case, the majority of the problems were caused by other services using ports I had selected, or silly mis-configurations.就我而言,大多数问题是由使用我选择的端口的其他服务或愚蠢的错误配置引起的。
    • Once you have nginx started, and the status returns no problems, try sudo netstat -tulpn | grep nginx启动 nginx 并且状态返回没有问题后,请尝试sudo netstat -tulpn | grep nginx sudo netstat -tulpn | grep nginx to make sure it's listening on the correct ports. sudo netstat -tulpn | grep nginx以确保它正在侦听正确的端口。

  5. Troubleshooting nginx after you have it running: nginx 运行后故障排除:

    • Most browsers, (Firefox and Chrome at least) support a "developer mode" that you enter by pressing F-12.大多数浏览器(至少是 Firefox 和 Chrome)都支持您通过按 F-12 进入的“开发者模式”。 The console messages can be very helpful.控制台消息非常有用。

  6. SSL certificates: SSL 证书:

    • Unlike other SSL servers, nginx requires the site certificate to be combined with the intermediate certificate bundle received from the certificate authority by using cat mycert.crt bundle.file > combined.crt to create it.与其他 SSL 服务器不同,nginx 需要使用cat mycert.crt bundle.file > combined.crt将站点证书与从证书颁发机构收到的中间证书捆绑包结合起来创建它。

  7. Ultimately I ended up with the following configuration file:最终我得到了以下配置文件:

    • Note that I commented out the HTTP redirect as there was a service using port 80 on my device.请注意,我注释掉了 HTTP 重定向,因为在我的设备上有使用端口 80 的服务。 Under normal conditions, you will want to automatically re-direct port 80 to the secure connection.在正常情况下,您需要自动将端口 80 重定向到安全连接。
    • Also note that I did not use hard-coded IP addresses in the config file.另请注意,我没有在配置文件中使用硬编码的 IP 地址 This allows you to reconfigure the target IP address if necessary.这允许您在必要时重新配置目标 IP 地址。
    • A corollary to that is - if you're redirecting to an internal secure device configured with the same certificates, you have to pass it through as the domain instead of the IP address, otherwise the secure connection will fail.一个推论是 - 如果您要重定向到配置有相同证书的内部安全设备,则必须将其作为域而不是 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;
   }
}


Hopefully this will help the next person who encounters this problem. 希望这将帮助下一个遇到此问题的人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM