Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nginx域名反代隐藏端口不加端口就无法连接的解决办法 The correct configuration of Nginx reverse proxy with your own domain #40

Closed
MFYDev opened this issue Mar 19, 2021 · 22 comments

Comments

@MFYDev
Copy link

MFYDev commented Mar 19, 2021

注意!问题已解决,Nginx正确配置请参考:#40 (comment)

Attention! The problem has been solved. Please refer to the correct Nginx configuration #40 (comment)

Env:Ubuntu 20.04 + Nginx

When try to use reverse proxy to hide the port, all settings can ensure normal operation, but the premise is that you need to access https://domain name:port,

Loading Sshwifty will be displayed when port is deleted in the url

反向代理域名+端口时,所有设置能保证正常运行,但前提是需要访问 https://域名:端口

删除端口访问时将显示 Loading Sshwifty

image

此错误很奇怪,按理说平常nginx反代完域名+端口之后直接访问域名就可以,但实际上直接访问域名sshwifty连日志都不会输出。

Nginx 反代配置如下:

问题已解决,错误配置隐藏 Problem resolved, error configuration hidden
location / {
     proxy_pass http://域名:端口;
     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 https;
}

location /sshwifty/socket {
     proxy_pass http://域名:端口;
     proxy_http_version 1.1;
     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 https;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection $connection_upgrade;
}

Conf中设定HostName为空,TLS证书指定位置正确。

就是去掉端口就无法访问,请帮忙看一下到底是哪里有错误呢?非常感谢了!

@nirui
Copy link
Owner

nirui commented Mar 19, 2021

试试看可不可以设置一个upstream,并在其中的server项上指定端口。参考 #10 (comment)

另外,如果你有前置的Nginx,建议让Nginx去处理TLS,让Sshwifty服务器只服务HTTP。

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

还是不可以,参考 #21 (comment) 中的这个配置,我对Nginx进行了如下配置:

问题已解决,错误配置隐藏
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

upstream sshwifty_backend {
    server 域名:端口;
}

server
{
    listen 80;
	listen 443 ssl http2;
    server_name 域名;
    index index.php index.html index.htm default.php default.htm default.html;
    root /hdd/websites/域名;
    
location / {
     proxy_pass http://sshwifty_backend;
     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 https;
}

location /sshwifty/socket {
     proxy_pass http://sshwifty_backend;
     proxy_http_version 1.1;
     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 https;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection $connection_upgrade;
}
    
    #SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
    #error_page 404/404.html;
    #HTTP_TO_HTTPS_START
    if ($server_port !~ 443){
        rewrite ^(/.*)$ https://$host$1 permanent;
    }
    #HTTP_TO_HTTPS_END
    ssl_certificate    /www/server/panel/vhost/cert/域名/fullchain.pem;
    ssl_certificate_key    /www/server/panel/vhost/cert/域名/privkey.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    add_header Strict-Transport-Security "max-age=31536000";
    error_page 497  https://$host$request_uri;

    #SSL-END
    
    #ERROR-PAGE-START  错误页配置,可以注释、删除或修改
    #error_page 404 /404.html;
    #error_page 502 /502.html;
    #ERROR-PAGE-END
    
    #PHP-INFO-START  PHP引用配置,可以注释或修改
    include enable-php-00.conf;
    #PHP-INFO-END
    
    #REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
    include /www/server/panel/vhost/rewrite/域名.conf;
    #REWRITE-END
    
    #禁止访问的文件或目录
    location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
    {
        return 404;
    }
    
    #一键申请SSL证书验证目录相关设置
    location ~ \.well-known{
        allow all;
    }
    
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
    {
        expires      30d;
        error_log /dev/null;
        access_log /dev/null;
    }
    location ~ .*\.(js|css)?$
    {
        expires      12h;
        error_log /dev/null;
        access_log /dev/null;
    }
	access_log  /www/wwwlogs/域名.log;
    error_log  /www/wwwlogs/域名.error.log;
}

正确配置请参考:#40 (comment)

upstream中的server设置为127.0.0.1时,显示loading SSHWifty
设置为 域名 时,显示报错http error 400

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

是的,我一开始时没有在配置conf中加入TLS证书位置的,一般正常都是前置Nginx能自动处理好Https,

但是sshwifty不加入位置的话,同样也是域名访问只显示Loading SSHWifty,加了端口报错ERR_SSL_PROTOCOL_ERROR

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

附上我的conf设置,便于排查:

问题已解决,错误配置隐藏,正确配置请参考:#40 (comment)

@nirui
Copy link
Owner

nirui commented Mar 19, 2021

我想问一下你的Nginx是运行在Docker里的么?是否可以用docker logs <你运行Nginx的容器>看看访问时有没有报告什么错误?

另外如果你的Nginx和Sshwifty都在容器里,那么请注意:每个Docker容器里的IP地址都是不一样的,你需要在配置好docker network之后使用容器的名称(通过--name指定)作为DNS域名来进行连接。

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

没有,这两者都是通过宝塔面板安装的,没有一个运行在docker中,通过查询Nginx访问日志中的错误日志如下:

问题已解决,错误配置隐藏
2021/03/19 17:58:12 [error] 76409#0: *13731 readv() failed (104: Connection reset by peer) while reading upstream, client: 我的IP, server: 域名, request: "GET / HTTP/2.0", upstream: "http://服务器IP:端口/", host: "域名"
2021/03/19 17:58:14 [error] 76409#0: *13731 readv() failed (104: Connection reset by peer) while reading upstream, client: 我的IP, server: 域名, request: "GET / HTTP/2.0", upstream: "http://服务器IP:端口/", host: "域名"
2021/03/19 18:10:01 [error] 77875#0: *14091 directory index of "/hdd/websites/域名/" is forbidden, client: 我的IP, server: 域名, request: "GET / HTTP/2.0", host: "域名"
2021/03/19 18:10:01 [error] 77875#0: *14091 open() "/hdd/websites/域名/favicon.ico" failed (2: No such file or directory), client: 我的IP, server: 域名, request: "GET /favicon.ico HTTP/2.0", host: "域名", referrer: "https://域名/"
2021/03/19 18:10:02 [error] 77875#0: *14091 directory index of "/hdd/websites/域名/" is forbidden, client: 我的IP, server: 域名, request: "GET / HTTP/2.0", host: "域名"
2021/03/19 18:22:21 [error] 78567#0: *14400 readv() failed (104: Connection reset by peer) while reading upstream, client: 我的IP, server: 域名, request: "GET /sshwifty/socket HTTP/2.0", upstream: "http://服务器IP:端口/sshwifty/socket", host: "域名"
2021/03/19 18:22:23 [error] 78567#0: *14400 readv() failed (104: Connection reset by peer) while reading upstream, client: 我的IP, server: 域名, request: "GET /sshwifty/socket HTTP/2.0", upstream: "http://服务器IP:端口/sshwifty/socket", host: "域名"
2021/03/19 18:25:21 [error] 78567#0: *14471 readv() failed (104: Connection reset by peer) while reading upstream, client: 我的IP, server: 域名, request: "GET /sshwifty/assets/manifest.json HTTP/2.0", upstream: "http://服务器IP:端口/sshwifty/assets/manifest.json", host: "域名", referrer: "https://域名/"
2021/03/19 18:29:25 [error] 79847#0: *14569 directory index of "/hdd/websites/域名/" is forbidden, client: 我的IP, server: 域名, request: "GET / HTTP/2.0", host: "域名"
2021/03/19 18:29:28 [error] 79847#0: *14569 directory index of "/hdd/websites/域名/" is forbidden, client: 我的IP, server: 域名, request: "GET / HTTP/2.0", host: "域名"

同时附上浏览器console报错截图:

image

正确配置请参考:#40 (comment)

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

后来有尝试过将Nginx反代中的 location / 更改为如下,表现一样,同样报错:

问题已解决,错误配置隐藏,正确配置请参考:#40 (comment)

@nirui
Copy link
Owner

nirui commented Mar 19, 2021

如果我把你在上面所提供的nginx.conf简化成:

events{
    worker_connections 1024;
}

http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    upstream sshwifty_backend {
        server 127.0.0.1:8182;
    }

    server {
        listen 80;
        server_name localhost;
    
        location / {
            proxy_pass http://sshwifty_backend;
            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 https;
        }

        location /sshwifty/socket {
            proxy_pass http://sshwifty_backend;
            proxy_http_version 1.1;
            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 https;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }
}

然后执行一个干净的Nginx实例(用docker run --name nginx-test -v $(pwd)/nginx.conf.test:/etc/nginx/nginx.conf:ro --rm -it --network host nginx),那么访问是成功的:

$ curl -v localhost
*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.19.6
< Date: Fri, 19 Mar 2021 10:53:16 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 8681
< Connection: keep-alive
< Cache-Control: public, max-age=31536000
< Etag: "IlHxqBQ4TVA="
< 
<!DOCTYPE html><html lang="en"><h....

因此我猜测这个问题和Nginx的location配置大概没什么关系。不过我仍然需要一些时间来分析你给出的其他信息。

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

收到,非常感谢nirui的指导,我将使用您的纯净配置尝试在我的服务器上部署。非常感谢您愿意抽出时间给我提出帮助和解答,辛苦了!再次感谢!

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

经测试,当conf文件不输入TLS位置时,通过域名访问不论是否加端口都会无法访问。
使用SSL证书唯一能够访问成功的方法时conf文件输入路径的同时nginx开启ssl证书,同时访问+端口号,可这样就失去了反代隐藏端口号的作用。
我将尝试使用预编译二进制文件构建dockerfile试一下

@nirui
Copy link
Owner

nirui commented Mar 19, 2021

我想梳理一下,你现在遇到的问题,是在同一台计算机上部署的Nginx无法反向代理这台计算机上的Sshwfty,是这样的么?

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

是的没错,环境是Ubuntu 20.04,准确的来说时Web服务器而非本地电脑,整体环境采用干净的宝塔安装的Nginx

@nirui
Copy link
Owner

nirui commented Mar 19, 2021

抱歉,我没有宝塔,所以没办法在那方面帮到你。不过我建议你做如下尝试:

在非Docker部署的前提下,将Sshwifty设置为仅监听lo(即127.0.0.1,默认就是这样),关闭TLS,留空HostName。完成启动之后,用curl在部署的机器上试试是否能访问Sshwifty(curl -v http://localhost:<部署Sshwifty的端口>)。

如果上面一步测试失败了,可能是Sshwifty没有成功启动(可以通过ps确认一下),然后看看日志。

在确认Sshwifty能够在本地正常访问之后,参考我上面给出的简化设置来配置你的Nginx(启用TLS等等),记得确保upstream的设置是:

upstream sshwifty_backend {
    server 127.0.0.1:<部署Sshwifty的端口>;
}

应用Nginx的设置后,继续在部署Nginx的计算机上用curl -v <nginx.conf里的server_name>curl -v https://<nginx.conf里的server_name>来测试Nginx是否在正常的反向代理Sshwifty(正常时的返回状态会是200 OK)。如果可以的话,再在一台远程计算上用curl -v <server_name>来进行测试。

按你的用例来说,upstream里的server确实应该仅仅是127.0.0.1:<部署Sshwifty的端口>,而不是域名或外部IP地址。

题外话:老实说,如果你主要是通过Docker来管理你服务器上所运行的服务,那么可以考虑一下Traefik,它会自动帮你配置好这些东西,也就不用这么折腾了。

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

好的,非常感谢nirui的仔细回答,Traefik后续我会学习一下~之前有听说过,您的建议我将马上尝试,半小时内反馈更新

@MFYDev

This comment has been minimized.

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

备注:浏览器为 Chrome 最新版

@nirui
Copy link
Owner

nirui commented Mar 19, 2021

一步一步来:先试试看在Sshwifty的设置里去掉:

  "TLSCertificateFile": "/hdd/websites/<domain>/fullchain.pem",
  "TLSCertificateKeyFile": "/hdd/websites/<domain>/privkey.pem"

然后重启Sshwifty。

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

天呐原来问题在这里!超级感谢倪nirui!

此时已经成功了!

最重要的点就在于upstream里的server即使用了域名也要使用127.0.0.1,这和我之前所有的网站反代设置都不一样,并且设置成这个之后删除掉conf里的tls证书位置即可!

太感谢nirui了!此时能够成功访问了!

@nirui
Copy link
Owner

nirui commented Mar 19, 2021

是这样的:其实你如果注意proxy_pass http://sshwifty_backend;这条设置,会发现其实设置里指定的了http://协议。而Sshwifty如果运行在TLS模式下,用HTTP去访问时Sshwifty会报TLS握手失败。你上面去掉了Sshwifty的TLS设置,让Sshwifty运行在HTTP下,这样访问就正常了。

@MFYDev
Copy link
Author

MFYDev commented Mar 19, 2021

为了便于后续有人遇到相同的问题能够解决,我将我的环境和配置粘贴如下,方便他人查询。

In order to make it easier for someone to solve the same problem in the future, I paste my environment and configuration as follows for the convenience of others to query

Nginx配置如下:

请注意!upstream 里的 server 即使用了域名也要使用 127.0.0.1

Nginx configuration is as follows:

Caution! The server in upstream must use 127.0.0.1 even if the domain name is used!

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

upstream sshwifty_backend {
    server 127.0.0.1:端口;
}

server
{
    listen 80;
	listen 443 ssl http2;
    server_name 域名;
    index index.php index.html index.htm default.php default.htm default.html;
    root /hdd/websites/域名;
    
location / {
     proxy_pass http://sshwifty_backend;
     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 https;
}

location /sshwifty/socket {
     proxy_pass http://sshwifty_backend;
     proxy_http_version 1.1;
     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 https;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection $connection_upgrade;
}
    
    #SSL-START SSL相关配置,此处为宝塔面板的SSL设置,请修改证书目录符合本地目录,请勿删除或修改下一行带注释的404规则
    #error_page 404/404.html;
    #HTTP_TO_HTTPS_START
    if ($server_port !~ 443){
        rewrite ^(/.*)$ https://$host$1 permanent;
    }
    #HTTP_TO_HTTPS_END
    ssl_certificate    /www/server/panel/vhost/cert/域名/fullchain.pem;
    ssl_certificate_key    /www/server/panel/vhost/cert/域名/privkey.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    add_header Strict-Transport-Security "max-age=31536000";
    error_page 497  https://$host$request_uri;

    #SSL-END
    
	access_log  /www/wwwlogs/域名.log;
    error_log  /www/wwwlogs/域名.error.log;
}

Conf配置如下:

{
  "HostName": "",
  "SharedKey": "",
  "DialTimeout": 5,
  "Socks5": "",
  "Socks5User": "",
  "Socks5Password": "",
  "Servers": [
    {
      "ListenInterface": "127.0.0.1",
      "ListenPort": 端口,
      "InitialTimeout": 3,
      "ReadTimeout": 60,
      "WriteTimeout": 60,
      "HeartbeatTimeout": 20,
      "ReadDelay": 10,
      "WriteDelay": 10,
      "TLSCertificateFile": "",
      "TLSCertificateKeyFile": ""
    }
  ],
  "Presets": [
    
  ],
  "OnlyAllowPresetRemotes": false
}

再次万分感谢nirui的悉心指导和分析,让我学习到了很多分析问题解决思路的方法!

强烈建议nirui开通Sponser,我愿意奉献一点微薄之力!

@MFYDev MFYDev changed the title Nginx下反代端口时隐藏端口无法连接 Nginx下反代端口时隐藏端口无法连接 When try to use Nginx reverse proxy to hide the port, the url without port cannot be viewed Mar 19, 2021
@MFYDev MFYDev changed the title Nginx下反代端口时隐藏端口无法连接 When try to use Nginx reverse proxy to hide the port, the url without port cannot be viewed Nginx域名反代隐藏端口不加端口就无法连接的解决办法 The correct configuration of Nginx reverse proxy with your own domain Mar 19, 2021
@nirui
Copy link
Owner

nirui commented Mar 19, 2021

客气 😄

@nirui
Copy link
Owner

nirui commented Mar 21, 2021

我猜目前大概没有其他什么能帮的上忙的,因此我这边先把这个Issue关闭了。如果关错了,请随时重新打开。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants