Nginx代理Docker中Angular应用的SSL与路由问题排查
解决方案
1. 修复外部Nginx代理配置
问题核心是内部Nginx返回的301重定向暴露了内部端口和HTTP协议,加上HSTS强制转HTTPS导致访问非SSL端口出错。修改外部Nginx的/test location块:
# 先处理不带斜杠的请求,直接重定向到带斜杠的HTTPS地址 location = /test { return 301 https://$host/test/; } location /test/ { proxy_pass http://project1/test/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Host $host; proxy_set_header Connection $http_upgrade; proxy_cache_bypass $http_upgrade; 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 X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; # 禁止内部Nginx的重定向修改地址 proxy_redirect off; }
2. 调整内部Angular的Nginx配置
确保内部Nginx正确处理路由,同时传递外部请求的头部信息给Angular:
server { listen 3000; listen [::]:3000; root /var/www/nginx; server_tokens off; location /test/ { try_files $uri $uri/ /test/index.html; # 传递外部协议、域名、端口给Angular add_header X-Forwarded-Proto $http_x_forwarded_proto; add_header X-Forwarded-Host $http_x_forwarded_host; add_header X-Forwarded-Port $http_x_forwarded_port; } }
3. 配置Angular应用的Base Href
构建Angular时指定正确的基础路径,避免生成带内部端口的链接:
ng build --base-href "/test/"
原提问内容
我正尝试配置Nginx以加密通往Docker服务的外部流量,计划搭建一个带有Let's Encrypt SSL证书、监听外部IP的代理,将请求路由至Docker容器内的不同服务器。目前已完成外部Nginx服务器的安全配置,测试表明静态文件可正常访问,SSL功能运行良好。
但在将路径路由至部署Angular应用的非SSL Nginx服务器时,遇到了一些问题:
- 请求末尾带斜杠
/的URL时,访问正常; - 请求不带斜杠的URL时,出现如下错误:
curl: (35) OpenSSL/3.0.8: error:0A00010B:SSL routines::wrong version number - Angular路由与当前配置冲突,Web应用内视图间的跳转链接会混淆内部端口与外部域名。
外部SSL加密Nginx服务器配置:
# web.conf upstream project1 { server nginx:3000; } server { listen 443 default_server ssl http2; listen [::]:443 ssl http2; ssl_certificate /etc/letsencrypt/live/my.domain.some/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/my.domain.some/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # Extra config add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; always"; add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; server_name my.domain.some; location / { root /var/www/nginx; } location /test { proxy_pass http://project1; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Host $host; proxy_set_header Connection 'upgrade'; proxy_cache_bypass $http_upgrade; # Extra config 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; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; } }
Angular项目部署的Nginx实例配置:
server { listen 3000; listen [::]:3000; root /var/www/nginx; server_tokens off; location /test { alias /var/www/nginx; autoindex off; index index.html index.htm; try_files $uri $uri/ /index.html; } }
执行curl -v -L https://my.domain.some/test(无末尾斜杠)的返回报错:
* Trying 111.111.111.111:443... * Connected to my.domain.some (111.111.111.111) port 443 (#0) * ALPN: offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Request CERT (13): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Certificate (11): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN: server accepted h2 * Server certificate: * subject: CN=my.domain.some * start date: May 5 13:49:51 2023 GMT * expire date: Aug 3 13:49:50 2023 GMT * subjectAltName: host "my.domain.some" matched cert's "my.domain.some" * issuer: C=US; O=Let's Encrypt; CN=R3 * SSL certificate verify ok. * using HTTP/2 * h2h3 [:method: GET] * h2h3 [:path: /test] * h2h3 [:scheme: https] * h2h3 [:authority: my.domain.some] * h2h3 [user-agent: curl/7.88.1] * h2h3 [accept: */*] * Using Stream ID: 1 (easy handle 0x55a78c81e680) > GET /test HTTP/2 > Host: my.domain.some > user-agent: curl/7.88.1 > accept: */* > * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * old SSL session ID is stale, removing < HTTP/2 301 < server: nginx/1.15.12 < date: Mon, 03 Jul 2023 15:42:05 GMT < content-type: text/html < content-length: 162 < location: http://my.domain.some:3000/test/ < strict-transport-security: max-age=31536000; includeSubDomains; always < x-frame-options: SAMEORIGIN < x-content-type-options: nosniff < x-xss-protection: 1; mode=block < * Ignoring the response-body * Connection #0 to host my.domain.some left intact * Clear auth, redirects to port from 443 to 3000 * Issue another request to this URL: 'http://my.domain.some:3000/test/' * Switched from HTTP to HTTPS due to HSTS => https://my.domain.some:3000/test/ * Trying 111.111.111.111:3000... * Connected to my.domain.some (111.111.111.111) port 3000 (#1) * ALPN: offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * OpenSSL/3.0.8: error:0A00010B:SSL routines::wrong version number * Closing connection 1 curl: (35) OpenSSL/3.0.8: error:0A00010B:SSL routines::wrong version number
内容的提问来源于stack exchange,提问作者GonAlonso
相关产品推荐
相关产品推荐

