저는 최근 모든 내부 서버를 TLSv1.2에서 TLSv1.3으로 전환하고 싶었습니다. 모두 최신 상태로 유지되고 이전 장치를 지원할 필요가 없기 때문입니다.
내 설정은 다음과 같습니다
역방향 프록시의 경우 주소는 192.168.20.2(Debian 11, NGINX v1.21.6)입니다. 이로 인해 공개적으로 유효한 Let Crypto 인증서가 중단되고 계속해서 TLSv1.2 및 TLSv1.3을 사용하여 다양한 클라이언트를 지원하게 됩니다. 요청은 다른 TLS 세션을 통해 server_name을 통해 올바른 백엔드 서버 IP로 전달됩니다.
여러 백엔드 서버가 있지만 단순화를 위해 하나만 설명하겠습니다(모든 구성은 동일함).
백엔드 서버, 주소는 192.168.30.2(Debian 11, NGINX v1.21.6)입니다. 이렇게 하면 웹 서버 인덱스 파일이 제공되는 다른 TLS 세션(자체 서명된 내부 인증서를 사용하여 역방향 프록시에 의해 시작됨)이 종료됩니다.
내 목표는 TLS 세션의 클라이언트와 서버를 모두 제어하므로 모든 백엔드 서버에서 TLSv1.2를 비활성화하여 새로운 TLS 버전과의 호환성을 유지하는 것이 가능합니다.
기본 사이트 구성에서 지적한 ssl-params.conf에 들어가서 TLSv1.2
해당 섹션에서 간단히 ssl_protocols
삭제했습니다 . nginx를 다시 시작한 후(오류 없이 잘 다시 시작됨) 사이트를 탐색하고 502 Bad Gateway
.
문제가 TLS1.2를 제거하는 것일 수도 있다고 생각했지만 역방향 프록시 자체에서 컬을 실행한 후 웹 서버 인덱스 파일을 정상적으로 얻을 수 있었습니다. 그래서 문제는 리버스 프록시 NGINX 서버에 있다고 생각합니다.
여기에 누락된 모호한 TLS NGINX 트랩이 있을 수 있습니다.
온라인에서 아무것도 찾을 수 없으니 누군가 내 문제를 알려줄 수 있을까요?
백엔드 서버에 TLS를 사용하는 이유가 궁금하다면 역방향 프록시와 백엔드 서버 간의 연결이 네트워크의 신뢰할 수 없는 부분에 걸쳐 있으므로 암호화하기 때문입니다.
다음은 특정 백엔드 사이트에 연결하기 위한 모든 관련 구성입니다.
역방향 프록시:
# configuration file /etc/nginx/nginx.conf:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Rate Limiting
##
limit_conn_zone $binary_remote_addr zone=limit_conn:1m;
limit_conn limit_conn 100;
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
client_max_body_size 10000m;
##
# Virtual Host Configs
##
include /etc/nginx/sites-enabled/*;
##
# Hardening
##
add_header Allow "GET, POST, HEAD" always;
}
# configuration file /etc/nginx/snippets/ssl-params.conf:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
resolver 192.168.20.1 valid=300s;
resolver_timeout 5s;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# configuration file /etc/nginx/sites-enabled/wiki.domain.com:
server {
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/wiki.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/wiki.domain.com/privkey.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/wiki.domain.com/chain.pem;
include snippets/ssl-params.conf;
server_name wiki.domain.com;
location / {
proxy_pass https://192.168.30.2;
proxy_set_header X-Real-IP $remote_addr;
}
}
백엔드 서버:
# configuration file /etc/nginx/nginx.conf:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Logging Settings
##
access_log off;
error_log off;
##
# Gzip Settings
##
gzip on;
client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 10k;
large_client_header_buffers 2 1k;
server_tokens off;
##
# Virtual Host Configs
##
include /etc/nginx/sites-enabled/*;
}
# configuration file /etc/nginx/sites-enabled/dokuwiki.conf:
server {
listen 443 ssl http2;
include snippets/self-signed.conf;
include snippets/ssl-params.conf;
server_name _;
root /var/www;
index index.html;
}
# configuration file /etc/nginx/snippets/self-signed.conf:
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
# configuration file /etc/nginx/snippets/ssl-params.conf:
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 192.168.30.1 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy "default-src 'self';";
add_header X-XSS-Protection "1; mode=block";
ssl_dhparam /etc/ssl/certs/dhparam.pem;
저는 테스트용 백엔드 서버로 기본 index.html을 사용했습니다.
내가 탐색하려고 할 때클라이언트 컴퓨터에서 역방향 프록시로:
user@clientmachine:~$ curl -vvvv https://wiki.domain.com
* Trying PUBLICIP:443...
* Connected to wiki.domain.com (PUBLICIP) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* 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 handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=wiki.domain.com
* start date: May 17 09:56:32 2022 GMT
* expire date: Aug 15 09:56:31 2022 GMT
* subjectAltName: host "wiki.domain.com" matched cert's "wiki.domain.com"
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55619a9a25c0)
> GET / HTTP/2
> Host: wiki.domain.com
> user-agent: curl/7.74.0
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 502
< server: nginx
< date: Mon, 13 Jun 2022 21:31:20 GMT
< content-type: text/html
< content-length: 150
< allow: GET, POST, HEAD
<
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host wiki.domain.com left intact
백엔드 서버를 탐색하려고 하면역방향 프록시에서 백엔드로:
user@revproxy:~$ curl -kvvvv https://192.168.30.2/
* Trying 192.168.30.2:443...
* Connected to 192.168.30.2 (192.168.30.2) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* 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 handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=US; ST=State; L=city; O=; CN=192.168.30.2
* start date: Dec 10 16:29:30 2021 GMT
* expire date: Feb 26 16:29:30 2031 GMT
* issuer: C=US; ST=State; L=city; O=; CN=192.168.30.2
* SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x555ab8d305c0)
> GET / HTTP/2
> Host: 192.168.30.2
> user-agent: curl/7.74.0
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200
< server: nginx
< date: Mon, 13 Jun 2022 21:33:38 GMT
< content-type: text/html
< content-length: 329
< last-modified: Mon, 13 Jun 2022 21:05:52 GMT
< etag: "62a7a6b0-149"
< strict-transport-security: max-age=63072000; includeSubdomains
< x-frame-options: DENY
< x-content-type-options: nosniff
< content-security-policy: default-src 'self';
< x-xss-protection: 1; mode=block
< accept-ranges: bytes
<
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Spoon-Knife</title>
<LINK href="styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<!-- Feel free to change this text here -->
<p>
Fork me? Fork you!
</p>
<p>
I made a change
</p>
</body>
</html>
* Connection #0 to host 192.168.30.2 left intact
물론 TLSv1.2
백엔드 서버의 ssl_protocols 섹션에 있는 ssl-params.conf에 이를 추가하면 갑자기 클라이언트 요청이 통과됩니다(클라이언트는 역방향 프록시에 대한 초기 연결에 여전히 TLSv1.3을 사용합니다).
답변1
여기서 해결책을 찾았습니다. https://forum.nginx.org/read.php?11,294147
분명히 NGINX는 프록시 통과 연결에 사용할 프로토콜을 알려줘야 합니다.
proxy_ssl_protocols TLSv1.3;
역방향 프록시 서버 블록을 사용하면 문제가 해결되었습니다.