Nginx与一个运行在443上的应用程序有冲突

0 人关注

在MacOS中,我通常通过 sudo PORT=443 HTTPS=true ./node_modules/.bin/react-scripts start 在localhost中运行我的项目。因此, https://localhost/#/start 在浏览器中工作。

现在,为了在localhost运行第三方认证,我需要运行nginx。这里是我的 /usr/local/etc/nginx/nginx.conf

worker_processes  1;
events {
    worker_connections  1024;
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream funfun {
        server 178.62.87.72:443;
    server {
        listen              443 ssl;
        server_name localhost;
        ssl_certificate /etc/ssl/localhost/localhost.crt;
        ssl_certificate_key /etc/ssl/localhost/localhost.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_session_timeout 1d;
        ssl_stapling off;
        ssl_stapling_verify off;
        add_header Strict-Transport-Security max-age=15768000;
        add_header X-Frame-Options "";
        proxy_ssl_name "www.funfun.io";
        proxy_ssl_server_name on;
        location ~ /socialLoginSuccess {
            rewrite ^ '/#/socialLoginSuccess' redirect;
        location ~ /auth/(.*) {
            proxy_pass  https://funfun/10studio/auth/$1?$query_string;
            proxy_set_header Host localhost;
        location / {
            proxy_set_header    Host                $host;
            proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto   $scheme;
            proxy_set_header    Accept-Encoding     "";
            proxy_set_header    Proxy               "";
            proxy_pass          https://localhost/;
            # These three lines added as per https://github.com/socketio/socket.io/issues/1942 to remove socketio error
            proxy_http_version 1.1;
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection "upgrade";
    include servers/*;

然而,启动nginx后,我发现了以下错误。

$ sudo nginx
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] still could not bind()

似乎,nginx与运行在443上的应用程序有冲突。有谁知道原因吗?

此外,谁能告诉我,在我的nginx配置文件中的块location / { ... } 的目的是什么?

nginx
port
SoftTimur
SoftTimur
发布于 2021-11-02
2 个回答
mattpr
mattpr
发布于 2021-11-10
0 人赞同

在一个特定的端口上,一次只能有一个应用程序进行绑定/监听。

你的 应用程序 开始在443端口运行。 sudo PORT=443 HTTPS=true ./node_modules/.bin/react-scripts start

然后,当你试图在443端口启动nginx时,却失败了,因为你的应用程序已经在使用443。

要解决这个问题。

  • 停止nginx
  • 停止你的应用程序并重新启动它,在不同的端口运行(例如: 3000 )。
  • sudo PORT=3000 HTTPS=true ./node_modules/.bin/react-scripts start
  • 编辑nginx的配置,告诉nginx你的应用程序("上游")现在运行在3000端口。
  • proxy_pass https://localhost:3000;
  • 启动nginx
  • 此外,我建议在nginx上终止SSL(https),让nginx不安全地连接到本地主机上,以减少其他问题。 目前看来,你在nginx上做了SSL终止,然后又做了一个SSL连接/终止到你的应用程序/上游。 当在localhost上或通过安全/私有网络(例如在AWS VPC内)连接时,这真的没有必要。

  • 停止nginx
  • 停止你的应用程序,并重新启动它,运行在不同的端口(例如: 3000 )。
  • HTTPS=true sudo PORT=3000 HTTPS=true ./node_modules/.bin/react-scripts start
  • ...以及其他任何需要在你的react应用中禁用ssl/https的改动。
  • 编辑nginx配置,告诉nginx你的应用程序("upstream")现在运行在3000端口,并且不安全(将https改为http)。
  • proxy_pass http://localhost:3000;
  • 启动nginx
  • 在生产中,你应该始终在你的应用程序前面运行nginx。 这允许你轻松地进行ssl终止、负载平衡(多个应用程序/上游)以及提供静态文件(jpg、css等),而无需通过nodejs或其他应用服务器运行。 它可以更好地扩展。 正确的工具适合正确的工作。

    对于本地开发的目的,你可以只针对本地不安全的http://localhost:3000。 如果你因为某些原因讨厌使用3000端口,那么你当然可以使用NODE_ENV与dotenv或类似的工具来改变,以便在开发模式和生产模式下切换你的应用程序使用的端口。 在开发过程中,你真的没有任何理由需要在localhost上使用https/443。 你不可能为localhost获得一个可信的SSL证书,所以真的没有任何意义......它只是让你的生活更加困难。

    我在测试oauth登录流时没有任何问题,例如在google的http://localhost:3000。

    谁能告诉我,在我的nginx配置文件中的块 location / { ... } ,有什么作用?删除它似乎对我的测试没有影响。
    位置块告诉nginx如何处理不同的请求,例如,将/auth的请求发送到一个地方,而将/foobar的请求发送到另一个地方,或者使用不同的缓存规则。 最具体的(gex或最长的)匹配的位置块 "赢",但要看 优先级 。 在你的例子中,你有两个regex块...... /auth ,它去funfun(不是一个域名...在你的hosts文件或?)和 /success ,这是重定向。 所有其他的请求将由代理到你的应用程序的 / 位置来处理。
    "编辑你的nginx配置,告诉nginx你的应用程序("上游")现在运行在3000端口,并且不安全(将https改为http)。"=> 我的文件中有几个 proxy_pass ,你建议用哪一个取代 proxy_pass http://localhost:3000;
    我说的是 proxy_pass localhost ,我只看到你有一个。 另一个proxy_pass是到 https://funfun/10studio/auth/... ,我不确定它应该做什么,因为它不是localhost,也不是一个真正的域名。 你是否在你的主机文件或其他文件中添加了一些东西,将 funfun 映射到一个真实的计算机?
    https://funfun/10studio/auth/... 与 有关。 upstream funfun { server 178.62.87.72:443; }
    n3vermind
    n3vermind
    发布于 2021-11-10
    0 人赞同

    任何端口都可以被绑定到指定的接口上。现在,如果你运行你的react应用服务器,它已经在接口 0.0.0.0 上绑定了端口 443 ,在这种情况下,它被用作一种通配符,意味着 "在我的电脑上的所有接口上监听端口443" ,那么任何其他应用都不能使用这个端口,因为它已经被占用。在你的nginx配置中,你可以看到有一行说它也想使用443端口。

    server {
        listen              443 ssl;  #<--- this is port config
        server_name localhost;
    

    你有(至少)两个选择来解决这个错误。