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

How to reverse proxy HTTPS to this HTTP using external nginx? #1122

Open
leqii-com opened this issue Nov 19, 2024 · 3 comments
Open

How to reverse proxy HTTPS to this HTTP using external nginx? #1122

leqii-com opened this issue Nov 19, 2024 · 3 comments
Assignees

Comments

@leqii-com
Copy link

Describe the issue
A clear and concise description of what the issue is.

To Reproduce
Steps to reproduce the issue:

  1. Go to ...
  2. Perform action ...
  3. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

  • OS: [e.g. Ubuntu Linux]
  • Installation method: [Docker install, or single server install]
  • Browser, if applicable

Additional context

外部nginx,如何反向代理https到该http?
我在配置反向代理过程中发现http被前端写死http://,无法转发到https://
换了proxy nginx docker容器,浏览器提示域名被拒绝访问

How to reverse proxy HTTPS to this HTTP using external nginx?
I found that HTTP was written as' http://'by the frontend during the reverse proxy configuration process, making it impossible to forward to' https://'
Replaced proxy nginx docker container, browser prompts domain access denied ,“ERR_CONNECTION_REFUSED”.

@leqii-com
Copy link
Author

Complete.

已自行解决。如下是mediacms使用外部nginx多层反向代理方法:

一层代理,location中有proxy_set_header Host $http_host;

# nginx-proxy version : 1.6.3-33-gd7acd93
# Networks available to the container running docker-gen (which are assumed to
# match the networks available to the container running nginx):
#     mediacms-main_default
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
    default $http_x_forwarded_proto;
    '' $scheme;
}
map $http_x_forwarded_host $proxy_x_forwarded_host {
    default $http_x_forwarded_host;
    '' $host;
}
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
# server port the client connected to
map $http_x_forwarded_port $proxy_x_forwarded_port {
    default $http_x_forwarded_port;
    '' $server_port;
}
# Include the port in the Host header sent to the container if it is non-standard
map $server_port $host_port {
    default :$server_port;
    80 '';
    443 '';
}
# If the request from the downstream client has an "Upgrade:" header (set to any
# non-empty value), pass "Connection: upgrade" to the upstream (backend) server.
# Otherwise, the value for the "Connection" header depends on whether the user
# has enabled keepalive to the upstream server.
map $http_upgrade $proxy_connection {
    default upgrade;
    '' $proxy_connection_noupgrade;
}
map $upstream_keepalive $proxy_connection_noupgrade {
    # Preserve nginx's default behavior (send "Connection: close").
    default close;
    # Use an empty string to cancel nginx's default behavior.
    true '';
}
# Abuse the map directive (see <https://stackoverflow.com/q/14433309>) to ensure
# that $upstream_keepalive is always defined.  This is necessary because:
#   - The $proxy_connection variable is indirectly derived from
#     $upstream_keepalive, so $upstream_keepalive must be defined whenever
#     $proxy_connection is resolved.
#   - The $proxy_connection variable is used in a proxy_set_header directive in
#     the http block, so it is always fully resolved for every request -- even
#     those where proxy_pass is not used (e.g., unknown virtual host).
map "" $upstream_keepalive {
    # The value here should not matter because it should always be overridden in
    # a location block (see the "location" template) for all requests where the
    # value actually matters.
    default false;
}
# Apply fix for very long server names
server_names_hash_bucket_size 128;
# Default dhparam
# Set appropriate X-Forwarded-Ssl header based on $proxy_x_forwarded_proto
map $proxy_x_forwarded_proto $proxy_x_forwarded_ssl {
    default off;
    https on;
}
log_format vhost escape=default '$host $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$upstream_addr"';
access_log off;
    #Ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    #ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305';
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers  ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;


# HTTP 1.1 support
proxy_http_version 1.1;
proxy_set_header Host $host$host_port;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Original-URI $request_uri;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
server {
    server_name test.cn;
    access_log /data/logs/nginx/test.log vhost;
    listen 80;
    server_tokens off;
    return 301 https://$host$request_uri;
}
server {
    server_name test.cn;
    access_log  /data/logs/nginx/test.cn.log vhost;
    listen 443 ssl ;
    server_tokens off;
    if ( $host ~* "\d+\.\d+\.\d+\.\d+" ) {
        return 500;
    }
    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:1m;
    ssl_certificate /data/nginx/.cert/test.cn.pem;
    ssl_certificate_key /data/nginx/.cert/test.cn.key;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    location / {
        proxy_set_header Host $http_host;
        proxy_pass https://公司IP;
    }
}

二层代理:localtion中无proxy_set_header Host $http_host;

# nginx-proxy version : 1.6.3-33-gd7acd93
# Networks available to the container running docker-gen (which are assumed to
# match the networks available to the container running nginx):
#     mediacms-main_default
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
    default $http_x_forwarded_proto;
    '' $scheme;
}
map $http_x_forwarded_host $proxy_x_forwarded_host {
    default $http_x_forwarded_host;
    '' $host;
}
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
# server port the client connected to
map $http_x_forwarded_port $proxy_x_forwarded_port {
    default $http_x_forwarded_port;
    '' $server_port;
}
# Include the port in the Host header sent to the container if it is non-standard
map $server_port $host_port {
    default :$server_port;
    80 '';
    443 '';
}
# If the request from the downstream client has an "Upgrade:" header (set to any
# non-empty value), pass "Connection: upgrade" to the upstream (backend) server.
# Otherwise, the value for the "Connection" header depends on whether the user
# has enabled keepalive to the upstream server.
map $http_upgrade $proxy_connection {
    default upgrade;
    '' $proxy_connection_noupgrade;
}
map $upstream_keepalive $proxy_connection_noupgrade {
    # Preserve nginx's default behavior (send "Connection: close").
    default close;
    # Use an empty string to cancel nginx's default behavior.
    true '';
}
# Abuse the map directive (see <https://stackoverflow.com/q/14433309>) to ensure
# that $upstream_keepalive is always defined.  This is necessary because:
#   - The $proxy_connection variable is indirectly derived from
#     $upstream_keepalive, so $upstream_keepalive must be defined whenever
#     $proxy_connection is resolved.
#   - The $proxy_connection variable is used in a proxy_set_header directive in
#     the http block, so it is always fully resolved for every request -- even
#     those where proxy_pass is not used (e.g., unknown virtual host).
map "" $upstream_keepalive {
    # The value here should not matter because it should always be overridden in
    # a location block (see the "location" template) for all requests where the
    # value actually matters.
    default false;
}
# Apply fix for very long server names
server_names_hash_bucket_size 128;
# Default dhparam
# Set appropriate X-Forwarded-Ssl header based on $proxy_x_forwarded_proto
map $proxy_x_forwarded_proto $proxy_x_forwarded_ssl {
    default off;
    https on;
}
log_format vhost escape=default '$host $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$upstream_addr"';
access_log off;
    #Ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    #ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305';
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers  ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;


# HTTP 1.1 support
proxy_http_version 1.1;
proxy_set_header Host $host$host_port;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $proxy_x_forwarded_host;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Original-URI $request_uri;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
server {
    server_name test.cn;
    access_log /data/logs/nginx/test.log vhost;
    listen 80;
    server_tokens off;
    return 301 https://$host$request_uri;
}
server {
    server_name test.cn;
    access_log  /data/logs/nginx/test.log vhost;
    listen 443 ssl ;
    server_tokens off;
    if ( $host ~* "\d+\.\d+\.\d+\.\d+" ) {
        return 500;
    }
    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:1m;
    ssl_certificate /data/nginx/.cert/test.pem;
    ssl_certificate_key /data/nginx/.cert/test.key;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    location / {
        proxy_pass http://内网mediacms主机IP;
    }
}

@leqii-com
Copy link
Author

补充:本人用的nginx是1.20.1,有些版本可能某些模块不支持,不支持的可以注释掉再试试。注意:多试试。

@codyray2015
Copy link

I have to say, you're overcomplicating things. MediaCMS determines whether to use HTTP or HTTPS based on the request type. You just need to ensure it receives the correct X-Forwarded-Proto header.

I wasted a considerable amount of time on this myself, until I realized another forwarding tool was overriding my X-Forwarded-Proto header.


我不得不说, 你把问题变得复杂了, mediacms会根据请求来的类型决定是HTTP还是HTTPS , 你只要保证它接受到正确的 X-Forwarded-Proto 就可以了

我曾经也在这件事情上浪费了不少时间,直到我发现是因为我使用了其他转发工具给我覆盖了 X-Forwarded-Proto

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

3 participants